summaryrefslogtreecommitdiff
path: root/teleirc/matterbridge/vendor/github.com/d5/tengo/v2/builtins.go
diff options
context:
space:
mode:
Diffstat (limited to 'teleirc/matterbridge/vendor/github.com/d5/tengo/v2/builtins.go')
-rw-r--r--teleirc/matterbridge/vendor/github.com/d5/tengo/v2/builtins.go680
1 files changed, 680 insertions, 0 deletions
diff --git a/teleirc/matterbridge/vendor/github.com/d5/tengo/v2/builtins.go b/teleirc/matterbridge/vendor/github.com/d5/tengo/v2/builtins.go
new file mode 100644
index 0000000..b954d07
--- /dev/null
+++ b/teleirc/matterbridge/vendor/github.com/d5/tengo/v2/builtins.go
@@ -0,0 +1,680 @@
+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,
+ },
+ {
+ Name: "range",
+ Value: builtinRange,
+ },
+}
+
+// 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(),
+ }
+ }
+}
+
+//range(start, stop[, step])
+func builtinRange(args ...Object) (Object, error) {
+ numArgs := len(args)
+ if numArgs < 2 || numArgs > 3 {
+ return nil, ErrWrongNumArguments
+ }
+ var start, stop, step *Int
+
+ for i, arg := range args {
+ v, ok := args[i].(*Int)
+ if !ok {
+ var name string
+ switch i {
+ case 0:
+ name = "start"
+ case 1:
+ name = "stop"
+ case 2:
+ name = "step"
+ }
+
+ return nil, ErrInvalidArgumentType{
+ Name: name,
+ Expected: "int",
+ Found: arg.TypeName(),
+ }
+ }
+ if i == 2 && v.Value <= 0 {
+ return nil, ErrInvalidRangeStep
+ }
+ switch i {
+ case 0:
+ start = v
+ case 1:
+ stop = v
+ case 2:
+ step = v
+ }
+ }
+
+ if step == nil {
+ step = &Int{Value: int64(1)}
+ }
+
+ return buildRange(start.Value, stop.Value, step.Value), nil
+}
+
+func buildRange(start, stop, step int64) *Array {
+ array := &Array{}
+ if start <= stop {
+ for i := start; i < stop; i += step {
+ array.Value = append(array.Value, &Int{
+ Value: i,
+ })
+ }
+ } else {
+ for i := start; i > stop; i -= step {
+ array.Value = append(array.Value, &Int{
+ Value: i,
+ })
+ }
+ }
+ return array
+}
+
+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
+}