소스 검색

if statement object evaluator

simon 3 년 전
부모
커밋
505f69cc15
2개의 변경된 파일61개의 추가작업 그리고 0개의 파일을 삭제
  1. 28 0
      evaluator/evaluator.go
  2. 33 0
      evaluator/evaluator_test.go

+ 28 - 0
evaluator/evaluator.go

@@ -32,6 +32,11 @@ func Eval(node ast.Node) object.Object {
 		left := Eval(node.Left)
 		right := Eval(node.Right)
 		return evalInfixExpression(node.Operator, left, right)
+
+	case *ast.BlockStatement:
+		return evalStatements(node.Statements)
+	case *ast.IfExpression:
+		return evalIfExpression(node)
 	}
 
 	return nil
@@ -76,6 +81,16 @@ func evalInfixExpression(operator string, left object.Object, right object.Objec
 		return NULL
 	}
 }
+func evalIfExpression(node *ast.IfExpression) object.Object {
+	condition := Eval(node.Condition)
+	if isTruthy(condition) {
+		return Eval(node.Consequence)
+	} else if node.Alternative != nil {
+		return Eval(node.Alternative)
+	} else {
+		return NULL
+	}
+}
 
 func evalIntegerInfixExpression(operator string,
 	left object.Object, right object.Object) object.Object {
@@ -122,3 +137,16 @@ func evalBangOperatorExpression(right object.Object) object.Object {
 		return FALSE
 	}
 }
+
+func isTruthy(obj object.Object) bool {
+	switch obj {
+	case NULL:
+		return false
+	case TRUE:
+		return true
+	case FALSE:
+		return false
+	default:
+		return true
+	}
+}

+ 33 - 0
evaluator/evaluator_test.go

@@ -70,6 +70,39 @@ func TestBangOperator(t *testing.T) {
 	}
 }
 
+func TestIfElseExpression(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}", 10},
+		{"if(1>2){10} else {20}", 20},
+	}
+
+	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
+}
+
 func testIntegerObject(t *testing.T, obj object.Object, expected int64) bool {
 	result, ok := obj.(*object.Integer)
 	if !ok {