From d38f4dec8a1ab01f32964161f138261356ad9a59 Mon Sep 17 00:00:00 2001 From: tijani Date: Thu, 18 Aug 2022 14:32:13 +0000 Subject: [PATCH] Tests - Ensure value producing expression in a let statement and also identifiers bound to a variable name. - Tests to ensure valid errors with unbound identifiers git-svn-id: https://svn.tlawal.org/svn/monkey@51 f6afcba9-9ef1-4bdd-9b72-7484f5705bac --- evaluator/evaluator.go | 38 +++++++++++++++++++++---------------- evaluator/evaluator_test.go | 18 ++++++++++++++++++ 2 files changed, 40 insertions(+), 16 deletions(-) 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)