umx_compiler

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

commit 4469a343e5eb7af7b7ec8fb3a348630b159b60fc
parent 7b8cd20ca0804b40f3621fea353739f8214c8055
Author: bsandro <email@bsandro.tech>
Date:   Thu, 23 Jun 2022 23:49:10 +0300

eval ! and - prefix operators

Diffstat:
Meval/eval.go | 43+++++++++++++++++++++++++++++++++++++++----
Meval/eval_test.go | 20++++++++++++++++++++
2 files changed, 59 insertions(+), 4 deletions(-)

diff --git a/eval/eval.go b/eval/eval.go @@ -11,6 +11,14 @@ var ( NULL = &object.Null{} ) +func boolToObject(value bool) *object.Boolean { + if value { + return TRUE + } else { + return FALSE + } +} + func Eval(node ast.Node) object.Object { switch node := node.(type) { case *ast.Program: @@ -20,7 +28,10 @@ func Eval(node ast.Node) object.Object { case *ast.IntegerLiteral: return &object.Integer{Value: node.Value} case *ast.Boolean: - return nativeBoolToBooleanObject(node.Value) + return boolToObject(node.Value) + case *ast.PrefixExpression: + right := Eval(node.Right) + return evalPrefixExpression(node.Operator, right) } return nil } @@ -33,10 +44,34 @@ func evalStatements(statements []ast.Statement) object.Object { return result } -func nativeBoolToBooleanObject(input bool) *object.Boolean { - if input { +func evalPrefixExpression(operator string, right object.Object) object.Object { + switch operator { + case "!": + return evalShriekOperatorExpression(right) + case "-": + return evalMinusPrefixOperatorExpression(right) + default: + return NULL + } +} + +func evalShriekOperatorExpression(right object.Object) object.Object { + switch right { + case TRUE: + return FALSE + case FALSE: return TRUE - } else { + case NULL: + return TRUE + default: return FALSE } } + +func evalMinusPrefixOperatorExpression(right object.Object) object.Object { + if right.Type() != object.INTEGER_OBJ { + return NULL + } + value := right.(*object.Integer).Value + return &object.Integer{Value: -value} +} diff --git a/eval/eval_test.go b/eval/eval_test.go @@ -13,7 +13,9 @@ func TestEvalIntegerExpression(t *testing.T) { expected int64 }{ {"6", 6}, + {"-8", -8}, {"10", 10}, + {"-256", -256}, } for _, tt := range tests { evaluated := testEval(tt.input) @@ -67,3 +69,21 @@ func testBooleanObject(t *testing.T, obj object.Object, expected bool) bool { } return true } + +func TestShriekOperator(t *testing.T) { + tests := []struct { + input string + expected bool + }{ + {"!true", false}, + {"!false", true}, + {"!5", false}, + {"!!true", true}, + {"!!!false", true}, + {"!!8", true}, + } + for _, tt := range tests { + evaluated := testEval(tt.input) + testBooleanObject(t, evaluated, tt.expected) + } +}