Skip to content

Commit

Permalink
finish assembler
Browse files Browse the repository at this point in the history
  • Loading branch information
qazwsxedckll committed Dec 27, 2023
1 parent baac451 commit 1c0253a
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 84 deletions.
35 changes: 31 additions & 4 deletions assembler/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,53 @@ func main() {
}
}

func parse(in io.Reader, out io.Writer) error {
func parse(in io.ReadSeeker, out io.Writer) error {
symbolTable := NewSymbolTable()

parser, err := NewParser(in)
if err != nil {
return err
}

rom := 0
for parser.HasMoreCommands() {
parser.Advance()

switch parser.CommandType() {
case ACommand, CCommand:
rom++
case LCommand:
symbolTable.AddEntry(parser.Symbol(), rom)
}
}

_, err = in.Seek(0, io.SeekStart)
if err != nil {
return err
}
parser, err = NewParser(in)
if err != nil {
return err
}

ram := 16
for parser.HasMoreCommands() {
parser.Advance()

switch symbol := parser.Symbol(); parser.CommandType() {
case ACommand:
i, err := strconv.Atoi(parser.Symbol())
i, err := strconv.Atoi(symbol)
if err != nil {
return fmt.Errorf("error converting symbol to int: %v", err)
if !symbolTable.Contains(symbol) {
symbolTable.AddEntry(symbol, ram)
ram++
}
i = symbolTable.GetAddress(symbol)
}
fmt.Fprintf(out, "0%015b\n", i)
case CCommand:
fmt.Fprintf(out, "111%s%s%s\n", Comp(parser.Comp()), Dest(parser.Dest()), Jump(parser.Jump()))
}
}

return nil
}
41 changes: 41 additions & 0 deletions assembler/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,47 @@ func TestNoSymbol(t *testing.T) {
name: "PongL.asm",
file: "testdata/Pong/PongL.asm",
},
{
name: "RectL.asm",
file: "testdata/Rect/RectL.asm",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
file, err := os.Open(tt.file)
require.NoError(t, err)

buf := bytes.Buffer{}

err = parse(file, &buf)
require.NoError(t, err)

want, err := os.ReadFile(tt.file[:len(tt.file)-4] + ".hack")
require.NoError(t, err)
require.Equal(t, string(want), buf.String())
})
}
}

func TestWithSymbol(t *testing.T) {
tests := []struct {
name string
file string
want string
}{
{
name: "Max.asm",
file: "testdata/Max/Max.asm",
},
{
name: "Pong.asm",
file: "testdata/Pong/Pong.asm",
},
{
name: "Rect.asm",
file: "testdata/Rect/Rect.asm",
},
}

for _, tt := range tests {
Expand Down
56 changes: 31 additions & 25 deletions assembler/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,30 @@ func TestNewParser(t *testing.T) {
`M=D`,
},
},
{
name: "MaxL.asm",
file: "testdata/Max/MaxL.asm",
want: []string{
`@0`,
`D=M`,
`@1`,
`D=D-M`,
`@12`,
`D;JGT`,
`@1`,
`D=M`,
`@2`,
`M=D`,
`@16`,
`0;JMP`,
`@0`,
`D=M`,
`@2`,
`M=D`,
`@16`,
`0;JMP`,
},
},
{
name: "Max.asm",
file: "testdata/Max/Max.asm",
Expand All @@ -33,20 +57,21 @@ func TestNewParser(t *testing.T) {
`D=M`,
`@R1`,
`D=D-M`,
`@OUTPUT_FIRST`,
`@ITSR0`,
`D;JGT`,
`@R1`,
`D=M`,
`@OUTPUT_D`,
`@R2`,
`M=D`,
`@END`,
`0;JMP`,
`(OUTPUT_FIRST)`,
`(ITSR0)`,
`@R0`,
`D=M`,
`(OUTPUT_D)`,
`@R2`,
`M=D`,
`(INFINITE_LOOP)`,
`@INFINITE_LOOP`,
`(END)`,
`@END`,
`0;JMP`,
},
},
Expand All @@ -64,22 +89,3 @@ func TestNewParser(t *testing.T) {
})
}
}

// func TestCommandType(t *testing.T) {
// file, err := os.Open("testdata/Add.asm")
// require.NoError(t, err)

// p := NewParser(file)

// p.Advance()
// require.Equal(t, ACommand, p.CommandType())

// p.Advance()
// require.Equal(t, CCommand, p.CommandType())

// p.Advance()
// require.Equal(t, LCommand, p.CommandType())

// p.Advance()
// require.Equal(t, CCommand, p.CommandType())
// }
40 changes: 37 additions & 3 deletions assembler/symbol_table.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,48 @@
package main

type SymbolTable struct{}
type SymbolTable struct {
table map[string]int
}

func NewSymbolTable() *SymbolTable {
return &SymbolTable{
table: map[string]int{
"SP": 0,
"LCL": 1,
"ARG": 2,
"THIS": 3,
"THAT": 4,
"R0": 0,
"R1": 1,
"R2": 2,
"R3": 3,
"R4": 4,
"R5": 5,
"R6": 6,
"R7": 7,
"R8": 8,
"R9": 9,
"R10": 10,
"R11": 11,
"R12": 12,
"R13": 13,
"R14": 14,
"R15": 15,
"SCREEN": 16384,
"KBD": 24576,
},
}
}

func (s *SymbolTable) AddEntry(symbol string, address int) {
s.table[symbol] = address
}

func (s *SymbolTable) Contains(symbol string) bool {
return false
_, ok := s.table[symbol]
return ok
}

func (s *SymbolTable) GetAddress(symbol string) int {
return 0
return s.table[symbol]
}
52 changes: 26 additions & 26 deletions assembler/testdata/Rect/Rect.hack
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
0000000000000000
1111110000010000
0000000000011000
1110001100000110
0000000000010000
1110001100001000
0100000000000000
1110110000010000
0000000000010001
1110001100001000
0000000000010001
1111110000100000
1110111010001000
0000000000010001
1111110000010000
0000000000100000
1110000010010000
0000000000010001
1110001100001000
0000000000010000
1111110010001000
1111110000010000
0000000000001010
1110001100000001
0000000000011000
1110101010000111
0000000000000000
1111110000010000
0000000000011000
1110001100000110
0000000000010000
1110001100001000
0100000000000000
1110110000010000
0000000000010001
1110001100001000
0000000000010001
1111110000100000
1110111010001000
0000000000010001
1111110000010000
0000000000100000
1110000010010000
0000000000010001
1110001100001000
0000000000010000
1111110010001000
1111110000010000
0000000000001010
1110001100000001
0000000000011000
1110101010000111
52 changes: 26 additions & 26 deletions assembler/testdata/Rect/RectL.hack
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
0000000000000000
1111110000010000
0000000000011000
1110001100000110
0000000000010000
1110001100001000
0100000000000000
1110110000010000
0000000000010001
1110001100001000
0000000000010001
1111110000100000
1110111010001000
0000000000010001
1111110000010000
0000000000100000
1110000010010000
0000000000010001
1110001100001000
0000000000010000
1111110010001000
1111110000010000
0000000000001010
1110001100000001
0000000000011000
1110101010000111
0000000000000000
1111110000010000
0000000000011000
1110001100000110
0000000000010000
1110001100001000
0100000000000000
1110110000010000
0000000000010001
1110001100001000
0000000000010001
1111110000100000
1110111010001000
0000000000010001
1111110000010000
0000000000100000
1110000010010000
0000000000010001
1110001100001000
0000000000010000
1111110010001000
1111110000010000
0000000000001010
1110001100000001
0000000000011000
1110101010000111

0 comments on commit 1c0253a

Please sign in to comment.