feat: compile second test program

This commit is contained in:
2026-04-29 00:03:33 +01:00
parent d9d77cec9e
commit e7b58ad256
@@ -64,7 +64,7 @@ func compileTerm(output *strings.Builder, tokens []tokenizer.Token, index *int)
} }
if tokens[*index].Value == "this" { if tokens[*index].Value == "this" {
variable, found := table.GetVariable([]*map[string]table.Variable{&subroutineSymbolTable, &classSymbolTable}, tokens[*index].Value) variable, found := table.GetVariable([]*map[string]table.Variable{&subroutineSymbolTable}, tokens[*index].Value)
if !found { if !found {
return errors.New("Invalid identifier!") return errors.New("Invalid identifier!")
@@ -110,12 +110,14 @@ func compileTerm(output *strings.Builder, tokens []tokenizer.Token, index *int)
return errors.New("Invalid identifier!") return errors.New("Invalid identifier!")
} }
var identifier string
if found { if found {
code.WritePush(output, segmentFromVariableKind(variable.Kind), variable.Count) code.WritePush(output, segmentFromVariableKind(variable.Kind), variable.Count)
} else {
identifier = tokens[*index].Value
} }
identifier := tokens[*index].Value
(*index)++ (*index)++
if tokens[*index].Value == "[" { if tokens[*index].Value == "[" {
@@ -281,20 +283,9 @@ func compileSubroutineCall(output *strings.Builder, tokens []tokenizer.Token, in
var class string var class string
var function string var function string
isMethod := false
if tokens[*index].Value == "." { if tokens[*index].Value == "." {
variable, found := table.GetVariable([]*map[string]table.Variable{&subroutineSymbolTable, &classSymbolTable}, identifier)
if found { class = identifier
code.WritePush(output, segmentFromVariableKind(variable.Kind), variable.Count)
code.WritePop(output, code.ARGUMENT, 0)
isMethod = true
class = variable.Type
} else {
class = identifier
}
(*index)++ (*index)++
@@ -323,10 +314,6 @@ func compileSubroutineCall(output *strings.Builder, tokens []tokenizer.Token, in
return errors.New("Missing subroutine call closing parenthese!") return errors.New("Missing subroutine call closing parenthese!")
} }
if isMethod {
args++
}
code.WriteCall(output, function, args) code.WriteCall(output, function, args)
(*index)++ (*index)++
@@ -388,6 +375,11 @@ func compileLetStatement(output *strings.Builder, tokens []tokenizer.Token, inde
} }
func compileIfStatement(output *strings.Builder, tokens []tokenizer.Token, index *int) error { func compileIfStatement(output *strings.Builder, tokens []tokenizer.Token, index *int) error {
endLabel := "IF_END_" + fmt.Sprint(ifLabelIndex)
elseLabel := "IF_ELSE_" + fmt.Sprint(ifLabelIndex)
ifLabelIndex++
if tokens[*index].Type != tokenizer.KEYWORD || tokens[*index].Value != "if" { if tokens[*index].Type != tokenizer.KEYWORD || tokens[*index].Value != "if" {
return errors.New("Invalid if statement!") return errors.New("Invalid if statement!")
} }
@@ -405,7 +397,7 @@ func compileIfStatement(output *strings.Builder, tokens []tokenizer.Token, index
} }
code.WriteArithmeticLogical(output, code.NOT) code.WriteArithmeticLogical(output, code.NOT)
code.WriteIfGoto(output, "IF_ELSE_"+fmt.Sprint(ifLabelIndex)) code.WriteIfGoto(output, elseLabel)
if tokens[*index].Type != tokenizer.SYMBOL || tokens[*index].Value != ")" { if tokens[*index].Type != tokenizer.SYMBOL || tokens[*index].Value != ")" {
return errors.New("Missing if statement closing parenthese!") return errors.New("Missing if statement closing parenthese!")
@@ -423,7 +415,7 @@ func compileIfStatement(output *strings.Builder, tokens []tokenizer.Token, index
return err return err
} }
code.WriteGoto(output, "IF_END_"+fmt.Sprint(ifLabelIndex)) code.WriteGoto(output, endLabel)
if tokens[*index].Type != tokenizer.SYMBOL || tokens[*index].Value != "}" { if tokens[*index].Type != tokenizer.SYMBOL || tokens[*index].Value != "}" {
return errors.New("Missing if statement closing curly brace!") return errors.New("Missing if statement closing curly brace!")
@@ -440,7 +432,7 @@ func compileIfStatement(output *strings.Builder, tokens []tokenizer.Token, index
(*index)++ (*index)++
code.WriteLabel(output, "IF_ELSE_"+fmt.Sprint(ifLabelIndex)) code.WriteLabel(output, elseLabel)
if err := compileStatements(output, tokens, index); err != nil { if err := compileStatements(output, tokens, index); err != nil {
return err return err
@@ -453,13 +445,17 @@ func compileIfStatement(output *strings.Builder, tokens []tokenizer.Token, index
(*index)++ (*index)++
} }
code.WriteLabel(output, "IF_END_"+fmt.Sprint(ifLabelIndex)) code.WriteLabel(output, endLabel)
ifLabelIndex++
return nil return nil
} }
func compileWhileStatement(output *strings.Builder, tokens []tokenizer.Token, index *int) error { func compileWhileStatement(output *strings.Builder, tokens []tokenizer.Token, index *int) error {
startLabel := "WHILE_START_"+fmt.Sprint(whileLabelIndex)
endLabel := "WHILE_END_"+fmt.Sprint(whileLabelIndex)
whileLabelIndex++
if tokens[*index].Type != tokenizer.KEYWORD || tokens[*index].Value != "while" { if tokens[*index].Type != tokenizer.KEYWORD || tokens[*index].Value != "while" {
return errors.New("Invalid while statement!") return errors.New("Invalid while statement!")
} }
@@ -472,14 +468,14 @@ func compileWhileStatement(output *strings.Builder, tokens []tokenizer.Token, in
(*index)++ (*index)++
code.WriteLabel(output, "WHILE_START_"+fmt.Sprint(whileLabelIndex)) code.WriteLabel(output, startLabel)
if err := compileExpression(output, tokens, index); err != nil { if err := compileExpression(output, tokens, index); err != nil {
return err return err
} }
code.WriteArithmeticLogical(output, code.NOT) code.WriteArithmeticLogical(output, code.NOT)
code.WriteIfGoto(output, "WHILE_END_"+fmt.Sprint(whileLabelIndex)) code.WriteIfGoto(output, endLabel)
if tokens[*index].Type != tokenizer.SYMBOL || tokens[*index].Value != ")" { if tokens[*index].Type != tokenizer.SYMBOL || tokens[*index].Value != ")" {
return errors.New("Missing while statement closing parenthese!") return errors.New("Missing while statement closing parenthese!")
@@ -497,14 +493,14 @@ func compileWhileStatement(output *strings.Builder, tokens []tokenizer.Token, in
return err return err
} }
code.WriteGoto(output, "WHILE_START_"+fmt.Sprint(whileLabelIndex)) code.WriteGoto(output, startLabel)
if tokens[*index].Type != tokenizer.SYMBOL || tokens[*index].Value != "}" { if tokens[*index].Type != tokenizer.SYMBOL || tokens[*index].Value != "}" {
return errors.New("Missing while statement closing curly brace!") return errors.New("Missing while statement closing curly brace!")
} }
code.WriteLabel(output, "WHILE_END_"+fmt.Sprint(whileLabelIndex)) code.WriteLabel(output, endLabel)
whileLabelIndex++
(*index)++ (*index)++
return nil return nil
@@ -604,7 +600,7 @@ func compileSubroutineBody(output *strings.Builder, tokens []tokenizer.Token, in
} }
} }
code.WriteFunction(output, className+"."+function, table.CountVariables(&subroutineSymbolTable, table.VAR) + 1) code.WriteFunction(output, className+"."+function, table.CountVariables(&subroutineSymbolTable, table.VAR)+1)
if isMethod { if isMethod {
code.WritePush(output, code.ARGUMENT, 0) code.WritePush(output, code.ARGUMENT, 0)