builtins
Some checks failed
Build / build (push) Failing after 1h2m55s
Test / build (push) Failing after 29m38s

This commit is contained in:
Chuck Smith
2024-03-12 16:35:24 -04:00
parent 1d2c7f0a51
commit e373e9f68a
11 changed files with 354 additions and 125 deletions

View File

@@ -1,119 +1,14 @@
package evaluator
import (
"fmt"
"monkey/object"
"unicode/utf8"
)
var builtins = map[string]*object.Builtin{
"len": &object.Builtin{
Fn: func(args ...object.Object) object.Object {
if len(args) != 1 {
return newError("wrong number of arguments. got=%d, want=1", len(args))
}
switch arg := args[0].(type) {
case *object.Array:
return &object.Integer{Value: int64(len(arg.Elements))}
case *object.String:
return &object.Integer{Value: int64(utf8.RuneCountInString(arg.Value))}
default:
return newError("argument to `len` not supported, got %s", args[0].Type())
}
},
},
"first": &object.Builtin{
Fn: func(args ...object.Object) object.Object {
if len(args) != 1 {
return newError("wrong number of arguments. got=%d, want=1", len(args))
}
if args[0].Type() != object.ARRAY_OBJ {
return newError("argument to `first` must be ARRAY, got %s", args[0].Type())
}
arr := args[0].(*object.Array)
if len(arr.Elements) > 0 {
return arr.Elements[0]
}
return NULL
},
},
"last": &object.Builtin{
Fn: func(args ...object.Object) object.Object {
if len(args) != 1 {
return newError("wrong number of arguments. got=%d, want=1", len(args))
}
if args[0].Type() != object.ARRAY_OBJ {
return newError("argument to `last` must be ARRAY, got %s", args[0].Type())
}
arr := args[0].(*object.Array)
length := len(arr.Elements)
if length > 0 {
return arr.Elements[length-1]
}
return NULL
},
},
"rest": &object.Builtin{
Fn: func(args ...object.Object) object.Object {
if len(args) != 1 {
return newError("wrong number of arguments. got=%d, want=1",
len(args))
}
if args[0].Type() != object.ARRAY_OBJ {
return newError("argument to `rest` must be ARRAY, got %s",
args[0].Type())
}
arr := args[0].(*object.Array)
length := len(arr.Elements)
if length > 0 {
newElements := make([]object.Object, length-1, length-1)
copy(newElements, arr.Elements[1:length])
return &object.Array{Elements: newElements}
}
return NULL
},
},
"push": &object.Builtin{
Fn: func(args ...object.Object) object.Object {
if len(args) != 2 {
return newError("wrong number of arguments. got=%d, want=2",
len(args))
}
if args[0].Type() != object.ARRAY_OBJ {
return newError("argument to `push` must be ARRAY, got %s",
args[0].Type())
}
arr := args[0].(*object.Array)
length := len(arr.Elements)
newElements := make([]object.Object, length+1, length+1)
copy(newElements, arr.Elements)
newElements[length] = args[1]
return &object.Array{Elements: newElements}
},
},
"puts": &object.Builtin{
Fn: func(args ...object.Object) object.Object {
for _, arg := range args {
fmt.Println(arg.Inspect())
}
return NULL
},
},
"len": object.GetBuiltinByName("len"),
"first": object.GetBuiltinByName("first"),
"last": object.GetBuiltinByName("last"),
"rest": object.GetBuiltinByName("rest"),
"push": object.GetBuiltinByName("push"),
"puts": object.GetBuiltinByName("puts"),
}

View File

@@ -319,7 +319,10 @@ func applyFunction(fn object.Object, args []object.Object) object.Object {
return unwrapReturnValue(evaluated)
case *object.Builtin:
return fn.Fn(args...)
if result := fn.Fn(args...); result != nil {
return result
}
return NULL
default:
return newError("not a function: %s", fn.Type())