Skip to content

Commit

Permalink
Merge pull request #7 from kamilturek/eval-infix-expressions
Browse files Browse the repository at this point in the history
Evaluate infix expressions
  • Loading branch information
kamilturek authored Jun 23, 2024
2 parents 1ce28af + 0805b01 commit 86ab4e4
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 4 deletions.
56 changes: 54 additions & 2 deletions evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@ func Eval(node ast.Node) object.Object {
right := Eval(node.Right)

return evalPrefixExpression(node.Operator, right)
}
case *ast.InfixExpression:
left := Eval(node.Left)
right := Eval(node.Right)

return nil
return evalInfixExpression(node.Operator, left, right)
default:
return nil
}
}

func evalStatements(stmts []ast.Statement) object.Object {
Expand Down Expand Up @@ -84,6 +89,53 @@ func evalMinusPrefixOperatorExpression(right object.Object) object.Object {
}
}

func evalInfixExpression(operator string, left object.Object, right object.Object) object.Object {
switch {
case left.Type() == object.INTEGER_OBJ && right.Type() == object.INTEGER_OBJ:
return evalIntegerInfixExpression(operator, left, right)
// Left and right must be booleans then.
case operator == "==":
return nativeBoolToBooleanObject(left == right)
case operator == "!=":
return nativeBoolToBooleanObject(left != right)
default:
return NULL
}
}

func evalIntegerInfixExpression(operator string, left object.Object, right object.Object) object.Object {
leftInteger, ok := left.(*object.Integer)
if !ok {
return NULL
}

rightInteger, ok := right.(*object.Integer)
if !ok {
return NULL
}

switch operator {
case "+":
return &object.Integer{Value: leftInteger.Value + rightInteger.Value}
case "-":
return &object.Integer{Value: leftInteger.Value - rightInteger.Value}
case "*":
return &object.Integer{Value: leftInteger.Value * rightInteger.Value}
case "/":
return &object.Integer{Value: leftInteger.Value / rightInteger.Value}
case "<":
return nativeBoolToBooleanObject(leftInteger.Value < rightInteger.Value)
case ">":
return nativeBoolToBooleanObject(leftInteger.Value > rightInteger.Value)
case "==":
return nativeBoolToBooleanObject(leftInteger.Value == rightInteger.Value)
case "!=":
return nativeBoolToBooleanObject(leftInteger.Value != rightInteger.Value)
default:
return NULL
}
}

func nativeBoolToBooleanObject(input bool) *object.Boolean {
if input {
return TRUE
Expand Down
32 changes: 30 additions & 2 deletions evaluator/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func testIntegerObject(t *testing.T, obj object.Object, expected int64) bool {
}

if result.Value != expected {
t.Errorf("object has wrong value. got=%d, want=%d", expected, result.Value)
t.Errorf("object has wrong value. got=%d, want=%d", result.Value, expected)

return false
}
Expand All @@ -47,7 +47,7 @@ func testBooleanObject(t *testing.T, obj object.Object, expected bool) bool { //
}

if result.Value != expected {
t.Errorf("object has wrong value. got=%t, want=%t", expected, result.Value)
t.Errorf("object has wrong value. got=%t, want=%t", result.Value, expected)

return false
}
Expand All @@ -66,6 +66,17 @@ func TestEvalIntegerExpression(t *testing.T) {
{"10", 10},
{"-5", -5},
{"-10", -10},
{"5 + 5 + 5 + 5 - 10", 10},
{"2 * 2 * 2 * 2 * 2", 32},
{"-50 + 100 - 50", 0},
{"5 * 2 + 10", 20},
{"5 + 2 * 10", 25},
{"20 + 2 * -10", 0},
{"50 / 2 * 2 + 10", 60},
{"2 * (5 + 10)", 30},
{"3 * 3 * 3 + 10", 37},
{"3 * ( 3 * 3) + 10", 37},
{"(5 + 10 * 2 + 15 / 3) * 2 - 10", 50},
}

for _, tt := range tests {
Expand All @@ -83,6 +94,23 @@ func TestEvalBooleanExpression(t *testing.T) {
}{
{"true", true},
{"false", false},
{"1 < 2", true},
{"1 > 2", false},
{"1 < 1", false},
{"1 > 1", false},
{"1 == 1", true},
{"1 != 1", false},
{"1 == 2", false},
{"1 != 2", true},
{"true == true", true},
{"false == false", true},
{"true == false", false},
{"true != false", true},
{"false != true", true},
{"(1 < 2) == true", true},
{"(1 < 2) == false", false},
{"(1 > 2) == true", false},
{"(1 > 2) == false", true},
}

for _, tt := range tests {
Expand Down

0 comments on commit 86ab4e4

Please sign in to comment.