Eval complete
This commit is contained in:
@@ -52,6 +52,11 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
|
||||
case *ast.Identifier:
|
||||
return evalIdentifier(node, env)
|
||||
|
||||
case *ast.FunctionLiteral:
|
||||
params := node.Parameters
|
||||
body := node.Body
|
||||
return &object.Function{Parameters: params, Env: env, Body: body}
|
||||
|
||||
// Expressions
|
||||
case *ast.IntegerLiteral:
|
||||
return &object.Integer{Value: node.Value}
|
||||
@@ -77,6 +82,18 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
|
||||
}
|
||||
return evalInfixExpression(node.Operator, left, right)
|
||||
|
||||
case *ast.CallExpression:
|
||||
function := Eval(node.Function, env)
|
||||
if isError(function) {
|
||||
return function
|
||||
}
|
||||
args := evalExpressions(node.Arguments, env)
|
||||
if len(args) == 1 && isError(args[0]) {
|
||||
return args[0]
|
||||
}
|
||||
|
||||
return applyFunction(function, args)
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -237,3 +254,46 @@ func evalIdentifier(node *ast.Identifier, env *object.Environment) object.Object
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func evalExpressions(exps []ast.Expression, env *object.Environment) []object.Object {
|
||||
var result []object.Object
|
||||
|
||||
for _, e := range exps {
|
||||
evaluated := Eval(e, env)
|
||||
if isError(evaluated) {
|
||||
return []object.Object{evaluated}
|
||||
}
|
||||
result = append(result, evaluated)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func applyFunction(fn object.Object, args []object.Object) object.Object {
|
||||
function, ok := fn.(*object.Function)
|
||||
if !ok {
|
||||
newError("not a function: %s", fn.Type())
|
||||
}
|
||||
|
||||
extendedEnv := extendFunctionEnv(function, args)
|
||||
evaluated := Eval(function.Body, extendedEnv)
|
||||
return unwrapReturnValue(evaluated)
|
||||
}
|
||||
|
||||
func extendFunctionEnv(fn *object.Function, args []object.Object) *object.Environment {
|
||||
env := object.NewEnclosedEnvironment(fn.Env)
|
||||
|
||||
for paramIdx, param := range fn.Parameters {
|
||||
env.Set(param.Value, args[paramIdx])
|
||||
}
|
||||
|
||||
return env
|
||||
}
|
||||
|
||||
func unwrapReturnValue(obj object.Object) object.Object {
|
||||
if returnValue, ok := obj.(*object.ReturnValue); ok {
|
||||
return returnValue.Value
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user