123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680 |
- 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
- }
|