4
0
mirror of https://github.com/cwinfo/matterbridge.git synced 2025-06-27 19:19:24 +00:00

Add scripting (tengo) support for every incoming message (#731)

TengoModifyMessage allows you to specify the location of a tengo (https://github.com/d5/tengo/) script.
This script will receive every incoming message and can be used to modify the Username and the Text of that message.
The script will have the following global variables:
to modify: msgUsername and msgText
to read: msgChannel and msgAccount

The script is reloaded on every message, so you can modify the script on the fly.

Example script can be found in https://github.com/42wim/matterbridge/tree/master/gateway/bench.tengo
and https://github.com/42wim/matterbridge/tree/master/contrib/example.tengo

The example below will check if the text contains blah and if so, it'll replace the text and the username of that message.
text := import("text")
if text.re_match("blah",msgText) {
    msgText="replaced by this"
    msgUsername="fakeuser"
}

More information about tengo on: https://github.com/d5/tengo/blob/master/docs/tutorial.md and
https://github.com/d5/tengo/blob/master/docs/stdlib.md
This commit is contained in:
Wim
2019-02-23 16:39:44 +01:00
committed by GitHub
parent 3190703dc8
commit 1bb39eba87
147 changed files with 14201 additions and 0 deletions

130
vendor/github.com/d5/tengo/objects/array.go generated vendored Normal file
View File

@ -0,0 +1,130 @@
package objects
import (
"fmt"
"strings"
"github.com/d5/tengo/compiler/token"
)
// Array represents an array of objects.
type Array struct {
Value []Object
}
// TypeName returns the name of the type.
func (o *Array) TypeName() string {
return "array"
}
func (o *Array) String() string {
var elements []string
for _, e := range o.Value {
elements = append(elements, e.String())
}
return fmt.Sprintf("[%s]", strings.Join(elements, ", "))
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Array) BinaryOp(op token.Token, rhs Object) (Object, error) {
if rhs, ok := rhs.(*Array); ok {
switch op {
case token.Add:
if len(rhs.Value) == 0 {
return o, nil
}
return &Array{Value: append(o.Value, rhs.Value...)}, nil
}
}
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Array) Copy() Object {
var c []Object
for _, elem := range o.Value {
c = append(c, elem.Copy())
}
return &Array{Value: c}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Array) IsFalsy() bool {
return len(o.Value) == 0
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Array) Equals(x Object) bool {
var xVal []Object
switch x := x.(type) {
case *Array:
xVal = x.Value
case *ImmutableArray:
xVal = x.Value
default:
return false
}
if len(o.Value) != len(xVal) {
return false
}
for i, e := range o.Value {
if !e.Equals(xVal[i]) {
return false
}
}
return true
}
// IndexGet returns an element at a given index.
func (o *Array) IndexGet(index Object) (res Object, err error) {
intIdx, ok := index.(*Int)
if !ok {
err = ErrInvalidIndexType
return
}
idxVal := int(intIdx.Value)
if idxVal < 0 || idxVal >= len(o.Value) {
res = UndefinedValue
return
}
res = o.Value[idxVal]
return
}
// IndexSet sets an element at a given index.
func (o *Array) IndexSet(index, value Object) (err error) {
intIdx, ok := ToInt(index)
if !ok {
err = ErrInvalidIndexType
return
}
if intIdx < 0 || intIdx >= len(o.Value) {
err = ErrIndexOutOfBounds
return
}
o.Value[intIdx] = value
return nil
}
// Iterate creates an array iterator.
func (o *Array) Iterate() Iterator {
return &ArrayIterator{
v: o.Value,
l: len(o.Value),
}
}

57
vendor/github.com/d5/tengo/objects/array_iterator.go generated vendored Normal file
View File

@ -0,0 +1,57 @@
package objects
import "github.com/d5/tengo/compiler/token"
// ArrayIterator is an iterator for an array.
type ArrayIterator struct {
v []Object
i int
l int
}
// TypeName returns the name of the type.
func (i *ArrayIterator) TypeName() string {
return "array-iterator"
}
func (i *ArrayIterator) String() string {
return "<array-iterator>"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (i *ArrayIterator) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// IsFalsy returns true if the value of the type is falsy.
func (i *ArrayIterator) IsFalsy() bool {
return true
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (i *ArrayIterator) Equals(Object) bool {
return false
}
// Copy returns a copy of the type.
func (i *ArrayIterator) Copy() Object {
return &ArrayIterator{v: i.v, i: i.i, l: i.l}
}
// Next returns true if there are more elements to iterate.
func (i *ArrayIterator) Next() bool {
i.i++
return i.i <= i.l
}
// Key returns the key or index value of the current element.
func (i *ArrayIterator) Key() Object {
return &Int{Value: int64(i.i - 1)}
}
// Value returns the value of the current element.
func (i *ArrayIterator) Value() Object {
return i.v[i.i-1]
}

64
vendor/github.com/d5/tengo/objects/bool.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
package objects
import (
"github.com/d5/tengo/compiler/token"
)
// Bool represents a boolean value.
type Bool struct {
// this is intentionally non-public to force using objects.TrueValue and FalseValue always
value bool
}
func (o *Bool) String() string {
if o.value {
return "true"
}
return "false"
}
// TypeName returns the name of the type.
func (o *Bool) TypeName() string {
return "bool"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Bool) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Bool) Copy() Object {
return o
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Bool) IsFalsy() bool {
return !o.value
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Bool) Equals(x Object) bool {
return o == x
}
// GobDecode decodes bool value from input bytes.
func (o *Bool) GobDecode(b []byte) (err error) {
o.value = b[0] == 1
return
}
// GobEncode encodes bool values into bytes.
func (o *Bool) GobEncode() (b []byte, err error) {
if o.value {
b = []byte{1}
} else {
b = []byte{0}
}
return
}

37
vendor/github.com/d5/tengo/objects/break.go generated vendored Normal file
View File

@ -0,0 +1,37 @@
package objects
import "github.com/d5/tengo/compiler/token"
// Break represents a break statement.
type Break struct{}
// TypeName returns the name of the type.
func (o *Break) TypeName() string {
return "break"
}
func (o *Break) String() string {
return "<break>"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Break) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Break) Copy() Object {
return &Break{}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Break) IsFalsy() bool {
return false
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Break) Equals(x Object) bool {
return false
}

21
vendor/github.com/d5/tengo/objects/builtin_append.go generated vendored Normal file
View File

@ -0,0 +1,21 @@
package objects
// 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(),
}
}
}

155
vendor/github.com/d5/tengo/objects/builtin_convert.go generated vendored Normal file
View File

@ -0,0 +1,155 @@
package objects
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 {
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 {
return &Bytes{Value: make([]byte, int(n.Value))}, nil
}
v, ok := ToByteSlice(args[0])
if ok {
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
}

9
vendor/github.com/d5/tengo/objects/builtin_copy.go generated vendored Normal file
View File

@ -0,0 +1,9 @@
package objects
func builtinCopy(args ...Object) (Object, error) {
if len(args) != 1 {
return nil, ErrWrongNumArguments
}
return args[0].Copy(), nil
}

47
vendor/github.com/d5/tengo/objects/builtin_function.go generated vendored Normal file
View File

@ -0,0 +1,47 @@
package objects
import (
"github.com/d5/tengo/compiler/token"
)
// BuiltinFunction represents a builtin function.
type BuiltinFunction struct {
Name string
Value CallableFunc
}
// TypeName returns the name of the type.
func (o *BuiltinFunction) TypeName() string {
return "builtin-function:" + o.Name
}
func (o *BuiltinFunction) String() string {
return "<builtin-function>"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *BuiltinFunction) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *BuiltinFunction) Copy() Object {
return &BuiltinFunction{Value: o.Value}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *BuiltinFunction) IsFalsy() bool {
return false
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *BuiltinFunction) Equals(x Object) bool {
return false
}
// Call executes a builtin function.
func (o *BuiltinFunction) Call(args ...Object) (Object, error) {
return o.Value(args...)
}

54
vendor/github.com/d5/tengo/objects/builtin_json.go generated vendored Normal file
View File

@ -0,0 +1,54 @@
package objects
import (
"encoding/json"
)
// to_json(v object) => bytes
func builtinToJSON(args ...Object) (Object, error) {
if len(args) != 1 {
return nil, ErrWrongNumArguments
}
res, err := json.Marshal(objectToInterface(args[0]))
if err != nil {
return &Error{Value: &String{Value: err.Error()}}, nil
}
return &Bytes{Value: res}, nil
}
// from_json(data string/bytes) => object
func builtinFromJSON(args ...Object) (Object, error) {
if len(args) != 1 {
return nil, ErrWrongNumArguments
}
var target interface{}
switch o := args[0].(type) {
case *Bytes:
err := json.Unmarshal(o.Value, &target)
if err != nil {
return &Error{Value: &String{Value: err.Error()}}, nil
}
case *String:
err := json.Unmarshal([]byte(o.Value), &target)
if err != nil {
return &Error{Value: &String{Value: err.Error()}}, nil
}
default:
return nil, ErrInvalidArgumentType{
Name: "first",
Expected: "bytes/string",
Found: args[0].TypeName(),
}
}
res, err := FromInterface(target)
if err != nil {
return nil, err
}
return res, nil
}

29
vendor/github.com/d5/tengo/objects/builtin_len.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
package objects
// 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(),
}
}
}

75
vendor/github.com/d5/tengo/objects/builtin_print.go generated vendored Normal file
View File

@ -0,0 +1,75 @@
package objects
import (
"fmt"
)
// print(args...)
func builtinPrint(args ...Object) (Object, error) {
for _, arg := range args {
if str, ok := arg.(*String); ok {
fmt.Println(str.Value)
} else {
fmt.Println(arg.String())
}
}
return nil, nil
}
// printf("format", args...)
func builtinPrintf(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 {
fmt.Print(format)
return nil, nil
}
formatArgs := make([]interface{}, numArgs-1, numArgs-1)
for idx, arg := range args[1:] {
formatArgs[idx] = objectToInterface(arg)
}
fmt.Printf(format.Value, formatArgs...)
return nil, nil
}
// sprintf("format", args...)
func builtinSprintf(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 {
return format, nil // okay to return 'format' directly as String is immutable
}
formatArgs := make([]interface{}, numArgs-1, numArgs-1)
for idx, arg := range args[1:] {
formatArgs[idx] = objectToInterface(arg)
}
return &String{Value: fmt.Sprintf(format.Value, formatArgs...)}, nil
}

9
vendor/github.com/d5/tengo/objects/builtin_type.go generated vendored Normal file
View File

@ -0,0 +1,9 @@
package objects
func builtinTypeName(args ...Object) (Object, error) {
if len(args) != 1 {
return nil, ErrWrongNumArguments
}
return &String{Value: args[0].TypeName()}, nil
}

View File

@ -0,0 +1,183 @@
package objects
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, *Closure:
return TrueValue, nil
}
return FalseValue, nil
}
func builtinIsCallable(args ...Object) (Object, error) {
if len(args) != 1 {
return nil, ErrWrongNumArguments
}
switch args[0].(type) {
case *CompiledFunction, *Closure, Callable: // BuiltinFunction is Callable
return TrueValue, nil
}
return FalseValue, nil
}

135
vendor/github.com/d5/tengo/objects/builtins.go generated vendored Normal file
View File

@ -0,0 +1,135 @@
package objects
// NamedBuiltinFunc is a named builtin function.
type NamedBuiltinFunc struct {
Name string
Func CallableFunc
}
// Builtins contains all default builtin functions.
var Builtins = []NamedBuiltinFunc{
{
Name: "print",
Func: builtinPrint,
},
{
Name: "printf",
Func: builtinPrintf,
},
{
Name: "sprintf",
Func: builtinSprintf,
},
{
Name: "len",
Func: builtinLen,
},
{
Name: "copy",
Func: builtinCopy,
},
{
Name: "append",
Func: builtinAppend,
},
{
Name: "string",
Func: builtinString,
},
{
Name: "int",
Func: builtinInt,
},
{
Name: "bool",
Func: builtinBool,
},
{
Name: "float",
Func: builtinFloat,
},
{
Name: "char",
Func: builtinChar,
},
{
Name: "bytes",
Func: builtinBytes,
},
{
Name: "time",
Func: builtinTime,
},
{
Name: "is_int",
Func: builtinIsInt,
},
{
Name: "is_float",
Func: builtinIsFloat,
},
{
Name: "is_string",
Func: builtinIsString,
},
{
Name: "is_bool",
Func: builtinIsBool,
},
{
Name: "is_char",
Func: builtinIsChar,
},
{
Name: "is_bytes",
Func: builtinIsBytes,
},
{
Name: "is_array",
Func: builtinIsArray,
},
{
Name: "is_immutable_array",
Func: builtinIsImmutableArray,
},
{
Name: "is_map",
Func: builtinIsMap,
},
{
Name: "is_immutable_map",
Func: builtinIsImmutableMap,
},
{
Name: "is_time",
Func: builtinIsTime,
},
{
Name: "is_error",
Func: builtinIsError,
},
{
Name: "is_undefined",
Func: builtinIsUndefined,
},
{
Name: "is_function",
Func: builtinIsFunction,
},
{
Name: "is_callable",
Func: builtinIsCallable,
},
{
Name: "to_json",
Func: builtinToJSON,
},
{
Name: "from_json",
Func: builtinFromJSON,
},
{
Name: "type_name",
Func: builtinTypeName,
},
}

76
vendor/github.com/d5/tengo/objects/bytes.go generated vendored Normal file
View File

@ -0,0 +1,76 @@
package objects
import (
"bytes"
"github.com/d5/tengo/compiler/token"
)
// Bytes represents a byte array.
type Bytes struct {
Value []byte
}
func (o *Bytes) String() string {
return string(o.Value)
}
// TypeName returns the name of the type.
func (o *Bytes) TypeName() string {
return "bytes"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Bytes) BinaryOp(op token.Token, rhs Object) (Object, error) {
switch op {
case token.Add:
switch rhs := rhs.(type) {
case *Bytes:
return &Bytes{Value: append(o.Value, rhs.Value...)}, nil
}
}
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Bytes) Copy() Object {
return &Bytes{Value: append([]byte{}, o.Value...)}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Bytes) IsFalsy() bool {
return len(o.Value) == 0
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Bytes) Equals(x Object) bool {
t, ok := x.(*Bytes)
if !ok {
return false
}
return bytes.Compare(o.Value, t.Value) == 0
}
// IndexGet returns an element (as Int) at a given index.
func (o *Bytes) IndexGet(index Object) (res Object, err error) {
intIdx, ok := index.(*Int)
if !ok {
err = ErrInvalidIndexType
return
}
idxVal := int(intIdx.Value)
if idxVal < 0 || idxVal >= len(o.Value) {
res = UndefinedValue
return
}
res = &Int{Value: int64(o.Value[idxVal])}
return
}

9
vendor/github.com/d5/tengo/objects/callable.go generated vendored Normal file
View File

@ -0,0 +1,9 @@
package objects
// Callable represents an object that can be called like a function.
type Callable interface {
// Call should take an arbitrary number of arguments
// and returns a return value and/or an error,
// which the VM will consider as a run-time error.
Call(args ...Object) (ret Object, err error)
}

4
vendor/github.com/d5/tengo/objects/callable_func.go generated vendored Normal file
View File

@ -0,0 +1,4 @@
package objects
// CallableFunc is a function signature for the callable functions.
type CallableFunc func(args ...Object) (ret Object, err error)

119
vendor/github.com/d5/tengo/objects/char.go generated vendored Normal file
View File

@ -0,0 +1,119 @@
package objects
import (
"github.com/d5/tengo/compiler/token"
)
// Char represents a character value.
type Char struct {
Value rune
}
func (o *Char) String() string {
return string(o.Value)
}
// TypeName returns the name of the type.
func (o *Char) TypeName() string {
return "char"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Char) BinaryOp(op token.Token, rhs Object) (Object, error) {
switch rhs := rhs.(type) {
case *Char:
switch op {
case token.Add:
r := o.Value + rhs.Value
if r == o.Value {
return o, nil
}
return &Char{Value: r}, nil
case token.Sub:
r := o.Value - rhs.Value
if r == o.Value {
return o, nil
}
return &Char{Value: r}, nil
case token.Less:
if o.Value < rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.Greater:
if o.Value > rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.LessEq:
if o.Value <= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.GreaterEq:
if o.Value >= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
}
case *Int:
switch op {
case token.Add:
r := o.Value + rune(rhs.Value)
if r == o.Value {
return o, nil
}
return &Char{Value: r}, nil
case token.Sub:
r := o.Value - rune(rhs.Value)
if r == o.Value {
return o, nil
}
return &Char{Value: r}, nil
case token.Less:
if int64(o.Value) < rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.Greater:
if int64(o.Value) > rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.LessEq:
if int64(o.Value) <= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.GreaterEq:
if int64(o.Value) >= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
}
}
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Char) Copy() Object {
return &Char{Value: o.Value}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Char) IsFalsy() bool {
return o.Value == 0
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Char) Equals(x Object) bool {
t, ok := x.(*Char)
if !ok {
return false
}
return o.Value == t.Value
}

45
vendor/github.com/d5/tengo/objects/closure.go generated vendored Normal file
View File

@ -0,0 +1,45 @@
package objects
import (
"github.com/d5/tengo/compiler/token"
)
// Closure represents a function closure.
type Closure struct {
Fn *CompiledFunction
Free []*Object
}
// TypeName returns the name of the type.
func (o *Closure) TypeName() string {
return "closure"
}
func (o *Closure) String() string {
return "<closure>"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Closure) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Closure) Copy() Object {
return &Closure{
Fn: o.Fn.Copy().(*CompiledFunction),
Free: append([]*Object{}, o.Free...), // DO NOT Copy() of elements; these are variable pointers
}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Closure) IsFalsy() bool {
return false
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Closure) Equals(x Object) bool {
return false
}

View File

@ -0,0 +1,49 @@
package objects
import (
"github.com/d5/tengo/compiler/source"
"github.com/d5/tengo/compiler/token"
)
// CompiledFunction represents a compiled function.
type CompiledFunction struct {
Instructions []byte
NumLocals int // number of local variables (including function parameters)
NumParameters int
SourceMap map[int]source.Pos
}
// TypeName returns the name of the type.
func (o *CompiledFunction) TypeName() string {
return "compiled-function"
}
func (o *CompiledFunction) String() string {
return "<compiled-function>"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *CompiledFunction) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *CompiledFunction) Copy() Object {
return &CompiledFunction{
Instructions: append([]byte{}, o.Instructions...),
NumLocals: o.NumLocals,
NumParameters: o.NumParameters,
}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *CompiledFunction) IsFalsy() bool {
return false
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *CompiledFunction) Equals(x Object) bool {
return false
}

38
vendor/github.com/d5/tengo/objects/continue.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
package objects
import "github.com/d5/tengo/compiler/token"
// Continue represents a continue statement.
type Continue struct {
}
// TypeName returns the name of the type.
func (o *Continue) TypeName() string {
return "continue"
}
func (o *Continue) String() string {
return "<continue>"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Continue) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Continue) Copy() Object {
return &Continue{}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Continue) IsFalsy() bool {
return false
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Continue) Equals(x Object) bool {
return false
}

249
vendor/github.com/d5/tengo/objects/conversion.go generated vendored Normal file
View File

@ -0,0 +1,249 @@
package objects
import (
"fmt"
"strconv"
"time"
)
// ToString will try to convert object o to string value.
func ToString(o Object) (v string, ok bool) {
if o == UndefinedValue {
//ok = false
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
}
}
//ok = false
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
}
}
//ok = false
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
}
}
//ok = false
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 = rune(o.Value)
ok = true
}
//ok = false
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
}
//ok = false
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
}
//ok = false
return
}
// objectToInterface attempts to convert an object o to an interface{} value
func objectToInterface(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] = objectToInterface(val)
}
case *Map:
res = make(map[string]interface{})
for key, v := range o.Value {
res.(map[string]interface{})[key] = objectToInterface(v)
}
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:
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:
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), 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
}
return nil, fmt.Errorf("cannot convert to object: %T", v)
}

47
vendor/github.com/d5/tengo/objects/error.go generated vendored Normal file
View File

@ -0,0 +1,47 @@
package objects
import (
"fmt"
"github.com/d5/tengo/compiler/token"
)
// Error represents a string value.
type Error struct {
Value Object
}
// TypeName returns the name of the type.
func (o *Error) TypeName() string {
return "error"
}
func (o *Error) String() string {
if o.Value != nil {
return fmt.Sprintf("error: %s", o.Value.String())
}
return "error"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Error) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Error) IsFalsy() bool {
return true // error is always false.
}
// Copy returns a copy of the type.
func (o *Error) Copy() Object {
return &Error{Value: o.Value.Copy()}
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Error) Equals(x Object) bool {
return o == x // pointer equality
}

32
vendor/github.com/d5/tengo/objects/errors.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
package objects
import (
"errors"
"fmt"
)
// ErrIndexOutOfBounds is an error where a given index is out of the bounds.
var ErrIndexOutOfBounds = errors.New("index out of bounds")
// ErrInvalidIndexType represents an invalid index type.
var ErrInvalidIndexType = errors.New("invalid index type")
// ErrInvalidIndexValueType represents an invalid index value type.
var ErrInvalidIndexValueType = errors.New("invalid index value type")
// ErrInvalidOperator represents an error for invalid operator usage.
var ErrInvalidOperator = errors.New("invalid operator")
// ErrWrongNumArguments represents a wrong number of arguments error.
var ErrWrongNumArguments = errors.New("wrong number of arguments")
// ErrInvalidArgumentType represents an invalid argument value type error.
type ErrInvalidArgumentType struct {
Name string
Expected string
Found string
}
func (e ErrInvalidArgumentType) Error() string {
return fmt.Sprintf("invalid type for argument '%s': expected %s, found %s", e.Name, e.Expected, e.Found)
}

146
vendor/github.com/d5/tengo/objects/float.go generated vendored Normal file
View File

@ -0,0 +1,146 @@
package objects
import (
"math"
"strconv"
"github.com/d5/tengo/compiler/token"
)
// Float represents a floating point number value.
type Float struct {
Value float64
}
func (o *Float) String() string {
return strconv.FormatFloat(o.Value, 'f', -1, 64)
}
// TypeName returns the name of the type.
func (o *Float) TypeName() string {
return "float"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Float) BinaryOp(op token.Token, rhs Object) (Object, error) {
switch rhs := rhs.(type) {
case *Float:
switch op {
case token.Add:
r := o.Value + rhs.Value
if r == o.Value {
return o, nil
}
return &Float{Value: r}, nil
case token.Sub:
r := o.Value - rhs.Value
if r == o.Value {
return o, nil
}
return &Float{Value: r}, nil
case token.Mul:
r := o.Value * rhs.Value
if r == o.Value {
return o, nil
}
return &Float{Value: r}, nil
case token.Quo:
r := o.Value / rhs.Value
if r == o.Value {
return o, nil
}
return &Float{Value: r}, nil
case token.Less:
if o.Value < rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.Greater:
if o.Value > rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.LessEq:
if o.Value <= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.GreaterEq:
if o.Value >= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
}
case *Int:
switch op {
case token.Add:
r := o.Value + float64(rhs.Value)
if r == o.Value {
return o, nil
}
return &Float{Value: r}, nil
case token.Sub:
r := o.Value - float64(rhs.Value)
if r == o.Value {
return o, nil
}
return &Float{Value: r}, nil
case token.Mul:
r := o.Value * float64(rhs.Value)
if r == o.Value {
return o, nil
}
return &Float{Value: r}, nil
case token.Quo:
r := o.Value / float64(rhs.Value)
if r == o.Value {
return o, nil
}
return &Float{Value: r}, nil
case token.Less:
if o.Value < float64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.Greater:
if o.Value > float64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.LessEq:
if o.Value <= float64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.GreaterEq:
if o.Value >= float64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
}
}
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Float) Copy() Object {
return &Float{Value: o.Value}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Float) IsFalsy() bool {
return math.IsNaN(o.Value)
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Float) Equals(x Object) bool {
t, ok := x.(*Float)
if !ok {
return false
}
return o.Value == t.Value
}

109
vendor/github.com/d5/tengo/objects/immautable_array.go generated vendored Normal file
View File

@ -0,0 +1,109 @@
package objects
import (
"fmt"
"strings"
"github.com/d5/tengo/compiler/token"
)
// ImmutableArray represents an immutable array of objects.
type ImmutableArray struct {
Value []Object
}
// TypeName returns the name of the type.
func (o *ImmutableArray) TypeName() string {
return "immutable-array"
}
func (o *ImmutableArray) String() string {
var elements []string
for _, e := range o.Value {
elements = append(elements, e.String())
}
return fmt.Sprintf("[%s]", strings.Join(elements, ", "))
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *ImmutableArray) BinaryOp(op token.Token, rhs Object) (Object, error) {
if rhs, ok := rhs.(*ImmutableArray); ok {
switch op {
case token.Add:
return &Array{Value: append(o.Value, rhs.Value...)}, nil
}
}
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *ImmutableArray) Copy() Object {
var c []Object
for _, elem := range o.Value {
c = append(c, elem.Copy())
}
return &Array{Value: c}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *ImmutableArray) IsFalsy() bool {
return len(o.Value) == 0
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *ImmutableArray) Equals(x Object) bool {
var xVal []Object
switch x := x.(type) {
case *Array:
xVal = x.Value
case *ImmutableArray:
xVal = x.Value
default:
return false
}
if len(o.Value) != len(xVal) {
return false
}
for i, e := range o.Value {
if !e.Equals(xVal[i]) {
return false
}
}
return true
}
// IndexGet returns an element at a given index.
func (o *ImmutableArray) IndexGet(index Object) (res Object, err error) {
intIdx, ok := index.(*Int)
if !ok {
err = ErrInvalidIndexType
return
}
idxVal := int(intIdx.Value)
if idxVal < 0 || idxVal >= len(o.Value) {
res = UndefinedValue
return
}
res = o.Value[idxVal]
return
}
// Iterate creates an array iterator.
func (o *ImmutableArray) Iterate() Iterator {
return &ArrayIterator{
v: o.Value,
l: len(o.Value),
}
}

105
vendor/github.com/d5/tengo/objects/immutable_map.go generated vendored Normal file
View File

@ -0,0 +1,105 @@
package objects
import (
"fmt"
"strings"
"github.com/d5/tengo/compiler/token"
)
// ImmutableMap represents an immutable map object.
type ImmutableMap struct {
Value map[string]Object
}
// TypeName returns the name of the type.
func (o *ImmutableMap) TypeName() string {
return "immutable-map"
}
func (o *ImmutableMap) String() string {
var pairs []string
for k, v := range o.Value {
pairs = append(pairs, fmt.Sprintf("%s: %s", k, v.String()))
}
return fmt.Sprintf("{%s}", strings.Join(pairs, ", "))
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *ImmutableMap) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *ImmutableMap) Copy() Object {
c := make(map[string]Object)
for k, v := range o.Value {
c[k] = v.Copy()
}
return &Map{Value: c}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *ImmutableMap) IsFalsy() bool {
return len(o.Value) == 0
}
// IndexGet returns the value for the given key.
func (o *ImmutableMap) IndexGet(index Object) (res Object, err error) {
strIdx, ok := ToString(index)
if !ok {
err = ErrInvalidIndexType
return
}
val, ok := o.Value[strIdx]
if !ok {
val = UndefinedValue
}
return val, nil
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *ImmutableMap) Equals(x Object) bool {
var xVal map[string]Object
switch x := x.(type) {
case *Map:
xVal = x.Value
case *ImmutableMap:
xVal = x.Value
default:
return false
}
if len(o.Value) != len(xVal) {
return false
}
for k, v := range o.Value {
tv := xVal[k]
if !v.Equals(tv) {
return false
}
}
return true
}
// Iterate creates an immutable map iterator.
func (o *ImmutableMap) Iterate() Iterator {
var keys []string
for k := range o.Value {
keys = append(keys, k)
}
return &MapIterator{
v: o.Value,
k: keys,
l: len(keys),
}
}

View File

@ -0,0 +1,9 @@
package objects
// IndexAssignable is an object that can take an index and a value
// on the left-hand side of the assignment statement.
type IndexAssignable interface {
// IndexSet should take an index Object and a value Object.
// If an error is returned, it will be treated as a run-time error.
IndexSet(index, value Object) error
}

9
vendor/github.com/d5/tengo/objects/indexable.go generated vendored Normal file
View File

@ -0,0 +1,9 @@
package objects
// Indexable is an object that can take an index and return an object.
type Indexable interface {
// IndexGet should take an index Object and return a result Object or an error.
// If error is returned, the runtime will treat it as a run-time error and ignore returned value.
// If nil is returned as value, it will be converted to Undefined value by the runtime.
IndexGet(index Object) (value Object, err error)
}

198
vendor/github.com/d5/tengo/objects/int.go generated vendored Normal file
View File

@ -0,0 +1,198 @@
package objects
import (
"strconv"
"github.com/d5/tengo/compiler/token"
)
// Int represents an integer value.
type Int struct {
Value int64
}
func (o *Int) String() string {
return strconv.FormatInt(o.Value, 10)
}
// TypeName returns the name of the type.
func (o *Int) TypeName() string {
return "int"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Int) BinaryOp(op token.Token, rhs Object) (Object, error) {
switch rhs := rhs.(type) {
case *Int:
switch op {
case token.Add:
r := o.Value + rhs.Value
if r == o.Value {
return o, nil
}
return &Int{Value: r}, nil
case token.Sub:
r := o.Value - rhs.Value
if r == o.Value {
return o, nil
}
return &Int{Value: r}, nil
case token.Mul:
r := o.Value * rhs.Value
if r == o.Value {
return o, nil
}
return &Int{Value: r}, nil
case token.Quo:
r := o.Value / rhs.Value
if r == o.Value {
return o, nil
}
return &Int{Value: r}, nil
case token.Rem:
r := o.Value % rhs.Value
if r == o.Value {
return o, nil
}
return &Int{Value: r}, nil
case token.And:
r := o.Value & rhs.Value
if r == o.Value {
return o, nil
}
return &Int{Value: r}, nil
case token.Or:
r := o.Value | rhs.Value
if r == o.Value {
return o, nil
}
return &Int{Value: r}, nil
case token.Xor:
r := o.Value ^ rhs.Value
if r == o.Value {
return o, nil
}
return &Int{Value: r}, nil
case token.AndNot:
r := o.Value &^ rhs.Value
if r == o.Value {
return o, nil
}
return &Int{Value: r}, nil
case token.Shl:
r := o.Value << uint64(rhs.Value)
if r == o.Value {
return o, nil
}
return &Int{Value: r}, nil
case token.Shr:
r := o.Value >> uint64(rhs.Value)
if r == o.Value {
return o, nil
}
return &Int{Value: r}, nil
case token.Less:
if o.Value < rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.Greater:
if o.Value > rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.LessEq:
if o.Value <= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.GreaterEq:
if o.Value >= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
}
case *Float:
switch op {
case token.Add:
return &Float{float64(o.Value) + rhs.Value}, nil
case token.Sub:
return &Float{float64(o.Value) - rhs.Value}, nil
case token.Mul:
return &Float{float64(o.Value) * rhs.Value}, nil
case token.Quo:
return &Float{float64(o.Value) / rhs.Value}, nil
case token.Less:
if float64(o.Value) < rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.Greater:
if float64(o.Value) > rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.LessEq:
if float64(o.Value) <= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.GreaterEq:
if float64(o.Value) >= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
}
case *Char:
switch op {
case token.Add:
return &Char{rune(o.Value) + rhs.Value}, nil
case token.Sub:
return &Char{rune(o.Value) - rhs.Value}, nil
case token.Less:
if o.Value < int64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.Greater:
if o.Value > int64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.LessEq:
if o.Value <= int64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.GreaterEq:
if o.Value >= int64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
}
}
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Int) Copy() Object {
return &Int{Value: o.Value}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Int) IsFalsy() bool {
return o.Value == 0
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Int) Equals(x Object) bool {
t, ok := x.(*Int)
if !ok {
return false
}
return o.Value == t.Value
}

7
vendor/github.com/d5/tengo/objects/iterable.go generated vendored Normal file
View File

@ -0,0 +1,7 @@
package objects
// Iterable represents an object that has iterator.
type Iterable interface {
// Iterate should return an Iterator for the type.
Iterate() Iterator
}

15
vendor/github.com/d5/tengo/objects/iterator.go generated vendored Normal file
View File

@ -0,0 +1,15 @@
package objects
// Iterator represents an iterator for underlying data type.
type Iterator interface {
Object
// Next returns true if there are more elements to iterate.
Next() bool
// Key returns the key or index value of the current element.
Key() Object
// Value returns the value of the current element.
Value() Object
}

118
vendor/github.com/d5/tengo/objects/map.go generated vendored Normal file
View File

@ -0,0 +1,118 @@
package objects
import (
"fmt"
"strings"
"github.com/d5/tengo/compiler/token"
)
// Map represents a map of objects.
type Map struct {
Value map[string]Object
}
// TypeName returns the name of the type.
func (o *Map) TypeName() string {
return "map"
}
func (o *Map) String() string {
var pairs []string
for k, v := range o.Value {
pairs = append(pairs, fmt.Sprintf("%s: %s", k, v.String()))
}
return fmt.Sprintf("{%s}", strings.Join(pairs, ", "))
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Map) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Map) Copy() Object {
c := make(map[string]Object)
for k, v := range o.Value {
c[k] = v.Copy()
}
return &Map{Value: c}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Map) IsFalsy() bool {
return len(o.Value) == 0
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Map) Equals(x Object) bool {
var xVal map[string]Object
switch x := x.(type) {
case *Map:
xVal = x.Value
case *ImmutableMap:
xVal = x.Value
default:
return false
}
if len(o.Value) != len(xVal) {
return false
}
for k, v := range o.Value {
tv := xVal[k]
if !v.Equals(tv) {
return false
}
}
return true
}
// IndexGet returns the value for the given key.
func (o *Map) IndexGet(index Object) (res Object, err error) {
strIdx, ok := index.(*String)
if !ok {
err = ErrInvalidIndexType
return
}
val, ok := o.Value[strIdx.Value]
if !ok {
val = UndefinedValue
}
return val, nil
}
// IndexSet sets the value for the given key.
func (o *Map) IndexSet(index, value Object) (err error) {
strIdx, ok := ToString(index)
if !ok {
err = ErrInvalidIndexType
return
}
o.Value[strIdx] = value
return nil
}
// Iterate creates a map iterator.
func (o *Map) Iterate() Iterator {
var keys []string
for k := range o.Value {
keys = append(keys, k)
}
return &MapIterator{
v: o.Value,
k: keys,
l: len(keys),
}
}

62
vendor/github.com/d5/tengo/objects/map_iterator.go generated vendored Normal file
View File

@ -0,0 +1,62 @@
package objects
import "github.com/d5/tengo/compiler/token"
// MapIterator represents an iterator for the map.
type MapIterator struct {
v map[string]Object
k []string
i int
l int
}
// TypeName returns the name of the type.
func (i *MapIterator) TypeName() string {
return "map-iterator"
}
func (i *MapIterator) String() string {
return "<map-iterator>"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (i *MapIterator) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// IsFalsy returns true if the value of the type is falsy.
func (i *MapIterator) IsFalsy() bool {
return true
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (i *MapIterator) Equals(Object) bool {
return false
}
// Copy returns a copy of the type.
func (i *MapIterator) Copy() Object {
return &MapIterator{v: i.v, k: i.k, i: i.i, l: i.l}
}
// Next returns true if there are more elements to iterate.
func (i *MapIterator) Next() bool {
i.i++
return i.i <= i.l
}
// Key returns the key or index value of the current element.
func (i *MapIterator) Key() Object {
k := i.k[i.i-1]
return &String{Value: k}
}
// Value returns the value of the current element.
func (i *MapIterator) Value() Object {
k := i.k[i.i-1]
return i.v[k]
}

30
vendor/github.com/d5/tengo/objects/object.go generated vendored Normal file
View File

@ -0,0 +1,30 @@
package objects
import "github.com/d5/tengo/compiler/token"
// Object represents an object in the VM.
type Object interface {
// TypeName should return the name of the type.
TypeName() string
// String should return a string representation of the type's value.
String() string
// BinaryOp should return another object that is the result of
// a given binary operator and a right-hand side object.
// If BinaryOp returns an error, the VM will treat it as a run-time error.
BinaryOp(op token.Token, rhs Object) (Object, error)
// IsFalsy should return true if the value of the type
// should be considered as falsy.
IsFalsy() bool
// Equals should return true if the value of the type
// should be considered as equal to the value of another object.
Equals(another Object) bool
// Copy should return a copy of the type (and its value).
// Copy function will be used for copy() builtin function
// which is expected to deep-copy the values generally.
Copy() Object
}

12
vendor/github.com/d5/tengo/objects/objects.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
package objects
var (
// TrueValue represents a true value.
TrueValue Object = &Bool{value: true}
// FalseValue represents a false value.
FalseValue Object = &Bool{value: false}
// UndefinedValue represents an undefined value.
UndefinedValue Object = &Undefined{}
)

39
vendor/github.com/d5/tengo/objects/return_value.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
package objects
import "github.com/d5/tengo/compiler/token"
// ReturnValue represents a value that is being returned.
type ReturnValue struct {
Value Object
}
// TypeName returns the name of the type.
func (o *ReturnValue) TypeName() string {
return "return-value"
}
func (o *ReturnValue) String() string {
return "<return-value>"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *ReturnValue) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *ReturnValue) Copy() Object {
return &ReturnValue{Value: o.Copy()}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *ReturnValue) IsFalsy() bool {
return false
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *ReturnValue) Equals(x Object) bool {
return false
}

95
vendor/github.com/d5/tengo/objects/string.go generated vendored Normal file
View File

@ -0,0 +1,95 @@
package objects
import (
"strconv"
"github.com/d5/tengo/compiler/token"
)
// String represents a string value.
type String struct {
Value string
runeStr []rune
}
// TypeName returns the name of the type.
func (o *String) TypeName() string {
return "string"
}
func (o *String) String() string {
return strconv.Quote(o.Value)
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *String) BinaryOp(op token.Token, rhs Object) (Object, error) {
switch op {
case token.Add:
switch rhs := rhs.(type) {
case *String:
return &String{Value: o.Value + rhs.Value}, nil
default:
return &String{Value: o.Value + rhs.String()}, nil
}
}
return nil, ErrInvalidOperator
}
// IsFalsy returns true if the value of the type is falsy.
func (o *String) IsFalsy() bool {
return len(o.Value) == 0
}
// Copy returns a copy of the type.
func (o *String) Copy() Object {
return &String{Value: o.Value}
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *String) Equals(x Object) bool {
t, ok := x.(*String)
if !ok {
return false
}
return o.Value == t.Value
}
// IndexGet returns a character at a given index.
func (o *String) IndexGet(index Object) (res Object, err error) {
intIdx, ok := index.(*Int)
if !ok {
err = ErrInvalidIndexType
return
}
idxVal := int(intIdx.Value)
if o.runeStr == nil {
o.runeStr = []rune(o.Value)
}
if idxVal < 0 || idxVal >= len(o.runeStr) {
res = UndefinedValue
return
}
res = &Char{Value: o.runeStr[idxVal]}
return
}
// Iterate creates a string iterator.
func (o *String) Iterate() Iterator {
if o.runeStr == nil {
o.runeStr = []rune(o.Value)
}
return &StringIterator{
v: o.runeStr,
l: len(o.runeStr),
}
}

57
vendor/github.com/d5/tengo/objects/string_iterator.go generated vendored Normal file
View File

@ -0,0 +1,57 @@
package objects
import "github.com/d5/tengo/compiler/token"
// StringIterator represents an iterator for a string.
type StringIterator struct {
v []rune
i int
l int
}
// TypeName returns the name of the type.
func (i *StringIterator) TypeName() string {
return "string-iterator"
}
func (i *StringIterator) String() string {
return "<string-iterator>"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (i *StringIterator) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// IsFalsy returns true if the value of the type is falsy.
func (i *StringIterator) IsFalsy() bool {
return true
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (i *StringIterator) Equals(Object) bool {
return false
}
// Copy returns a copy of the type.
func (i *StringIterator) Copy() Object {
return &StringIterator{v: i.v, i: i.i, l: i.l}
}
// Next returns true if there are more elements to iterate.
func (i *StringIterator) Next() bool {
i.i++
return i.i <= i.l
}
// Key returns the key or index value of the current element.
func (i *StringIterator) Key() Object {
return &Int{Value: int64(i.i - 1)}
}
// Value returns the value of the current element.
func (i *StringIterator) Value() Object {
return &Char{Value: i.v[i.i-1]}
}

89
vendor/github.com/d5/tengo/objects/time.go generated vendored Normal file
View File

@ -0,0 +1,89 @@
package objects
import (
"time"
"github.com/d5/tengo/compiler/token"
)
// Time represents a time value.
type Time struct {
Value time.Time
}
func (o *Time) String() string {
return o.Value.String()
}
// TypeName returns the name of the type.
func (o *Time) TypeName() string {
return "time"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Time) BinaryOp(op token.Token, rhs Object) (Object, error) {
switch rhs := rhs.(type) {
case *Int:
switch op {
case token.Add: // time + int => time
if rhs.Value == 0 {
return o, nil
}
return &Time{Value: o.Value.Add(time.Duration(rhs.Value))}, nil
case token.Sub: // time - int => time
if rhs.Value == 0 {
return o, nil
}
return &Time{Value: o.Value.Add(time.Duration(-rhs.Value))}, nil
}
case *Time:
switch op {
case token.Sub: // time - time => int (duration)
return &Int{Value: int64(o.Value.Sub(rhs.Value))}, nil
case token.Less: // time < time => bool
if o.Value.Before(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.Greater:
if o.Value.After(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.LessEq:
if o.Value.Equal(rhs.Value) || o.Value.Before(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.GreaterEq:
if o.Value.Equal(rhs.Value) || o.Value.After(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
}
}
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Time) Copy() Object {
return &Time{Value: o.Value}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Time) IsFalsy() bool {
return o.Value.IsZero()
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Time) Equals(x Object) bool {
t, ok := x.(*Time)
if !ok {
return false
}
return o.Value.Equal(t.Value)
}

42
vendor/github.com/d5/tengo/objects/undefined.go generated vendored Normal file
View File

@ -0,0 +1,42 @@
package objects
import "github.com/d5/tengo/compiler/token"
// Undefined represents an undefined value.
type Undefined struct{}
// TypeName returns the name of the type.
func (o *Undefined) TypeName() string {
return "undefined"
}
func (o *Undefined) String() string {
return "<undefined>"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Undefined) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *Undefined) Copy() Object {
return o
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Undefined) IsFalsy() bool {
return true
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *Undefined) Equals(x Object) bool {
return o == x
}
// IndexGet returns an element at a given index.
func (o *Undefined) IndexGet(index Object) (Object, error) {
return UndefinedValue, nil
}

47
vendor/github.com/d5/tengo/objects/user_function.go generated vendored Normal file
View File

@ -0,0 +1,47 @@
package objects
import (
"github.com/d5/tengo/compiler/token"
)
// UserFunction represents a user function.
type UserFunction struct {
Name string
Value CallableFunc
}
// TypeName returns the name of the type.
func (o *UserFunction) TypeName() string {
return "user-function:" + o.Name
}
func (o *UserFunction) String() string {
return "<user-function>"
}
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *UserFunction) BinaryOp(op token.Token, rhs Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *UserFunction) Copy() Object {
return &UserFunction{Value: o.Value}
}
// IsFalsy returns true if the value of the type is falsy.
func (o *UserFunction) IsFalsy() bool {
return false
}
// Equals returns true if the value of the type
// is equal to the value of another object.
func (o *UserFunction) Equals(x Object) bool {
return false
}
// Call invokes a user function.
func (o *UserFunction) Call(args ...Object) (Object, error) {
return o.Value(args...)
}