diff options
| author | Bobby <[email protected]> | 2024-03-01 20:35:25 +0000 |
|---|---|---|
| committer | Bobby <[email protected]> | 2024-03-01 20:35:25 +0000 |
| commit | f793e4bac77ff15949e510b135cf917a303698f4 (patch) | |
| tree | f85029edef6cd0734a5968ffbba51d220a4eaade /evaluator | |
| parent | 8e6447a42c363cf567ec3146bb588c7ed7ce7260 (diff) | |
| download | mana-f793e4bac77ff15949e510b135cf917a303698f4.tar.xz mana-f793e4bac77ff15949e510b135cf917a303698f4.zip | |
Evaluate `return` Statement
Diffstat (limited to 'evaluator')
| -rw-r--r-- | evaluator/evaluator.go | 30 | ||||
| -rw-r--r-- | evaluator/evaluator_test.go | 25 |
2 files changed, 51 insertions, 4 deletions
diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go index 7aeaa24..3a9e54a 100644 --- a/evaluator/evaluator.go +++ b/evaluator/evaluator.go @@ -16,13 +16,13 @@ func Eval(node ast.Node) object.Object { switch node := node.(type) { // Statements case *ast.Program: - return evalStatements(node.Statements) + return evalProgram(node) case *ast.ExpressionStatement: return Eval(node.Expression) case *ast.BlockStatement: - return evalStatements(node.Statements) + return evalBlockStatement(node) // Expressions case *ast.IntegerLiteral: @@ -42,16 +42,38 @@ func Eval(node ast.Node) object.Object { case *ast.IfExpression: return evalIfExpression(node) + + case *ast.ReturnStatement: + val := Eval(node.ReturnValue) + return &object.ReturnValue{Value: val} } return nil } -func evalStatements(stmts []ast.Statement) object.Object { +func evalProgram(program *ast.Program) object.Object { var result object.Object - for _, statement := range stmts { + for _, statement := range program.Statements { result = Eval(statement) + + if returnValue, ok := result.(*object.ReturnValue); ok { + return returnValue.Value + } + } + + return result +} + +func evalBlockStatement(block *ast.BlockStatement) object.Object { + var result object.Object + + for _, statement := range block.Statements { + result = Eval(statement) + + if result != nil && result.Type() == object.RETURN_VALUE_OBJ { + return result + } } return result diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go index b124144..ca7738f 100644 --- a/evaluator/evaluator_test.go +++ b/evaluator/evaluator_test.go @@ -112,6 +112,31 @@ func TestIfElseExpressions(t *testing.T) { } } +func TestReturnStatements(t *testing.T) { + tests := []struct { + input string + expected int64 + }{ + {"return 10;", 10}, + {"return 10; 9;", 10}, + {"return 2 * 5; 9;", 10}, + {"9; return 2 * 5; 9;", 10}, + {` + if (10 > 1) { + if (10 > 1) { + return 10; + } + return 1; + } + `, 10}, + } + + for _, tt := range tests { + evaulated := testEval(tt.input) + testIntegerObject(t, evaulated, tt.expected) + } +} + func testEval(input string) object.Object { l := lexer.New(input) p := parser.New(l) |
