Return statements

This commit is contained in:
Chuck Smith
2024-01-19 17:50:02 -05:00
parent e6d5567681
commit 7eba7471c8
3 changed files with 70 additions and 7 deletions

View File

@@ -16,17 +16,21 @@ 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 evalBlockStatements(node)
case *ast.IfExpression:
return evalIfExpression(node)
case *ast.ReturnStatement:
val := Eval(node.ReturnValue)
return &object.ReturnValue{Value: val}
// Expressions
case *ast.IntegerLiteral:
return &object.Integer{Value: node.Value}
@@ -48,11 +52,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 evalBlockStatements(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

View File

@@ -111,6 +111,34 @@ func TestIfElseExpression(t *testing.T) {
}
}
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)
}
}
func testEval(input string) object.Object {
l := lexer.New(input)
p := parser.New(l)