umx_compiler

UMX virtual machine "Monkey" interpreter / bytecode compiler
git clone git://bsandro.tech/umx_compiler
Log | Files | Refs

commit ed5362ca03dff4a3b9d7b3c0958a450b9a46db7d
parent d068fe3b1d66c3d0500299e2c3ae1388b4d0cf0a
Author: bsandro <email@bsandro.tech>
Date:   Fri, 24 Jun 2022 00:44:54 +0300

if-else eval

Diffstat:
Meval/eval.go | 28++++++++++++++++++++++++++++
Meval/eval_test.go | 32++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/eval/eval.go b/eval/eval.go @@ -36,6 +36,10 @@ func Eval(node ast.Node) object.Object { left := Eval(node.Left) right := Eval(node.Right) return evalInfixExpression(node.Operator, left, right) + case *ast.BlockStatement: + return evalStatements(node.Statements) + case *ast.IfExpression: + return evalIfExpression(node) } return nil } @@ -117,3 +121,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/eval/eval_test.go b/eval/eval_test.go @@ -99,3 +99,35 @@ func TestShriekOperator(t *testing.T) { testBooleanObject(t, evaluated, tt.expected) } } + +func TestIfElseExpressions(t *testing.T) { + tests := []struct { + input string + expected interface{} + }{ + {"if (true) { 10 }", 10}, + {"if (false) { 20 }", nil}, + {"if (1) { 30 }", 30}, + {"if (1<2) { 40 }", 40}, + {"if (1>2) { 11 }", nil}, + {"if (1>2) { 50 } else { 60 }", 60}, + {"if (1<2) { 50 } else { 60 }", 50}, + } + for _, tt := range tests { + evaluated := testEval(tt.input) + integer, ok := tt.expected.(int) + if ok { + testIntegerObject(t, evaluated, int64(integer)) + } else { + testNullObject(t, evaluated) + } + } +} + +func testNullObject(t *testing.T, obj object.Object) bool { + if obj != NULL { + t.Errorf("obj is not NULL but %T (%+v)", obj, obj) + return false + } + return true +}