summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/d5/tengo/v2/tengo.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/d5/tengo/v2/tengo.go')
-rw-r--r--vendor/github.com/d5/tengo/v2/tengo.go306
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)
+}