/vendor/github.com/d5/tengo/v2/builtins.go
https://github.com/42wim/matterbridge · Go · 611 lines · 559 code · 38 blank · 14 comment · 138 complexity · f3d73e2be33ce98d74022cb5c7c1e8ff MD5 · raw file
- package tengo
- var builtinFuncs = []*BuiltinFunction{
- {
- Name: "len",
- Value: builtinLen,
- },
- {
- Name: "copy",
- Value: builtinCopy,
- },
- {
- Name: "append",
- Value: builtinAppend,
- },
- {
- Name: "delete",
- Value: builtinDelete,
- },
- {
- Name: "splice",
- Value: builtinSplice,
- },
- {
- Name: "string",
- Value: builtinString,
- },
- {
- Name: "int",
- Value: builtinInt,
- },
- {
- Name: "bool",
- Value: builtinBool,
- },
- {
- Name: "float",
- Value: builtinFloat,
- },
- {
- Name: "char",
- Value: builtinChar,
- },
- {
- Name: "bytes",
- Value: builtinBytes,
- },
- {
- Name: "time",
- Value: builtinTime,
- },
- {
- Name: "is_int",
- Value: builtinIsInt,
- },
- {
- Name: "is_float",
- Value: builtinIsFloat,
- },
- {
- Name: "is_string",
- Value: builtinIsString,
- },
- {
- Name: "is_bool",
- Value: builtinIsBool,
- },
- {
- Name: "is_char",
- Value: builtinIsChar,
- },
- {
- Name: "is_bytes",
- Value: builtinIsBytes,
- },
- {
- Name: "is_array",
- Value: builtinIsArray,
- },
- {
- Name: "is_immutable_array",
- Value: builtinIsImmutableArray,
- },
- {
- Name: "is_map",
- Value: builtinIsMap,
- },
- {
- Name: "is_immutable_map",
- Value: builtinIsImmutableMap,
- },
- {
- Name: "is_iterable",
- Value: builtinIsIterable,
- },
- {
- Name: "is_time",
- Value: builtinIsTime,
- },
- {
- Name: "is_error",
- Value: builtinIsError,
- },
- {
- Name: "is_undefined",
- Value: builtinIsUndefined,
- },
- {
- Name: "is_function",
- Value: builtinIsFunction,
- },
- {
- Name: "is_callable",
- Value: builtinIsCallable,
- },
- {
- Name: "type_name",
- Value: builtinTypeName,
- },
- {
- Name: "format",
- Value: builtinFormat,
- },
- }
- // GetAllBuiltinFunctions returns all builtin function objects.
- func GetAllBuiltinFunctions() []*BuiltinFunction {
- return append([]*BuiltinFunction{}, builtinFuncs...)
- }
- func builtinTypeName(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- return &String{Value: args[0].TypeName()}, nil
- }
- func builtinIsString(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*String); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsInt(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Int); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsFloat(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Float); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsBool(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Bool); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsChar(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Char); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsBytes(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Bytes); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsArray(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Array); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsImmutableArray(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*ImmutableArray); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsMap(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Map); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsImmutableMap(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*ImmutableMap); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsTime(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Time); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsError(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Error); ok {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsUndefined(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if args[0] == UndefinedValue {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsFunction(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- switch args[0].(type) {
- case *CompiledFunction:
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsCallable(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if args[0].CanCall() {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- func builtinIsIterable(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if args[0].CanIterate() {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- // len(obj object) => int
- func builtinLen(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- switch arg := args[0].(type) {
- case *Array:
- return &Int{Value: int64(len(arg.Value))}, nil
- case *ImmutableArray:
- return &Int{Value: int64(len(arg.Value))}, nil
- case *String:
- return &Int{Value: int64(len(arg.Value))}, nil
- case *Bytes:
- return &Int{Value: int64(len(arg.Value))}, nil
- case *Map:
- return &Int{Value: int64(len(arg.Value))}, nil
- case *ImmutableMap:
- return &Int{Value: int64(len(arg.Value))}, nil
- default:
- return nil, ErrInvalidArgumentType{
- Name: "first",
- Expected: "array/string/bytes/map",
- Found: arg.TypeName(),
- }
- }
- }
- func builtinFormat(args ...Object) (Object, error) {
- numArgs := len(args)
- if numArgs == 0 {
- return nil, ErrWrongNumArguments
- }
- format, ok := args[0].(*String)
- if !ok {
- return nil, ErrInvalidArgumentType{
- Name: "format",
- Expected: "string",
- Found: args[0].TypeName(),
- }
- }
- if numArgs == 1 {
- // okay to return 'format' directly as String is immutable
- return format, nil
- }
- s, err := Format(format.Value, args[1:]...)
- if err != nil {
- return nil, err
- }
- return &String{Value: s}, nil
- }
- func builtinCopy(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- return args[0].Copy(), nil
- }
- func builtinString(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*String); ok {
- return args[0], nil
- }
- v, ok := ToString(args[0])
- if ok {
- if len(v) > MaxStringLen {
- return nil, ErrStringLimit
- }
- return &String{Value: v}, nil
- }
- if argsLen == 2 {
- return args[1], nil
- }
- return UndefinedValue, nil
- }
- func builtinInt(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Int); ok {
- return args[0], nil
- }
- v, ok := ToInt64(args[0])
- if ok {
- return &Int{Value: v}, nil
- }
- if argsLen == 2 {
- return args[1], nil
- }
- return UndefinedValue, nil
- }
- func builtinFloat(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Float); ok {
- return args[0], nil
- }
- v, ok := ToFloat64(args[0])
- if ok {
- return &Float{Value: v}, nil
- }
- if argsLen == 2 {
- return args[1], nil
- }
- return UndefinedValue, nil
- }
- func builtinBool(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Bool); ok {
- return args[0], nil
- }
- v, ok := ToBool(args[0])
- if ok {
- if v {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- return UndefinedValue, nil
- }
- func builtinChar(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Char); ok {
- return args[0], nil
- }
- v, ok := ToRune(args[0])
- if ok {
- return &Char{Value: v}, nil
- }
- if argsLen == 2 {
- return args[1], nil
- }
- return UndefinedValue, nil
- }
- func builtinBytes(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
- // bytes(N) => create a new bytes with given size N
- if n, ok := args[0].(*Int); ok {
- if n.Value > int64(MaxBytesLen) {
- return nil, ErrBytesLimit
- }
- return &Bytes{Value: make([]byte, int(n.Value))}, nil
- }
- v, ok := ToByteSlice(args[0])
- if ok {
- if len(v) > MaxBytesLen {
- return nil, ErrBytesLimit
- }
- return &Bytes{Value: v}, nil
- }
- if argsLen == 2 {
- return args[1], nil
- }
- return UndefinedValue, nil
- }
- func builtinTime(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
- if _, ok := args[0].(*Time); ok {
- return args[0], nil
- }
- v, ok := ToTime(args[0])
- if ok {
- return &Time{Value: v}, nil
- }
- if argsLen == 2 {
- return args[1], nil
- }
- return UndefinedValue, nil
- }
- // append(arr, items...)
- func builtinAppend(args ...Object) (Object, error) {
- if len(args) < 2 {
- return nil, ErrWrongNumArguments
- }
- switch arg := args[0].(type) {
- case *Array:
- return &Array{Value: append(arg.Value, args[1:]...)}, nil
- case *ImmutableArray:
- return &Array{Value: append(arg.Value, args[1:]...)}, nil
- default:
- return nil, ErrInvalidArgumentType{
- Name: "first",
- Expected: "array",
- Found: arg.TypeName(),
- }
- }
- }
- // builtinDelete deletes Map keys
- // usage: delete(map, "key")
- // key must be a string
- func builtinDelete(args ...Object) (Object, error) {
- argsLen := len(args)
- if argsLen != 2 {
- return nil, ErrWrongNumArguments
- }
- switch arg := args[0].(type) {
- case *Map:
- if key, ok := args[1].(*String); ok {
- delete(arg.Value, key.Value)
- return UndefinedValue, nil
- }
- return nil, ErrInvalidArgumentType{
- Name: "second",
- Expected: "string",
- Found: args[1].TypeName(),
- }
- default:
- return nil, ErrInvalidArgumentType{
- Name: "first",
- Expected: "map",
- Found: arg.TypeName(),
- }
- }
- }
- // builtinSplice deletes and changes given Array, returns deleted items.
- // usage:
- // deleted_items := splice(array[,start[,delete_count[,item1[,item2[,...]]]])
- func builtinSplice(args ...Object) (Object, error) {
- argsLen := len(args)
- if argsLen == 0 {
- return nil, ErrWrongNumArguments
- }
- array, ok := args[0].(*Array)
- if !ok {
- return nil, ErrInvalidArgumentType{
- Name: "first",
- Expected: "array",
- Found: args[0].TypeName(),
- }
- }
- arrayLen := len(array.Value)
- var startIdx int
- if argsLen > 1 {
- arg1, ok := args[1].(*Int)
- if !ok {
- return nil, ErrInvalidArgumentType{
- Name: "second",
- Expected: "int",
- Found: args[1].TypeName(),
- }
- }
- startIdx = int(arg1.Value)
- if startIdx < 0 || startIdx > arrayLen {
- return nil, ErrIndexOutOfBounds
- }
- }
- delCount := len(array.Value)
- if argsLen > 2 {
- arg2, ok := args[2].(*Int)
- if !ok {
- return nil, ErrInvalidArgumentType{
- Name: "third",
- Expected: "int",
- Found: args[2].TypeName(),
- }
- }
- delCount = int(arg2.Value)
- if delCount < 0 {
- return nil, ErrIndexOutOfBounds
- }
- }
- // if count of to be deleted items is bigger than expected, truncate it
- if startIdx+delCount > arrayLen {
- delCount = arrayLen - startIdx
- }
- // delete items
- endIdx := startIdx + delCount
- deleted := append([]Object{}, array.Value[startIdx:endIdx]...)
- head := array.Value[:startIdx]
- var items []Object
- if argsLen > 3 {
- items = make([]Object, 0, argsLen-3)
- for i := 3; i < argsLen; i++ {
- items = append(items, args[i])
- }
- }
- items = append(items, array.Value[endIdx:]...)
- array.Value = append(head, items...)
- // return deleted items
- return &Array{Value: deleted}, nil
- }