|
|
@@ -73,11 +73,41 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
|
|
|
if len(args) == 1 && isError(args[0]) {
|
|
|
return args[0]
|
|
|
}
|
|
|
+
|
|
|
+ return applyFunction(function, args)
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+func applyFunction(fn object.Object, args []object.Object) object.Object {
|
|
|
+ function, ok := fn.(*object.Function)
|
|
|
+ if !ok {
|
|
|
+ return newError("not a function: %s", fn.Type())
|
|
|
+ }
|
|
|
+
|
|
|
+ extendEnv := extendFunctionEnv(function, args)
|
|
|
+ evaluated := Eval(function.Body, extendEnv)
|
|
|
+ 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
|
|
|
+}
|
|
|
+
|
|
|
func newError(format string, a ...interface{}) *object.Error {
|
|
|
return &object.Error{Msg: fmt.Sprintf(format, a...)}
|
|
|
}
|