aboutsummaryrefslogtreecommitdiff
path: root/evaluator/evaluator.go
diff options
context:
space:
mode:
Diffstat (limited to 'evaluator/evaluator.go')
-rw-r--r--evaluator/evaluator.go53
1 files changed, 36 insertions, 17 deletions
diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go
index b9b8bb9..9cead89 100644
--- a/evaluator/evaluator.go
+++ b/evaluator/evaluator.go
@@ -13,17 +13,27 @@ var (
)
// Eval evaluates the given ast.Node and returns an object.Object.
-func Eval(node ast.Node) object.Object {
+func Eval(node ast.Node, env *object.Environment) object.Object {
switch node := node.(type) {
// Statements
case *ast.Program:
- return evalProgram(node)
+ return evalProgram(node, env)
case *ast.ExpressionStatement:
- return Eval(node.Expression)
+ return Eval(node.Expression, env)
case *ast.BlockStatement:
- return evalBlockStatement(node)
+ return evalBlockStatement(node, env)
+
+ case *ast.LetStatement:
+ val := Eval(node.Value, env)
+ if isError(val) {
+ return val
+ }
+ env.Set(node.Name.Value, val)
+
+ case *ast.Identifier:
+ return evalIdentifier(node, env)
// Expressions
case *ast.IntegerLiteral:
@@ -33,28 +43,28 @@ func Eval(node ast.Node) object.Object {
return nativeBoolToBooleanObject(node.Value)
case *ast.PrefixExpression:
- right := Eval(node.Right)
+ right := Eval(node.Right, env)
if isError(right) {
return right
}
return evalPrefixExpression(node.Operator, right)
case *ast.InfixExpression:
- left := Eval(node.Left)
+ left := Eval(node.Left, env)
if isError(left) {
return left
}
- right := Eval(node.Right)
+ right := Eval(node.Right, env)
if isError(right) {
return right
}
return evalInfixExpression(node.Operator, left, right)
case *ast.IfExpression:
- return evalIfExpression(node)
+ return evalIfExpression(node, env)
case *ast.ReturnStatement:
- val := Eval(node.ReturnValue)
+ val := Eval(node.ReturnValue, env)
if isError(val) {
return val
}
@@ -64,11 +74,11 @@ func Eval(node ast.Node) object.Object {
return nil
}
-func evalProgram(program *ast.Program) object.Object {
+func evalProgram(program *ast.Program, env *object.Environment) object.Object {
var result object.Object
for _, statement := range program.Statements {
- result = Eval(statement)
+ result = Eval(statement, env)
switch result := result.(type) {
case *object.ReturnValue:
@@ -81,11 +91,12 @@ func evalProgram(program *ast.Program) object.Object {
return result
}
-func evalBlockStatement(block *ast.BlockStatement) object.Object {
+
+func evalBlockStatement(block *ast.BlockStatement, env *object.Environment) object.Object {
var result object.Object
for _, statement := range block.Statements {
- result = Eval(statement)
+ result = Eval(statement, env)
if result != nil {
rt := result.Type()
@@ -182,20 +193,28 @@ func evalIntegerInfixExpression(operator string, left, right object.Object) obje
}
}
-func evalIfExpression(ie *ast.IfExpression) object.Object {
- condition := Eval(ie.Condition)
+func evalIfExpression(ie *ast.IfExpression, env *object.Environment) object.Object {
+ condition := Eval(ie.Condition, env)
if isError(condition) {
return condition
}
if isTruthy(condition) {
- return Eval(ie.Consequence)
+ return Eval(ie.Consequence, env)
} else if ie.Alternative != nil {
- return Eval(ie.Alternative)
+ return Eval(ie.Alternative, env)
} else {
return NULL
}
}
+func evalIdentifier(node *ast.Identifier, env *object.Environment) object.Object {
+ val, ok := env.Get(node.Value)
+ if !ok {
+ return newError("identifier not found: " + node.Value)
+ }
+ return val
+}
+
func isTruthy(obj object.Object) bool {
switch obj {
case NULL: