Skip to content

Commit

Permalink
3.5: Evaluate boolean and prefix expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
nibral committed Jan 16, 2019
1 parent e018d49 commit fa18985
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 0 deletions.
52 changes: 52 additions & 0 deletions evaluator/evaluator.go
Expand Up @@ -5,6 +5,12 @@ import (
"monkey_interpreter/object"
)

var (
NULL = &object.Null{}
TRUE = &object.Boolean{Value: true}
FALSE = &object.Boolean{Value: false}
)

func Eval(node ast.Node) object.Object {
switch node := node.(type) {

Expand All @@ -17,6 +23,12 @@ func Eval(node ast.Node) object.Object {
// expressions
case *ast.IntegerLiteral:
return &object.Integer{Value: node.Value}
case *ast.Boolean:
return nativeBoolToBooleanObject(node.Value)
case *ast.PrefixExpression:
right := Eval(node.Right)
return evalPrefixExpression(node.Operator, right)

}

return nil
Expand All @@ -31,3 +43,43 @@ func evalStatements(stmts []ast.Statement) object.Object {

return result
}

func evalPrefixExpression(operator string, right object.Object) object.Object {
switch operator {
case "!":
return evalBangOperatorExpression(right)
case "-":
return evalMinusPrefixOperatorExpression(right)
default:
return NULL
}
}

func evalBangOperatorExpression(right object.Object) object.Object {
switch right {
case TRUE:
return FALSE
case FALSE:
return TRUE
case NULL:
return TRUE
default:
return FALSE
}
}

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

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

func nativeBoolToBooleanObject(input bool) *object.Boolean {
if input {
return TRUE
}
return FALSE
}
50 changes: 50 additions & 0 deletions evaluator/evaluator_test.go
Expand Up @@ -14,6 +14,8 @@ func TestEvalIntegerExpression(t *testing.T) {
}{
{"5", 5},
{"10", 10},
{"-5", -5},
{"-10", -10},
}

for _, tt := range tests {
Expand Down Expand Up @@ -44,3 +46,51 @@ func testIntegerObject(t *testing.T, obj object.Object, expected int64) bool {

return true
}

func TestEvalBooleanExpression(t *testing.T) {
tests := []struct {
input string
expected bool
}{
{"true", true},
{"false", false},
}

for _, tt := range tests {
evaluated := testEval(tt.input)
testBooleanObject(t, evaluated, tt.expected)
}
}

func testBooleanObject(t *testing.T, obj object.Object, expected bool) bool {
result, ok := obj.(*object.Boolean)
if !ok {
t.Errorf("object is not Boolean. got=%T (%+v)", obj, obj)
return false
}
if result.Value != expected {
t.Errorf("object has wrong value. got=%t, want=%t",
result.Value, expected)
return false
}
return true
}

func TestBangOperator(t *testing.T) {
tests := []struct {
input string
expected bool
}{
{"!true", false},
{"!false", true},
{"!5", false},
{"!!true", true},
{"!!false", false},
{"!!5", true},
}

for _, tt := range tests {
evaluated := testEval(tt.input)
testBooleanObject(t, evaluated, tt.expected)
}
}

0 comments on commit fa18985

Please sign in to comment.