diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go index 884787e..c8de3fc 100644 --- a/evaluator/evaluator.go +++ b/evaluator/evaluator.go @@ -18,9 +18,25 @@ func Eval(node ast.Node) object.Object { case *ast.Program: return eval_program(node) + case *ast.BlockStatement: + return eval_block_statement(node) + case *ast.ExpressionStatement: return Eval(node.Expression) + case *ast.ReturnStatement: + val := Eval(node.ReturnValue) + if is_error(val) { + return val + } + return &object.ReturnValue{Value: val} + + case *ast.LetStatement: + val := Eval(node.Value) + if is_error(val) { + return val + } + // Expressions case *ast.IntegerLiteral: return &object.Integer{Value: node.Value} @@ -30,35 +46,25 @@ func Eval(node ast.Node) object.Object { case *ast.PrefixExpression: right := Eval(node.Right) - if is_error(right){ + if is_error(right) { return right } return eval_prefix_expression(node.Operator, right) case *ast.InfixExpression: left := Eval(node.Left) - if is_error(left){ + if is_error(left) { return left } - + right := Eval(node.Right) - if is_error(right){ + if is_error(right) { return right } return eval_infix_expression(node.Operator, left, right) - case *ast.BlockStatement: - return eval_block_statement(node) - case *ast.IfExpression: return eval_if_expression(node) - - case *ast.ReturnStatement: - val := Eval(node.ReturnValue) - if is_error(val){ - return val - } - return &object.ReturnValue{Value: val} } return nil @@ -196,10 +202,10 @@ func eval_integer_infix_expression(operator string, left object.Object, right ob func eval_if_expression(ie *ast.IfExpression) object.Object { condition := Eval(ie.Condition) - if is_error(condition){ + if is_error(condition) { return condition } - + if is_truthy(condition) { return Eval(ie.Consequence) } else if ie.Alternative != nil { diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go index ee6b70e..a43f594 100644 --- a/evaluator/evaluator_test.go +++ b/evaluator/evaluator_test.go @@ -55,6 +55,7 @@ func TestErrorHandling(l_test *testing.T) { return 1; } `, "unknown operator: BOOLEAN + BOOLEAN"}, + {"foobar", "identifier not found:foobar"}, } for _, tt := range tests { @@ -167,6 +168,23 @@ func TestReturnStatements(l_test *testing.T) { } } +func TestLetStatements(l_test *testing.T) { + tests := []struct { + input string + expected int64 + }{ + {"let a = 5; a;", 5}, + {"let a = 5 * 5; a;", 25}, + {"let a = 5; let b = a; b", 5}, + {"let a = 5; let b = a; let c = a + b + 5", 15}, + } + + for _, tt := range tests { + evaluated := test_eval(tt.input) + test_integer_object(l_test, evaluated, tt.expected) + } +} + // Helpers func test_eval(input string) object.Object { l_lexer := lexer.New(input)