Skip to content

Commit

Permalink
3.6: Evaluate if statements
Browse files Browse the repository at this point in the history
  • Loading branch information
nibral committed Jan 23, 2019
1 parent d341f9e commit 9645d49
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
29 changes: 29 additions & 0 deletions evaluator/evaluator.go
Expand Up @@ -19,6 +19,8 @@ func Eval(node ast.Node) object.Object {
return evalStatements(node.Statements)
case *ast.ExpressionStatement:
return Eval(node.Expression)
case *ast.BlockStatement:
return evalStatements(node.Statements)

// expressions
case *ast.IntegerLiteral:
Expand All @@ -32,6 +34,8 @@ func Eval(node ast.Node) object.Object {
left := Eval(node.Left)
right := Eval(node.Right)
return evalInfixExpression(node.Operator, left, right)
case *ast.IfExpression:
return evalIfExpression(node)

}

Expand Down Expand Up @@ -126,3 +130,28 @@ func nativeBoolToBooleanObject(input bool) *object.Boolean {
}
return FALSE
}

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
}
}
33 changes: 33 additions & 0 deletions evaluator/evaluator_test.go
Expand Up @@ -122,3 +122,36 @@ func TestBangOperator(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) { 10 }", nil},
{"if (1) { 10 }", 10},
{"if (1 < 2) { 10 }", 10},
{"if (1 > 2) { 10 }", nil},
{"if (1 > 2) { 10 } else { 20 }", 20},
{"if (1 < 2) { 10 } else { 20 }", 10},
}

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("object is not NULL. got=%T (%+v)", obj, obj)
return false
}
return true
}

0 comments on commit 9645d49

Please sign in to comment.