- Ensure value producing expression in a let statement and also identifiers bound to a 
variable name.
- Tests to ensure valid errors with unbound identifiers

git-svn-id: https://svn.tlawal.org/svn/monkey@51 f6afcba9-9ef1-4bdd-9b72-7484f5705bac
This commit is contained in:
Tijani Lawal 2022-08-18 14:32:13 +00:00
parent 44612f0756
commit d38f4dec8a
2 changed files with 40 additions and 16 deletions

View File

@ -18,9 +18,25 @@ func Eval(node ast.Node) object.Object {
case *ast.Program:
return eval_program(node)
case *ast.BlockStatement:
return eval_block_statement(node)
case *ast.ExpressionStatement:
return Eval(node.Expression)
case *ast.ReturnStatement:
val := Eval(node.ReturnValue)
if is_error(val) {
return val
}
return &object.ReturnValue{Value: val}
case *ast.LetStatement:
val := Eval(node.Value)
if is_error(val) {
return val
}
// Expressions
case *ast.IntegerLiteral:
return &object.Integer{Value: node.Value}
@ -30,35 +46,25 @@ func Eval(node ast.Node) object.Object {
case *ast.PrefixExpression:
right := Eval(node.Right)
if is_error(right){
if is_error(right) {
return right
}
return eval_prefix_expression(node.Operator, right)
case *ast.InfixExpression:
left := Eval(node.Left)
if is_error(left){
if is_error(left) {
return left
}
right := Eval(node.Right)
if is_error(right){
if is_error(right) {
return right
}
return eval_infix_expression(node.Operator, left, right)
case *ast.BlockStatement:
return eval_block_statement(node)
case *ast.IfExpression:
return eval_if_expression(node)
case *ast.ReturnStatement:
val := Eval(node.ReturnValue)
if is_error(val){
return val
}
return &object.ReturnValue{Value: val}
}
return nil
@ -196,7 +202,7 @@ func eval_integer_infix_expression(operator string, left object.Object, right ob
func eval_if_expression(ie *ast.IfExpression) object.Object {
condition := Eval(ie.Condition)
if is_error(condition){
if is_error(condition) {
return condition
}

View File

@ -55,6 +55,7 @@ func TestErrorHandling(l_test *testing.T) {
return 1;
}
`, "unknown operator: BOOLEAN + BOOLEAN"},
{"foobar", "identifier not found:foobar"},
}
for _, tt := range tests {
@ -167,6 +168,23 @@ func TestReturnStatements(l_test *testing.T) {
}
}
func TestLetStatements(l_test *testing.T) {
tests := []struct {
input string
expected int64
}{
{"let a = 5; a;", 5},
{"let a = 5 * 5; a;", 25},
{"let a = 5; let b = a; b", 5},
{"let a = 5; let b = a; let c = a + b + 5", 15},
}
for _, tt := range tests {
evaluated := test_eval(tt.input)
test_integer_object(l_test, evaluated, tt.expected)
}
}
// Helpers
func test_eval(input string) object.Object {
l_lexer := lexer.New(input)