diff --git a/README.md b/README.md
index 3eb81c5..69a45a7 100644
--- a/README.md
+++ b/README.md
@@ -89,22 +89,24 @@ ACC | The ACC register
variable | A variable from the memory
label | Jump label
[ ] | "Value of"
+```${memAddr}``` | Memory address parameter
+```${jumpTo}``` | Instruction index or jump label parameter
### Instructions Table
Assembly Command | Short Instruction Description | Long Instruction Description | Short Param Description | Long Param Description
--- | --- | --- | --- | ---
-nop | - | This instruction doesn't perform any action | - | No parameter is required
-copy | [ACC] = [variable] | A value from the memory is copied to the ACC register | variable | It's the name of the variable that will be used in the instruction
-store | [variable] = [ACC] | The value from the ACC register is stored into memory | variable | It's the name of the variable that will be used in the instruction
-add | [ACC] = [ACC] + [variable] | The sum of the value of the ACC register and a value from the memory is stored in the ACC register | variable | It's the name of the variable that will be used in the instruction
-sub | [ACC] = [ACC] - [variable] | The difference between the value of the ACC register and a value from the memory is stored in the ACC register | variable | It's the name of the variable that will be used in the instruction
-input | [variable] = input value | The input value is copied to the memory | variable | It's the name of the variable that will be used in the instruction
-output | Output [variable] | Outputs a value from the memory into the circuit LEDs | variable | It's the name of the variable that will be used in the instruction
-kill | Finishes program | When this instruction is encountered, the program is finished and no more instructions will be executed | - | No parameter is required
-jmp | Jump to EE | Jump to another line of code | label | The jump label the program will jump to
-jg | Jump to EE if [ACC] > 0 | Jump to another line of code if the value of the ACC register is positive | label | The jump label the program will jump to if the condition is right
-je | Jump to EE if [ACC] = 0 | Jump to another line of code if the value of the ACC register is zero | label | The jump label the program will jump to if the condition is right
-jl | Jump to EE if [ACC] < 0 | Jump to another line of code if the value of the ACC register is negative | label | The jump label the program will jump to if the condition is right
+```nop``` | - | This instruction doesn't perform any action | - | No parameter is required
+```copy ${memAddr}``` | [ACC] = [variable] | A value from the memory is copied to the ACC register | variable | It's the name of the variable that will be used in the instruction
+```store ${memAddr}``` | [variable] = [ACC] | The value from the ACC register is stored into memory | variable | It's the name of the variable that will be used in the instruction
+```add ${memAddr}``` | [ACC] = [ACC] + [variable] | The sum of the value of the ACC register and a value from the memory is stored in the ACC register | variable | It's the name of the variable that will be used in the instruction
+```sub ${memAddr}``` | [ACC] = [ACC] - [variable] | The difference between the value of the ACC register and a value from the memory is stored in the ACC register | variable | It's the name of the variable that will be used in the instruction
+```input ${memAddr}``` | [variable] = input value | The input value is copied to the memory | variable | It's the name of the variable that will be used in the instruction
+```output ${memAddr}``` | Output [variable] | Outputs a value from the memory into the circuit LEDs | variable | It's the name of the variable that will be used in the instruction
+```kill``` | Finishes program | When this instruction is encountered, the program is finished and no more instructions will be executed | - | No parameter is required
+```jmp ${jumpTo}``` | Jump to EE | Jump to another line of code | label | The jump label the program will jump to
+```jg ${jumpTo}``` | Jump to EE if [ACC] > 0 | Jump to another line of code if the value of the ACC register is positive | label | The jump label the program will jump to if the condition is right
+```je ${jumpTo}``` | Jump to EE if [ACC] = 0 | Jump to another line of code if the value of the ACC register is zero | label | The jump label the program will jump to if the condition is right
+```jl ${jumpTo}``` | Jump to EE if [ACC] < 0 | Jump to another line of code if the value of the ACC register is negative | label | The jump label the program will jump to if the condition is right
@@ -137,10 +139,19 @@ Read the specifications below to learn the code syntax.
- **Numbers** can be written in hexadecimal in the form of ```0xff``` or in decimal as ```255```;
## Naming Practices
-- A **label name** should start with a letter and the rest of the name can have more letters and numbers;
+- A **variable or label name** should start with a letter and the rest of the name can have more letters and numbers;
- Every name should obey the following regex: ```[a-z][a-zA-Z0-9]*```;
- Snake-case is not allowed and the use of camel-case is encouraged.
+## Declaring Variables
+- The variables should be declared between the imports and instructions.
+- Form: ```declare {variableName} {number}```
+- Example
+ ```sh
+ declare variable 0xff
+ ```
+- Remember to follow the [naming practices](#naming-practices)
+
## Jump Label
- Definition: it marks the line for possible jumps to that line;
- Form: ```{labelName}:```
@@ -154,7 +165,7 @@ An instruction line is a line that contains an instruction call.
***Components***
- ```instruction``` is the actual instruction that will be executed, it must be one of the following in the instruction table;
-- ```arg``` can be either a jump label or a
+- ```arg``` can be a jump label, variable or a number (depending on the instruction)
***Form***
- A instruction line should be in the following form ```{instruction} [arg]```;
@@ -171,22 +182,30 @@ Check out [here](#-instructions) the instruction table to know what instructions
# 👨🏻💻 Code Example
+The following assembly code gets two numbers from input and outputs the sum of them. If the sum is greater than zero it will output zero.
+
+*ps: Since the ```input``` instruction doesn't wait for a change, expect the output to be zero.*
```sh
-# Let's get two numbers as input and print the result of the sum of them
+# data inputs
+input 0x55
+input 0x56
+# sum
+copy 0x55
+add 0x56
+store 0x57
+# output
+output 0x57
-procedure procSub
- copy 0xff # copy value in the address ff in RAM
- store 0x0a # stores the value of ACC in the address 0a
-end
+# if output higher than zero, it will output zero
+copy 0x57
+je finish # if
+jl finish # if
+output 0xff # [0xff] = 0 since we didn't change it
-start:
- procSub
+finish:
- copy 0xff # copy value in the address ff in RAM
- store 0x0a # stores the value of ACC in the address 0a
- je start # jumps to the 'start' label if ACC is 0
kill
```
diff --git a/commands/instruction/config.go b/commands/instruction/config.go
new file mode 100644
index 0000000..1f27cbd
--- /dev/null
+++ b/commands/instruction/config.go
@@ -0,0 +1,26 @@
+package instruction
+
+import (
+ "github.com/open-machine/assembler/commands/instruction/engine"
+ "github.com/open-machine/assembler/core/commandsassembler"
+)
+
+func GetInstructionsConfig() map[string]commandsassembler.CommandAssembler {
+ return instructions
+}
+
+// TODO: test if any instruction has the same code
+var instructions = map[string]commandsassembler.CommandAssembler{
+ "nop": engine.NewNoParamInstruct(0x0),
+ "copy": engine.NewOneParamInstruct(0x1, !engine.ACCEPT_STRING_PARAM),
+ "store": engine.NewOneParamInstruct(0x2, !engine.ACCEPT_STRING_PARAM),
+ "add": engine.NewOneParamInstruct(0x3, !engine.ACCEPT_STRING_PARAM),
+ "sub": engine.NewOneParamInstruct(0x4, !engine.ACCEPT_STRING_PARAM),
+ "input": engine.NewOneParamInstruct(0x7, !engine.ACCEPT_STRING_PARAM),
+ "output": engine.NewOneParamInstruct(0x8, !engine.ACCEPT_STRING_PARAM),
+ "kill": engine.NewNoParamInstruct(0x9),
+ "jmp": engine.NewOneParamInstruct(0xA, engine.ACCEPT_STRING_PARAM),
+ "jg": engine.NewOneParamInstruct(0xB, engine.ACCEPT_STRING_PARAM),
+ "je": engine.NewOneParamInstruct(0xD, engine.ACCEPT_STRING_PARAM),
+ "jl": engine.NewOneParamInstruct(0xF, engine.ACCEPT_STRING_PARAM),
+}
diff --git a/core/instruction/instructionsconfig_test.go b/commands/instruction/config_test.go
similarity index 100%
rename from core/instruction/instructionsconfig_test.go
rename to commands/instruction/config_test.go
diff --git a/commands/instruction/engine/index_test.go b/commands/instruction/engine/index_test.go
new file mode 100644
index 0000000..6dc4fac
--- /dev/null
+++ b/commands/instruction/engine/index_test.go
@@ -0,0 +1,326 @@
+package engine
+
+// TODO
+
+// func TestGetNoParam(t *testing.T) {
+// got, err := getParamNoParam("nop", []string{"nop"})
+// if !(err == nil && !got.IsStr && got.Num == 0) {
+// t.Errorf("Wrong")
+// }
+// }
+
+// func TestGetSecondParamAsInt(t *testing.T) {
+// var tests = []struct {
+// line string
+// expected *data.InstructionParameter
+// expectsErr bool
+// }{
+// // Decimal Number
+// {"mov 1", newCmdIntParam(1), false},
+// // Hexadecimal Number
+// {"mov 0x1a", newCmdIntParam(26), false},
+// {"mov 0x001", newCmdIntParam(1), false},
+// {"mov 0x0f", newCmdIntParam(15), false},
+// {"mov 0xff", newCmdIntParam(255), false},
+// {"mov 0x0ff", newCmdIntParam(255), false},
+// // Variable
+// {"mov 0xx0ff", nil, true},
+// {"mov x1", nil, true},
+// {"mov 0x1g", nil, true},
+// {"mov 1a", nil, true},
+// // Words
+// {"mov", nil, true},
+// {"mov a b", nil, true},
+// {"mov a b c", nil, true},
+// }
+
+// for i, test := range tests {
+// arrayWords := strings.Split(test.line, " ")
+// got, err := getSecondWord(arrayWords[0], arrayWords, false)
+// gotError := err != nil
+
+// if test.expectsErr != gotError {
+// t.Errorf("[%d] Expected error: %t, Got error: %t", i, test.expectsErr, gotError)
+// }
+
+// if !helper.SafeIsEqualInstructionParamPointer(test.expected, got) {
+// t.Errorf("[%d] Expected: %v, Got: %v", i, test.expected, got)
+// }
+
+// if got != nil && got.IsStr {
+// t.Errorf("[%d] Expecting int parameter", i)
+// }
+// }
+// }
+
+// func TestGetSecondParamAsIntOrString(t *testing.T) {
+// var tests = []struct {
+// line string
+// expected *data.InstructionParameter
+// expectsErr bool
+// }{
+// // Decimal Number
+// {"jmp 1", newCmdIntParam(1), false},
+// // Hexadecimal Number
+// {"jmp 0x001", newCmdIntParam(1), false},
+// {"jmp 0x0f", newCmdIntParam(15), false},
+// {"jmp 0xff", newCmdIntParam(255), false},
+// {"jmp 0x0ff", newCmdIntParam(255), false},
+// // Variable
+// {"jmp a8", newCmdStringParam("a8"), false},
+// {"jmp x1", newCmdStringParam("x1"), false},
+// {"jmp a1", newCmdStringParam("a1"), false},
+// // Errors 1 param
+// {"jmp 0xx0ff", nil, true},
+// {"jmp 0x1g", nil, true},
+// {"jmp 1a", nil, true},
+// // Erros amnt params
+// {"jmp", nil, true},
+// {"jmp a b", nil, true},
+// {"jmp a b c", nil, true},
+// }
+
+// for i, test := range tests {
+// arrayWords := strings.Split(test.line, " ")
+// got, err := getSecondWord(arrayWords[0], arrayWords, true)
+// gotError := err != nil
+
+// if test.expectsErr != gotError {
+// t.Errorf("[%d] Expected error: %t, Got error: %t", i, test.expectsErr, gotError)
+// }
+
+// if !helper.SafeIsEqualInstructionParamPointer(test.expected, got) {
+// t.Errorf("[%d] Expected: %v, Got: %v", i, test.expected, got)
+// }
+
+// if got != nil && test.expected != nil && got.IsStr != test.expected.IsStr {
+// t.Errorf("[%d] Expected IsStr: %t, Got IsStr: %t", i, test.expected.IsStr, got.IsStr)
+// }
+// }
+// }
+// func newCmdIntParam(num int) *data.InstructionParameter {
+// param := data.NewIntParam(num)
+// return ¶m
+// }
+// func newCmdStringParam(str string) *data.InstructionParameter {
+// param := data.NewStringParam(str)
+// return ¶m
+// }
+
+// func TestAssembleInstruction(t *testing.T) {
+// if len(instructions) != 12 {
+// t.Errorf("Tests were not updated")
+// }
+
+// var tests = []struct {
+// line string
+// expected *data.Instruction
+// expectsErr bool
+// }{
+// // Success Number
+// {"nop", getInstruction(0x0, 0), false},
+// {"copy 0x10", getInstruction(0x1, 16), false},
+// {"store 0x10", getInstruction(0x2, 16), false},
+// {"add 10", getInstruction(0x3, 10), false},
+// {"sub 10", getInstruction(0x4, 10), false},
+// {"input 7", getInstruction(0x7, 7), false},
+// {"output 8", getInstruction(0x8, 8), false},
+// {"kill", getInstruction(0x9, 0), false},
+// {"jmp 0x8", getInstruction(0xA, 8), false},
+// {"jg 0x8", getInstruction(0xB, 8), false},
+// {"je 0x8", getInstruction(0xD, 8), false},
+// {"jl 0x8", getInstruction(0xF, 8), false},
+// // Success Label
+// {"jmp label", getInstructionStr(0xA, "label"), false},
+// {"jg label", getInstructionStr(0xB, "label"), false},
+// {"je label", getInstructionStr(0xD, "label"), false},
+// {"jl label", getInstructionStr(0xF, "label"), false},
+// // Fail: Wrong Instruction
+// {"nope", nil, true},
+// // Fail: No label as param
+// {"copy label", nil, true},
+// {"store label", nil, true},
+// {"add label", nil, true},
+// {"sub label", nil, true},
+// {"input label", nil, true},
+// {"output label", nil, true},
+// // Fail: Wrong param
+// {"add 1x10", nil, true},
+// // Fail: Amnt params
+// {"kill 0", nil, true},
+// {"output", nil, true},
+// {"output 8 1", nil, true},
+// }
+
+// for i, test := range tests {
+// got, err := AssembleInstruction(test.line)
+// gotError := err != nil
+
+// if test.expectsErr != gotError {
+// t.Errorf("[%d] Expected error: %t, Got error: %t", i, test.expectsErr, gotError)
+// }
+// if !helper.SafeIsEqualInstructionPointer(test.expected, got) {
+// t.Errorf("Instruction expected is: %v, Got expected is: %v", test.expected, got)
+// }
+// }
+// }
+// func getInstruction(code int, param int) *data.Instruction {
+// cmd, _ := data.NewInstruction(code, data.NewIntParam(param))
+// return cmd
+// }
+// func getInstructionStr(code int, param string) *data.Instruction {
+// cmd, _ := data.NewInstruction(code, data.NewStringParam(param))
+// return cmd
+// }
+
+// func TestGetInstructionParams(t *testing.T) {
+// var tests = []struct {
+// param []string
+// expected []string
+// }{
+// {
+// []string{"mov", "0x1", "1", "label"},
+// []string{"0x1", "1", "label"},
+// },
+// {
+// []string{"cp", "to", "here"},
+// []string{"to", "here"},
+// },
+// {
+// []string{"cp"},
+// []string{},
+// },
+// }
+
+// for i, test := range tests {
+// got := getInstructionParams(test.param)
+// if !reflect.DeepEqual(got, test.expected) {
+// t.Errorf("[%d] Expected: %v, Got: %v", i, test.expected, got)
+// }
+// }
+// }
+
+// func TestCheckAmntWords(t *testing.T) {
+// var tests = []struct {
+// amntParamsExpected int
+// instructionName string
+// words []string
+// expectedErr bool
+// }{
+// // Success: no param
+// {
+// amntParamsExpected: 0,
+// instructionName: "mov",
+// words: []string{},
+// expectedErr: false,
+// },
+// // Success: one param
+// {
+// amntParamsExpected: 1,
+// instructionName: "mov",
+// words: []string{"hello"},
+// expectedErr: false,
+// },
+// // Success: two param
+// {
+// amntParamsExpected: 2,
+// instructionName: "mov",
+// words: []string{"hello", "there"},
+// expectedErr: false,
+// },
+// // Fail: expected more (no param)
+// {
+// amntParamsExpected: 1,
+// instructionName: "mov",
+// words: []string{},
+// expectedErr: true,
+// },
+// // Fail: expected more (more params)
+// {
+// amntParamsExpected: 5,
+// instructionName: "mov",
+// words: []string{"hello", "there", "now"},
+// expectedErr: true,
+// },
+// // Fail: expected less
+// {
+// amntParamsExpected: 0,
+// instructionName: "mov",
+// words: []string{"hello"},
+// expectedErr: true,
+// },
+// }
+
+// for i, test := range tests {
+// err := checkAmntWords(test.amntParamsExpected, test.instructionName, test.words)
+// gotErr := err != nil
+
+// if gotErr != test.expectedErr {
+// t.Errorf("[%d] Expected error: %t, Got error: %t", i, test.expectedError, gotErr)
+// }
+// }
+// }
+
+// func TestAddInstruction(t *testing.T) {
+// var tests = []struct {
+// code int
+// param data.InstructionParameter
+// program data.Program
+// expectedError bool
+// expectedProgram data.Program
+// }{
+// // Success
+// {
+// code: 5,
+// param: 1000,
+// program: newProgramPointer([]data.Instruction{
+// newInstruction(1, 2),
+// newInstruction(3, 4),
+// }),
+// expectedError: false,
+// expectedProgram: newProgramPointer([]data.Instruction{
+// newInstruction(1, 2),
+// newInstruction(3, 4),
+// newInstruction(5, 1000),
+// }),
+// },
+// // Fail
+// {
+// code: 1000,
+// param: 200,
+// program: newProgramPointer([]data.Instruction{
+// newInstruction(1, 2),
+// newInstruction(3, 4),
+// }),
+// expectedError: true,
+// expectedProgram: newProgramPointer([]data.Instruction{
+// newInstruction(1, 2),
+// newInstruction(3, 4),
+// }),
+// },
+// }
+
+// for i, test := range tests {
+// err := addInstruction(test.code, test.param, test.program)
+// gotErr := err != nil
+
+// if gotErr != test.expectedError {
+// t.Errorf("[%d] Expected error: %t, Got error: %t", i, test.expectedError, gotErr)
+// }
+// if test.program != test.expectedProgram {
+// t.Errorf("[%d] Expected program: %v, Got program: %v", i, test.expectedProgram, test.program)
+// }
+// }
+// }
+
+// func newInstruction(code int, numParam int) data.Instruction {
+// config.Testing = true
+// param := data.NewParamTest(numParam, "", true)
+// instruc, _ := data.NewInstruction(code, param)
+// return instruc
+// }
+
+// func newProgramPointer(instructions []data.Instruction) *data.Program {
+// prog := data.ProgramFromInstructionsAndLabels(instructions, map[string]int{})
+// return &prog
+// }
diff --git a/commands/instruction/engine/noparam.go b/commands/instruction/engine/noparam.go
new file mode 100644
index 0000000..22f77d7
--- /dev/null
+++ b/commands/instruction/engine/noparam.go
@@ -0,0 +1,29 @@
+package engine
+
+import (
+ "strings"
+
+ "github.com/open-machine/assembler/config/myerrors"
+ "github.com/open-machine/assembler/data"
+)
+
+const DEFAULT_INT_PARAM = 0
+
+type NoParamInstruct struct {
+ code int
+}
+
+func NewNoParamInstruct(c int) NoParamInstruct {
+ return NoParamInstruct{code: c}
+}
+
+func (assembler NoParamInstruct) Assemble(instructionName string, line string, program *data.Program) *myerrors.CustomError {
+ words := strings.Split(line, " ")
+
+ errAmntWords := checkAmntWords(0, instructionName, words)
+ if errAmntWords != nil {
+ return errAmntWords
+ }
+
+ return addInstructionIntParam(assembler.code, DEFAULT_INT_PARAM, program)
+}
diff --git a/commands/instruction/engine/oneparam.go b/commands/instruction/engine/oneparam.go
new file mode 100644
index 0000000..fc452d0
--- /dev/null
+++ b/commands/instruction/engine/oneparam.go
@@ -0,0 +1,49 @@
+package engine
+
+import (
+ "strings"
+
+ "github.com/open-machine/assembler/config/myerrors"
+ "github.com/open-machine/assembler/data"
+ "github.com/open-machine/assembler/utils"
+)
+
+const ACCEPT_STRING_PARAM = true
+
+type OneParamInstruct struct {
+ code int
+ acceptStringParam bool
+}
+
+func NewOneParamInstruct(code int, acceptStringParam bool) OneParamInstruct {
+ return OneParamInstruct{code: code, acceptStringParam: acceptStringParam}
+}
+
+func (assembler OneParamInstruct) Assemble(instructionName string, line string, program *data.Program) *myerrors.CustomError {
+ words := strings.Split(line, " ")
+
+ errAmntWords := checkAmntWords(1, instructionName, words)
+ if errAmntWords != nil {
+ return errAmntWords
+ }
+
+ strParam := words[1]
+
+ if assembler.acceptStringParam && utils.IsValidName(strParam) {
+ return addInstructionStrParam(assembler.code, strParam, program)
+ }
+
+ num, err := utils.StrToPositiveInt(strParam)
+
+ if err != nil {
+ var customMsgErr error
+ if assembler.acceptStringParam {
+ customMsgErr = myerrors.InvalidParamLabelOrInt(strParam, err)
+ } else {
+ customMsgErr = myerrors.InvalidParamInt(strParam, err)
+ }
+ return myerrors.NewCodeError(customMsgErr)
+ }
+
+ return addInstructionIntParam(assembler.code, num, program)
+}
diff --git a/commands/instruction/engine/utils.go b/commands/instruction/engine/utils.go
new file mode 100644
index 0000000..98b1416
--- /dev/null
+++ b/commands/instruction/engine/utils.go
@@ -0,0 +1,54 @@
+package engine
+
+import (
+ "github.com/open-machine/assembler/config/myerrors"
+ "github.com/open-machine/assembler/data"
+)
+
+func checkAmntWords(amntParamsExpected int, instructionName string, words []string) *myerrors.CustomError {
+ params := getInstructionParams(words)
+ amntParamsReceived := len(params)
+ if amntParamsReceived < amntParamsExpected {
+ err := myerrors.WrongNumberOfParamsError(instructionName, amntParamsExpected, amntParamsReceived, params)
+ return myerrors.NewCodeError(err)
+ } else if amntParamsReceived > amntParamsExpected {
+ err := myerrors.WrongNumberOfParamsError(instructionName, amntParamsExpected, amntParamsReceived, params)
+ return myerrors.NewCodeError(err)
+ }
+
+ return nil
+}
+
+func addInstructionStrParam(code int, strParam string, program *data.Program) *myerrors.CustomError {
+ param, err := data.NewStringParam(strParam)
+ // TODO: test
+ if err != nil {
+ return myerrors.NewCodeError(err)
+ }
+
+ return addInstruction(code, *param, program)
+}
+
+func addInstructionIntParam(code int, intParam int, program *data.Program) *myerrors.CustomError {
+ param, err := data.NewIntParam(intParam)
+ // TODO: test
+ if err != nil {
+ return myerrors.NewCodeError(err)
+ }
+
+ return addInstruction(code, *param, program)
+}
+
+func addInstruction(code int, param data.InstructionParameter, program *data.Program) *myerrors.CustomError {
+ instruction, errNew := data.NewInstruction(code, param)
+ if errNew != nil {
+ return myerrors.NewCodeError(errNew)
+ }
+
+ program.AddInstruction(*instruction)
+ return nil
+}
+
+func getInstructionParams(words []string) []string {
+ return words[1:]
+}
diff --git a/core/label/label.go b/commands/label/label.go
similarity index 100%
rename from core/label/label.go
rename to commands/label/label.go
diff --git a/core/label/label_test.go b/commands/label/label_test.go
similarity index 100%
rename from core/label/label_test.go
rename to commands/label/label_test.go
diff --git a/config/myerrors/param.go b/config/myerrors/param.go
index 8832b58..5a45918 100644
--- a/config/myerrors/param.go
+++ b/config/myerrors/param.go
@@ -6,6 +6,10 @@ func ParamOverflow(param int, amntBits int) error {
return fmt.Errorf("Param '%b' overflows %d bits", param, amntBits)
}
+func ThereIsNoSpaceLeft(err error) error {
+ return fmt.Errorf("There is no space left: %s", err.Error())
+}
+
func InvalidParamLabelOrInt(param string, err error) error {
return fmt.Errorf("Param '%s' is not a valid label nor a valid number (Conversion error: %s)", param, err.Error())
}
diff --git a/config/myerrors/setup.go b/config/myerrors/setup.go
new file mode 100644
index 0000000..73626d1
--- /dev/null
+++ b/config/myerrors/setup.go
@@ -0,0 +1,9 @@
+package myerrors
+
+import (
+ "fmt"
+)
+
+func CommandAlreadyExistError(instructionStr string) error {
+ return fmt.Errorf("Map key '%s' already exists, there can't be any commands with the same name", instructionStr)
+}
diff --git a/core/commandsassembler/config.go b/core/commandsassembler/config.go
new file mode 100644
index 0000000..88429f5
--- /dev/null
+++ b/core/commandsassembler/config.go
@@ -0,0 +1,32 @@
+package commandsassembler
+
+import (
+ "github.com/open-machine/assembler/config/myerrors"
+)
+
+type AssemblerConfig struct {
+ mapAssemblers map[string]CommandAssembler
+ regexAssemblers []RegexCommandAssembler
+ last *CommandAssembler
+}
+
+func NewAssemblerConfig() AssemblerConfig {
+ return AssemblerConfig{mapAssemblers: map[string]CommandAssembler{}, regexAssemblers: []RegexCommandAssembler{}, last: nil}
+}
+
+// TODO: check every command if it is only accepted in only one regex (in the beginning test if the number of tests is equal to the setup)
+
+func (a *AssemblerConfig) AppendRegexAssembler(assembler RegexCommandAssembler) *myerrors.CustomError {
+ a.regexAssemblers = append(a.regexAssemblers, assembler)
+ return nil
+}
+
+func (a *AssemblerConfig) AppendMapAssembler(key string, assembler CommandAssembler) *myerrors.CustomError {
+ _, exists := a.mapAssemblers[key]
+ if exists {
+ return myerrors.NewAssemblerError(myerrors.CommandAlreadyExistError(key))
+ }
+
+ a.mapAssemblers[key] = assembler
+ return nil
+}
diff --git a/core/commandsassembler/index.go b/core/commandsassembler/index.go
new file mode 100644
index 0000000..731a395
--- /dev/null
+++ b/core/commandsassembler/index.go
@@ -0,0 +1,10 @@
+package commandsassembler
+
+import (
+ "github.com/open-machine/assembler/config/myerrors"
+ "github.com/open-machine/assembler/data"
+)
+
+type CommandAssembler interface {
+ Assemble(mapKey string, line string, program *data.Program) *myerrors.CustomError
+}
diff --git a/core/commandsassembler/regexcmdassembler.go b/core/commandsassembler/regexcmdassembler.go
new file mode 100644
index 0000000..ebd685c
--- /dev/null
+++ b/core/commandsassembler/regexcmdassembler.go
@@ -0,0 +1,23 @@
+package commandsassembler
+
+import (
+ "github.com/open-machine/assembler/config/myerrors"
+ "github.com/open-machine/assembler/data"
+)
+
+type RegexCommandAssembler struct {
+ regex string
+ fun func(mapKey string, line string, program *data.Program) *myerrors.CustomError
+}
+
+func NewRegexCommandAssembler(regex string, f func(mapKey string, line string, program *data.Program) *myerrors.CustomError) RegexCommandAssembler {
+ return RegexCommandAssembler{regex: regex, fun: f}
+}
+
+func RegexAssemblerFrom(regex string, assembler CommandAssembler) RegexCommandAssembler {
+ return RegexCommandAssembler{regex: regex, fun: assembler.Assemble}
+}
+
+func (regexassemble *RegexCommandAssembler) Assemble(k string, l string, p *data.Program) *myerrors.CustomError {
+ return regexassemble.fun(k, l, p)
+}
diff --git a/core/comment/index.go b/core/comment/index.go
deleted file mode 100644
index a47b84a..0000000
--- a/core/comment/index.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package comment
-
-import (
- "strings"
-)
-
-func RemoveComment(line string) string {
- index := strings.Index(line, "#")
- if index < 0 {
- return line
- }
- return line[:index]
-}
diff --git a/core/comment/index_test.go b/core/comment/index_test.go
deleted file mode 100644
index 9e86a02..0000000
--- a/core/comment/index_test.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package comment
-
-import (
- "testing"
-)
-
-func TestRemoveComment(t *testing.T) {
- tests := []struct {
- param string
- expected string
- }{
- {"", ""},
- {"copy 0x0", "copy 0x0"},
- {"# Hello World ", ""},
- {"copy 0x0 # Hello World", "copy 0x0 "},
- {"luca dillenburg doing stuff # Hello World", "luca dillenburg doing stuff "},
- }
-
- for _, test := range tests {
- got := RemoveComment(test.param)
- if got != test.expected {
- t.Errorf("Comment removed wrongly. Expected '%s', Got: '%s'", test.expected, test.param)
- }
- }
-}
diff --git a/core/fileio/progrfromfile.go b/core/fileio/progrfromfile.go
new file mode 100644
index 0000000..4984cf1
--- /dev/null
+++ b/core/fileio/progrfromfile.go
@@ -0,0 +1,46 @@
+package fileio
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+
+ "github.com/open-machine/assembler/utils"
+
+ "github.com/open-machine/assembler/data"
+ "github.com/open-machine/assembler/helper"
+)
+
+func ProgramFromFile(file utils.MyFileInterface) *data.Program {
+ reader := bufio.NewReader(file.Reader())
+ lineIndex := 1
+ program := data.NewProgram(0)
+
+ successful := true
+
+ for {
+ line, errRead := reader.ReadString('\n')
+
+ if errRead != nil && errRead != io.EOF {
+ helper.LogOtherError(fmt.Sprintf("Error while reading file. Error: %s", errRead.Error()))
+ return nil
+ }
+
+ errAssemble := assembleEntireLine(line, &program)
+
+ if errAssemble != nil {
+ successful = false
+ helper.LogErrorInLine(*errAssemble, lineIndex, line)
+ }
+
+ if errRead == io.EOF {
+ break
+ }
+ lineIndex++
+ }
+
+ if !successful {
+ return nil
+ }
+ return &program
+}
diff --git a/core/readwriteprogram_test.go b/core/fileio/progrfromfile_test.go
similarity index 55%
rename from core/readwriteprogram_test.go
rename to core/fileio/progrfromfile_test.go
index 535dad9..8d8adaf 100644
--- a/core/readwriteprogram_test.go
+++ b/core/fileio/progrfromfile_test.go
@@ -1,8 +1,7 @@
-package core
+package fileio
import (
"bytes"
- "reflect"
"strings"
"testing"
@@ -122,7 +121,7 @@ func TestProgramFromFile(t *testing.T) {
config.Err = new(bytes.Buffer)
f := utils.NewMyBufferAsFile(strings.NewReader(str), "file.asm")
- got := programFromFile(&f)
+ got := ProgramFromFile(&f)
if !helper.SafeIsEqualProgramPointer(test.expected, got) {
t.Errorf("[%d] Expected: %v, Got: %v", i, test.expected, got)
@@ -140,81 +139,3 @@ func newProgramPointer(instructions []data.Instruction, jumpLabelsDict map[strin
prog := data.ProgramFromInstructionsAndLabels(instructions, jumpLabelsDict)
return &prog
}
-
-func TestWriteAssembledFile(t *testing.T) {
- config.Out = new(bytes.Buffer)
- config.Err = new(bytes.Buffer)
-
- config.Testing = true
-
- var tests = []struct {
- param data.Program
- expectedFileStr string
- expectedCode int
- expectsErr bool
- }{
- {
- data.ProgramFromInstructionsAndLabels([]data.Instruction{
- *newInstruction(0x2, 1),
- *newInstruction(0x2, 12),
- }, map[string]int{}),
- "v2.0 raw\n00002001200c",
- 0,
- false,
- },
- {
- data.ProgramFromInstructionsAndLabels([]data.Instruction{
- *newInstruction(0x2, 1),
- *newInstruction(0x2, 12),
- *newInstruction(0xD, 15),
- }, map[string]int{}),
- "v2.0 raw\n00002001200cd00f",
- 0,
- false,
- },
- {
- data.ProgramFromInstructionsAndLabels([]data.Instruction{
- *newInstruction(0x2, 1),
- *data.NewInstructionTest(0x222, data.NewIntParam(12)),
- *newInstruction(0xD, 115),
- }, map[string]int{}),
- "",
- 1,
- true,
- },
- {
- data.ProgramFromInstructionsAndLabels([]data.Instruction{
- *newInstruction(0x2, 1),
- *data.NewInstructionTest(0x2, data.NewStringParam("a")),
- }, map[string]int{}),
- "",
- 1,
- true,
- },
- }
-
- for i, test := range tests {
- fileWriter := new(bytes.Buffer)
- got := writeExecProgram(test.param, "File", fileWriter)
-
- if !reflect.DeepEqual(test.expectedCode, got) {
- t.Errorf("[%d] Expected: %v, Got: %v", i, test.expectedCode, got)
- }
-
- gotFileStr := fileWriter.String()
- if gotFileStr != test.expectedFileStr {
- t.Errorf("[%d] Expected file str: %v, Got file str: %v", i, test.expectedFileStr, gotFileStr)
- }
-
- stderrStr := config.Err.(*bytes.Buffer).String()
- gotErr := stderrStr != ""
- if test.expectsErr != gotErr {
- t.Errorf("[%d] Expected error: %t, Got error: %t // ", i, test.expectsErr, gotErr)
- t.Errorf("\t\t StdErr: %s", stderrStr)
- }
- }
-}
-func newInstruction(cmdCode int, param int) *data.Instruction {
- got, _ := data.NewInstruction(cmdCode, data.NewIntParam(param))
- return got
-}
diff --git a/core/fileio/writeexec.go b/core/fileio/writeexec.go
new file mode 100644
index 0000000..ee1625a
--- /dev/null
+++ b/core/fileio/writeexec.go
@@ -0,0 +1,34 @@
+package fileio
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+
+ "github.com/open-machine/assembler/config"
+ "github.com/open-machine/assembler/data"
+ "github.com/open-machine/assembler/helper"
+)
+
+func WriteExecProgram(program data.Program, execFileName string, execFile io.Writer) int {
+ writer := bufio.NewWriter(execFile)
+ defer writer.Flush()
+
+ execStr, errs := program.ToExecuter()
+
+ if len(errs) > 0 {
+ for _, err := range errs {
+ // TODO: infrastructure to get line
+ helper.LogErrorInLine(err, 0, "")
+ }
+ return config.FailStatus
+ }
+
+ _, err := writer.WriteString(execStr)
+ if err != nil {
+ helper.LogOtherError(fmt.Sprintf("Could not write to file %s \n", execFileName))
+ return config.FailStatus
+ }
+
+ return config.SuccessStatus
+}
diff --git a/core/fileio/writeexec_test.go b/core/fileio/writeexec_test.go
new file mode 100644
index 0000000..67a891e
--- /dev/null
+++ b/core/fileio/writeexec_test.go
@@ -0,0 +1,95 @@
+package fileio
+
+import (
+ "bytes"
+ "reflect"
+ "testing"
+
+ "github.com/open-machine/assembler/config"
+ "github.com/open-machine/assembler/data"
+)
+
+func TestWriteAssembledFile(t *testing.T) {
+ config.Out = new(bytes.Buffer)
+ config.Err = new(bytes.Buffer)
+
+ config.Testing = true
+
+ var tests = []struct {
+ param data.Program
+ expectedFileStr string
+ expectedCode int
+ expectsErr bool
+ }{
+ {
+ data.ProgramFromInstructionsAndLabels([]data.Instruction{
+ *newInstruction(0x2, 1),
+ *newInstruction(0x2, 12),
+ }, map[string]int{}),
+ "v2.0 raw\n00002001200c",
+ 0,
+ false,
+ },
+ {
+ data.ProgramFromInstructionsAndLabels([]data.Instruction{
+ *newInstruction(0x2, 1),
+ *newInstruction(0x2, 12),
+ *newInstruction(0xD, 15),
+ }, map[string]int{}),
+ "v2.0 raw\n00002001200cd00f",
+ 0,
+ false,
+ },
+ {
+ data.ProgramFromInstructionsAndLabels([]data.Instruction{
+ *newInstruction(0x2, 1),
+ *newInstruction(0x222, 12),
+ *newInstruction(0xD, 115),
+ }, map[string]int{}),
+ "",
+ 1,
+ true,
+ },
+ {
+ data.ProgramFromInstructionsAndLabels([]data.Instruction{
+ *newInstruction(0x2, 1),
+ *newInstruction(0x2, 1),
+ *newInstructionStr(0x2, "a"),
+ }, map[string]int{}),
+ "",
+ 1,
+ true,
+ },
+ }
+
+ for i, test := range tests {
+ fileWriter := new(bytes.Buffer)
+ got := WriteExecProgram(test.param, "File", fileWriter)
+
+ if !reflect.DeepEqual(test.expectedCode, got) {
+ t.Errorf("[%d] Expected: %v, Got: %v", i, test.expectedCode, got)
+ }
+
+ gotFileStr := fileWriter.String()
+ if gotFileStr != test.expectedFileStr {
+ t.Errorf("[%d] Expected file str: %v, Got file str: %v", i, test.expectedFileStr, gotFileStr)
+ }
+
+ stderrStr := config.Err.(*bytes.Buffer).String()
+ gotErr := stderrStr != ""
+ if test.expectsErr != gotErr {
+ t.Errorf("[%d] Expected error: %t, Got error: %t // ", i, test.expectsErr, gotErr)
+ t.Errorf("\t\t StdErr: %s", stderrStr)
+ }
+ }
+}
+func newInstruction(cmdCode int, intParam int) *data.Instruction {
+ param, _ := data.NewIntParam(intParam)
+ got, _ := data.NewInstruction(cmdCode, *param)
+ return got
+}
+func newInstructionStr(cmdCode int, strParam string) *data.Instruction {
+ param, _ := data.NewStringParam(strParam)
+ got, _ := data.NewInstruction(cmdCode, *param)
+ return got
+}
diff --git a/core/index.go b/core/index.go
index 27c0935..b8544af 100644
--- a/core/index.go
+++ b/core/index.go
@@ -5,6 +5,7 @@ import (
"io"
"os"
+ "github.com/open-machine/assembler/core/fileio"
"github.com/open-machine/assembler/utils"
"github.com/open-machine/assembler/config"
@@ -53,7 +54,7 @@ func AssembleFileAux(path string, execFileNameParam *string, ioReaderFromPath io
}
defer file.Close()
- ptrProgram := programFromFile(file)
+ ptrProgram := fileio.ProgramFromFile(file)
if ptrProgram == nil {
return config.FailStatus, ""
}
@@ -67,8 +68,6 @@ func AssembleFileAux(path string, execFileNameParam *string, ioReaderFromPath io
return config.FailStatus, ""
}
- // TODO: verify execFileName as possible name or not ([a-zA-Z_-]+)
-
var execFileName string
if execFileNameParam == nil {
execFileName = helper.FileNameWithoutExtension(file.Name())
@@ -82,7 +81,7 @@ func AssembleFileAux(path string, execFileNameParam *string, ioReaderFromPath io
return config.FailStatus, ""
}
- writeStatus := writeExecProgram(*ptrProgram, execFileName, execFile)
+ writeStatus := fileio.WriteExecProgram(*ptrProgram, execFileName, execFile)
if writeStatus == config.FailStatus {
return config.FailStatus, ""
}
diff --git a/core/instruction/index.go b/core/instruction/index.go
deleted file mode 100644
index 4b5650a..0000000
--- a/core/instruction/index.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package instruction
-
-import (
- "strings"
-
- "github.com/open-machine/assembler/config/myerrors"
- "github.com/open-machine/assembler/data"
- "github.com/open-machine/assembler/utils"
-)
-
-func AssembleInstruction(line string) (*data.Instruction, *myerrors.CustomError) {
- arrayWords := strings.Split(line, " ")
- instructionName := arrayWords[0]
-
- instructionConfig, exists := instructions[instructionName]
- if !exists {
- err := myerrors.InstructionDoesNotExistError(instructionName)
- return nil, myerrors.NewCodeError(err)
- }
-
- param, paramErr := instructionConfig.getParam(instructionName, arrayWords)
- if paramErr != nil {
- return nil, paramErr
- }
-
- instructionPointer, customErr := data.NewInstruction(instructionConfig.code, *param)
- return instructionPointer, customErr
-}
-
-func getParamNoParam(instructionName string, words []string) (*data.InstructionParameter, *myerrors.CustomError) {
- if len(words) != 1 {
- remainingParams := getInstructionParams(words)
- err := myerrors.WrongNumberOfParamsError(instructionName, 0, len(remainingParams), remainingParams)
- return nil, myerrors.NewCodeError(err)
- }
-
- param := data.NewIntParam(0)
- return ¶m, nil
-}
-
-func getSecondWordAsInt(instructionName string, words []string) (*data.InstructionParameter, *myerrors.CustomError) {
- return getSecondWord(instructionName, words, false)
-}
-
-func getSecondWordAsIntOrString(instructionName string, words []string) (*data.InstructionParameter, *myerrors.CustomError) {
- return getSecondWord(instructionName, words, true)
-}
-
-func getSecondWord(instructionName string, words []string, acceptStringParam bool) (*data.InstructionParameter, *myerrors.CustomError) {
- if len(words) != 2 {
- if len(words) < 2 {
- err := myerrors.WrongNumberOfParamsError(instructionName, 1, 0, []string{})
- return nil, myerrors.NewCodeError(err)
- }
-
- remainingParams := getInstructionParams(words)
- err := myerrors.WrongNumberOfParamsError(instructionName, 1, len(remainingParams), remainingParams)
- return nil, myerrors.NewCodeError(err)
- }
-
- strParam := words[1]
-
- if acceptStringParam && utils.IsValidName(strParam) {
- param := data.NewStringParam(strParam)
- return ¶m, nil
- }
-
- num, err := utils.StrToPositiveInt(strParam)
-
- if err != nil {
- var customMsgErr error
- if acceptStringParam {
- customMsgErr = myerrors.InvalidParamLabelOrInt(strParam, err)
- } else {
- customMsgErr = myerrors.InvalidParamInt(strParam, err)
- }
- return nil, myerrors.NewCodeError(customMsgErr)
- }
-
- param := data.NewIntParam(num)
- return ¶m, nil
-}
-
-func getInstructionParams(words []string) []string {
- return words[1:]
-}
diff --git a/core/instruction/index_test.go b/core/instruction/index_test.go
deleted file mode 100644
index 905c4c7..0000000
--- a/core/instruction/index_test.go
+++ /dev/null
@@ -1,189 +0,0 @@
-package instruction
-
-import (
- "reflect"
- "strings"
- "testing"
-
- "github.com/open-machine/assembler/data"
- "github.com/open-machine/assembler/helper"
-)
-
-func TestGetNoParam(t *testing.T) {
- got, err := getParamNoParam("nop", []string{"nop"})
- if !(err == nil && !got.IsStr && got.Num == 0) {
- t.Errorf("Wrong")
- }
-}
-
-func TestGetSecondParamAsInt(t *testing.T) {
- var tests = []struct {
- line string
- expected *data.InstructionParameter
- expectsErr bool
- }{
- // Decimal Number
- {"mov 1", newCmdIntParam(1), false},
- // Hexadecimal Number
- {"mov 0x1a", newCmdIntParam(26), false},
- {"mov 0x001", newCmdIntParam(1), false},
- {"mov 0x0f", newCmdIntParam(15), false},
- {"mov 0xff", newCmdIntParam(255), false},
- {"mov 0x0ff", newCmdIntParam(255), false},
- // Variable
- {"mov 0xx0ff", nil, true},
- {"mov x1", nil, true},
- {"mov 0x1g", nil, true},
- {"mov 1a", nil, true},
- // Words
- {"mov", nil, true},
- {"mov a b", nil, true},
- {"mov a b c", nil, true},
- }
-
- for i, test := range tests {
- arrayWords := strings.Split(test.line, " ")
- got, err := getSecondWord(arrayWords[0], arrayWords, false)
- gotError := err != nil
-
- if test.expectsErr != gotError {
- t.Errorf("[%d] Expected error: %t, Got error: %t", i, test.expectsErr, gotError)
- }
-
- if !helper.SafeIsEqualInstructionParamPointer(test.expected, got) {
- t.Errorf("[%d] Expected: %v, Got: %v", i, test.expected, got)
- }
-
- if got != nil && got.IsStr {
- t.Errorf("[%d] Expecting int parameter", i)
- }
- }
-}
-
-func TestGetSecondParamAsIntOrString(t *testing.T) {
- var tests = []struct {
- line string
- expected *data.InstructionParameter
- expectsErr bool
- }{
- // Decimal Number
- {"jmp 1", newCmdIntParam(1), false},
- // Hexadecimal Number
- {"jmp 0x001", newCmdIntParam(1), false},
- {"jmp 0x0f", newCmdIntParam(15), false},
- {"jmp 0xff", newCmdIntParam(255), false},
- {"jmp 0x0ff", newCmdIntParam(255), false},
- // Variable
- {"jmp a8", newCmdStringParam("a8"), false},
- {"jmp x1", newCmdStringParam("x1"), false},
- {"jmp a1", newCmdStringParam("a1"), false},
- // Errors 1 param
- {"jmp 0xx0ff", nil, true},
- {"jmp 0x1g", nil, true},
- {"jmp 1a", nil, true},
- // Erros amnt params
- {"jmp", nil, true},
- {"jmp a b", nil, true},
- {"jmp a b c", nil, true},
- }
-
- for i, test := range tests {
- arrayWords := strings.Split(test.line, " ")
- got, err := getSecondWord(arrayWords[0], arrayWords, true)
- gotError := err != nil
-
- if test.expectsErr != gotError {
- t.Errorf("[%d] Expected error: %t, Got error: %t", i, test.expectsErr, gotError)
- }
-
- if !helper.SafeIsEqualInstructionParamPointer(test.expected, got) {
- t.Errorf("[%d] Expected: %v, Got: %v", i, test.expected, got)
- }
-
- if got != nil && test.expected != nil && got.IsStr != test.expected.IsStr {
- t.Errorf("[%d] Expected IsStr: %t, Got IsStr: %t", i, test.expected.IsStr, got.IsStr)
- }
- }
-}
-func newCmdIntParam(num int) *data.InstructionParameter {
- param := data.NewIntParam(num)
- return ¶m
-}
-func newCmdStringParam(str string) *data.InstructionParameter {
- param := data.NewStringParam(str)
- return ¶m
-}
-
-func TestAssembleInstruction(t *testing.T) {
- if len(instructions) != 12 {
- t.Errorf("Tests were not updated")
- }
-
- var tests = []struct {
- line string
- expected *data.Instruction
- expectsErr bool
- }{
- // Success Number
- {"nop", getInstruction(0x0, 0), false},
- {"copy 0x10", getInstruction(0x1, 16), false},
- {"store 0x10", getInstruction(0x2, 16), false},
- {"add 10", getInstruction(0x3, 10), false},
- {"sub 10", getInstruction(0x4, 10), false},
- {"input 7", getInstruction(0x7, 7), false},
- {"output 8", getInstruction(0x8, 8), false},
- {"kill", getInstruction(0x9, 0), false},
- {"jmp 0x8", getInstruction(0xA, 8), false},
- {"jg 0x8", getInstruction(0xB, 8), false},
- {"je 0x8", getInstruction(0xD, 8), false},
- {"jl 0x8", getInstruction(0xF, 8), false},
- // Success Label
- {"jmp label", getInstructionStr(0xA, "label"), false},
- {"jg label", getInstructionStr(0xB, "label"), false},
- {"je label", getInstructionStr(0xD, "label"), false},
- {"jl label", getInstructionStr(0xF, "label"), false},
- // Fail: Wrong Instruction
- {"nope", nil, true},
- // Fail: No label as param
- {"copy label", nil, true},
- {"store label", nil, true},
- {"add label", nil, true},
- {"sub label", nil, true},
- {"input label", nil, true},
- {"output label", nil, true},
- // Fail: Wrong param
- {"add 1x10", nil, true},
- // Fail: Amnt params
- {"kill 0", nil, true},
- {"output", nil, true},
- {"output 8 1", nil, true},
- }
-
- for i, test := range tests {
- got, err := AssembleInstruction(test.line)
- gotError := err != nil
-
- if test.expectsErr != gotError {
- t.Errorf("[%d] Expected error: %t, Got error: %t", i, test.expectsErr, gotError)
- }
- if !helper.SafeIsEqualInstructionPointer(test.expected, got) {
- t.Errorf("Instruction expected is: %v, Got expected is: %v", test.expected, got)
- }
- }
-}
-func getInstruction(code int, param int) *data.Instruction {
- cmd, _ := data.NewInstruction(code, data.NewIntParam(param))
- return cmd
-}
-func getInstructionStr(code int, param string) *data.Instruction {
- cmd, _ := data.NewInstruction(code, data.NewStringParam(param))
- return cmd
-}
-
-func TestGetInstructionParams(t *testing.T) {
- expected := []string{"0x1", "1", "label"}
- got := getInstructionParams([]string{"mov", "0x1", "1", "label"})
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("Error")
- }
-}
diff --git a/core/instruction/instructionsconfig.go b/core/instruction/instructionsconfig.go
deleted file mode 100644
index 249d6d3..0000000
--- a/core/instruction/instructionsconfig.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package instruction
-
-import (
- "github.com/open-machine/assembler/config/myerrors"
- "github.com/open-machine/assembler/data"
-)
-
-type InstructionConfig struct {
- code int
- getParam func(instructionName string, words []string) (*data.InstructionParameter, *myerrors.CustomError)
-}
-
-func GetInstructionsConfig() map[string]InstructionConfig {
- return instructions
-}
-
-var instructions = map[string]InstructionConfig{
- "nop": InstructionConfig{
- getParam: getParamNoParam,
- code: 0x0,
- },
- "copy": InstructionConfig{
- getParam: getSecondWordAsInt,
- code: 0x1,
- },
- "store": InstructionConfig{
- getParam: getSecondWordAsInt,
- code: 0x2,
- },
- "add": InstructionConfig{
- getParam: getSecondWordAsInt,
- code: 0x3,
- },
- "sub": InstructionConfig{
- getParam: getSecondWordAsInt,
- code: 0x4,
- },
- "input": InstructionConfig{
- getParam: getSecondWordAsInt,
- code: 0x7,
- },
- "output": InstructionConfig{
- getParam: getSecondWordAsInt,
- code: 0x8,
- },
- "kill": InstructionConfig{
- getParam: getParamNoParam,
- code: 0x9,
- },
- "jmp": InstructionConfig{
- getParam: getSecondWordAsIntOrString,
- code: 0xA,
- },
- "jg": InstructionConfig{
- getParam: getSecondWordAsIntOrString,
- code: 0xB,
- },
- "je": InstructionConfig{
- getParam: getSecondWordAsIntOrString,
- code: 0xD,
- },
- "jl": InstructionConfig{
- getParam: getSecondWordAsIntOrString,
- code: 0xF,
- },
-}
diff --git a/core/lineassembler.go b/core/lineassembler.go
index a079d1b..0914bfd 100644
--- a/core/lineassembler.go
+++ b/core/lineassembler.go
@@ -1,35 +1,29 @@
package core
import (
- "strings"
-
+ "github.com/open-machine/assembler/commands/instruction"
+ "github.com/open-machine/assembler/commands/label"
"github.com/open-machine/assembler/config/myerrors"
- "github.com/open-machine/assembler/core/comment"
- "github.com/open-machine/assembler/core/instruction"
- "github.com/open-machine/assembler/core/label"
"github.com/open-machine/assembler/data"
"github.com/open-machine/assembler/utils"
)
-func assembleEntireLine(line string) (*string, *data.Instruction, *myerrors.CustomError) {
+func assembleEntireLine(line string, program *data.Program) *myerrors.CustomError {
normalizedStr := utils.LineNormalization(line)
- lineWithoutCommand := comment.RemoveComment(normalizedStr)
- lineWithoutCommand = strings.TrimSpace(lineWithoutCommand)
-
- if lineWithoutCommand == "" {
- return nil, nil, nil
+ if normalizedStr == "" {
+ return nil
}
// Jump Label
- jumpLabel, restOfLine, errLabel := label.AssembleJumpLabel(lineWithoutCommand)
+ jumpLabel, restOfLine, errLabel := label.AssembleJumpLabel(normalizedStr)
if errLabel != nil {
return nil, nil, errLabel
}
- if jumpLabel != nil && restOfLine != "" {
- return nil, nil, myerrors.NewCodeError(myerrors.MoreThanOneCommandInLine(restOfLine))
- }
if jumpLabel != nil {
+ if restOfLine != "" {
+ return nil, nil, myerrors.NewCodeError(myerrors.MoreThanOneCommandInLine(restOfLine))
+ }
return jumpLabel, nil, nil
}
diff --git a/core/lineassembler_test.go b/core/lineassembler_test.go
index d35ea33..2291e95 100644
--- a/core/lineassembler_test.go
+++ b/core/lineassembler_test.go
@@ -34,6 +34,7 @@ func TestAssembleEntireLine(t *testing.T) {
// Label: Success
{" label: ", helper.StringPointer("label"), nil, false},
+ {" label:\t ", helper.StringPointer("label"), nil, false},
// Label: Fail
{" 1label: input 0x1 ", nil, nil, true},
diff --git a/core/readwriteprogram.go b/core/readwriteprogram.go
deleted file mode 100644
index 2a7060d..0000000
--- a/core/readwriteprogram.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package core
-
-import (
- "bufio"
- "fmt"
- "io"
-
- "github.com/open-machine/assembler/config/myerrors"
- "github.com/open-machine/assembler/utils"
-
- "github.com/open-machine/assembler/config"
- "github.com/open-machine/assembler/data"
- "github.com/open-machine/assembler/helper"
-)
-
-func programFromFile(file utils.MyFileInterface) *data.Program {
- reader := bufio.NewReader(file.Reader())
- lineIndex := 1
- program := data.NewProgram(0)
-
- successful := true
-
- for {
- line, errRead := reader.ReadString('\n')
-
- if errRead != nil && errRead != io.EOF {
- helper.LogOtherError(fmt.Sprintf("Error while reading file. Error: %s", errRead.Error()))
- return nil
- }
-
- jumpLabel, instructionPointer, errAssemble := assembleEntireLine(line)
-
- if jumpLabel != nil {
- errJumpLabel := program.AddJumpLabel(*jumpLabel, program.LenInstructions())
- if errJumpLabel != nil {
- helper.LogErrorInLine(*myerrors.NewCodeError(errJumpLabel), lineIndex, line)
- return nil
- }
- }
-
- if errAssemble != nil {
- successful = false
- helper.LogErrorInLine(*errAssemble, lineIndex, line)
- } else if instructionPointer != nil {
- program.AddInstruction(*instructionPointer)
- }
-
- if errRead == io.EOF {
- break
- }
- lineIndex++
- }
-
- if !successful {
- return nil
- }
- return &program
-}
-
-func writeExecProgram(program data.Program, execFileName string, execFile io.Writer) int {
- writer := bufio.NewWriter(execFile)
- defer writer.Flush()
-
- execStr, errs := program.ToExecuter()
-
- if len(errs) > 0 {
- for _, err := range errs {
- // TODO: infrastructure to get line
- helper.LogErrorInLine(err, 0, "")
- }
- return config.FailStatus
- }
-
- _, err := writer.WriteString(execStr)
- if err != nil {
- helper.LogOtherError(fmt.Sprintf("Could not write to file %s \n", execFileName))
- return config.FailStatus
- }
-
- return config.SuccessStatus
-}
diff --git a/data/instruction.go b/data/instruction.go
index e53b726..cfbcdae 100644
--- a/data/instruction.go
+++ b/data/instruction.go
@@ -17,18 +17,6 @@ func NewInstruction(code int, param InstructionParameter) (*Instruction, *myerro
return nil, myerrors.NewAssemblerError(err)
}
- if param.IsStr {
- err := utils.CheckParamName(param.Str)
- if err != nil {
- return nil, myerrors.NewAssemblerError(err)
- }
- } else {
- if !param.IsStr && utils.IsOverflow(uint(param.Num), config.AmntBitsParam) {
- err := myerrors.ParamOverflow(param.Num, config.AmntBitsParam)
- return nil, myerrors.NewCodeError(err)
- }
- }
-
return &Instruction{code, param}, nil
}
diff --git a/data/instructionParameter.go b/data/instructionParameter.go
index 629c816..566d799 100644
--- a/data/instructionParameter.go
+++ b/data/instructionParameter.go
@@ -1,15 +1,39 @@
package data
+import (
+ "github.com/open-machine/assembler/config"
+ "github.com/open-machine/assembler/config/myerrors"
+ "github.com/open-machine/assembler/utils"
+)
+
type InstructionParameter struct {
Num int
Str string
IsStr bool
}
-func NewStringParam(str string) InstructionParameter {
- return InstructionParameter{Num: 0, Str: str, IsStr: true}
+func NewStringParam(str string) (*InstructionParameter, *myerrors.CustomError) {
+ err := utils.CheckParamName(str)
+ if err != nil {
+ return nil, myerrors.NewAssemblerError(err)
+ }
+
+ return &InstructionParameter{Num: 0, Str: str, IsStr: true}, nil
+}
+
+func NewIntParam(num int) (*InstructionParameter, *myerrors.CustomError) {
+ if utils.IsOverflow(uint(num), config.AmntBitsParam) {
+ err := myerrors.ParamOverflow(num, config.AmntBitsParam)
+ return nil, myerrors.NewCodeError(err)
+ }
+
+ return &InstructionParameter{Num: num, Str: "", IsStr: false}, nil
}
-func NewIntParam(num int) InstructionParameter {
- return InstructionParameter{Num: num, Str: "", IsStr: false}
+func NewParamTest(num int, str string, isStr bool) *InstructionParameter {
+ if config.Testing {
+ return &InstructionParameter{Num: num, Str: str, IsStr: isStr}
+ } else {
+ return nil
+ }
}
diff --git a/data/instructionParameter_test.go b/data/instructionParameter_test.go
index 05fe407..b9c46d0 100644
--- a/data/instructionParameter_test.go
+++ b/data/instructionParameter_test.go
@@ -1,15 +1,91 @@
package data
-import "testing"
+import (
+ "testing"
-func TestParamConstructors(t *testing.T) {
- strParam := NewStringParam("Hello World")
- if !strParam.IsStr {
- t.Errorf("String param should have true isStr")
+ "github.com/open-machine/assembler/config"
+)
+
+func TestStrParamConstructors(t *testing.T) {
+ var tests = []struct {
+ str string
+ expectedErr bool
+ }{
+ // Success
+ {
+ str: "helloWorld",
+ expectedErr: false,
+ },
+ // Fail
+ {
+ str: "Hello World",
+ expectedErr: true,
+ },
+ {
+ str: "Hello",
+ expectedErr: true,
+ },
+ }
+
+ for i, test := range tests {
+ strParam, err := NewStringParam("Hello World")
+ gotErr := err != nil
+
+ if gotErr != test.expectedErr {
+ t.Errorf("[%d] Expected error: %t, got error: %t", i, test.expectedErr, gotErr)
+ }
+
+ if !strParam.IsStr {
+ t.Errorf("String param should have true isStr")
+ }
+ }
+}
+
+func TestIntParamConstructors(t *testing.T) {
+ var tests = []struct {
+ num int
+ expectedErr bool
+ }{
+ // Success
+ {
+ num: 1,
+ expectedErr: false,
+ },
+ // Fail
+ {
+ num: 5000,
+ expectedErr: true,
+ },
+ }
+
+ for i, test := range tests {
+ strParam, err := NewStringParam("Hello World")
+ gotErr := err != nil
+
+ if gotErr != test.expectedErr {
+ t.Errorf("[%d] Expected error: %t, got error: %t", i, test.expectedErr, gotErr)
+ }
+
+ if strParam.IsStr {
+ t.Errorf("Int param should have false isStr")
+ }
+ }
+}
+
+func TestParamConstructorsTesting(t *testing.T) {
+ num := 0
+ str := "a"
+ isStr := true
+
+ config.Testing = true
+ instruc1 := NewParamTest(num, str, isStr)
+ if instruc1 == nil {
+ t.Errorf("Instruction should not be nil")
}
- numParam := NewIntParam(1)
- if numParam.IsStr {
- t.Errorf("Int param should have false isStr")
+ config.Testing = false
+ instruc2 := NewParamTest(num, str, isStr)
+ if instruc2 != nil {
+ t.Errorf("Instruction should be nil")
}
}
diff --git a/data/instruction_test.go b/data/instruction_test.go
index 3a85b15..e3197e2 100644
--- a/data/instruction_test.go
+++ b/data/instruction_test.go
@@ -27,7 +27,8 @@ func TestNewInstructionOverflowValidation(t *testing.T) {
}
for i, test := range tests {
- _, err := NewInstruction(test.code, NewIntParam(test.param))
+ param, _ := NewIntParam(test.param)
+ _, err := NewInstruction(test.code, *param)
gotErr := err != nil
if test.expectsError != gotErr {
@@ -48,7 +49,8 @@ func TestNewInstructionWrongStringParam(t *testing.T) {
}
for i, test := range tests {
- _, err := NewInstruction(test.code, NewStringParam(test.param))
+ param, _ := NewStringParam(test.param)
+ _, err := NewInstruction(test.code, *param)
gotErr := err != nil
if test.expectsError != gotErr {
@@ -63,12 +65,12 @@ func TestToExecuter(t *testing.T) {
expected string
expectsError bool
}{
- {Instruction{0, NewIntParam(0)}, "0000", false},
- {Instruction{11, NewIntParam(5)}, "b005", false},
- {Instruction{5, NewIntParam(300)}, "512c", false},
- {Instruction{5000, NewIntParam(5)}, "", true},
- {Instruction{5, NewIntParam(5000)}, "", true},
- {Instruction{5, NewStringParam("abc")}, "", true},
+ {Instruction{0, newIntParam(0)}, "0000", false},
+ {Instruction{11, newIntParam(5)}, "b005", false},
+ {Instruction{5, newIntParam(300)}, "512c", false},
+ {Instruction{5000, newIntParam(5)}, "", true},
+ {Instruction{5, newIntParam(5000)}, "", true},
+ {Instruction{5, newStringParam("abc")}, "", true},
}
for i, test := range tests {
@@ -84,24 +86,30 @@ func TestToExecuter(t *testing.T) {
}
}
}
+func newIntParam(num int) InstructionParameter {
+ return InstructionParameter{Num: 0, Str: "", IsStr: false}
+}
+func newStringParam(str string) InstructionParameter {
+ return InstructionParameter{Num: 0, Str: str, IsStr: true}
+}
func TestNewInstructionTest(t *testing.T) {
code := 300
- param := NewIntParam(300)
+ param, _ := NewIntParam(300)
- _, err := NewInstruction(code, param)
+ _, err := NewInstruction(code, *param)
if err == nil {
t.Errorf("Expected error! NewInstruction should verify params and these params should be wrong to validate the NewInstructionTest function")
}
config.Testing = false
- ptrInstructionNil := NewInstructionTest(code, param)
+ ptrInstructionNil := NewInstructionTest(code, *param)
if ptrInstructionNil != nil {
t.Errorf("Expected nil instruction, got not nil instruction")
}
config.Testing = true
- ptrInstructionNotNil := NewInstructionTest(code, param)
+ ptrInstructionNotNil := NewInstructionTest(code, *param)
if ptrInstructionNotNil == nil {
t.Errorf("Expected nil instruction, got not nil instruction")
}
diff --git a/data/program.go b/data/program.go
index 06ac2c1..1913f55 100644
--- a/data/program.go
+++ b/data/program.go
@@ -46,8 +46,15 @@ func (p *Program) ReplaceLabelsWithNumbers() []error {
if !exists {
errs = append(errs, myerrors.JumpLabelDoesNotExistError(label))
} else {
- instruction.parameter = NewIntParam(instructionIndex)
- p.instructions[i] = instruction
+ updatedParam, err := NewIntParam(instructionIndex)
+ // TODO: test this error
+
+ if err != nil {
+ errs = append(errs, myerrors.ThereIsNoSpaceLeft(err))
+ } else {
+ instruction.parameter = *updatedParam
+ p.instructions[i] = instruction
+ }
}
}
}
diff --git a/data/program_test.go b/data/program_test.go
index b06a950..4a93a73 100644
--- a/data/program_test.go
+++ b/data/program_test.go
@@ -12,7 +12,7 @@ func TestAddInstruction(t *testing.T) {
t.Errorf("Expected length 0, got: %d", len(program.instructions))
}
- program.AddInstruction(Instruction{0, NewIntParam(0)})
+ program.AddInstruction(Instruction{0, newIntParam(0)})
if len(program.instructions) != 1 {
t.Errorf("Expected length 1, got: %d", len(program.instructions))
@@ -28,9 +28,9 @@ func TestProgToExecuter(t *testing.T) {
// Success with header
{
[]Instruction{
- Instruction{1, NewIntParam(2)},
- Instruction{15, NewIntParam(7)},
- Instruction{0, NewIntParam(0)},
+ Instruction{1, newIntParam(2)},
+ Instruction{15, newIntParam(7)},
+ Instruction{0, newIntParam(0)},
},
"v2.0 raw\n00001002f0070000",
0,
@@ -38,9 +38,9 @@ func TestProgToExecuter(t *testing.T) {
// 1 Overflow
{
[]Instruction{
- Instruction{1, NewIntParam(2)},
- Instruction{1200, NewIntParam(7)},
- Instruction{0, NewIntParam(0)},
+ Instruction{1, newIntParam(2)},
+ Instruction{1200, newIntParam(7)},
+ Instruction{0, newIntParam(0)},
},
"",
1,
@@ -48,9 +48,9 @@ func TestProgToExecuter(t *testing.T) {
// 2 Overflows
{
[]Instruction{
- Instruction{1, NewIntParam(2)},
- Instruction{1200, NewIntParam(7)},
- Instruction{3000, NewIntParam(7)},
+ Instruction{1, newIntParam(2)},
+ Instruction{1200, newIntParam(7)},
+ Instruction{3000, newIntParam(7)},
},
"",
2,
@@ -109,19 +109,19 @@ func TestReplaceLabelsWithNumbers(t *testing.T) {
{
&Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{1, NewStringParam("label")},
- Instruction{5, NewIntParam(3)},
- Instruction{7, NewIntParam(3)},
+ Instruction{3, newIntParam(1)},
+ Instruction{1, newStringParam("label")},
+ Instruction{5, newIntParam(3)},
+ Instruction{7, newIntParam(3)},
},
map[string]int{"label": 3},
},
Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{1, NewIntParam(3)},
- Instruction{5, NewIntParam(3)},
- Instruction{7, NewIntParam(3)},
+ Instruction{3, newIntParam(1)},
+ Instruction{1, newIntParam(3)},
+ Instruction{5, newIntParam(3)},
+ Instruction{7, newIntParam(3)},
},
map[string]int{},
},
@@ -131,23 +131,23 @@ func TestReplaceLabelsWithNumbers(t *testing.T) {
{
&Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{1, NewStringParam("label")},
- Instruction{5, NewIntParam(3)},
- Instruction{2, NewIntParam(0)},
- Instruction{1, NewStringParam("abc")},
- Instruction{11, NewIntParam(15)},
+ Instruction{3, newIntParam(1)},
+ Instruction{1, newStringParam("label")},
+ Instruction{5, newIntParam(3)},
+ Instruction{2, newIntParam(0)},
+ Instruction{1, newStringParam("abc")},
+ Instruction{11, newIntParam(15)},
},
map[string]int{"abc": 0, "label": 0},
},
Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{1, NewIntParam(0)},
- Instruction{5, NewIntParam(3)},
- Instruction{2, NewIntParam(0)},
- Instruction{1, NewIntParam(0)},
- Instruction{11, NewIntParam(15)},
+ Instruction{3, newIntParam(1)},
+ Instruction{1, newIntParam(0)},
+ Instruction{5, newIntParam(3)},
+ Instruction{2, newIntParam(0)},
+ Instruction{1, newIntParam(0)},
+ Instruction{11, newIntParam(15)},
},
map[string]int{},
},
@@ -157,19 +157,19 @@ func TestReplaceLabelsWithNumbers(t *testing.T) {
{
&Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{5, NewIntParam(3)},
- Instruction{2, NewIntParam(0)},
- Instruction{11, NewIntParam(15)},
+ Instruction{3, newIntParam(1)},
+ Instruction{5, newIntParam(3)},
+ Instruction{2, newIntParam(0)},
+ Instruction{11, newIntParam(15)},
},
map[string]int{},
},
Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{5, NewIntParam(3)},
- Instruction{2, NewIntParam(0)},
- Instruction{11, NewIntParam(15)},
+ Instruction{3, newIntParam(1)},
+ Instruction{5, newIntParam(3)},
+ Instruction{2, newIntParam(0)},
+ Instruction{11, newIntParam(15)},
},
map[string]int{},
},
@@ -179,23 +179,23 @@ func TestReplaceLabelsWithNumbers(t *testing.T) {
{
&Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{1, NewStringParam("label")},
- Instruction{5, NewIntParam(3)},
- Instruction{2, NewIntParam(0)},
- Instruction{1, NewStringParam("abc")},
- Instruction{11, NewIntParam(15)},
+ Instruction{3, newIntParam(1)},
+ Instruction{1, newStringParam("label")},
+ Instruction{5, newIntParam(3)},
+ Instruction{2, newIntParam(0)},
+ Instruction{1, newStringParam("abc")},
+ Instruction{11, newIntParam(15)},
},
map[string]int{"abc": 0, "label": 0, "abcdario": 11},
},
Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{1, NewIntParam(0)},
- Instruction{5, NewIntParam(3)},
- Instruction{2, NewIntParam(0)},
- Instruction{1, NewIntParam(0)},
- Instruction{11, NewIntParam(15)},
+ Instruction{3, newIntParam(1)},
+ Instruction{1, newIntParam(0)},
+ Instruction{5, newIntParam(3)},
+ Instruction{2, newIntParam(0)},
+ Instruction{1, newIntParam(0)},
+ Instruction{11, newIntParam(15)},
},
map[string]int{},
},
@@ -205,23 +205,23 @@ func TestReplaceLabelsWithNumbers(t *testing.T) {
{
&Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{1, NewStringParam("luca")},
- Instruction{5, NewIntParam(3)},
- Instruction{2, NewIntParam(0)},
- Instruction{1, NewStringParam("abc")},
- Instruction{11, NewIntParam(15)},
+ Instruction{3, newIntParam(1)},
+ Instruction{1, newStringParam("luca")},
+ Instruction{5, newIntParam(3)},
+ Instruction{2, newIntParam(0)},
+ Instruction{1, newStringParam("abc")},
+ Instruction{11, newIntParam(15)},
},
map[string]int{"abc": 0, "label": 0, "abcdario": 11},
},
Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{1, NewStringParam("luca")},
- Instruction{5, NewIntParam(3)},
- Instruction{2, NewIntParam(0)},
- Instruction{1, NewIntParam(0)},
- Instruction{11, NewIntParam(15)},
+ Instruction{3, newIntParam(1)},
+ Instruction{1, newStringParam("luca")},
+ Instruction{5, newIntParam(3)},
+ Instruction{2, newIntParam(0)},
+ Instruction{1, newIntParam(0)},
+ Instruction{11, newIntParam(15)},
},
map[string]int{"abc": 0, "label": 0, "abcdario": 11},
},
@@ -231,23 +231,23 @@ func TestReplaceLabelsWithNumbers(t *testing.T) {
{
&Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{1, NewStringParam("luca")},
- Instruction{5, NewIntParam(3)},
- Instruction{2, NewIntParam(0)},
- Instruction{1, NewStringParam("abc")},
- Instruction{11, NewIntParam(15)},
+ Instruction{3, newIntParam(1)},
+ Instruction{1, newStringParam("luca")},
+ Instruction{5, newIntParam(3)},
+ Instruction{2, newIntParam(0)},
+ Instruction{1, newStringParam("abc")},
+ Instruction{11, newIntParam(15)},
},
map[string]int{"label": 0, "abcdario": 11},
},
Program{
[]Instruction{
- Instruction{3, NewIntParam(1)},
- Instruction{1, NewStringParam("luca")},
- Instruction{5, NewIntParam(3)},
- Instruction{2, NewIntParam(0)},
- Instruction{1, NewStringParam("abc")},
- Instruction{11, NewIntParam(15)},
+ Instruction{3, newIntParam(1)},
+ Instruction{1, newStringParam("luca")},
+ Instruction{5, newIntParam(3)},
+ Instruction{2, newIntParam(0)},
+ Instruction{1, newStringParam("abc")},
+ Instruction{11, newIntParam(15)},
},
map[string]int{"label": 0, "abcdario": 11},
},
@@ -281,6 +281,6 @@ func TestLenInstructions(t *testing.T) {
}
}
func mockInstruction() Instruction {
- cmd, _ := NewInstruction(0, NewIntParam(1))
+ cmd, _ := NewInstruction(0, newIntParam(1))
return *cmd
}
diff --git a/helper/comparisons_test.go b/helper/comparisons_test.go
index 2d4f706..b77db02 100644
--- a/helper/comparisons_test.go
+++ b/helper/comparisons_test.go
@@ -1,8 +1,9 @@
package helper
import (
- "github.com/open-machine/assembler/data"
"testing"
+
+ "github.com/open-machine/assembler/data"
)
func TestSafeIsEqualStringPointer(t *testing.T) {
@@ -47,7 +48,8 @@ func TestSafeIsEqualProgramPointer(t *testing.T) {
}
}
func newProgram(a int, b int) *data.Program {
- cmd, _ := data.NewInstruction(a, data.NewIntParam(b))
+ param, _ := data.NewIntParam(b)
+ cmd, _ := data.NewInstruction(a, *param)
program := data.ProgramFromInstructionsAndLabels([]data.Instruction{*cmd}, map[string]int{})
return &program
}
@@ -73,7 +75,8 @@ func TestSafeIsEqualInstructionPointer(t *testing.T) {
}
}
func newInstruction(a int, b int) *data.Instruction {
- cmd, _ := data.NewInstruction(a, data.NewIntParam(b))
+ param, _ := data.NewIntParam(b)
+ cmd, _ := data.NewInstruction(a, *param)
return cmd
}
@@ -98,6 +101,6 @@ func TestSafeIsEqualInstructionParamPointer(t *testing.T) {
}
}
func newIntParam(a int) *data.InstructionParameter {
- param := data.NewIntParam(a)
- return ¶m
+ param, _ := data.NewIntParam(a)
+ return param
}
diff --git a/utils/normalization.go b/utils/normalization.go
index fb82052..cc438cd 100644
--- a/utils/normalization.go
+++ b/utils/normalization.go
@@ -6,11 +6,12 @@ import (
)
func LineNormalization(line string) string {
- withoutNewLine := RemoveNewLine(line)
- return removeUnecessarySpaces(withoutNewLine)
+ withoutNewLine := removeNewLine(line)
+ withoutComment := removeComment(withoutNewLine)
+ return removeUnecessarySpaces(withoutComment)
}
-func RemoveNewLine(line string) string {
+func removeNewLine(line string) string {
lineWithoutEndingUnix := strings.TrimSuffix(line, "\n")
lineWithoutEndingUnixAndWindows := strings.TrimSuffix(lineWithoutEndingUnix, "\r")
return lineWithoutEndingUnixAndWindows
@@ -21,3 +22,11 @@ func removeUnecessarySpaces(line string) string {
str := space.ReplaceAllString(line, " ")
return strings.TrimSpace(str)
}
+
+func removeComment(line string) string {
+ index := strings.Index(line, "#")
+ if index < 0 {
+ return line
+ }
+ return line[:index]
+}
diff --git a/utils/normalization_test.go b/utils/normalization_test.go
index 0a3aaef..473630b 100644
--- a/utils/normalization_test.go
+++ b/utils/normalization_test.go
@@ -9,6 +9,8 @@ func TestLineNormalization(t *testing.T) {
}{
{" MOV\t 8 \r\n", "MOV 8"},
{"MoV 8\n", "MoV 8"},
+ {"MoV 8 #asdf", "MoV 8"},
+ {"hello, my name is Luca #adfd \n", "hello, my name is Luca"},
}
for _, test := range tests {
@@ -33,7 +35,7 @@ func TestRemoveNewLine(t *testing.T) {
}
for _, test := range tests {
- got := RemoveNewLine(test.param)
+ got := removeNewLine(test.param)
if got != test.expected {
t.Errorf("Expected: '%s', Got: '%s'", test.expected, got)
@@ -59,3 +61,23 @@ func TestRemoveUnecessarySpaces(t *testing.T) {
}
}
}
+
+func TestRemoveComment(t *testing.T) {
+ tests := []struct {
+ param string
+ expected string
+ }{
+ {"", ""},
+ {"copy 0x0", "copy 0x0"},
+ {"# Hello World ", ""},
+ {"copy 0x0 # Hello World", "copy 0x0 "},
+ {"luca dillenburg doing stuff # Hello World", "luca dillenburg doing stuff "},
+ }
+
+ for _, test := range tests {
+ got := removeComment(test.param)
+ if got != test.expected {
+ t.Errorf("Comment removed wrongly. Expected '%s', Got: '%s'", test.expected, test.param)
+ }
+ }
+}