diff options
| author | Bobby <[email protected]> | 2024-03-01 20:26:52 +0000 |
|---|---|---|
| committer | Bobby <[email protected]> | 2024-03-01 20:26:52 +0000 |
| commit | 8e6447a42c363cf567ec3146bb588c7ed7ce7260 (patch) | |
| tree | 6931b526be8410cd1ae1f07ab5194b357dc2a229 /evaluator | |
| parent | 4a930511b3aad05682aae69cbfbf7e7273e20264 (diff) | |
| download | mana-8e6447a42c363cf567ec3146bb588c7ed7ce7260.tar.xz mana-8e6447a42c363cf567ec3146bb588c7ed7ce7260.zip | |
`Eval` for `IfElseStatement`
Diffstat (limited to 'evaluator')
| -rw-r--r-- | evaluator/evaluator.go | 30 | ||||
| -rw-r--r-- | evaluator/evaluator_test.go | 33 |
2 files changed, 63 insertions, 0 deletions
diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go index 479e244..7aeaa24 100644 --- a/evaluator/evaluator.go +++ b/evaluator/evaluator.go @@ -21,6 +21,9 @@ func Eval(node ast.Node) object.Object { case *ast.ExpressionStatement: return Eval(node.Expression) + case *ast.BlockStatement: + return evalStatements(node.Statements) + // Expressions case *ast.IntegerLiteral: return &object.Integer{Value: node.Value} @@ -36,6 +39,9 @@ func Eval(node ast.Node) object.Object { left := Eval(node.Left) right := Eval(node.Right) return evalInfixExpression(node.Operator, left, right) + + case *ast.IfExpression: + return evalIfExpression(node) } return nil @@ -132,3 +138,27 @@ func evalIntegerInfixExpression(operator string, left, right object.Object) obje return NULL } } + +func evalIfExpression(ie *ast.IfExpression) object.Object { + condition := Eval(ie.Condition) + if isTruthy(condition) { + return Eval(ie.Consequence) + } else if ie.Alternative != nil { + return Eval(ie.Alternative) + } else { + return NULL + } +} + +func isTruthy(obj object.Object) bool { + switch obj { + case NULL: + return false + case TRUE: + return true + case FALSE: + return false + default: + return true + } +} diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go index e5bc66c..b124144 100644 --- a/evaluator/evaluator_test.go +++ b/evaluator/evaluator_test.go @@ -87,6 +87,31 @@ func TestBangOperator(t *testing.T) { } } +func TestIfElseExpressions(t *testing.T) { + tests := []struct { + input string + expected interface{} + }{ + {"if (true) { 10 }", 10}, + {"if (false) { 10 }", nil}, + {"if (1) { 10 }", 10}, + {"if (1 < 2) { 10 }", 10}, + {"if (1 > 2) { 10 }", nil}, + {"if (1 > 2) { 10 } else { 20 }", 20}, + {"if (1 < 2) { 10 } else { 20 }", 10}, + } + + for _, tt := range tests { + evaulated := testEval(tt.input) + integer, ok := tt.expected.(int) + if ok { + testIntegerObject(t, evaulated, int64(integer)) + } else { + testNullObject(t, evaulated) + } + } +} + func testEval(input string) object.Object { l := lexer.New(input) p := parser.New(l) @@ -119,3 +144,11 @@ func testBooleanObject(t *testing.T, obj object.Object, expected bool) bool { } return true } + +func testNullObject(t *testing.T, obj object.Object) bool { + if obj != NULL { + t.Errorf("object is not NULL. got=%T (%+v)", obj, obj) + return false + } + return true +} |
