diff options
author | Wim <wim@42.be> | 2020-01-09 21:52:19 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-09 21:52:19 +0100 |
commit | 9d84d6dd643c4017074e81465671cd9b25f9539a (patch) | |
tree | 8a767f91d655a6cf21d476e4fb7aa6fd8a952df8 /vendor/github.com/d5/tengo/v2/tengo.go | |
parent | 0f708daf2d14dcca261ef98cc698a1b1f2a6aa74 (diff) | |
download | matterbridge-msglm-9d84d6dd643c4017074e81465671cd9b25f9539a.tar.gz matterbridge-msglm-9d84d6dd643c4017074e81465671cd9b25f9539a.tar.bz2 matterbridge-msglm-9d84d6dd643c4017074e81465671cd9b25f9539a.zip |
Update to tengo v2 (#976)
Diffstat (limited to 'vendor/github.com/d5/tengo/v2/tengo.go')
-rw-r--r-- | vendor/github.com/d5/tengo/v2/tengo.go | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/vendor/github.com/d5/tengo/v2/tengo.go b/vendor/github.com/d5/tengo/v2/tengo.go new file mode 100644 index 00000000..098a1970 --- /dev/null +++ b/vendor/github.com/d5/tengo/v2/tengo.go @@ -0,0 +1,306 @@ +package tengo + +import ( + "errors" + "fmt" + "strconv" + "time" +) + +var ( + // MaxStringLen is the maximum byte-length for string value. Note this + // limit applies to all compiler/VM instances in the process. + MaxStringLen = 2147483647 + + // MaxBytesLen is the maximum length for bytes value. Note this limit + // applies to all compiler/VM instances in the process. + MaxBytesLen = 2147483647 +) + +const ( + // GlobalsSize is the maximum number of global variables for a VM. + GlobalsSize = 1024 + + // StackSize is the maximum stack size for a VM. + StackSize = 2048 + + // MaxFrames is the maximum number of function frames for a VM. + MaxFrames = 1024 +) + +// CallableFunc is a function signature for the callable functions. +type CallableFunc = func(args ...Object) (ret Object, err error) + +// CountObjects returns the number of objects that a given object o contains. +// For scalar value types, it will always be 1. For compound value types, +// this will include its elements and all of their elements recursively. +func CountObjects(o Object) (c int) { + c = 1 + switch o := o.(type) { + case *Array: + for _, v := range o.Value { + c += CountObjects(v) + } + case *ImmutableArray: + for _, v := range o.Value { + c += CountObjects(v) + } + case *Map: + for _, v := range o.Value { + c += CountObjects(v) + } + case *ImmutableMap: + for _, v := range o.Value { + c += CountObjects(v) + } + case *Error: + c += CountObjects(o.Value) + } + return +} + +// ToString will try to convert object o to string value. +func ToString(o Object) (v string, ok bool) { + if o == UndefinedValue { + return + } + ok = true + if str, isStr := o.(*String); isStr { + v = str.Value + } else { + v = o.String() + } + return +} + +// ToInt will try to convert object o to int value. +func ToInt(o Object) (v int, ok bool) { + switch o := o.(type) { + case *Int: + v = int(o.Value) + ok = true + case *Float: + v = int(o.Value) + ok = true + case *Char: + v = int(o.Value) + ok = true + case *Bool: + if o == TrueValue { + v = 1 + } + ok = true + case *String: + c, err := strconv.ParseInt(o.Value, 10, 64) + if err == nil { + v = int(c) + ok = true + } + } + return +} + +// ToInt64 will try to convert object o to int64 value. +func ToInt64(o Object) (v int64, ok bool) { + switch o := o.(type) { + case *Int: + v = o.Value + ok = true + case *Float: + v = int64(o.Value) + ok = true + case *Char: + v = int64(o.Value) + ok = true + case *Bool: + if o == TrueValue { + v = 1 + } + ok = true + case *String: + c, err := strconv.ParseInt(o.Value, 10, 64) + if err == nil { + v = c + ok = true + } + } + return +} + +// ToFloat64 will try to convert object o to float64 value. +func ToFloat64(o Object) (v float64, ok bool) { + switch o := o.(type) { + case *Int: + v = float64(o.Value) + ok = true + case *Float: + v = o.Value + ok = true + case *String: + c, err := strconv.ParseFloat(o.Value, 64) + if err == nil { + v = c + ok = true + } + } + return +} + +// ToBool will try to convert object o to bool value. +func ToBool(o Object) (v bool, ok bool) { + ok = true + v = !o.IsFalsy() + return +} + +// ToRune will try to convert object o to rune value. +func ToRune(o Object) (v rune, ok bool) { + switch o := o.(type) { + case *Int: + v = rune(o.Value) + ok = true + case *Char: + v = o.Value + ok = true + } + return +} + +// ToByteSlice will try to convert object o to []byte value. +func ToByteSlice(o Object) (v []byte, ok bool) { + switch o := o.(type) { + case *Bytes: + v = o.Value + ok = true + case *String: + v = []byte(o.Value) + ok = true + } + return +} + +// ToTime will try to convert object o to time.Time value. +func ToTime(o Object) (v time.Time, ok bool) { + switch o := o.(type) { + case *Time: + v = o.Value + ok = true + case *Int: + v = time.Unix(o.Value, 0) + ok = true + } + return +} + +// ToInterface attempts to convert an object o to an interface{} value +func ToInterface(o Object) (res interface{}) { + switch o := o.(type) { + case *Int: + res = o.Value + case *String: + res = o.Value + case *Float: + res = o.Value + case *Bool: + res = o == TrueValue + case *Char: + res = o.Value + case *Bytes: + res = o.Value + case *Array: + res = make([]interface{}, len(o.Value)) + for i, val := range o.Value { + res.([]interface{})[i] = ToInterface(val) + } + case *ImmutableArray: + res = make([]interface{}, len(o.Value)) + for i, val := range o.Value { + res.([]interface{})[i] = ToInterface(val) + } + case *Map: + res = make(map[string]interface{}) + for key, v := range o.Value { + res.(map[string]interface{})[key] = ToInterface(v) + } + case *ImmutableMap: + res = make(map[string]interface{}) + for key, v := range o.Value { + res.(map[string]interface{})[key] = ToInterface(v) + } + case *Time: + res = o.Value + case *Error: + res = errors.New(o.String()) + case *Undefined: + res = nil + case Object: + return o + } + return +} + +// FromInterface will attempt to convert an interface{} v to a Tengo Object +func FromInterface(v interface{}) (Object, error) { + switch v := v.(type) { + case nil: + return UndefinedValue, nil + case string: + if len(v) > MaxStringLen { + return nil, ErrStringLimit + } + return &String{Value: v}, nil + case int64: + return &Int{Value: v}, nil + case int: + return &Int{Value: int64(v)}, nil + case bool: + if v { + return TrueValue, nil + } + return FalseValue, nil + case rune: + return &Char{Value: v}, nil + case byte: + return &Char{Value: rune(v)}, nil + case float64: + return &Float{Value: v}, nil + case []byte: + if len(v) > MaxBytesLen { + return nil, ErrBytesLimit + } + return &Bytes{Value: v}, nil + case error: + return &Error{Value: &String{Value: v.Error()}}, nil + case map[string]Object: + return &Map{Value: v}, nil + case map[string]interface{}: + kv := make(map[string]Object) + for vk, vv := range v { + vo, err := FromInterface(vv) + if err != nil { + return nil, err + } + kv[vk] = vo + } + return &Map{Value: kv}, nil + case []Object: + return &Array{Value: v}, nil + case []interface{}: + arr := make([]Object, len(v)) + for i, e := range v { + vo, err := FromInterface(e) + if err != nil { + return nil, err + } + arr[i] = vo + } + return &Array{Value: arr}, nil + case time.Time: + return &Time{Value: v}, nil + case Object: + return v, nil + case CallableFunc: + return &UserFunction{Value: v}, nil + } + return nil, fmt.Errorf("cannot convert to object: %T", v) +} |