Skip to content

Commit

Permalink
3.7: Evaluate return statements
Browse files Browse the repository at this point in the history
  • Loading branch information
nibral committed Jan 23, 2019
1 parent 9645d49 commit 2f9e42d
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 7 deletions.
29 changes: 25 additions & 4 deletions evaluator/evaluator.go
Expand Up @@ -16,11 +16,14 @@ func Eval(node ast.Node) object.Object {

// statements
case *ast.Program:
return evalStatements(node.Statements)
return evalProgram(node)
case *ast.ExpressionStatement:
return Eval(node.Expression)
case *ast.BlockStatement:
return evalStatements(node.Statements)
return evalBlockStatement(node)
case *ast.ReturnStatement:
val := Eval(node.ReturnValue)
return &object.ReturnValue{Value: val}

// expressions
case *ast.IntegerLiteral:
Expand All @@ -42,11 +45,29 @@ func Eval(node ast.Node) object.Object {
return nil
}

func evalStatements(stmts []ast.Statement) object.Object {
func evalProgram(program *ast.Program) object.Object {
var result object.Object

for _, statement := range stmts {
for _, statement := range program.Statements {
result = Eval(statement)

if returnValue, ok := result.(*object.ReturnValue); ok {
return returnValue.Value
}
}

return result
}

func evalBlockStatement(block *ast.BlockStatement) object.Object {
var result object.Object

for _, statement := range block.Statements {
result = Eval(statement)

if result != nil && result.Type() == object.RETURN_VALUE_OBJ {
return result
}
}

return result
Expand Down
27 changes: 27 additions & 0 deletions evaluator/evaluator_test.go
Expand Up @@ -155,3 +155,30 @@ func testNullObject(t *testing.T, obj object.Object) bool {
}
return true
}

func TestReturnStatements(t *testing.T) {
tests := []struct {
input string
expected int64
}{
{"return 10;", 10},
{"return 10; 9;", 10},
{"return 2 * 5; 9;", 10},
{"9; return 2 * 5; 9;", 10},
{`
if (10 > 1) {
if (10 > 1) {
return 10;
}
return 1;
}
`, 10,
},
}

for _, tt := range tests {
evaluated := testEval(tt.input)
testIntegerObject(t, evaluated, tt.expected)
}
}
14 changes: 11 additions & 3 deletions object/object.go
Expand Up @@ -5,9 +5,10 @@ import "fmt"
type ObjectType string

const (
INTEGER_OBJ = "INTEGER"
BOOLEAN_OBJ = "BOOLEAN"
NULL_OBJ = "NULL"
INTEGER_OBJ = "INTEGER"
BOOLEAN_OBJ = "BOOLEAN"
NULL_OBJ = "NULL"
RETURN_VALUE_OBJ = "RETURN_VALUE"
)

type Object interface {
Expand All @@ -33,3 +34,10 @@ type Null struct{}

func (n *Null) Type() ObjectType { return NULL_OBJ }
func (n *Null) Inspect() string { return "null" }

type ReturnValue struct {
Value Object
}

func (rv *ReturnValue) Type() ObjectType { return RETURN_VALUE_OBJ }
func (rv *ReturnValue) Inspect() string { return rv.Value.Inspect() }

0 comments on commit 2f9e42d

Please sign in to comment.