Skip to content

Commit

Permalink
3.5: Evaluate infix expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
nibral committed Jan 16, 2019
1 parent fa18985 commit d341f9e
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 1 deletion.
45 changes: 44 additions & 1 deletion evaluator/evaluator.go
Expand Up @@ -28,6 +28,10 @@ func Eval(node ast.Node) object.Object {
case *ast.PrefixExpression:
right := Eval(node.Right)
return evalPrefixExpression(node.Operator, right)
case *ast.InfixExpression:
left := Eval(node.Left)
right := Eval(node.Right)
return evalInfixExpression(node.Operator, left, right)

}

Expand Down Expand Up @@ -70,13 +74,52 @@ func evalBangOperatorExpression(right object.Object) object.Object {

func evalMinusPrefixOperatorExpression(right object.Object) object.Object {
if right.Type() != object.INTEGER_OBJ {
return nil
return NULL
}

value := right.(*object.Integer).Value
return &object.Integer{Value: -value}
}

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

func evalIntegerInfixExpression(operator string, left, right object.Object) object.Object {
leftVal := left.(*object.Integer).Value
rightVal := right.(*object.Integer).Value

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

func nativeBoolToBooleanObject(input bool) *object.Boolean {
if input {
return TRUE
Expand Down
28 changes: 28 additions & 0 deletions evaluator/evaluator_test.go
Expand Up @@ -16,6 +16,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 Down Expand Up @@ -54,6 +65,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 d341f9e

Please sign in to comment.