commit 4469a343e5eb7af7b7ec8fb3a348630b159b60fc
parent 7b8cd20ca0804b40f3621fea353739f8214c8055
Author: bsandro <email@bsandro.tech>
Date: Thu, 23 Jun 2022 23:49:10 +0300
eval ! and - prefix operators
Diffstat:
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)
+ }
+}