Compare commits

...

3 commits

Author SHA1 Message Date
E Sequeira
fe792a9369 value semantics for bools 2022-07-20 16:20:02 +01:00
E Sequeira
9515d2f2c0 fix comment 2022-07-20 10:17:49 +01:00
E Sequeira
e302d643a1 faster BinaryOp 2022-07-20 10:17:49 +01:00
34 changed files with 881 additions and 819 deletions

View file

@ -153,7 +153,7 @@ func builtinIsInt(args ...Object) (Object, error) {
if len(args) != 1 {
return nil, ErrWrongNumArguments
}
if _, ok := args[0].(*Int); ok {
if _, ok := args[0].(Int); ok {
return TrueValue, nil
}
return FalseValue, nil
@ -163,7 +163,7 @@ func builtinIsFloat(args ...Object) (Object, error) {
if len(args) != 1 {
return nil, ErrWrongNumArguments
}
if _, ok := args[0].(*Float); ok {
if _, ok := args[0].(Float); ok {
return TrueValue, nil
}
return FalseValue, nil
@ -173,7 +173,7 @@ func builtinIsBool(args ...Object) (Object, error) {
if len(args) != 1 {
return nil, ErrWrongNumArguments
}
if _, ok := args[0].(*Bool); ok {
if _, ok := args[0].(Bool); ok {
return TrueValue, nil
}
return FalseValue, nil
@ -183,7 +183,7 @@ func builtinIsChar(args ...Object) (Object, error) {
if len(args) != 1 {
return nil, ErrWrongNumArguments
}
if _, ok := args[0].(*Char); ok {
if _, ok := args[0].(Char); ok {
return TrueValue, nil
}
return FalseValue, nil
@ -307,17 +307,17 @@ func builtinLen(args ...Object) (Object, error) {
}
switch arg := args[0].(type) {
case *Array:
return &Int{Value: int64(len(arg.Value))}, nil
return Int{Value: int64(len(arg.Value))}, nil
case *ImmutableArray:
return &Int{Value: int64(len(arg.Value))}, nil
return Int{Value: int64(len(arg.Value))}, nil
case *String:
return &Int{Value: int64(len(arg.Value))}, nil
return Int{Value: int64(len(arg.Value))}, nil
case *Bytes:
return &Int{Value: int64(len(arg.Value))}, nil
return Int{Value: int64(len(arg.Value))}, nil
case *Map:
return &Int{Value: int64(len(arg.Value))}, nil
return Int{Value: int64(len(arg.Value))}, nil
case *ImmutableMap:
return &Int{Value: int64(len(arg.Value))}, nil
return Int{Value: int64(len(arg.Value))}, nil
default:
return nil, ErrInvalidArgumentType{
Name: "first",
@ -333,10 +333,11 @@ func builtinRange(args ...Object) (Object, error) {
if numArgs < 2 || numArgs > 3 {
return nil, ErrWrongNumArguments
}
var start, stop, step *Int
var start, stop Int
step := Int{Value: 1}
for i, arg := range args {
v, ok := args[i].(*Int)
v, ok := args[i].(Int)
if !ok {
var name string
switch i {
@ -367,10 +368,6 @@ func builtinRange(args ...Object) (Object, error) {
}
}
if step == nil {
step = &Int{Value: int64(1)}
}
return buildRange(start.Value, stop.Value, step.Value), nil
}
@ -378,13 +375,13 @@ 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{
array.Value = append(array.Value, Int{
Value: i,
})
}
} else {
for i := start; i > stop; i -= step {
array.Value = append(array.Value, &Int{
array.Value = append(array.Value, Int{
Value: i,
})
}
@ -449,12 +446,12 @@ func builtinInt(args ...Object) (Object, error) {
if !(argsLen == 1 || argsLen == 2) {
return nil, ErrWrongNumArguments
}
if _, ok := args[0].(*Int); ok {
if _, ok := args[0].(Int); ok {
return args[0], nil
}
v, ok := ToInt64(args[0])
if ok {
return &Int{Value: v}, nil
return Int{Value: v}, nil
}
if argsLen == 2 {
return args[1], nil
@ -467,12 +464,12 @@ func builtinFloat(args ...Object) (Object, error) {
if !(argsLen == 1 || argsLen == 2) {
return nil, ErrWrongNumArguments
}
if _, ok := args[0].(*Float); ok {
if _, ok := args[0].(Float); ok {
return args[0], nil
}
v, ok := ToFloat64(args[0])
if ok {
return &Float{Value: v}, nil
return Float{Value: v}, nil
}
if argsLen == 2 {
return args[1], nil
@ -484,7 +481,7 @@ func builtinBool(args ...Object) (Object, error) {
if len(args) != 1 {
return nil, ErrWrongNumArguments
}
if _, ok := args[0].(*Bool); ok {
if _, ok := args[0].(Bool); ok {
return args[0], nil
}
v, ok := ToBool(args[0])
@ -502,12 +499,12 @@ func builtinChar(args ...Object) (Object, error) {
if !(argsLen == 1 || argsLen == 2) {
return nil, ErrWrongNumArguments
}
if _, ok := args[0].(*Char); ok {
if _, ok := args[0].(Char); ok {
return args[0], nil
}
v, ok := ToRune(args[0])
if ok {
return &Char{Value: v}, nil
return Char{Value: v}, nil
}
if argsLen == 2 {
return args[1], nil
@ -522,7 +519,7 @@ func builtinBytes(args ...Object) (Object, error) {
}
// bytes(N) => create a new bytes with given size N
if n, ok := args[0].(*Int); ok {
if n, ok := args[0].(Int); ok {
if n.Value > int64(MaxBytesLen) {
return nil, ErrBytesLimit
}
@ -627,7 +624,7 @@ func builtinSplice(args ...Object) (Object, error) {
var startIdx int
if argsLen > 1 {
arg1, ok := args[1].(*Int)
arg1, ok := args[1].(Int)
if !ok {
return nil, ErrInvalidArgumentType{
Name: "second",
@ -643,7 +640,7 @@ func builtinSplice(args ...Object) (Object, error) {
delCount := len(array.Value)
if argsLen > 2 {
arg2, ok := args[2].(*Int)
arg2, ok := args[2].(Int)
if !ok {
return nil, ErrInvalidArgumentType{
Name: "third",

View file

@ -52,7 +52,7 @@ func Test_builtinDelete(t *testing.T) {
},
{name: "nil-map-nonstr-key",
args: args{[]tengo.Object{
&tengo.Map{}, &tengo.Int{}}}, wantErr: true,
&tengo.Map{}, tengo.Int{}}}, wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
Name: "second", Expected: "string", Found: "int"},
},
@ -88,12 +88,12 @@ func Test_builtinDelete(t *testing.T) {
[]tengo.Object{
&tengo.Map{Value: map[string]tengo.Object{
"key1": &tengo.String{Value: "value1"},
"key2": &tengo.Int{Value: 10},
"key2": tengo.Int{Value: 10},
}},
&tengo.String{Value: "key1"}}},
want: tengo.UndefinedValue,
target: &tengo.Map{Value: map[string]tengo.Object{
"key2": &tengo.Int{Value: 10}}},
"key2": tengo.Int{Value: 10}}},
},
}
for _, tt := range tests {
@ -166,12 +166,12 @@ func Test_builtinSplice(t *testing.T) {
Name: "second", Expected: "int", Found: "string"},
},
{name: "negative index",
args: []tengo.Object{&tengo.Array{}, &tengo.Int{Value: -1}},
args: []tengo.Object{&tengo.Array{}, tengo.Int{Value: -1}},
wantErr: true,
wantedErr: tengo.ErrIndexOutOfBounds},
{name: "non int count",
args: []tengo.Object{
&tengo.Array{}, &tengo.Int{Value: 0},
&tengo.Array{}, tengo.Int{Value: 0},
&tengo.String{Value: ""}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
@ -180,153 +180,153 @@ func Test_builtinSplice(t *testing.T) {
{name: "negative count",
args: []tengo.Object{
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
&tengo.Int{Value: 0},
&tengo.Int{Value: -1}},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
tengo.Int{Value: 0},
tengo.Int{Value: -1}},
wantErr: true,
wantedErr: tengo.ErrIndexOutOfBounds,
},
{name: "insert with zero count",
args: []tengo.Object{
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
&tengo.Int{Value: 0},
&tengo.Int{Value: 0},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
tengo.Int{Value: 0},
tengo.Int{Value: 0},
&tengo.String{Value: "b"}},
deleted: &tengo.Array{Value: []tengo.Object{}},
Array: &tengo.Array{Value: []tengo.Object{
&tengo.String{Value: "b"},
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
},
{name: "insert",
args: []tengo.Object{
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
&tengo.Int{Value: 1},
&tengo.Int{Value: 0},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
tengo.Int{Value: 1},
tengo.Int{Value: 0},
&tengo.String{Value: "c"},
&tengo.String{Value: "d"}},
deleted: &tengo.Array{Value: []tengo.Object{}},
Array: &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
tengo.Int{Value: 0},
&tengo.String{Value: "c"},
&tengo.String{Value: "d"},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
},
{name: "insert with zero count",
args: []tengo.Object{
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
&tengo.Int{Value: 1},
&tengo.Int{Value: 0},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
tengo.Int{Value: 1},
tengo.Int{Value: 0},
&tengo.String{Value: "c"},
&tengo.String{Value: "d"}},
deleted: &tengo.Array{Value: []tengo.Object{}},
Array: &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
tengo.Int{Value: 0},
&tengo.String{Value: "c"},
&tengo.String{Value: "d"},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
},
{name: "insert with delete",
args: []tengo.Object{
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
&tengo.Int{Value: 1},
&tengo.Int{Value: 1},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
tengo.Int{Value: 1},
tengo.Int{Value: 1},
&tengo.String{Value: "c"},
&tengo.String{Value: "d"}},
deleted: &tengo.Array{
Value: []tengo.Object{&tengo.Int{Value: 1}}},
Value: []tengo.Object{tengo.Int{Value: 1}}},
Array: &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
tengo.Int{Value: 0},
&tengo.String{Value: "c"},
&tengo.String{Value: "d"},
&tengo.Int{Value: 2}}},
tengo.Int{Value: 2}}},
},
{name: "insert with delete multi",
args: []tengo.Object{
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
tengo.Int{Value: 1},
tengo.Int{Value: 2},
&tengo.String{Value: "c"},
&tengo.String{Value: "d"}},
deleted: &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
Array: &tengo.Array{
Value: []tengo.Object{
&tengo.Int{Value: 0},
tengo.Int{Value: 0},
&tengo.String{Value: "c"},
&tengo.String{Value: "d"}}},
},
{name: "delete all with positive count",
args: []tengo.Object{
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
&tengo.Int{Value: 0},
&tengo.Int{Value: 3}},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
tengo.Int{Value: 0},
tengo.Int{Value: 3}},
deleted: &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
Array: &tengo.Array{Value: []tengo.Object{}},
},
{name: "delete all with big count",
args: []tengo.Object{
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
&tengo.Int{Value: 0},
&tengo.Int{Value: 5}},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
tengo.Int{Value: 0},
tengo.Int{Value: 5}},
deleted: &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
Array: &tengo.Array{Value: []tengo.Object{}},
},
{name: "nothing2",
args: []tengo.Object{
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}}},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}}},
Array: &tengo.Array{Value: []tengo.Object{}},
deleted: &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
},
{name: "pop without count",
args: []tengo.Object{
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0},
&tengo.Int{Value: 1},
&tengo.Int{Value: 2}}},
&tengo.Int{Value: 2}},
deleted: &tengo.Array{Value: []tengo.Object{&tengo.Int{Value: 2}}},
tengo.Int{Value: 0},
tengo.Int{Value: 1},
tengo.Int{Value: 2}}},
tengo.Int{Value: 2}},
deleted: &tengo.Array{Value: []tengo.Object{tengo.Int{Value: 2}}},
Array: &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 0}, &tengo.Int{Value: 1}}},
tengo.Int{Value: 0}, tengo.Int{Value: 1}}},
},
}
for _, tt := range tests {
@ -388,36 +388,36 @@ func Test_builtinRange(t *testing.T) {
Name: "start", Expected: "int", Found: "string"},
},
{name: "invalid stop",
args: []tengo.Object{&tengo.Int{}, &tengo.String{}},
args: []tengo.Object{tengo.Int{}, &tengo.String{}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
Name: "stop", Expected: "int", Found: "string"},
},
{name: "invalid step",
args: []tengo.Object{&tengo.Int{}, &tengo.Int{}, &tengo.String{}},
args: []tengo.Object{tengo.Int{}, tengo.Int{}, &tengo.String{}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
Name: "step", Expected: "int", Found: "string"},
},
{name: "zero step",
args: []tengo.Object{&tengo.Int{}, &tengo.Int{}, &tengo.Int{}}, //must greate than 0
args: []tengo.Object{tengo.Int{}, tengo.Int{}, tengo.Int{}}, //must greate than 0
wantErr: true,
wantedErr: tengo.ErrInvalidRangeStep,
},
{name: "negative step",
args: []tengo.Object{&tengo.Int{}, &tengo.Int{}, intObject(-2)}, //must greate than 0
args: []tengo.Object{tengo.Int{}, tengo.Int{}, intObject(-2)}, //must greate than 0
wantErr: true,
wantedErr: tengo.ErrInvalidRangeStep,
},
{name: "same bound",
args: []tengo.Object{&tengo.Int{}, &tengo.Int{}},
args: []tengo.Object{tengo.Int{}, tengo.Int{}},
wantErr: false,
result: &tengo.Array{
Value: nil,
},
},
{name: "positive range",
args: []tengo.Object{&tengo.Int{}, &tengo.Int{Value: 5}},
args: []tengo.Object{tengo.Int{}, tengo.Int{Value: 5}},
wantErr: false,
result: &tengo.Array{
Value: []tengo.Object{
@ -430,7 +430,7 @@ func Test_builtinRange(t *testing.T) {
},
},
{name: "negative range",
args: []tengo.Object{&tengo.Int{}, &tengo.Int{Value: -5}},
args: []tengo.Object{tengo.Int{}, tengo.Int{Value: -5}},
wantErr: false,
result: &tengo.Array{
Value: []tengo.Object{
@ -444,7 +444,7 @@ func Test_builtinRange(t *testing.T) {
},
{name: "positive with step",
args: []tengo.Object{&tengo.Int{}, &tengo.Int{Value: 5}, &tengo.Int{Value: 2}},
args: []tengo.Object{tengo.Int{}, tengo.Int{Value: 5}, tengo.Int{Value: 2}},
wantErr: false,
result: &tengo.Array{
Value: []tengo.Object{
@ -456,7 +456,7 @@ func Test_builtinRange(t *testing.T) {
},
{name: "negative with step",
args: []tengo.Object{&tengo.Int{}, &tengo.Int{Value: -10}, &tengo.Int{Value: 2}},
args: []tengo.Object{tengo.Int{}, tengo.Int{Value: -10}, tengo.Int{Value: 2}},
wantErr: false,
result: &tengo.Array{
Value: []tengo.Object{
@ -470,7 +470,7 @@ func Test_builtinRange(t *testing.T) {
},
{name: "large range",
args: []tengo.Object{intObject(-10), intObject(10), &tengo.Int{Value: 3}},
args: []tengo.Object{intObject(-10), intObject(10), tengo.Int{Value: 3}},
wantErr: false,
result: &tengo.Array{
Value: []tengo.Object{

View file

@ -4,7 +4,6 @@ import (
"encoding/gob"
"fmt"
"io"
"reflect"
"github.com/d5/tengo/v2/parser"
)
@ -56,7 +55,7 @@ func (b *Bytecode) FormatConstants() (output []string) {
}
default:
output = append(output, fmt.Sprintf("[% 3d] %s (%s|%p)",
cidx, cn, reflect.TypeOf(cn).Elem().Name(), &cn))
cidx, cn, cn.TypeName(), &cn))
}
}
return
@ -126,7 +125,7 @@ func (b *Bytecode) RemoveDuplicates() {
indexMap[curIdx] = newIdx
deduped = append(deduped, c)
}
case *Int:
case Int:
if newIdx, ok := ints[c.Value]; ok {
indexMap[curIdx] = newIdx
} else {
@ -144,7 +143,7 @@ func (b *Bytecode) RemoveDuplicates() {
indexMap[curIdx] = newIdx
deduped = append(deduped, c)
}
case *Float:
case Float:
if newIdx, ok := floats[c.Value]; ok {
indexMap[curIdx] = newIdx
} else {
@ -153,7 +152,7 @@ func (b *Bytecode) RemoveDuplicates() {
indexMap[curIdx] = newIdx
deduped = append(deduped, c)
}
case *Char:
case Char:
if newIdx, ok := chars[c.Value]; ok {
indexMap[curIdx] = newIdx
} else {
@ -188,7 +187,7 @@ func fixDecodedObject(
modules *ModuleMap,
) (Object, error) {
switch o := o.(type) {
case *Bool:
case Bool:
if o.IsFalsy() {
return FalseValue, nil
}
@ -281,15 +280,15 @@ func init() {
gob.Register(&parser.SourceFileSet{})
gob.Register(&parser.SourceFile{})
gob.Register(&Array{})
gob.Register(&Bool{})
gob.Register(Bool{})
gob.Register(&Bytes{})
gob.Register(&Char{})
gob.Register(Char{})
gob.Register(&CompiledFunction{})
gob.Register(&Error{})
gob.Register(&Float{})
gob.Register(Float{})
gob.Register(&ImmutableArray{})
gob.Register(&ImmutableMap{})
gob.Register(&Int{})
gob.Register(Int{})
gob.Register(&Map{})
gob.Register(&String{})
gob.Register(&Time{})

View file

@ -20,15 +20,15 @@ func TestBytecode(t *testing.T) {
testBytecodeSerialization(t, bytecode(
concatInsts(), objectsArray(
&tengo.Char{Value: 'y'},
&tengo.Float{Value: 93.11},
tengo.Char{Value: 'y'},
tengo.Float{Value: 93.11},
compiledFunction(1, 0,
tengo.MakeInstruction(parser.OpConstant, 3),
tengo.MakeInstruction(parser.OpSetLocal, 0),
tengo.MakeInstruction(parser.OpGetGlobal, 0),
tengo.MakeInstruction(parser.OpGetFree, 0)),
&tengo.Float{Value: 39.2},
&tengo.Int{Value: 192},
tengo.Float{Value: 39.2},
tengo.Int{Value: 192},
&tengo.String{Value: "bar"})))
testBytecodeSerialization(t, bytecodeFileSet(
@ -38,17 +38,17 @@ func TestBytecode(t *testing.T) {
tengo.MakeInstruction(parser.OpConstant, 6),
tengo.MakeInstruction(parser.OpPop)),
objectsArray(
&tengo.Int{Value: 55},
&tengo.Int{Value: 66},
&tengo.Int{Value: 77},
&tengo.Int{Value: 88},
tengo.Int{Value: 55},
tengo.Int{Value: 66},
tengo.Int{Value: 77},
tengo.Int{Value: 88},
&tengo.ImmutableMap{
Value: map[string]tengo.Object{
"array": &tengo.ImmutableArray{
Value: []tengo.Object{
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
&tengo.Int{Value: 3},
tengo.Int{Value: 1},
tengo.Int{Value: 2},
tengo.Int{Value: 3},
tengo.TrueValue,
tengo.FalseValue,
tengo.UndefinedValue,
@ -57,16 +57,16 @@ func TestBytecode(t *testing.T) {
"true": tengo.TrueValue,
"false": tengo.FalseValue,
"bytes": &tengo.Bytes{Value: make([]byte, 16)},
"char": &tengo.Char{Value: 'Y'},
"char": tengo.Char{Value: 'Y'},
"error": &tengo.Error{Value: &tengo.String{
Value: "some error",
}},
"float": &tengo.Float{Value: -19.84},
"float": tengo.Float{Value: -19.84},
"immutable_array": &tengo.ImmutableArray{
Value: []tengo.Object{
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
&tengo.Int{Value: 3},
tengo.Int{Value: 1},
tengo.Int{Value: 2},
tengo.Int{Value: 3},
tengo.TrueValue,
tengo.FalseValue,
tengo.UndefinedValue,
@ -74,20 +74,20 @@ func TestBytecode(t *testing.T) {
},
"immutable_map": &tengo.ImmutableMap{
Value: map[string]tengo.Object{
"a": &tengo.Int{Value: 1},
"b": &tengo.Int{Value: 2},
"c": &tengo.Int{Value: 3},
"a": tengo.Int{Value: 1},
"b": tengo.Int{Value: 2},
"c": tengo.Int{Value: 3},
"d": tengo.TrueValue,
"e": tengo.FalseValue,
"f": tengo.UndefinedValue,
},
},
"int": &tengo.Int{Value: 91},
"int": tengo.Int{Value: 91},
"map": &tengo.Map{
Value: map[string]tengo.Object{
"a": &tengo.Int{Value: 1},
"b": &tengo.Int{Value: 2},
"c": &tengo.Int{Value: 3},
"a": tengo.Int{Value: 1},
"b": tengo.Int{Value: 2},
"c": tengo.Int{Value: 3},
"d": tengo.TrueValue,
"e": tengo.FalseValue,
"f": tengo.UndefinedValue,
@ -130,27 +130,27 @@ func TestBytecode_RemoveDuplicates(t *testing.T) {
testBytecodeRemoveDuplicates(t,
bytecode(
concatInsts(), objectsArray(
&tengo.Char{Value: 'y'},
&tengo.Float{Value: 93.11},
tengo.Char{Value: 'y'},
tengo.Float{Value: 93.11},
compiledFunction(1, 0,
tengo.MakeInstruction(parser.OpConstant, 3),
tengo.MakeInstruction(parser.OpSetLocal, 0),
tengo.MakeInstruction(parser.OpGetGlobal, 0),
tengo.MakeInstruction(parser.OpGetFree, 0)),
&tengo.Float{Value: 39.2},
&tengo.Int{Value: 192},
tengo.Float{Value: 39.2},
tengo.Int{Value: 192},
&tengo.String{Value: "bar"})),
bytecode(
concatInsts(), objectsArray(
&tengo.Char{Value: 'y'},
&tengo.Float{Value: 93.11},
tengo.Char{Value: 'y'},
tengo.Float{Value: 93.11},
compiledFunction(1, 0,
tengo.MakeInstruction(parser.OpConstant, 3),
tengo.MakeInstruction(parser.OpSetLocal, 0),
tengo.MakeInstruction(parser.OpGetGlobal, 0),
tengo.MakeInstruction(parser.OpGetFree, 0)),
&tengo.Float{Value: 39.2},
&tengo.Int{Value: 192},
tengo.Float{Value: 39.2},
tengo.Int{Value: 192},
&tengo.String{Value: "bar"})))
testBytecodeRemoveDuplicates(t,
@ -167,9 +167,9 @@ func TestBytecode_RemoveDuplicates(t *testing.T) {
tengo.MakeInstruction(parser.OpConstant, 8),
tengo.MakeInstruction(parser.OpClosure, 4, 1)),
objectsArray(
&tengo.Int{Value: 1},
&tengo.Float{Value: 2.0},
&tengo.Char{Value: '3'},
tengo.Int{Value: 1},
tengo.Float{Value: 2.0},
tengo.Char{Value: '3'},
&tengo.String{Value: "four"},
compiledFunction(1, 0,
tengo.MakeInstruction(parser.OpConstant, 3),
@ -177,9 +177,9 @@ func TestBytecode_RemoveDuplicates(t *testing.T) {
tengo.MakeInstruction(parser.OpSetLocal, 0),
tengo.MakeInstruction(parser.OpGetGlobal, 0),
tengo.MakeInstruction(parser.OpGetFree, 0)),
&tengo.Int{Value: 1},
&tengo.Float{Value: 2.0},
&tengo.Char{Value: '3'},
tengo.Int{Value: 1},
tengo.Float{Value: 2.0},
tengo.Char{Value: '3'},
&tengo.String{Value: "four"})),
bytecode(
concatInsts(
@ -194,9 +194,9 @@ func TestBytecode_RemoveDuplicates(t *testing.T) {
tengo.MakeInstruction(parser.OpConstant, 3),
tengo.MakeInstruction(parser.OpClosure, 4, 1)),
objectsArray(
&tengo.Int{Value: 1},
&tengo.Float{Value: 2.0},
&tengo.Char{Value: '3'},
tengo.Int{Value: 1},
tengo.Float{Value: 2.0},
tengo.Char{Value: '3'},
&tengo.String{Value: "four"},
compiledFunction(1, 0,
tengo.MakeInstruction(parser.OpConstant, 3),
@ -214,11 +214,11 @@ func TestBytecode_RemoveDuplicates(t *testing.T) {
tengo.MakeInstruction(parser.OpConstant, 3),
tengo.MakeInstruction(parser.OpConstant, 4)),
objectsArray(
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
&tengo.Int{Value: 3},
&tengo.Int{Value: 1},
&tengo.Int{Value: 3})),
tengo.Int{Value: 1},
tengo.Int{Value: 2},
tengo.Int{Value: 3},
tengo.Int{Value: 1},
tengo.Int{Value: 3})),
bytecode(
concatInsts(
tengo.MakeInstruction(parser.OpConstant, 0),
@ -227,19 +227,19 @@ func TestBytecode_RemoveDuplicates(t *testing.T) {
tengo.MakeInstruction(parser.OpConstant, 0),
tengo.MakeInstruction(parser.OpConstant, 2)),
objectsArray(
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
&tengo.Int{Value: 3})))
tengo.Int{Value: 1},
tengo.Int{Value: 2},
tengo.Int{Value: 3})))
}
func TestBytecode_CountObjects(t *testing.T) {
b := bytecode(
concatInsts(),
objectsArray(
&tengo.Int{Value: 55},
&tengo.Int{Value: 66},
&tengo.Int{Value: 77},
&tengo.Int{Value: 88},
tengo.Int{Value: 55},
tengo.Int{Value: 66},
tengo.Int{Value: 77},
tengo.Int{Value: 88},
compiledFunction(1, 0,
tengo.MakeInstruction(parser.OpConstant, 3),
tengo.MakeInstruction(parser.OpReturn, 1)),

View file

@ -36,9 +36,9 @@ fib := func(x) {
panic(err)
}
if nativeResult != int(result.(*tengo.Int).Value) {
if nativeResult != int(result.(tengo.Int).Value) {
panic(fmt.Errorf("wrong result: %d != %d", nativeResult,
int(result.(*tengo.Int).Value)))
int(result.(tengo.Int).Value)))
}
fmt.Println("-------------------------------------")
@ -73,9 +73,9 @@ fib := func(x, s) {
panic(err)
}
if nativeResult != int(result.(*tengo.Int).Value) {
if nativeResult != int(result.(tengo.Int).Value) {
panic(fmt.Errorf("wrong result: %d != %d", nativeResult,
int(result.(*tengo.Int).Value)))
int(result.(tengo.Int).Value)))
}
fmt.Println("-------------------------------------")
@ -110,9 +110,9 @@ fib := func(x, a, b) {
panic(err)
}
if nativeResult != int(result.(*tengo.Int).Value) {
if nativeResult != int(result.(tengo.Int).Value) {
panic(fmt.Errorf("wrong result: %d != %d", nativeResult,
int(result.(*tengo.Int).Value)))
int(result.(tengo.Int).Value)))
}
fmt.Println("-------------------------------------")

View file

@ -204,10 +204,10 @@ func (c *Compiler) Compile(node parser.Node) error {
}
case *parser.IntLit:
c.emit(node, parser.OpConstant,
c.addConstant(&Int{Value: node.Value}))
c.addConstant(Int{Value: node.Value}))
case *parser.FloatLit:
c.emit(node, parser.OpConstant,
c.addConstant(&Float{Value: node.Value}))
c.addConstant(Float{Value: node.Value}))
case *parser.BoolLit:
if node.Value {
c.emit(node, parser.OpTrue)
@ -222,7 +222,7 @@ func (c *Compiler) Compile(node parser.Node) error {
c.addConstant(&String{Value: node.Value}))
case *parser.CharLit:
c.emit(node, parser.OpConstant,
c.addConstant(&Char{Value: node.Value}))
c.addConstant(Char{Value: node.Value}))
case *parser.UndefinedLit:
c.emit(node, parser.OpNull)
case *parser.UnaryExpr:

View file

@ -1458,8 +1458,8 @@ func objectsArray(o ...tengo.Object) []tengo.Object {
return o
}
func intObject(v int64) *tengo.Int {
return &tengo.Int{Value: v}
func intObject(v int64) tengo.Int {
return tengo.Int{Value: v}
}
func stringObject(v string) *tengo.String {

View file

@ -227,14 +227,14 @@ for more details on these runtime types.
Users can easily extend and add their own types by implementing the same
[Object](https://godoc.org/github.com/d5/tengo#Object) interface and the
default `ObjectImpl` implementation. Tengo runtime will treat them in the
default `PtrObjectImpl` or `ObjectImpl` implementation. Tengo runtime will treat them in the
same way as its runtime types with no performance overhead.
Here's an example user type implementation, `StringArray`:
```golang
type StringArray struct {
tengo.ObjectImpl
tengo.PtrObjectImpl
Value []string
}
@ -309,7 +309,7 @@ It can also implement `IndexGet` and `IndexSet`:
```golang
func (o *StringArray) IndexGet(index tengo.Object) (tengo.Object, error) {
intIdx, ok := index.(*tengo.Int)
intIdx, ok := index.(tengo.Int)
if ok {
if intIdx.Value >= 0 && intIdx.Value < int64(len(o.Value)) {
return &tengo.String{Value: o.Value[intIdx.Value]}, nil
@ -322,7 +322,7 @@ func (o *StringArray) IndexGet(index tengo.Object) (tengo.Object, error) {
if ok {
for vidx, str := range o.Value {
if strIdx.Value == str {
return &tengo.Int{Value: int64(vidx)}, nil
return tengo.Int{Value: int64(vidx)}, nil
}
}
@ -338,7 +338,7 @@ func (o *StringArray) IndexSet(index, value tengo.Object) error {
return tengo.ErrInvalidIndexValueType
}
intIdx, ok := index.(*tengo.Int)
intIdx, ok := index.(tengo.Int)
if ok {
if intIdx.Value >= 0 && intIdx.Value < int64(len(o.Value)) {
o.Value[intIdx.Value] = strVal
@ -375,7 +375,7 @@ func (o *StringArray) Call(args ...tengo.Object) (ret tengo.Object, err error) {
for i, v := range o.Value {
if v == s1 {
return &tengo.Int{Value: int64(i)}, nil
return tengo.Int{Value: int64(i)}, nil
}
}
@ -409,7 +409,7 @@ func (o *StringArray) Iterate() tengo.Iterator {
}
type StringArrayIterator struct {
tengo.ObjectImpl
tengo.PtrObjectImpl
strArr *StringArray
idx int
}
@ -424,17 +424,16 @@ func (i *StringArrayIterator) Next() bool {
}
func (i *StringArrayIterator) Key() tengo.Object {
return &tengo.Int{Value: int64(i.idx - 1)}
return tengo.Int{Value: int64(i.idx - 1)}
}
func (i *StringArrayIterator) Value() tengo.Object {
return &tengo.String{Value: i.strArr.Value[i.idx-1]}
}
```
### PtrObjectImpl and ObjectImpl
### ObjectImpl
ObjectImpl represents a default Object Implementation. To defined a new value
type, one can embed ObjectImpl in their type declarations to avoid implementing
PtrObjectImpl and ObjectImpl represent a default Object Implementation. To defined a new value
type, one can embed PtrObjectImpl or ObjectImpl in their type declarations to avoid implementing
all non-significant methods. TypeName() and String() methods still need to be
implemented.

View file

@ -39,7 +39,7 @@ func NewGoProxy(ctx context.Context) *GoProxy {
// GoProxy is a builtin tengo module to register tengo functions and run them.
type GoProxy struct {
tengo.ObjectImpl
tengo.PtrObjectImpl
ctx context.Context
moduleMap map[string]tengo.Object
callbacks map[string]tengo.Object
@ -145,7 +145,7 @@ func (mod *GoProxy) args(args ...tengo.Object) (tengo.Object, error) {
}
return tengo.UndefinedValue, nil
}},
"num_params": &tengo.Int{Value: int64(compiledFunc.NumParameters)},
"num_params": tengo.Int{Value: int64(compiledFunc.NumParameters)},
"callable": compiledFunc,
"params": &tengo.Array{Value: params},
},
@ -243,8 +243,8 @@ func main() {
fmt.Println("Calling tengo sum function")
i1, i2 := rand.Int63n(100), rand.Int63n(100)
callChan <- &CallArgs{Func: "sum",
Params: []tengo.Object{&tengo.Int{Value: i1},
&tengo.Int{Value: i2}},
Params: []tengo.Object{tengo.Int{Value: i1},
tengo.Int{Value: i2}},
Result: result,
}
v := <-result
@ -253,8 +253,8 @@ func main() {
fmt.Println("Calling tengo multiply function")
i1, i2 = rand.Int63n(20), rand.Int63n(20)
callChan <- &CallArgs{Func: "multiply",
Params: []tengo.Object{&tengo.Int{Value: i1},
&tengo.Int{Value: i2}},
Params: []tengo.Object{tengo.Int{Value: i1},
tengo.Int{Value: i2}},
Result: result,
}
v = <-result

View file

@ -951,11 +951,11 @@ func (p *pp) printArg(arg Object, verb rune) {
// Some types can be done without reflection.
switch f := arg.(type) {
case *Bool:
case Bool:
p.fmtBool(!f.IsFalsy(), verb)
case *Float:
case Float:
p.fmtFloat(f.Value, 64, verb)
case *Int:
case Int:
p.fmtInteger(uint64(f.Value), signed, verb)
case *String:
p.fmtString(f.Value, verb)

View file

@ -16,7 +16,7 @@ type Iterator interface {
// ArrayIterator is an iterator for an array.
type ArrayIterator struct {
ObjectImpl
PtrObjectImpl
v []Object
i int
l int
@ -55,7 +55,7 @@ func (i *ArrayIterator) Next() bool {
// Key returns the key or index value of the current element.
func (i *ArrayIterator) Key() Object {
return &Int{Value: int64(i.i - 1)}
return Int{Value: int64(i.i - 1)}
}
// Value returns the value of the current element.
@ -65,7 +65,7 @@ func (i *ArrayIterator) Value() Object {
// BytesIterator represents an iterator for a string.
type BytesIterator struct {
ObjectImpl
PtrObjectImpl
v []byte
i int
l int
@ -99,17 +99,17 @@ func (i *BytesIterator) Next() bool {
// Key returns the key or index value of the current element.
func (i *BytesIterator) Key() Object {
return &Int{Value: int64(i.i - 1)}
return Int{Value: int64(i.i - 1)}
}
// Value returns the value of the current element.
func (i *BytesIterator) Value() Object {
return &Int{Value: int64(i.v[i.i-1])}
return Int{Value: int64(i.v[i.i-1])}
}
// MapIterator represents an iterator for the map.
type MapIterator struct {
ObjectImpl
PtrObjectImpl
v map[string]Object
k []string
i int
@ -161,7 +161,7 @@ func (i *MapIterator) Value() Object {
// StringIterator represents an iterator for a string.
type StringIterator struct {
ObjectImpl
PtrObjectImpl
v []rune
i int
l int
@ -200,10 +200,10 @@ func (i *StringIterator) Next() bool {
// Key returns the key or index value of the current element.
func (i *StringIterator) Key() Object {
return &Int{Value: int64(i.i - 1)}
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]}
return Char{Value: i.v[i.i-1]}
}

View file

@ -14,10 +14,10 @@ import (
var (
// TrueValue represents a true value.
TrueValue Object = &Bool{value: true}
TrueValue Object = Bool{value: true}
// FalseValue represents a false value.
FalseValue Object = &Bool{value: false}
FalseValue Object = Bool{value: false}
// UndefinedValue represents an undefined value.
UndefinedValue Object = &Undefined{}
@ -87,70 +87,139 @@ type ObjectImpl struct {
}
// TypeName returns the name of the type.
func (o *ObjectImpl) TypeName() string {
func (o ObjectImpl) TypeName() string {
panic(ErrNotImplemented)
}
func (o *ObjectImpl) String() string {
func (o ObjectImpl) String() string {
panic(ErrNotImplemented)
}
// BinaryOp returns another object that is the result of a given binary
// operator and a right-hand side object.
func (o *ObjectImpl) BinaryOp(_ token.Token, _ Object) (Object, error) {
func (o ObjectImpl) BinaryOp(_ token.Token, _ Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *ObjectImpl) Copy() Object {
func (o ObjectImpl) Copy() Object {
return nil
}
// IsFalsy returns true if the value of the type is falsy.
func (o *ObjectImpl) IsFalsy() bool {
func (o ObjectImpl) IsFalsy() bool {
return false
}
// Equals returns true if the value of the type is equal to the value of
// another object.
func (o *ObjectImpl) Equals(x Object) bool {
func (o ObjectImpl) Equals(x Object) bool {
return o == x
}
// IndexGet returns an element at a given index.
func (o *ObjectImpl) IndexGet(_ Object) (res Object, err error) {
func (o ObjectImpl) IndexGet(_ Object) (res Object, err error) {
return nil, ErrNotIndexable
}
// IndexSet sets an element at a given index.
func (o *ObjectImpl) IndexSet(_, _ Object) (err error) {
func (o ObjectImpl) IndexSet(_, _ Object) (err error) {
return ErrNotIndexAssignable
}
// Iterate returns an iterator.
func (o *ObjectImpl) Iterate() Iterator {
func (o ObjectImpl) Iterate() Iterator {
return nil
}
// CanIterate returns whether the Object can be Iterated.
func (o *ObjectImpl) CanIterate() bool {
func (o ObjectImpl) CanIterate() bool {
return false
}
// Call takes an arbitrary number of arguments and returns a return value
// and/or an error.
func (o *ObjectImpl) Call(_ ...Object) (ret Object, err error) {
func (o ObjectImpl) Call(_ ...Object) (ret Object, err error) {
return nil, nil
}
// CanCall returns whether the Object can be Called.
func (o *ObjectImpl) CanCall() bool {
func (o ObjectImpl) CanCall() bool {
return false
}
// PtrObjectImpl represents a default Object Implementation. To defined a new
// value type, one can embed PtrObjectImpl in their type declarations to avoid
// implementing all non-significant methods. TypeName() and String() methods
// still need to be implemented.
type PtrObjectImpl struct {
}
// TypeName returns the name of the type.
func (o *PtrObjectImpl) TypeName() string {
panic(ErrNotImplemented)
}
func (o *PtrObjectImpl) String() string {
panic(ErrNotImplemented)
}
// BinaryOp returns another object that is the result of a given binary
// operator and a right-hand side object.
func (o *PtrObjectImpl) BinaryOp(_ token.Token, _ Object) (Object, error) {
return nil, ErrInvalidOperator
}
// Copy returns a copy of the type.
func (o *PtrObjectImpl) Copy() Object {
return nil
}
// IsFalsy returns true if the value of the type is falsy.
func (o *PtrObjectImpl) IsFalsy() bool {
return false
}
// Equals returns true if the value of the type is equal to the value of
// another object.
func (o *PtrObjectImpl) Equals(x Object) bool {
return o == x
}
// IndexGet returns an element at a given index.
func (o *PtrObjectImpl) IndexGet(_ Object) (res Object, err error) {
return nil, ErrNotIndexable
}
// IndexSet sets an element at a given index.
func (o *PtrObjectImpl) IndexSet(_, _ Object) (err error) {
return ErrNotIndexAssignable
}
// Iterate returns an iterator.
func (o *PtrObjectImpl) Iterate() Iterator {
return nil
}
// CanIterate returns whether the Object can be Iterated.
func (o *PtrObjectImpl) CanIterate() bool {
return false
}
// Call takes an arbitrary number of arguments and returns a return value
// and/or an error.
func (o *PtrObjectImpl) Call(_ ...Object) (ret Object, err error) {
return nil, nil
}
// CanCall returns whether the Object can be Called.
func (o *PtrObjectImpl) CanCall() bool {
return false
}
// Array represents an array of objects.
type Array struct {
ObjectImpl
PtrObjectImpl
Value []Object
}
@ -221,7 +290,7 @@ func (o *Array) Equals(x Object) bool {
// IndexGet returns an element at a given index.
func (o *Array) IndexGet(index Object) (res Object, err error) {
intIdx, ok := index.(*Int)
intIdx, ok := index.(Int)
if !ok {
err = ErrInvalidIndexType
return
@ -272,7 +341,7 @@ type Bool struct {
value bool
}
func (o *Bool) String() string {
func (o Bool) String() string {
if o.value {
return "true"
}
@ -281,23 +350,23 @@ func (o *Bool) String() string {
}
// TypeName returns the name of the type.
func (o *Bool) TypeName() string {
func (o Bool) TypeName() string {
return "bool"
}
// Copy returns a copy of the type.
func (o *Bool) Copy() Object {
func (o Bool) Copy() Object {
return o
}
// IsFalsy returns true if the value of the type is falsy.
func (o *Bool) IsFalsy() bool {
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 {
func (o Bool) Equals(x Object) bool {
return o == x
}
@ -308,7 +377,7 @@ func (o *Bool) GobDecode(b []byte) (err error) {
}
// GobEncode encodes bool values into bytes.
func (o *Bool) GobEncode() (b []byte, err error) {
func (o Bool) GobEncode() (b []byte, err error) {
if o.value {
b = []byte{1}
} else {
@ -319,7 +388,7 @@ func (o *Bool) GobEncode() (b []byte, err error) {
// BuiltinFunction represents a builtin function.
type BuiltinFunction struct {
ObjectImpl
PtrObjectImpl
Name string
Value CallableFunc
}
@ -376,7 +445,7 @@ func (m *BuiltinModule) AsImmutableMap(moduleName string) *ImmutableMap {
// Bytes represents a byte array.
type Bytes struct {
ObjectImpl
PtrObjectImpl
Value []byte
}
@ -427,7 +496,7 @@ func (o *Bytes) Equals(x Object) bool {
// IndexGet returns an element (as Int) at a given index.
func (o *Bytes) IndexGet(index Object) (res Object, err error) {
intIdx, ok := index.(*Int)
intIdx, ok := index.(Int)
if !ok {
err = ErrInvalidIndexType
return
@ -437,7 +506,7 @@ func (o *Bytes) IndexGet(index Object) (res Object, err error) {
res = UndefinedValue
return
}
res = &Int{Value: int64(o.Value[idxVal])}
res = Int{Value: int64(o.Value[idxVal])}
return
}
@ -460,33 +529,33 @@ type Char struct {
Value rune
}
func (o *Char) String() string {
func (o Char) String() string {
return string(o.Value)
}
// TypeName returns the name of the type.
func (o *Char) TypeName() string {
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) {
func (o Char) BinaryOp(op token.Token, rhs Object) (Object, error) {
switch rhs := rhs.(type) {
case *Char:
case Char:
switch op {
case token.Add:
r := o.Value + rhs.Value
if r == o.Value {
return o, nil
}
return &Char{Value: r}, 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
return Char{Value: r}, nil
case token.Less:
if o.Value < rhs.Value {
return TrueValue, nil
@ -508,20 +577,20 @@ func (o *Char) BinaryOp(op token.Token, rhs Object) (Object, error) {
}
return FalseValue, nil
}
case *Int:
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
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
return Char{Value: r}, nil
case token.Less:
if int64(o.Value) < rhs.Value {
return TrueValue, nil
@ -548,19 +617,19 @@ func (o *Char) BinaryOp(op token.Token, rhs Object) (Object, error) {
}
// Copy returns a copy of the type.
func (o *Char) Copy() Object {
return &Char{Value: o.Value}
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 {
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)
func (o Char) Equals(x Object) bool {
t, ok := x.(Char)
if !ok {
return false
}
@ -569,7 +638,7 @@ func (o *Char) Equals(x Object) bool {
// CompiledFunction represents a compiled function.
type CompiledFunction struct {
ObjectImpl
PtrObjectImpl
Instructions []byte
NumLocals int // number of local variables (including function parameters)
NumParameters int
@ -622,7 +691,7 @@ func (o *CompiledFunction) CanCall() bool {
// Error represents an error value.
type Error struct {
ObjectImpl
PtrObjectImpl
Value Object
}
@ -670,45 +739,45 @@ type Float struct {
Value float64
}
func (o *Float) String() string {
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 {
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) {
func (o Float) BinaryOp(op token.Token, rhs Object) (Object, error) {
switch rhs := rhs.(type) {
case *Float:
case Float:
switch op {
case token.Add:
r := o.Value + rhs.Value
if r == o.Value {
return o, nil
}
return &Float{Value: r}, 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
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
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
return Float{Value: r}, nil
case token.Less:
if o.Value < rhs.Value {
return TrueValue, nil
@ -730,32 +799,32 @@ func (o *Float) BinaryOp(op token.Token, rhs Object) (Object, error) {
}
return FalseValue, nil
}
case *Int:
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
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
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
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
return Float{Value: r}, nil
case token.Less:
if o.Value < float64(rhs.Value) {
return TrueValue, nil
@ -782,19 +851,19 @@ func (o *Float) BinaryOp(op token.Token, rhs Object) (Object, error) {
}
// Copy returns a copy of the type.
func (o *Float) Copy() Object {
return &Float{Value: o.Value}
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 {
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)
func (o Float) Equals(x Object) bool {
t, ok := x.(Float)
if !ok {
return false
}
@ -803,7 +872,7 @@ func (o *Float) Equals(x Object) bool {
// ImmutableArray represents an immutable array of objects.
type ImmutableArray struct {
ObjectImpl
PtrObjectImpl
Value []Object
}
@ -871,7 +940,7 @@ func (o *ImmutableArray) Equals(x Object) bool {
// IndexGet returns an element at a given index.
func (o *ImmutableArray) IndexGet(index Object) (res Object, err error) {
intIdx, ok := index.(*Int)
intIdx, ok := index.(Int)
if !ok {
err = ErrInvalidIndexType
return
@ -900,7 +969,7 @@ func (o *ImmutableArray) CanIterate() bool {
// ImmutableMap represents an immutable map object.
type ImmutableMap struct {
ObjectImpl
PtrObjectImpl
Value map[string]Object
}
@ -993,87 +1062,87 @@ type Int struct {
Value int64
}
func (o *Int) String() string {
func (o Int) String() string {
return strconv.FormatInt(o.Value, 10)
}
// TypeName returns the name of the type.
func (o *Int) TypeName() string {
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) {
func (o Int) BinaryOp(op token.Token, rhs Object) (Object, error) {
switch rhs := rhs.(type) {
case *Int:
case Int:
switch op {
case token.Add:
r := o.Value + rhs.Value
if r == o.Value {
return o, nil
}
return &Int{Value: r}, 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
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
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
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
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
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
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
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
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
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
return Int{Value: r}, nil
case token.Less:
if o.Value < rhs.Value {
return TrueValue, nil
@ -1095,16 +1164,16 @@ func (o *Int) BinaryOp(op token.Token, rhs Object) (Object, error) {
}
return FalseValue, nil
}
case *Float:
case Float:
switch op {
case token.Add:
return &Float{Value: float64(o.Value) + rhs.Value}, nil
return Float{Value: float64(o.Value) + rhs.Value}, nil
case token.Sub:
return &Float{Value: float64(o.Value) - rhs.Value}, nil
return Float{Value: float64(o.Value) - rhs.Value}, nil
case token.Mul:
return &Float{Value: float64(o.Value) * rhs.Value}, nil
return Float{Value: float64(o.Value) * rhs.Value}, nil
case token.Quo:
return &Float{Value: float64(o.Value) / rhs.Value}, nil
return Float{Value: float64(o.Value) / rhs.Value}, nil
case token.Less:
if float64(o.Value) < rhs.Value {
return TrueValue, nil
@ -1126,12 +1195,12 @@ func (o *Int) BinaryOp(op token.Token, rhs Object) (Object, error) {
}
return FalseValue, nil
}
case *Char:
case Char:
switch op {
case token.Add:
return &Char{Value: rune(o.Value) + rhs.Value}, nil
return Char{Value: rune(o.Value) + rhs.Value}, nil
case token.Sub:
return &Char{Value: rune(o.Value) - rhs.Value}, nil
return Char{Value: rune(o.Value) - rhs.Value}, nil
case token.Less:
if o.Value < int64(rhs.Value) {
return TrueValue, nil
@ -1158,19 +1227,19 @@ func (o *Int) BinaryOp(op token.Token, rhs Object) (Object, error) {
}
// Copy returns a copy of the type.
func (o *Int) Copy() Object {
return &Int{Value: o.Value}
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 {
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)
func (o Int) Equals(x Object) bool {
t, ok := x.(Int)
if !ok {
return false
}
@ -1179,7 +1248,7 @@ func (o *Int) Equals(x Object) bool {
// Map represents a map of objects.
type Map struct {
ObjectImpl
PtrObjectImpl
Value map[string]Object
}
@ -1279,7 +1348,7 @@ func (o *Map) CanIterate() bool {
// ObjectPtr represents a free variable.
type ObjectPtr struct {
ObjectImpl
PtrObjectImpl
Value *Object
}
@ -1310,7 +1379,7 @@ func (o *ObjectPtr) Equals(x Object) bool {
// String represents a string value.
type String struct {
ObjectImpl
PtrObjectImpl
Value string
runeStr []rune
}
@ -1400,7 +1469,7 @@ func (o *String) Equals(x Object) bool {
// IndexGet returns a character at a given index.
func (o *String) IndexGet(index Object) (res Object, err error) {
intIdx, ok := index.(*Int)
intIdx, ok := index.(Int)
if !ok {
err = ErrInvalidIndexType
return
@ -1413,7 +1482,7 @@ func (o *String) IndexGet(index Object) (res Object, err error) {
res = UndefinedValue
return
}
res = &Char{Value: o.runeStr[idxVal]}
res = Char{Value: o.runeStr[idxVal]}
return
}
@ -1435,7 +1504,7 @@ func (o *String) CanIterate() bool {
// Time represents a time value.
type Time struct {
ObjectImpl
PtrObjectImpl
Value time.Time
}
@ -1452,7 +1521,7 @@ func (o *Time) TypeName() string {
// operator and a right-hand side object.
func (o *Time) BinaryOp(op token.Token, rhs Object) (Object, error) {
switch rhs := rhs.(type) {
case *Int:
case Int:
switch op {
case token.Add: // time + int => time
if rhs.Value == 0 {
@ -1468,7 +1537,7 @@ func (o *Time) BinaryOp(op token.Token, rhs Object) (Object, error) {
case *Time:
switch op {
case token.Sub: // time - time => int (duration)
return &Int{Value: int64(o.Value.Sub(rhs.Value))}, nil
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
@ -1516,7 +1585,7 @@ func (o *Time) Equals(x Object) bool {
// Undefined represents an undefined value.
type Undefined struct {
ObjectImpl
PtrObjectImpl
}
// TypeName returns the name of the type.
@ -1576,7 +1645,7 @@ func (o *Undefined) Value() Object {
// UserFunction represents a user function.
type UserFunction struct {
ObjectImpl
PtrObjectImpl
Name string
Value CallableFunc
}

View file

@ -9,15 +9,15 @@ import (
)
func TestObject_TypeName(t *testing.T) {
var o tengo.Object = &tengo.Int{}
var o tengo.Object = tengo.Int{}
require.Equal(t, "int", o.TypeName())
o = &tengo.Float{}
o = tengo.Float{}
require.Equal(t, "float", o.TypeName())
o = &tengo.Char{}
o = tengo.Char{}
require.Equal(t, "char", o.TypeName())
o = &tengo.String{}
require.Equal(t, "string", o.TypeName())
o = &tengo.Bool{}
o = tengo.Bool{}
require.Equal(t, "bool", o.TypeName())
o = &tengo.Array{}
require.Equal(t, "array", o.TypeName())
@ -44,17 +44,17 @@ func TestObject_TypeName(t *testing.T) {
}
func TestObject_IsFalsy(t *testing.T) {
var o tengo.Object = &tengo.Int{Value: 0}
var o tengo.Object = tengo.Int{Value: 0}
require.True(t, o.IsFalsy())
o = &tengo.Int{Value: 1}
o = tengo.Int{Value: 1}
require.False(t, o.IsFalsy())
o = &tengo.Float{Value: 0}
o = tengo.Float{Value: 0}
require.False(t, o.IsFalsy())
o = &tengo.Float{Value: 1}
o = tengo.Float{Value: 1}
require.False(t, o.IsFalsy())
o = &tengo.Char{Value: ' '}
o = tengo.Char{Value: ' '}
require.False(t, o.IsFalsy())
o = &tengo.Char{Value: 'T'}
o = tengo.Char{Value: 'T'}
require.False(t, o.IsFalsy())
o = &tengo.String{Value: ""}
require.True(t, o.IsFalsy())
@ -89,17 +89,17 @@ func TestObject_IsFalsy(t *testing.T) {
}
func TestObject_String(t *testing.T) {
var o tengo.Object = &tengo.Int{Value: 0}
var o tengo.Object = tengo.Int{Value: 0}
require.Equal(t, "0", o.String())
o = &tengo.Int{Value: 1}
o = tengo.Int{Value: 1}
require.Equal(t, "1", o.String())
o = &tengo.Float{Value: 0}
o = tengo.Float{Value: 0}
require.Equal(t, "0", o.String())
o = &tengo.Float{Value: 1}
o = tengo.Float{Value: 1}
require.Equal(t, "1", o.String())
o = &tengo.Char{Value: ' '}
o = tengo.Char{Value: ' '}
require.Equal(t, " ", o.String())
o = &tengo.Char{Value: 'T'}
o = tengo.Char{Value: 'T'}
require.Equal(t, "T", o.String())
o = &tengo.String{Value: ""}
require.Equal(t, `""`, o.String())
@ -128,10 +128,10 @@ func TestObject_String(t *testing.T) {
}
func TestObject_BinaryOp(t *testing.T) {
var o tengo.Object = &tengo.Char{}
var o tengo.Object = tengo.Char{}
_, err := o.BinaryOp(token.Add, tengo.UndefinedValue)
require.Error(t, err)
o = &tengo.Bool{}
o = tengo.Bool{}
_, err = o.BinaryOp(token.Add, tengo.UndefinedValue)
require.Error(t, err)
o = &tengo.Map{}
@ -172,45 +172,45 @@ func TestArray_BinaryOp(t *testing.T) {
&tengo.Array{Value: []tengo.Object{}})
testBinaryOp(t, &tengo.Array{Value: nil}, token.Add,
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 1},
tengo.Int{Value: 1},
}}, &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 1},
tengo.Int{Value: 1},
}})
testBinaryOp(t, &tengo.Array{Value: nil}, token.Add,
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
&tengo.Int{Value: 3},
tengo.Int{Value: 1},
tengo.Int{Value: 2},
tengo.Int{Value: 3},
}}, &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
&tengo.Int{Value: 3},
tengo.Int{Value: 1},
tengo.Int{Value: 2},
tengo.Int{Value: 3},
}})
testBinaryOp(t, &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
&tengo.Int{Value: 3},
tengo.Int{Value: 1},
tengo.Int{Value: 2},
tengo.Int{Value: 3},
}}, token.Add, &tengo.Array{Value: nil},
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
&tengo.Int{Value: 3},
tengo.Int{Value: 1},
tengo.Int{Value: 2},
tengo.Int{Value: 3},
}})
testBinaryOp(t, &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
&tengo.Int{Value: 3},
tengo.Int{Value: 1},
tengo.Int{Value: 2},
tengo.Int{Value: 3},
}}, token.Add, &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 4},
&tengo.Int{Value: 5},
&tengo.Int{Value: 6},
tengo.Int{Value: 4},
tengo.Int{Value: 5},
tengo.Int{Value: 6},
}}, &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
&tengo.Int{Value: 3},
&tengo.Int{Value: 4},
&tengo.Int{Value: 5},
&tengo.Int{Value: 6},
tengo.Int{Value: 1},
tengo.Int{Value: 2},
tengo.Int{Value: 3},
tengo.Int{Value: 4},
tengo.Int{Value: 5},
tengo.Int{Value: 6},
}})
}
@ -229,24 +229,24 @@ func TestFloat_BinaryOp(t *testing.T) {
// float + float
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := float64(-2); r <= 2.1; r += 0.4 {
testBinaryOp(t, &tengo.Float{Value: l}, token.Add,
&tengo.Float{Value: r}, &tengo.Float{Value: l + r})
testBinaryOp(t, tengo.Float{Value: l}, token.Add,
tengo.Float{Value: r}, tengo.Float{Value: l + r})
}
}
// float - float
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := float64(-2); r <= 2.1; r += 0.4 {
testBinaryOp(t, &tengo.Float{Value: l}, token.Sub,
&tengo.Float{Value: r}, &tengo.Float{Value: l - r})
testBinaryOp(t, tengo.Float{Value: l}, token.Sub,
tengo.Float{Value: r}, tengo.Float{Value: l - r})
}
}
// float * float
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := float64(-2); r <= 2.1; r += 0.4 {
testBinaryOp(t, &tengo.Float{Value: l}, token.Mul,
&tengo.Float{Value: r}, &tengo.Float{Value: l * r})
testBinaryOp(t, tengo.Float{Value: l}, token.Mul,
tengo.Float{Value: r}, tengo.Float{Value: l * r})
}
}
@ -254,8 +254,8 @@ func TestFloat_BinaryOp(t *testing.T) {
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := float64(-2); r <= 2.1; r += 0.4 {
if r != 0 {
testBinaryOp(t, &tengo.Float{Value: l}, token.Quo,
&tengo.Float{Value: r}, &tengo.Float{Value: l / r})
testBinaryOp(t, tengo.Float{Value: l}, token.Quo,
tengo.Float{Value: r}, tengo.Float{Value: l / r})
}
}
}
@ -263,56 +263,56 @@ func TestFloat_BinaryOp(t *testing.T) {
// float < float
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := float64(-2); r <= 2.1; r += 0.4 {
testBinaryOp(t, &tengo.Float{Value: l}, token.Less,
&tengo.Float{Value: r}, boolValue(l < r))
testBinaryOp(t, tengo.Float{Value: l}, token.Less,
tengo.Float{Value: r}, boolValue(l < r))
}
}
// float > float
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := float64(-2); r <= 2.1; r += 0.4 {
testBinaryOp(t, &tengo.Float{Value: l}, token.Greater,
&tengo.Float{Value: r}, boolValue(l > r))
testBinaryOp(t, tengo.Float{Value: l}, token.Greater,
tengo.Float{Value: r}, boolValue(l > r))
}
}
// float <= float
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := float64(-2); r <= 2.1; r += 0.4 {
testBinaryOp(t, &tengo.Float{Value: l}, token.LessEq,
&tengo.Float{Value: r}, boolValue(l <= r))
testBinaryOp(t, tengo.Float{Value: l}, token.LessEq,
tengo.Float{Value: r}, boolValue(l <= r))
}
}
// float >= float
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := float64(-2); r <= 2.1; r += 0.4 {
testBinaryOp(t, &tengo.Float{Value: l}, token.GreaterEq,
&tengo.Float{Value: r}, boolValue(l >= r))
testBinaryOp(t, tengo.Float{Value: l}, token.GreaterEq,
tengo.Float{Value: r}, boolValue(l >= r))
}
}
// float + int
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Float{Value: l}, token.Add,
&tengo.Int{Value: r}, &tengo.Float{Value: l + float64(r)})
testBinaryOp(t, tengo.Float{Value: l}, token.Add,
tengo.Int{Value: r}, tengo.Float{Value: l + float64(r)})
}
}
// float - int
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Float{Value: l}, token.Sub,
&tengo.Int{Value: r}, &tengo.Float{Value: l - float64(r)})
testBinaryOp(t, tengo.Float{Value: l}, token.Sub,
tengo.Int{Value: r}, tengo.Float{Value: l - float64(r)})
}
}
// float * int
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Float{Value: l}, token.Mul,
&tengo.Int{Value: r}, &tengo.Float{Value: l * float64(r)})
testBinaryOp(t, tengo.Float{Value: l}, token.Mul,
tengo.Int{Value: r}, tengo.Float{Value: l * float64(r)})
}
}
@ -320,9 +320,9 @@ func TestFloat_BinaryOp(t *testing.T) {
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := int64(-2); r <= 2; r++ {
if r != 0 {
testBinaryOp(t, &tengo.Float{Value: l}, token.Quo,
&tengo.Int{Value: r},
&tengo.Float{Value: l / float64(r)})
testBinaryOp(t, tengo.Float{Value: l}, token.Quo,
tengo.Int{Value: r},
tengo.Float{Value: l / float64(r)})
}
}
}
@ -330,32 +330,32 @@ func TestFloat_BinaryOp(t *testing.T) {
// float < int
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Float{Value: l}, token.Less,
&tengo.Int{Value: r}, boolValue(l < float64(r)))
testBinaryOp(t, tengo.Float{Value: l}, token.Less,
tengo.Int{Value: r}, boolValue(l < float64(r)))
}
}
// float > int
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Float{Value: l}, token.Greater,
&tengo.Int{Value: r}, boolValue(l > float64(r)))
testBinaryOp(t, tengo.Float{Value: l}, token.Greater,
tengo.Int{Value: r}, boolValue(l > float64(r)))
}
}
// float <= int
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Float{Value: l}, token.LessEq,
&tengo.Int{Value: r}, boolValue(l <= float64(r)))
testBinaryOp(t, tengo.Float{Value: l}, token.LessEq,
tengo.Int{Value: r}, boolValue(l <= float64(r)))
}
}
// float >= int
for l := float64(-2); l <= 2.1; l += 0.4 {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Float{Value: l}, token.GreaterEq,
&tengo.Int{Value: r}, boolValue(l >= float64(r)))
testBinaryOp(t, tengo.Float{Value: l}, token.GreaterEq,
tengo.Int{Value: r}, boolValue(l >= float64(r)))
}
}
}
@ -364,24 +364,24 @@ func TestInt_BinaryOp(t *testing.T) {
// int + int
for l := int64(-2); l <= 2; l++ {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Int{Value: l}, token.Add,
&tengo.Int{Value: r}, &tengo.Int{Value: l + r})
testBinaryOp(t, tengo.Int{Value: l}, token.Add,
tengo.Int{Value: r}, tengo.Int{Value: l + r})
}
}
// int - int
for l := int64(-2); l <= 2; l++ {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Int{Value: l}, token.Sub,
&tengo.Int{Value: r}, &tengo.Int{Value: l - r})
testBinaryOp(t, tengo.Int{Value: l}, token.Sub,
tengo.Int{Value: r}, tengo.Int{Value: l - r})
}
}
// int * int
for l := int64(-2); l <= 2; l++ {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Int{Value: l}, token.Mul,
&tengo.Int{Value: r}, &tengo.Int{Value: l * r})
testBinaryOp(t, tengo.Int{Value: l}, token.Mul,
tengo.Int{Value: r}, tengo.Int{Value: l * r})
}
}
@ -389,8 +389,8 @@ func TestInt_BinaryOp(t *testing.T) {
for l := int64(-2); l <= 2; l++ {
for r := int64(-2); r <= 2; r++ {
if r != 0 {
testBinaryOp(t, &tengo.Int{Value: l}, token.Quo,
&tengo.Int{Value: r}, &tengo.Int{Value: l / r})
testBinaryOp(t, tengo.Int{Value: l}, token.Quo,
tengo.Int{Value: r}, tengo.Int{Value: l / r})
}
}
}
@ -399,243 +399,243 @@ func TestInt_BinaryOp(t *testing.T) {
for l := int64(-4); l <= 4; l++ {
for r := -int64(-4); r <= 4; r++ {
if r == 0 {
testBinaryOp(t, &tengo.Int{Value: l}, token.Rem,
&tengo.Int{Value: r}, &tengo.Int{Value: l % r})
testBinaryOp(t, tengo.Int{Value: l}, token.Rem,
tengo.Int{Value: r}, tengo.Int{Value: l % r})
}
}
}
// int & int
testBinaryOp(t,
&tengo.Int{Value: 0}, token.And, &tengo.Int{Value: 0},
&tengo.Int{Value: int64(0)})
tengo.Int{Value: 0}, token.And, tengo.Int{Value: 0},
tengo.Int{Value: int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.And, &tengo.Int{Value: 0},
&tengo.Int{Value: int64(1) & int64(0)})
tengo.Int{Value: 1}, token.And, tengo.Int{Value: 0},
tengo.Int{Value: int64(1) & int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 0}, token.And, &tengo.Int{Value: 1},
&tengo.Int{Value: int64(0) & int64(1)})
tengo.Int{Value: 0}, token.And, tengo.Int{Value: 1},
tengo.Int{Value: int64(0) & int64(1)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.And, &tengo.Int{Value: 1},
&tengo.Int{Value: int64(1)})
tengo.Int{Value: 1}, token.And, tengo.Int{Value: 1},
tengo.Int{Value: int64(1)})
testBinaryOp(t,
&tengo.Int{Value: 0}, token.And, &tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(0) & int64(0xffffffff)})
tengo.Int{Value: 0}, token.And, tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(0) & int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.And, &tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(1) & int64(0xffffffff)})
tengo.Int{Value: 1}, token.And, tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(1) & int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: int64(0xffffffff)}, token.And,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(0xffffffff)})
tengo.Int{Value: int64(0xffffffff)}, token.And,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: 1984}, token.And,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(1984) & int64(0xffffffff)})
testBinaryOp(t, &tengo.Int{Value: -1984}, token.And,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(-1984) & int64(0xffffffff)})
tengo.Int{Value: 1984}, token.And,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(1984) & int64(0xffffffff)})
testBinaryOp(t, tengo.Int{Value: -1984}, token.And,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(-1984) & int64(0xffffffff)})
// int | int
testBinaryOp(t,
&tengo.Int{Value: 0}, token.Or, &tengo.Int{Value: 0},
&tengo.Int{Value: int64(0)})
tengo.Int{Value: 0}, token.Or, tengo.Int{Value: 0},
tengo.Int{Value: int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.Or, &tengo.Int{Value: 0},
&tengo.Int{Value: int64(1) | int64(0)})
tengo.Int{Value: 1}, token.Or, tengo.Int{Value: 0},
tengo.Int{Value: int64(1) | int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 0}, token.Or, &tengo.Int{Value: 1},
&tengo.Int{Value: int64(0) | int64(1)})
tengo.Int{Value: 0}, token.Or, tengo.Int{Value: 1},
tengo.Int{Value: int64(0) | int64(1)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.Or, &tengo.Int{Value: 1},
&tengo.Int{Value: int64(1)})
tengo.Int{Value: 1}, token.Or, tengo.Int{Value: 1},
tengo.Int{Value: int64(1)})
testBinaryOp(t,
&tengo.Int{Value: 0}, token.Or, &tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(0) | int64(0xffffffff)})
tengo.Int{Value: 0}, token.Or, tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(0) | int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.Or, &tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(1) | int64(0xffffffff)})
tengo.Int{Value: 1}, token.Or, tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(1) | int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: int64(0xffffffff)}, token.Or,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(0xffffffff)})
tengo.Int{Value: int64(0xffffffff)}, token.Or,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: 1984}, token.Or,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(1984) | int64(0xffffffff)})
tengo.Int{Value: 1984}, token.Or,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(1984) | int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: -1984}, token.Or,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(-1984) | int64(0xffffffff)})
tengo.Int{Value: -1984}, token.Or,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(-1984) | int64(0xffffffff)})
// int ^ int
testBinaryOp(t,
&tengo.Int{Value: 0}, token.Xor, &tengo.Int{Value: 0},
&tengo.Int{Value: int64(0)})
tengo.Int{Value: 0}, token.Xor, tengo.Int{Value: 0},
tengo.Int{Value: int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.Xor, &tengo.Int{Value: 0},
&tengo.Int{Value: int64(1) ^ int64(0)})
tengo.Int{Value: 1}, token.Xor, tengo.Int{Value: 0},
tengo.Int{Value: int64(1) ^ int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 0}, token.Xor, &tengo.Int{Value: 1},
&tengo.Int{Value: int64(0) ^ int64(1)})
tengo.Int{Value: 0}, token.Xor, tengo.Int{Value: 1},
tengo.Int{Value: int64(0) ^ int64(1)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.Xor, &tengo.Int{Value: 1},
&tengo.Int{Value: int64(0)})
tengo.Int{Value: 1}, token.Xor, tengo.Int{Value: 1},
tengo.Int{Value: int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 0}, token.Xor, &tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(0) ^ int64(0xffffffff)})
tengo.Int{Value: 0}, token.Xor, tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(0) ^ int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.Xor, &tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(1) ^ int64(0xffffffff)})
tengo.Int{Value: 1}, token.Xor, tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(1) ^ int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: int64(0xffffffff)}, token.Xor,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(0)})
tengo.Int{Value: int64(0xffffffff)}, token.Xor,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 1984}, token.Xor,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(1984) ^ int64(0xffffffff)})
tengo.Int{Value: 1984}, token.Xor,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(1984) ^ int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: -1984}, token.Xor,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(-1984) ^ int64(0xffffffff)})
tengo.Int{Value: -1984}, token.Xor,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(-1984) ^ int64(0xffffffff)})
// int &^ int
testBinaryOp(t,
&tengo.Int{Value: 0}, token.AndNot, &tengo.Int{Value: 0},
&tengo.Int{Value: int64(0)})
tengo.Int{Value: 0}, token.AndNot, tengo.Int{Value: 0},
tengo.Int{Value: int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.AndNot, &tengo.Int{Value: 0},
&tengo.Int{Value: int64(1) &^ int64(0)})
tengo.Int{Value: 1}, token.AndNot, tengo.Int{Value: 0},
tengo.Int{Value: int64(1) &^ int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 0}, token.AndNot,
&tengo.Int{Value: 1}, &tengo.Int{Value: int64(0) &^ int64(1)})
tengo.Int{Value: 0}, token.AndNot,
tengo.Int{Value: 1}, tengo.Int{Value: int64(0) &^ int64(1)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.AndNot, &tengo.Int{Value: 1},
&tengo.Int{Value: int64(0)})
tengo.Int{Value: 1}, token.AndNot, tengo.Int{Value: 1},
tengo.Int{Value: int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 0}, token.AndNot,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(0) &^ int64(0xffffffff)})
tengo.Int{Value: 0}, token.AndNot,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(0) &^ int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.AndNot,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(1) &^ int64(0xffffffff)})
tengo.Int{Value: 1}, token.AndNot,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(1) &^ int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: int64(0xffffffff)}, token.AndNot,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(0)})
tengo.Int{Value: int64(0xffffffff)}, token.AndNot,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(0)})
testBinaryOp(t,
&tengo.Int{Value: 1984}, token.AndNot,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(1984) &^ int64(0xffffffff)})
tengo.Int{Value: 1984}, token.AndNot,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(1984) &^ int64(0xffffffff)})
testBinaryOp(t,
&tengo.Int{Value: -1984}, token.AndNot,
&tengo.Int{Value: int64(0xffffffff)},
&tengo.Int{Value: int64(-1984) &^ int64(0xffffffff)})
tengo.Int{Value: -1984}, token.AndNot,
tengo.Int{Value: int64(0xffffffff)},
tengo.Int{Value: int64(-1984) &^ int64(0xffffffff)})
// int << int
for s := int64(0); s < 64; s++ {
testBinaryOp(t,
&tengo.Int{Value: 0}, token.Shl, &tengo.Int{Value: s},
&tengo.Int{Value: int64(0) << uint(s)})
tengo.Int{Value: 0}, token.Shl, tengo.Int{Value: s},
tengo.Int{Value: int64(0) << uint(s)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.Shl, &tengo.Int{Value: s},
&tengo.Int{Value: int64(1) << uint(s)})
tengo.Int{Value: 1}, token.Shl, tengo.Int{Value: s},
tengo.Int{Value: int64(1) << uint(s)})
testBinaryOp(t,
&tengo.Int{Value: 2}, token.Shl, &tengo.Int{Value: s},
&tengo.Int{Value: int64(2) << uint(s)})
tengo.Int{Value: 2}, token.Shl, tengo.Int{Value: s},
tengo.Int{Value: int64(2) << uint(s)})
testBinaryOp(t,
&tengo.Int{Value: -1}, token.Shl, &tengo.Int{Value: s},
&tengo.Int{Value: int64(-1) << uint(s)})
tengo.Int{Value: -1}, token.Shl, tengo.Int{Value: s},
tengo.Int{Value: int64(-1) << uint(s)})
testBinaryOp(t,
&tengo.Int{Value: -2}, token.Shl, &tengo.Int{Value: s},
&tengo.Int{Value: int64(-2) << uint(s)})
tengo.Int{Value: -2}, token.Shl, tengo.Int{Value: s},
tengo.Int{Value: int64(-2) << uint(s)})
testBinaryOp(t,
&tengo.Int{Value: int64(0xffffffff)}, token.Shl,
&tengo.Int{Value: s},
&tengo.Int{Value: int64(0xffffffff) << uint(s)})
tengo.Int{Value: int64(0xffffffff)}, token.Shl,
tengo.Int{Value: s},
tengo.Int{Value: int64(0xffffffff) << uint(s)})
}
// int >> int
for s := int64(0); s < 64; s++ {
testBinaryOp(t,
&tengo.Int{Value: 0}, token.Shr, &tengo.Int{Value: s},
&tengo.Int{Value: int64(0) >> uint(s)})
tengo.Int{Value: 0}, token.Shr, tengo.Int{Value: s},
tengo.Int{Value: int64(0) >> uint(s)})
testBinaryOp(t,
&tengo.Int{Value: 1}, token.Shr, &tengo.Int{Value: s},
&tengo.Int{Value: int64(1) >> uint(s)})
tengo.Int{Value: 1}, token.Shr, tengo.Int{Value: s},
tengo.Int{Value: int64(1) >> uint(s)})
testBinaryOp(t,
&tengo.Int{Value: 2}, token.Shr, &tengo.Int{Value: s},
&tengo.Int{Value: int64(2) >> uint(s)})
tengo.Int{Value: 2}, token.Shr, tengo.Int{Value: s},
tengo.Int{Value: int64(2) >> uint(s)})
testBinaryOp(t,
&tengo.Int{Value: -1}, token.Shr, &tengo.Int{Value: s},
&tengo.Int{Value: int64(-1) >> uint(s)})
tengo.Int{Value: -1}, token.Shr, tengo.Int{Value: s},
tengo.Int{Value: int64(-1) >> uint(s)})
testBinaryOp(t,
&tengo.Int{Value: -2}, token.Shr, &tengo.Int{Value: s},
&tengo.Int{Value: int64(-2) >> uint(s)})
tengo.Int{Value: -2}, token.Shr, tengo.Int{Value: s},
tengo.Int{Value: int64(-2) >> uint(s)})
testBinaryOp(t,
&tengo.Int{Value: int64(0xffffffff)}, token.Shr,
&tengo.Int{Value: s},
&tengo.Int{Value: int64(0xffffffff) >> uint(s)})
tengo.Int{Value: int64(0xffffffff)}, token.Shr,
tengo.Int{Value: s},
tengo.Int{Value: int64(0xffffffff) >> uint(s)})
}
// int < int
for l := int64(-2); l <= 2; l++ {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Int{Value: l}, token.Less,
&tengo.Int{Value: r}, boolValue(l < r))
testBinaryOp(t, tengo.Int{Value: l}, token.Less,
tengo.Int{Value: r}, boolValue(l < r))
}
}
// int > int
for l := int64(-2); l <= 2; l++ {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Int{Value: l}, token.Greater,
&tengo.Int{Value: r}, boolValue(l > r))
testBinaryOp(t, tengo.Int{Value: l}, token.Greater,
tengo.Int{Value: r}, boolValue(l > r))
}
}
// int <= int
for l := int64(-2); l <= 2; l++ {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Int{Value: l}, token.LessEq,
&tengo.Int{Value: r}, boolValue(l <= r))
testBinaryOp(t, tengo.Int{Value: l}, token.LessEq,
tengo.Int{Value: r}, boolValue(l <= r))
}
}
// int >= int
for l := int64(-2); l <= 2; l++ {
for r := int64(-2); r <= 2; r++ {
testBinaryOp(t, &tengo.Int{Value: l}, token.GreaterEq,
&tengo.Int{Value: r}, boolValue(l >= r))
testBinaryOp(t, tengo.Int{Value: l}, token.GreaterEq,
tengo.Int{Value: r}, boolValue(l >= r))
}
}
// int + float
for l := int64(-2); l <= 2; l++ {
for r := float64(-2); r <= 2.1; r += 0.5 {
testBinaryOp(t, &tengo.Int{Value: l}, token.Add,
&tengo.Float{Value: r},
&tengo.Float{Value: float64(l) + r})
testBinaryOp(t, tengo.Int{Value: l}, token.Add,
tengo.Float{Value: r},
tengo.Float{Value: float64(l) + r})
}
}
// int - float
for l := int64(-2); l <= 2; l++ {
for r := float64(-2); r <= 2.1; r += 0.5 {
testBinaryOp(t, &tengo.Int{Value: l}, token.Sub,
&tengo.Float{Value: r},
&tengo.Float{Value: float64(l) - r})
testBinaryOp(t, tengo.Int{Value: l}, token.Sub,
tengo.Float{Value: r},
tengo.Float{Value: float64(l) - r})
}
}
// int * float
for l := int64(-2); l <= 2; l++ {
for r := float64(-2); r <= 2.1; r += 0.5 {
testBinaryOp(t, &tengo.Int{Value: l}, token.Mul,
&tengo.Float{Value: r},
&tengo.Float{Value: float64(l) * r})
testBinaryOp(t, tengo.Int{Value: l}, token.Mul,
tengo.Float{Value: r},
tengo.Float{Value: float64(l) * r})
}
}
@ -643,9 +643,9 @@ func TestInt_BinaryOp(t *testing.T) {
for l := int64(-2); l <= 2; l++ {
for r := float64(-2); r <= 2.1; r += 0.5 {
if r != 0 {
testBinaryOp(t, &tengo.Int{Value: l}, token.Quo,
&tengo.Float{Value: r},
&tengo.Float{Value: float64(l) / r})
testBinaryOp(t, tengo.Int{Value: l}, token.Quo,
tengo.Float{Value: r},
tengo.Float{Value: float64(l) / r})
}
}
}
@ -653,39 +653,39 @@ func TestInt_BinaryOp(t *testing.T) {
// int < float
for l := int64(-2); l <= 2; l++ {
for r := float64(-2); r <= 2.1; r += 0.5 {
testBinaryOp(t, &tengo.Int{Value: l}, token.Less,
&tengo.Float{Value: r}, boolValue(float64(l) < r))
testBinaryOp(t, tengo.Int{Value: l}, token.Less,
tengo.Float{Value: r}, boolValue(float64(l) < r))
}
}
// int > float
for l := int64(-2); l <= 2; l++ {
for r := float64(-2); r <= 2.1; r += 0.5 {
testBinaryOp(t, &tengo.Int{Value: l}, token.Greater,
&tengo.Float{Value: r}, boolValue(float64(l) > r))
testBinaryOp(t, tengo.Int{Value: l}, token.Greater,
tengo.Float{Value: r}, boolValue(float64(l) > r))
}
}
// int <= float
for l := int64(-2); l <= 2; l++ {
for r := float64(-2); r <= 2.1; r += 0.5 {
testBinaryOp(t, &tengo.Int{Value: l}, token.LessEq,
&tengo.Float{Value: r}, boolValue(float64(l) <= r))
testBinaryOp(t, tengo.Int{Value: l}, token.LessEq,
tengo.Float{Value: r}, boolValue(float64(l) <= r))
}
}
// int >= float
for l := int64(-2); l <= 2; l++ {
for r := float64(-2); r <= 2.1; r += 0.5 {
testBinaryOp(t, &tengo.Int{Value: l}, token.GreaterEq,
&tengo.Float{Value: r}, boolValue(float64(l) >= r))
testBinaryOp(t, tengo.Int{Value: l}, token.GreaterEq,
tengo.Float{Value: r}, boolValue(float64(l) >= r))
}
}
}
func TestMap_Index(t *testing.T) {
m := &tengo.Map{Value: make(map[string]tengo.Object)}
k := &tengo.Int{Value: 1}
k := tengo.Int{Value: 1}
v := &tengo.String{Value: "abcdef"}
err := m.IndexSet(k, v)
@ -709,7 +709,7 @@ func TestString_BinaryOp(t *testing.T) {
rc := []rune(rstr)[r]
testBinaryOp(t, &tengo.String{Value: ls}, token.Add,
&tengo.Char{Value: rc},
tengo.Char{Value: rc},
&tengo.String{Value: ls + string(rc)})
}
}

View file

@ -134,15 +134,15 @@ func Equal(
}
case []tengo.Object:
equalObjectSlice(t, expected, actual.([]tengo.Object), msg...)
case *tengo.Int:
Equal(t, expected.Value, actual.(*tengo.Int).Value, msg...)
case *tengo.Float:
Equal(t, expected.Value, actual.(*tengo.Float).Value, msg...)
case tengo.Int:
Equal(t, expected.Value, actual.(tengo.Int).Value, msg...)
case tengo.Float:
Equal(t, expected.Value, actual.(tengo.Float).Value, msg...)
case *tengo.String:
Equal(t, expected.Value, actual.(*tengo.String).Value, msg...)
case *tengo.Char:
Equal(t, expected.Value, actual.(*tengo.Char).Value, msg...)
case *tengo.Bool:
case tengo.Char:
Equal(t, expected.Value, actual.(tengo.Char).Value, msg...)
case tengo.Bool:
if expected != actual {
failExpectedActual(t, expected, actual, msg...)
}

View file

@ -24,12 +24,12 @@ func TestScript_Add(t *testing.T) {
func(args ...tengo.Object) (ret tengo.Object, err error) {
if len(args) > 0 {
switch arg := args[0].(type) {
case *tengo.Int:
return &tengo.Int{Value: arg.Value + 1}, nil
case tengo.Int:
return tengo.Int{Value: arg.Value + 1}, nil
}
}
return &tengo.Int{Value: 0}, nil
return tengo.Int{Value: 0}, nil
}))
c, err := s.Compile()
require.NoError(t, err)
@ -177,7 +177,7 @@ e := mod1.double(s)
err error,
) {
arg0, _ := tengo.ToInt64(args[0])
ret = &tengo.Int{Value: arg0 * 2}
ret = tengo.Int{Value: arg0 * 2}
return
},
},
@ -227,7 +227,7 @@ e := mod1.double(s)
}
type Counter struct {
tengo.ObjectImpl
tengo.PtrObjectImpl
value int64
}
@ -251,7 +251,7 @@ func (o *Counter) BinaryOp(
case token.Sub:
return &Counter{value: o.value - rhs.value}, nil
}
case *tengo.Int:
case tengo.Int:
switch op {
case token.Add:
return &Counter{value: o.value + rhs.Value}, nil
@ -280,7 +280,7 @@ func (o *Counter) Copy() tengo.Object {
}
func (o *Counter) Call(_ ...tengo.Object) (tengo.Object, error) {
return &tengo.Int{Value: o.value}, nil
return tengo.Int{Value: o.value}, nil
}
func (o *Counter) CanCall() bool {

View file

@ -24,7 +24,7 @@ func FuncARI(fn func() int) tengo.CallableFunc {
if len(args) != 0 {
return nil, tengo.ErrWrongNumArguments
}
return &tengo.Int{Value: int64(fn())}, nil
return tengo.Int{Value: int64(fn())}, nil
}
}
@ -35,7 +35,7 @@ func FuncARI64(fn func() int64) tengo.CallableFunc {
if len(args) != 0 {
return nil, tengo.ErrWrongNumArguments
}
return &tengo.Int{Value: fn()}, nil
return tengo.Int{Value: fn()}, nil
}
}
@ -55,7 +55,7 @@ func FuncAI64RI64(fn func(int64) int64) tengo.CallableFunc {
Found: args[0].TypeName(),
}
}
return &tengo.Int{Value: fn(i1)}, nil
return tengo.Int{Value: fn(i1)}, nil
}
}
@ -163,7 +163,7 @@ func FuncARF(fn func() float64) tengo.CallableFunc {
if len(args) != 0 {
return nil, tengo.ErrWrongNumArguments
}
return &tengo.Float{Value: fn()}, nil
return tengo.Float{Value: fn()}, nil
}
}
@ -198,7 +198,7 @@ func FuncARIsE(fn func() ([]int, error)) tengo.CallableFunc {
}
arr := &tengo.Array{}
for _, v := range res {
arr.Value = append(arr.Value, &tengo.Int{Value: int64(v)})
arr.Value = append(arr.Value, tengo.Int{Value: int64(v)})
}
return arr, nil
}
@ -222,7 +222,7 @@ func FuncAIRIs(fn func(int) []int) tengo.CallableFunc {
res := fn(i1)
arr := &tengo.Array{}
for _, v := range res {
arr.Value = append(arr.Value, &tengo.Int{Value: int64(v)})
arr.Value = append(arr.Value, tengo.Int{Value: int64(v)})
}
return arr, nil
}
@ -243,7 +243,7 @@ func FuncAFRF(fn func(float64) float64) tengo.CallableFunc {
Found: args[0].TypeName(),
}
}
return &tengo.Float{Value: fn(f1)}, nil
return tengo.Float{Value: fn(f1)}, nil
}
}
@ -281,7 +281,7 @@ func FuncAIRF(fn func(int) float64) tengo.CallableFunc {
Found: args[0].TypeName(),
}
}
return &tengo.Float{Value: fn(i1)}, nil
return tengo.Float{Value: fn(i1)}, nil
}
}
@ -300,7 +300,7 @@ func FuncAFRI(fn func(float64) int) tengo.CallableFunc {
Found: args[0].TypeName(),
}
}
return &tengo.Int{Value: int64(fn(f1))}, nil
return tengo.Int{Value: int64(fn(f1))}, nil
}
}
@ -327,7 +327,7 @@ func FuncAFFRF(fn func(float64, float64) float64) tengo.CallableFunc {
Found: args[1].TypeName(),
}
}
return &tengo.Float{Value: fn(f1, f2)}, nil
return tengo.Float{Value: fn(f1, f2)}, nil
}
}
@ -354,7 +354,7 @@ func FuncAIFRF(fn func(int, float64) float64) tengo.CallableFunc {
Found: args[1].TypeName(),
}
}
return &tengo.Float{Value: fn(i1, f2)}, nil
return tengo.Float{Value: fn(i1, f2)}, nil
}
}
@ -381,7 +381,7 @@ func FuncAFIRF(fn func(float64, int) float64) tengo.CallableFunc {
Found: args[1].TypeName(),
}
}
return &tengo.Float{Value: fn(f1, i2)}, nil
return tengo.Float{Value: fn(f1, i2)}, nil
}
}
@ -662,7 +662,7 @@ func FuncASSRI(fn func(string, string) int) tengo.CallableFunc {
Found: args[0].TypeName(),
}
}
return &tengo.Int{Value: int64(fn(s1, s2))}, nil
return tengo.Int{Value: int64(fn(s1, s2))}, nil
}
}
@ -922,7 +922,7 @@ func FuncAYRIE(fn func([]byte) (int, error)) tengo.CallableFunc {
if err != nil {
return wrapError(err), nil
}
return &tengo.Int{Value: int64(res)}, nil
return tengo.Int{Value: int64(res)}, nil
}
}
@ -965,7 +965,7 @@ func FuncASRIE(fn func(string) (int, error)) tengo.CallableFunc {
if err != nil {
return wrapError(err), nil
}
return &tengo.Int{Value: int64(res)}, nil
return tengo.Int{Value: int64(res)}, nil
}
}

View file

@ -13,7 +13,7 @@ import (
func TestFuncAIR(t *testing.T) {
uf := stdlib.FuncAIR(func(int) {})
ret, err := funcCall(uf, &tengo.Int{Value: 10})
ret, err := funcCall(uf, tengo.Int{Value: 10})
require.NoError(t, err)
require.Equal(t, tengo.UndefinedValue, ret)
_, err = funcCall(uf)
@ -33,7 +33,7 @@ func TestFuncARI(t *testing.T) {
uf := stdlib.FuncARI(func() int { return 10 })
ret, err := funcCall(uf)
require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 10}, ret)
require.Equal(t, tengo.Int{Value: 10}, ret)
_, err = funcCall(uf, tengo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err)
}
@ -59,8 +59,8 @@ func TestFuncARIsE(t *testing.T) {
})
ret, err := funcCall(uf)
require.NoError(t, err)
require.Equal(t, array(&tengo.Int{Value: 1},
&tengo.Int{Value: 2}, &tengo.Int{Value: 3}), ret)
require.Equal(t, array(tengo.Int{Value: 1},
tengo.Int{Value: 2}, tengo.Int{Value: 3}), ret)
uf = stdlib.FuncARIsE(func() ([]int, error) {
return nil, errors.New("some error")
})
@ -146,13 +146,13 @@ func TestFuncASRSs(t *testing.T) {
func TestFuncASI64RE(t *testing.T) {
uf := stdlib.FuncASI64RE(func(a string, b int64) error { return nil })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}, &tengo.Int{Value: 5})
ret, err := funcCall(uf, &tengo.String{Value: "foo"}, tengo.Int{Value: 5})
require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret)
uf = stdlib.FuncASI64RE(func(a string, b int64) error {
return errors.New("some error")
})
ret, err = funcCall(uf, &tengo.String{Value: "foo"}, &tengo.Int{Value: 5})
ret, err = funcCall(uf, &tengo.String{Value: "foo"}, tengo.Int{Value: 5})
require.NoError(t, err)
require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret)
@ -162,13 +162,13 @@ func TestFuncASI64RE(t *testing.T) {
func TestFuncAIIRE(t *testing.T) {
uf := stdlib.FuncAIIRE(func(a, b int) error { return nil })
ret, err := funcCall(uf, &tengo.Int{Value: 5}, &tengo.Int{Value: 7})
ret, err := funcCall(uf, tengo.Int{Value: 5}, tengo.Int{Value: 7})
require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret)
uf = stdlib.FuncAIIRE(func(a, b int) error {
return errors.New("some error")
})
ret, err = funcCall(uf, &tengo.Int{Value: 5}, &tengo.Int{Value: 7})
ret, err = funcCall(uf, tengo.Int{Value: 5}, tengo.Int{Value: 7})
require.NoError(t, err)
require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret)
@ -178,15 +178,15 @@ func TestFuncAIIRE(t *testing.T) {
func TestFuncASIIRE(t *testing.T) {
uf := stdlib.FuncASIIRE(func(a string, b, c int) error { return nil })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}, &tengo.Int{Value: 5},
&tengo.Int{Value: 7})
ret, err := funcCall(uf, &tengo.String{Value: "foo"}, tengo.Int{Value: 5},
tengo.Int{Value: 7})
require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret)
uf = stdlib.FuncASIIRE(func(a string, b, c int) error {
return errors.New("some error")
})
ret, err = funcCall(uf, &tengo.String{Value: "foo"}, &tengo.Int{Value: 5},
&tengo.Int{Value: 7})
ret, err = funcCall(uf, &tengo.String{Value: "foo"}, tengo.Int{Value: 5},
tengo.Int{Value: 7})
require.NoError(t, err)
require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret)
@ -244,16 +244,16 @@ func TestFuncARF(t *testing.T) {
uf := stdlib.FuncARF(func() float64 { return 10.0 })
ret, err := funcCall(uf)
require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 10.0}, ret)
require.Equal(t, tengo.Float{Value: 10.0}, ret)
_, err = funcCall(uf, tengo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err)
}
func TestFuncAFRF(t *testing.T) {
uf := stdlib.FuncAFRF(func(a float64) float64 { return a })
ret, err := funcCall(uf, &tengo.Float{Value: 10.0})
ret, err := funcCall(uf, tengo.Float{Value: 10.0})
require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 10.0}, ret)
require.Equal(t, tengo.Float{Value: 10.0}, ret)
_, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue, tengo.TrueValue)
@ -264,9 +264,9 @@ func TestFuncAIRF(t *testing.T) {
uf := stdlib.FuncAIRF(func(a int) float64 {
return float64(a)
})
ret, err := funcCall(uf, &tengo.Int{Value: 10.0})
ret, err := funcCall(uf, tengo.Int{Value: 10.0})
require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 10.0}, ret)
require.Equal(t, tengo.Float{Value: 10.0}, ret)
_, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue, tengo.TrueValue)
@ -277,9 +277,9 @@ func TestFuncAFRI(t *testing.T) {
uf := stdlib.FuncAFRI(func(a float64) int {
return int(a)
})
ret, err := funcCall(uf, &tengo.Float{Value: 10.5})
ret, err := funcCall(uf, tengo.Float{Value: 10.5})
require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 10}, ret)
require.Equal(t, tengo.Int{Value: 10}, ret)
_, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue, tengo.TrueValue)
@ -290,7 +290,7 @@ func TestFuncAFRB(t *testing.T) {
uf := stdlib.FuncAFRB(func(a float64) bool {
return a > 0.0
})
ret, err := funcCall(uf, &tengo.Float{Value: 0.1})
ret, err := funcCall(uf, tengo.Float{Value: 0.1})
require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret)
_, err = funcCall(uf)
@ -303,10 +303,10 @@ func TestFuncAFFRF(t *testing.T) {
uf := stdlib.FuncAFFRF(func(a, b float64) float64 {
return a + b
})
ret, err := funcCall(uf, &tengo.Float{Value: 10.0},
&tengo.Float{Value: 20.0})
ret, err := funcCall(uf, tengo.Float{Value: 10.0},
tengo.Float{Value: 20.0})
require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 30.0}, ret)
require.Equal(t, tengo.Float{Value: 30.0}, ret)
_, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue)
@ -317,7 +317,7 @@ func TestFuncASIRS(t *testing.T) {
uf := stdlib.FuncASIRS(func(a string, b int) string {
return strings.Repeat(a, b)
})
ret, err := funcCall(uf, &tengo.String{Value: "ab"}, &tengo.Int{Value: 2})
ret, err := funcCall(uf, &tengo.String{Value: "ab"}, tengo.Int{Value: 2})
require.NoError(t, err)
require.Equal(t, &tengo.String{Value: "abab"}, ret)
_, err = funcCall(uf)
@ -330,9 +330,9 @@ func TestFuncAIFRF(t *testing.T) {
uf := stdlib.FuncAIFRF(func(a int, b float64) float64 {
return float64(a) + b
})
ret, err := funcCall(uf, &tengo.Int{Value: 10}, &tengo.Float{Value: 20.0})
ret, err := funcCall(uf, tengo.Int{Value: 10}, tengo.Float{Value: 20.0})
require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 30.0}, ret)
require.Equal(t, tengo.Float{Value: 30.0}, ret)
_, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue)
@ -343,9 +343,9 @@ func TestFuncAFIRF(t *testing.T) {
uf := stdlib.FuncAFIRF(func(a float64, b int) float64 {
return a + float64(b)
})
ret, err := funcCall(uf, &tengo.Float{Value: 10.0}, &tengo.Int{Value: 20})
ret, err := funcCall(uf, tengo.Float{Value: 10.0}, tengo.Int{Value: 20})
require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 30.0}, ret)
require.Equal(t, tengo.Float{Value: 30.0}, ret)
_, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue)
@ -356,7 +356,7 @@ func TestFuncAFIRB(t *testing.T) {
uf := stdlib.FuncAFIRB(func(a float64, b int) bool {
return a < float64(b)
})
ret, err := funcCall(uf, &tengo.Float{Value: 10.0}, &tengo.Int{Value: 20})
ret, err := funcCall(uf, tengo.Float{Value: 10.0}, tengo.Int{Value: 20})
require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret)
_, err = funcCall(uf)
@ -369,14 +369,14 @@ func TestFuncAIRSsE(t *testing.T) {
uf := stdlib.FuncAIRSsE(func(a int) ([]string, error) {
return []string{"foo", "bar"}, nil
})
ret, err := funcCall(uf, &tengo.Int{Value: 10})
ret, err := funcCall(uf, tengo.Int{Value: 10})
require.NoError(t, err)
require.Equal(t, array(&tengo.String{Value: "foo"},
&tengo.String{Value: "bar"}), ret)
uf = stdlib.FuncAIRSsE(func(a int) ([]string, error) {
return nil, errors.New("some error")
})
ret, err = funcCall(uf, &tengo.Int{Value: 10})
ret, err = funcCall(uf, tengo.Int{Value: 10})
require.NoError(t, err)
require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret)
@ -402,7 +402,7 @@ func TestFuncASSIRSs(t *testing.T) {
return []string{a, b, strconv.Itoa(c)}
})
ret, err := funcCall(uf, &tengo.String{Value: "foo"},
&tengo.String{Value: "bar"}, &tengo.Int{Value: 5})
&tengo.String{Value: "bar"}, tengo.Int{Value: 5})
require.NoError(t, err)
require.Equal(t, array(&tengo.String{Value: "foo"},
&tengo.String{Value: "bar"}, &tengo.String{Value: "5"}), ret)
@ -441,7 +441,7 @@ func TestFuncASRIE(t *testing.T) {
uf := stdlib.FuncASRIE(func(a string) (int, error) { return 5, nil })
ret, err := funcCall(uf, &tengo.String{Value: "foo"})
require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 5}, ret)
require.Equal(t, tengo.Int{Value: 5}, ret)
uf = stdlib.FuncASRIE(func(a string) (int, error) {
return 0, errors.New("some error")
})
@ -457,7 +457,7 @@ func TestFuncAYRIE(t *testing.T) {
uf := stdlib.FuncAYRIE(func(a []byte) (int, error) { return 5, nil })
ret, err := funcCall(uf, &tengo.Bytes{Value: []byte("foo")})
require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 5}, ret)
require.Equal(t, tengo.Int{Value: 5}, ret)
uf = stdlib.FuncAYRIE(func(a []byte) (int, error) {
return 0, errors.New("some error")
})
@ -474,7 +474,7 @@ func TestFuncASSRI(t *testing.T) {
ret, err := funcCall(uf,
&tengo.String{Value: "foo"}, &tengo.String{Value: "bar"})
require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 6}, ret)
require.Equal(t, tengo.Int{Value: 6}, ret)
_, err = funcCall(uf, &tengo.String{Value: "foo"})
require.Equal(t, tengo.ErrWrongNumArguments, err)
}
@ -501,7 +501,7 @@ func TestFuncASSRB(t *testing.T) {
func TestFuncAIRS(t *testing.T) {
uf := stdlib.FuncAIRS(func(a int) string { return strconv.Itoa(a) })
ret, err := funcCall(uf, &tengo.Int{Value: 55})
ret, err := funcCall(uf, tengo.Int{Value: 55})
require.NoError(t, err)
require.Equal(t, &tengo.String{Value: "55"}, ret)
_, err = funcCall(uf)
@ -510,16 +510,16 @@ func TestFuncAIRS(t *testing.T) {
func TestFuncAIRIs(t *testing.T) {
uf := stdlib.FuncAIRIs(func(a int) []int { return []int{a, a} })
ret, err := funcCall(uf, &tengo.Int{Value: 55})
ret, err := funcCall(uf, tengo.Int{Value: 55})
require.NoError(t, err)
require.Equal(t, array(&tengo.Int{Value: 55}, &tengo.Int{Value: 55}), ret)
require.Equal(t, array(tengo.Int{Value: 55}, tengo.Int{Value: 55}), ret)
_, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err)
}
func TestFuncAI64R(t *testing.T) {
uf := stdlib.FuncAIR(func(a int) {})
ret, err := funcCall(uf, &tengo.Int{Value: 55})
ret, err := funcCall(uf, tengo.Int{Value: 55})
require.NoError(t, err)
require.Equal(t, tengo.UndefinedValue, ret)
_, err = funcCall(uf)
@ -530,8 +530,8 @@ func TestFuncARI64(t *testing.T) {
uf := stdlib.FuncARI64(func() int64 { return 55 })
ret, err := funcCall(uf)
require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 55}, ret)
_, err = funcCall(uf, &tengo.Int{Value: 55})
require.Equal(t, tengo.Int{Value: 55}, ret)
_, err = funcCall(uf, tengo.Int{Value: 55})
require.Equal(t, tengo.ErrWrongNumArguments, err)
}
@ -550,9 +550,9 @@ func TestFuncASsSRS(t *testing.T) {
func TestFuncAI64RI64(t *testing.T) {
uf := stdlib.FuncAI64RI64(func(a int64) int64 { return a * 2 })
ret, err := funcCall(uf, &tengo.Int{Value: 55})
ret, err := funcCall(uf, tengo.Int{Value: 55})
require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 110}, ret)
require.Equal(t, tengo.Int{Value: 110}, ret)
_, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err)
}

View file

@ -211,7 +211,7 @@ func (d *decodeState) literal() (tengo.Object, error) {
panic(phasePanicMsg)
}
n, _ := strconv.ParseFloat(string(item), 10)
return &tengo.Float{Value: n}, nil
return tengo.Float{Value: n}, nil
}
}

View file

@ -193,7 +193,7 @@ func Encode(o tengo.Object) ([]byte, error) {
idx++
}
b = append(b, '}')
case *tengo.Bool:
case tengo.Bool:
if o.IsFalsy() {
b = strconv.AppendBool(b, false)
} else {
@ -206,9 +206,9 @@ func Encode(o tengo.Object) ([]byte, error) {
base64.StdEncoding.Encode(dst, o.Value)
b = append(b, dst...)
b = append(b, '"')
case *tengo.Char:
case tengo.Char:
b = strconv.AppendInt(b, int64(o.Value), 10)
case *tengo.Float:
case tengo.Float:
var y []byte
f := o.Value
@ -236,7 +236,7 @@ func Encode(o tengo.Object) ([]byte, error) {
}
b = append(b, y...)
case *tengo.Int:
case tengo.Int:
b = strconv.AppendInt(b, o.Value, 10)
case *tengo.String:
// string encoding bug is fixed with newly introduced function

View file

@ -7,17 +7,17 @@ import (
)
var mathModule = map[string]tengo.Object{
"e": &tengo.Float{Value: math.E},
"pi": &tengo.Float{Value: math.Pi},
"phi": &tengo.Float{Value: math.Phi},
"sqrt2": &tengo.Float{Value: math.Sqrt2},
"sqrtE": &tengo.Float{Value: math.SqrtE},
"sqrtPi": &tengo.Float{Value: math.SqrtPi},
"sqrtPhi": &tengo.Float{Value: math.SqrtPhi},
"ln2": &tengo.Float{Value: math.Ln2},
"log2E": &tengo.Float{Value: math.Log2E},
"ln10": &tengo.Float{Value: math.Ln10},
"log10E": &tengo.Float{Value: math.Log10E},
"e": tengo.Float{Value: math.E},
"pi": tengo.Float{Value: math.Pi},
"phi": tengo.Float{Value: math.Phi},
"sqrt2": tengo.Float{Value: math.Sqrt2},
"sqrtE": tengo.Float{Value: math.SqrtE},
"sqrtPi": tengo.Float{Value: math.SqrtPi},
"sqrtPhi": tengo.Float{Value: math.SqrtPhi},
"ln2": tengo.Float{Value: math.Ln2},
"log2E": tengo.Float{Value: math.Log2E},
"ln10": tengo.Float{Value: math.Ln10},
"log10E": tengo.Float{Value: math.Log10E},
"abs": &tengo.UserFunction{
Name: "abs",
Value: FuncAFRF(math.Abs),

View file

@ -11,34 +11,34 @@ import (
)
var osModule = map[string]tengo.Object{
"o_rdonly": &tengo.Int{Value: int64(os.O_RDONLY)},
"o_wronly": &tengo.Int{Value: int64(os.O_WRONLY)},
"o_rdwr": &tengo.Int{Value: int64(os.O_RDWR)},
"o_append": &tengo.Int{Value: int64(os.O_APPEND)},
"o_create": &tengo.Int{Value: int64(os.O_CREATE)},
"o_excl": &tengo.Int{Value: int64(os.O_EXCL)},
"o_sync": &tengo.Int{Value: int64(os.O_SYNC)},
"o_trunc": &tengo.Int{Value: int64(os.O_TRUNC)},
"mode_dir": &tengo.Int{Value: int64(os.ModeDir)},
"mode_append": &tengo.Int{Value: int64(os.ModeAppend)},
"mode_exclusive": &tengo.Int{Value: int64(os.ModeExclusive)},
"mode_temporary": &tengo.Int{Value: int64(os.ModeTemporary)},
"mode_symlink": &tengo.Int{Value: int64(os.ModeSymlink)},
"mode_device": &tengo.Int{Value: int64(os.ModeDevice)},
"mode_named_pipe": &tengo.Int{Value: int64(os.ModeNamedPipe)},
"mode_socket": &tengo.Int{Value: int64(os.ModeSocket)},
"mode_setuid": &tengo.Int{Value: int64(os.ModeSetuid)},
"mode_setgui": &tengo.Int{Value: int64(os.ModeSetgid)},
"mode_char_device": &tengo.Int{Value: int64(os.ModeCharDevice)},
"mode_sticky": &tengo.Int{Value: int64(os.ModeSticky)},
"mode_type": &tengo.Int{Value: int64(os.ModeType)},
"mode_perm": &tengo.Int{Value: int64(os.ModePerm)},
"path_separator": &tengo.Char{Value: os.PathSeparator},
"path_list_separator": &tengo.Char{Value: os.PathListSeparator},
"o_rdonly": tengo.Int{Value: int64(os.O_RDONLY)},
"o_wronly": tengo.Int{Value: int64(os.O_WRONLY)},
"o_rdwr": tengo.Int{Value: int64(os.O_RDWR)},
"o_append": tengo.Int{Value: int64(os.O_APPEND)},
"o_create": tengo.Int{Value: int64(os.O_CREATE)},
"o_excl": tengo.Int{Value: int64(os.O_EXCL)},
"o_sync": tengo.Int{Value: int64(os.O_SYNC)},
"o_trunc": tengo.Int{Value: int64(os.O_TRUNC)},
"mode_dir": tengo.Int{Value: int64(os.ModeDir)},
"mode_append": tengo.Int{Value: int64(os.ModeAppend)},
"mode_exclusive": tengo.Int{Value: int64(os.ModeExclusive)},
"mode_temporary": tengo.Int{Value: int64(os.ModeTemporary)},
"mode_symlink": tengo.Int{Value: int64(os.ModeSymlink)},
"mode_device": tengo.Int{Value: int64(os.ModeDevice)},
"mode_named_pipe": tengo.Int{Value: int64(os.ModeNamedPipe)},
"mode_socket": tengo.Int{Value: int64(os.ModeSocket)},
"mode_setuid": tengo.Int{Value: int64(os.ModeSetuid)},
"mode_setgui": tengo.Int{Value: int64(os.ModeSetgid)},
"mode_char_device": tengo.Int{Value: int64(os.ModeCharDevice)},
"mode_sticky": tengo.Int{Value: int64(os.ModeSticky)},
"mode_type": tengo.Int{Value: int64(os.ModeType)},
"mode_perm": tengo.Int{Value: int64(os.ModePerm)},
"path_separator": tengo.Char{Value: os.PathSeparator},
"path_list_separator": tengo.Char{Value: os.PathListSeparator},
"dev_null": &tengo.String{Value: os.DevNull},
"seek_set": &tengo.Int{Value: int64(io.SeekStart)},
"seek_cur": &tengo.Int{Value: int64(io.SeekCurrent)},
"seek_end": &tengo.Int{Value: int64(io.SeekEnd)},
"seek_set": tengo.Int{Value: int64(io.SeekStart)},
"seek_cur": tengo.Int{Value: int64(io.SeekCurrent)},
"seek_end": tengo.Int{Value: int64(io.SeekEnd)},
"args": &tengo.UserFunction{
Name: "args",
Value: osArgs,
@ -242,8 +242,8 @@ func osStat(args ...tengo.Object) (ret tengo.Object, err error) {
Value: map[string]tengo.Object{
"name": &tengo.String{Value: stat.Name()},
"mtime": &tengo.Time{Value: stat.ModTime()},
"size": &tengo.Int{Value: stat.Size()},
"mode": &tengo.Int{Value: int64(stat.Mode())},
"size": tengo.Int{Value: stat.Size()},
"mode": tengo.Int{Value: int64(stat.Mode())},
},
}
if stat.IsDir() {

View file

@ -99,7 +99,7 @@ func makeOSFile(file *os.File) *tengo.ImmutableMap {
if err != nil {
return wrapError(err), nil
}
return &tengo.Int{Value: res}, nil
return tengo.Int{Value: res}, nil
},
},
// stat() => imap(fileinfo)/error

View file

@ -50,8 +50,8 @@ func TestFileStatFile(t *testing.T) {
Value: map[string]tengo.Object{
"name": &tengo.String{Value: stat.Name()},
"mtime": &tengo.Time{Value: stat.ModTime()},
"size": &tengo.Int{Value: stat.Size()},
"mode": &tengo.Int{Value: int64(stat.Mode())},
"size": tengo.Int{Value: stat.Size()},
"mode": tengo.Int{Value: int64(stat.Mode())},
"directory": tengo.FalseValue,
},
})
@ -69,8 +69,8 @@ func TestFileStatDir(t *testing.T) {
Value: map[string]tengo.Object{
"name": &tengo.String{Value: stat.Name()},
"mtime": &tengo.Time{Value: stat.ModTime()},
"size": &tengo.Int{Value: stat.Size()},
"mode": &tengo.Int{Value: int64(stat.Mode())},
"size": tengo.Int{Value: stat.Size()},
"mode": tengo.Int{Value: int64(stat.Mode())},
"directory": tengo.TrueValue,
},
})

View file

@ -54,7 +54,7 @@ var randModule = map[string]tengo.Object{
ret = wrapError(err)
return
}
return &tengo.Int{Value: int64(res)}, nil
return tengo.Int{Value: int64(res)}, nil
},
},
"rand": &tengo.UserFunction{
@ -130,7 +130,7 @@ func randRand(r *rand.Rand) *tengo.ImmutableMap {
ret = wrapError(err)
return
}
return &tengo.Int{Value: int64(res)}, nil
return tengo.Int{Value: int64(res)}, nil
},
},
},

View file

@ -172,20 +172,20 @@ func object(v interface{}) tengo.Object {
case string:
return &tengo.String{Value: v}
case int64:
return &tengo.Int{Value: v}
return tengo.Int{Value: v}
case int: // for convenience
return &tengo.Int{Value: int64(v)}
return tengo.Int{Value: int64(v)}
case bool:
if v {
return tengo.TrueValue
}
return tengo.FalseValue
case rune:
return &tengo.Char{Value: v}
return tengo.Char{Value: v}
case byte: // for convenience
return &tengo.Char{Value: rune(v)}
return tengo.Char{Value: rune(v)}
case float64:
return &tengo.Float{Value: v}
return tengo.Float{Value: v}
case []byte:
return &tengo.Bytes{Value: v}
case MAP:
@ -221,7 +221,7 @@ func object(v interface{}) tengo.Object {
case []int:
var objs []tengo.Object
for _, e := range v {
objs = append(objs, &tengo.Int{Value: int64(e)})
objs = append(objs, tengo.Int{Value: int64(e)})
}
return &tengo.Array{Value: objs}

View file

@ -287,8 +287,8 @@ func textREFind(args ...tengo.Object) (ret tengo.Object, err error) {
arr.Value = append(arr.Value,
&tengo.ImmutableMap{Value: map[string]tengo.Object{
"text": &tengo.String{Value: s2[m[i]:m[i+1]]},
"begin": &tengo.Int{Value: int64(m[i])},
"end": &tengo.Int{Value: int64(m[i+1])},
"begin": tengo.Int{Value: int64(m[i])},
"end": tengo.Int{Value: int64(m[i+1])},
}})
}
@ -319,8 +319,8 @@ func textREFind(args ...tengo.Object) (ret tengo.Object, err error) {
subMatch.Value = append(subMatch.Value,
&tengo.ImmutableMap{Value: map[string]tengo.Object{
"text": &tengo.String{Value: s2[m[i]:m[i+1]]},
"begin": &tengo.Int{Value: int64(m[i])},
"end": &tengo.Int{Value: int64(m[i+1])},
"begin": tengo.Int{Value: int64(m[i])},
"end": tengo.Int{Value: int64(m[i+1])},
}})
}
@ -806,7 +806,7 @@ func textFormatBool(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
b1, ok := args[0].(*tengo.Bool)
b1, ok := args[0].(tengo.Bool)
if !ok {
err = tengo.ErrInvalidArgumentType{
Name: "first",
@ -831,7 +831,7 @@ func textFormatFloat(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
f1, ok := args[0].(*tengo.Float)
f1, ok := args[0].(tengo.Float)
if !ok {
err = tengo.ErrInvalidArgumentType{
Name: "first",
@ -882,7 +882,7 @@ func textFormatInt(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
i1, ok := args[0].(*tengo.Int)
i1, ok := args[0].(tengo.Int)
if !ok {
err = tengo.ErrInvalidArgumentType{
Name: "first",
@ -970,7 +970,7 @@ func textParseFloat(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
ret = &tengo.Float{Value: parsed}
ret = tengo.Float{Value: parsed}
return
}
@ -1017,7 +1017,7 @@ func textParseInt(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
ret = &tengo.Int{Value: parsed}
ret = tengo.Int{Value: parsed}
return
}

View file

@ -78,10 +78,10 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
"text": &tengo.String{
Value: s1[m[i]:m[i+1]],
},
"begin": &tengo.Int{
"begin": tengo.Int{
Value: int64(m[i]),
},
"end": &tengo.Int{
"end": tengo.Int{
Value: int64(m[i+1]),
},
}})
@ -117,10 +117,10 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
"text": &tengo.String{
Value: s1[m[i]:m[i+1]],
},
"begin": &tengo.Int{
"begin": tengo.Int{
Value: int64(m[i]),
},
"end": &tengo.Int{
"end": tengo.Int{
Value: int64(m[i+1]),
},
}})

View file

@ -22,24 +22,24 @@ var timesModule = map[string]tengo.Object{
"format_stamp_milli": &tengo.String{Value: time.StampMilli},
"format_stamp_micro": &tengo.String{Value: time.StampMicro},
"format_stamp_nano": &tengo.String{Value: time.StampNano},
"nanosecond": &tengo.Int{Value: int64(time.Nanosecond)},
"microsecond": &tengo.Int{Value: int64(time.Microsecond)},
"millisecond": &tengo.Int{Value: int64(time.Millisecond)},
"second": &tengo.Int{Value: int64(time.Second)},
"minute": &tengo.Int{Value: int64(time.Minute)},
"hour": &tengo.Int{Value: int64(time.Hour)},
"january": &tengo.Int{Value: int64(time.January)},
"february": &tengo.Int{Value: int64(time.February)},
"march": &tengo.Int{Value: int64(time.March)},
"april": &tengo.Int{Value: int64(time.April)},
"may": &tengo.Int{Value: int64(time.May)},
"june": &tengo.Int{Value: int64(time.June)},
"july": &tengo.Int{Value: int64(time.July)},
"august": &tengo.Int{Value: int64(time.August)},
"september": &tengo.Int{Value: int64(time.September)},
"october": &tengo.Int{Value: int64(time.October)},
"november": &tengo.Int{Value: int64(time.November)},
"december": &tengo.Int{Value: int64(time.December)},
"nanosecond": tengo.Int{Value: int64(time.Nanosecond)},
"microsecond": tengo.Int{Value: int64(time.Microsecond)},
"millisecond": tengo.Int{Value: int64(time.Millisecond)},
"second": tengo.Int{Value: int64(time.Second)},
"minute": tengo.Int{Value: int64(time.Minute)},
"hour": tengo.Int{Value: int64(time.Hour)},
"january": tengo.Int{Value: int64(time.January)},
"february": tengo.Int{Value: int64(time.February)},
"march": tengo.Int{Value: int64(time.March)},
"april": tengo.Int{Value: int64(time.April)},
"may": tengo.Int{Value: int64(time.May)},
"june": tengo.Int{Value: int64(time.June)},
"july": tengo.Int{Value: int64(time.July)},
"august": tengo.Int{Value: int64(time.August)},
"september": tengo.Int{Value: int64(time.September)},
"october": tengo.Int{Value: int64(time.October)},
"november": tengo.Int{Value: int64(time.November)},
"december": tengo.Int{Value: int64(time.December)},
"sleep": &tengo.UserFunction{
Name: "sleep",
Value: timesSleep,
@ -229,7 +229,7 @@ func timesParseDuration(args ...tengo.Object) (
return
}
ret = &tengo.Int{Value: int64(dur)}
ret = tengo.Int{Value: int64(dur)}
return
}
@ -253,7 +253,7 @@ func timesSince(args ...tengo.Object) (
return
}
ret = &tengo.Int{Value: int64(time.Since(t1))}
ret = tengo.Int{Value: int64(time.Since(t1))}
return
}
@ -277,7 +277,7 @@ func timesUntil(args ...tengo.Object) (
return
}
ret = &tengo.Int{Value: int64(time.Until(t1))}
ret = tengo.Int{Value: int64(time.Until(t1))}
return
}
@ -301,7 +301,7 @@ func timesDurationHours(args ...tengo.Object) (
return
}
ret = &tengo.Float{Value: time.Duration(i1).Hours()}
ret = tengo.Float{Value: time.Duration(i1).Hours()}
return
}
@ -325,7 +325,7 @@ func timesDurationMinutes(args ...tengo.Object) (
return
}
ret = &tengo.Float{Value: time.Duration(i1).Minutes()}
ret = tengo.Float{Value: time.Duration(i1).Minutes()}
return
}
@ -349,7 +349,7 @@ func timesDurationNanoseconds(args ...tengo.Object) (
return
}
ret = &tengo.Int{Value: time.Duration(i1).Nanoseconds()}
ret = tengo.Int{Value: time.Duration(i1).Nanoseconds()}
return
}
@ -373,7 +373,7 @@ func timesDurationSeconds(args ...tengo.Object) (
return
}
ret = &tengo.Float{Value: time.Duration(i1).Seconds()}
ret = tengo.Float{Value: time.Duration(i1).Seconds()}
return
}
@ -643,7 +643,7 @@ func timesSub(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
ret = &tengo.Int{Value: int64(t1.Sub(t2))}
ret = tengo.Int{Value: int64(t1.Sub(t2))}
return
}
@ -785,7 +785,7 @@ func timesTimeYear(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
ret = &tengo.Int{Value: int64(t1.Year())}
ret = tengo.Int{Value: int64(t1.Year())}
return
}
@ -806,7 +806,7 @@ func timesTimeMonth(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
ret = &tengo.Int{Value: int64(t1.Month())}
ret = tengo.Int{Value: int64(t1.Month())}
return
}
@ -827,7 +827,7 @@ func timesTimeDay(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
ret = &tengo.Int{Value: int64(t1.Day())}
ret = tengo.Int{Value: int64(t1.Day())}
return
}
@ -848,7 +848,7 @@ func timesTimeWeekday(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
ret = &tengo.Int{Value: int64(t1.Weekday())}
ret = tengo.Int{Value: int64(t1.Weekday())}
return
}
@ -869,7 +869,7 @@ func timesTimeHour(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
ret = &tengo.Int{Value: int64(t1.Hour())}
ret = tengo.Int{Value: int64(t1.Hour())}
return
}
@ -890,7 +890,7 @@ func timesTimeMinute(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
ret = &tengo.Int{Value: int64(t1.Minute())}
ret = tengo.Int{Value: int64(t1.Minute())}
return
}
@ -911,7 +911,7 @@ func timesTimeSecond(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
ret = &tengo.Int{Value: int64(t1.Second())}
ret = tengo.Int{Value: int64(t1.Second())}
return
}
@ -935,7 +935,7 @@ func timesTimeNanosecond(args ...tengo.Object) (
return
}
ret = &tengo.Int{Value: int64(t1.Nanosecond())}
ret = tengo.Int{Value: int64(t1.Nanosecond())}
return
}
@ -956,7 +956,7 @@ func timesTimeUnix(args ...tengo.Object) (ret tengo.Object, err error) {
return
}
ret = &tengo.Int{Value: t1.Unix()}
ret = tengo.Int{Value: t1.Unix()}
return
}
@ -980,7 +980,7 @@ func timesTimeUnixNano(args ...tengo.Object) (
return
}
ret = &tengo.Int{Value: t1.UnixNano()}
ret = tengo.Int{Value: t1.UnixNano()}
return
}

View file

@ -16,10 +16,10 @@ func TestTimes(t *testing.T) {
require.True(t, module(t, "times").
call("since", time.Now().Add(-time.Hour)).
o.(*tengo.Int).Value > 3600000000000)
o.(tengo.Int).Value > 3600000000000)
require.True(t, module(t, "times").
call("until", time.Now().Add(time.Hour)).
o.(*tengo.Int).Value < 3600000000000)
o.(tengo.Int).Value < 3600000000000)
module(t, "times").call("parse_duration", "1ns").expect(1)
module(t, "times").call("parse_duration", "1ms").expect(1000000)

View file

@ -79,16 +79,16 @@ func ToString(o Object) (v string, ok bool) {
// ToInt will try to convert object o to int value.
func ToInt(o Object) (v int, ok bool) {
switch o := o.(type) {
case *Int:
case Int:
v = int(o.Value)
ok = true
case *Float:
case Float:
v = int(o.Value)
ok = true
case *Char:
case Char:
v = int(o.Value)
ok = true
case *Bool:
case Bool:
if o == TrueValue {
v = 1
}
@ -106,16 +106,16 @@ func ToInt(o Object) (v int, ok bool) {
// ToInt64 will try to convert object o to int64 value.
func ToInt64(o Object) (v int64, ok bool) {
switch o := o.(type) {
case *Int:
case Int:
v = o.Value
ok = true
case *Float:
case Float:
v = int64(o.Value)
ok = true
case *Char:
case Char:
v = int64(o.Value)
ok = true
case *Bool:
case Bool:
if o == TrueValue {
v = 1
}
@ -133,10 +133,10 @@ func ToInt64(o Object) (v int64, ok bool) {
// ToFloat64 will try to convert object o to float64 value.
func ToFloat64(o Object) (v float64, ok bool) {
switch o := o.(type) {
case *Int:
case Int:
v = float64(o.Value)
ok = true
case *Float:
case Float:
v = o.Value
ok = true
case *String:
@ -159,10 +159,10 @@ func ToBool(o Object) (v bool, ok bool) {
// ToRune will try to convert object o to rune value.
func ToRune(o Object) (v rune, ok bool) {
switch o := o.(type) {
case *Int:
case Int:
v = rune(o.Value)
ok = true
case *Char:
case Char:
v = o.Value
ok = true
}
@ -188,7 +188,7 @@ func ToTime(o Object) (v time.Time, ok bool) {
case *Time:
v = o.Value
ok = true
case *Int:
case Int:
v = time.Unix(o.Value, 0)
ok = true
}
@ -198,15 +198,15 @@ func ToTime(o Object) (v time.Time, ok bool) {
// ToInterface attempts to convert an object o to an interface{} value
func ToInterface(o Object) (res interface{}) {
switch o := o.(type) {
case *Int:
case Int:
res = o.Value
case *String:
res = o.Value
case *Float:
case Float:
res = o.Value
case *Bool:
case Bool:
res = o == TrueValue
case *Char:
case Char:
res = o.Value
case *Bytes:
res = o.Value
@ -253,20 +253,20 @@ func FromInterface(v interface{}) (Object, error) {
}
return &String{Value: v}, nil
case int64:
return &Int{Value: v}, nil
return Int{Value: v}, nil
case int:
return &Int{Value: int64(v)}, nil
return Int{Value: int64(v)}, nil
case bool:
if v {
return TrueValue, nil
}
return FalseValue, nil
case rune:
return &Char{Value: v}, nil
return Char{Value: v}, nil
case byte:
return &Char{Value: rune(v)}, nil
return Char{Value: rune(v)}, nil
case float64:
return &Float{Value: v}, nil
return Float{Value: v}, nil
case []byte:
if len(v) > MaxBytesLen {
return nil, ErrBytesLimit

View file

@ -59,49 +59,49 @@ func TestMakeInstruction(t *testing.T) {
func TestNumObjects(t *testing.T) {
testCountObjects(t, &tengo.Array{}, 1)
testCountObjects(t, &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
tengo.Int{Value: 1},
tengo.Int{Value: 2},
&tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 3},
&tengo.Int{Value: 4},
&tengo.Int{Value: 5},
tengo.Int{Value: 3},
tengo.Int{Value: 4},
tengo.Int{Value: 5},
}},
}}, 7)
testCountObjects(t, tengo.TrueValue, 1)
testCountObjects(t, tengo.FalseValue, 1)
testCountObjects(t, &tengo.BuiltinFunction{}, 1)
testCountObjects(t, &tengo.Bytes{Value: []byte("foobar")}, 1)
testCountObjects(t, &tengo.Char{Value: '가'}, 1)
testCountObjects(t, tengo.Char{Value: '가'}, 1)
testCountObjects(t, &tengo.CompiledFunction{}, 1)
testCountObjects(t, &tengo.Error{Value: &tengo.Int{Value: 5}}, 2)
testCountObjects(t, &tengo.Float{Value: 19.84}, 1)
testCountObjects(t, &tengo.Error{Value: tengo.Int{Value: 5}}, 2)
testCountObjects(t, tengo.Float{Value: 19.84}, 1)
testCountObjects(t, &tengo.ImmutableArray{Value: []tengo.Object{
&tengo.Int{Value: 1},
&tengo.Int{Value: 2},
tengo.Int{Value: 1},
tengo.Int{Value: 2},
&tengo.ImmutableArray{Value: []tengo.Object{
&tengo.Int{Value: 3},
&tengo.Int{Value: 4},
&tengo.Int{Value: 5},
tengo.Int{Value: 3},
tengo.Int{Value: 4},
tengo.Int{Value: 5},
}},
}}, 7)
testCountObjects(t, &tengo.ImmutableMap{
Value: map[string]tengo.Object{
"k1": &tengo.Int{Value: 1},
"k2": &tengo.Int{Value: 2},
"k1": tengo.Int{Value: 1},
"k2": tengo.Int{Value: 2},
"k3": &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 3},
&tengo.Int{Value: 4},
&tengo.Int{Value: 5},
tengo.Int{Value: 3},
tengo.Int{Value: 4},
tengo.Int{Value: 5},
}},
}}, 7)
testCountObjects(t, &tengo.Int{Value: 1984}, 1)
testCountObjects(t, tengo.Int{Value: 1984}, 1)
testCountObjects(t, &tengo.Map{Value: map[string]tengo.Object{
"k1": &tengo.Int{Value: 1},
"k2": &tengo.Int{Value: 2},
"k1": tengo.Int{Value: 1},
"k2": tengo.Int{Value: 2},
"k3": &tengo.Array{Value: []tengo.Object{
&tengo.Int{Value: 3},
&tengo.Int{Value: 4},
&tengo.Int{Value: 5},
tengo.Int{Value: 3},
tengo.Int{Value: 4},
tengo.Int{Value: 5},
}},
}}, 7)
testCountObjects(t, &tengo.String{Value: "foo bar"}, 1)

View file

@ -33,7 +33,7 @@ func TestVariable(t *testing.T) {
CharValue: rune(1),
BoolValue: true,
StringValue: "1",
Object: &tengo.Int{Value: 1},
Object: tengo.Int{Value: 1},
},
{
Name: "b",

27
vm.go
View file

@ -175,8 +175,8 @@ func (v *VM) run() {
v.sp--
switch x := operand.(type) {
case *Int:
var res Object = &Int{Value: ^x.Value}
case Int:
var res Object = Int{Value: ^x.Value}
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
@ -194,8 +194,8 @@ func (v *VM) run() {
v.sp--
switch x := operand.(type) {
case *Int:
var res Object = &Int{Value: -x.Value}
case Int:
var res Object = Int{Value: -x.Value}
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
@ -203,8 +203,8 @@ func (v *VM) run() {
}
v.stack[v.sp] = res
v.sp++
case *Float:
var res Object = &Float{Value: -x.Value}
case Float:
var res Object = Float{Value: -x.Value}
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
@ -275,7 +275,7 @@ func (v *VM) run() {
v.ip += 2
numElements := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
var elements []Object
elements := make([]Object, 0, numElements)
for i := v.sp - numElements; i < v.sp; i++ {
elements = append(elements, v.stack[i])
}
@ -376,7 +376,7 @@ func (v *VM) run() {
var lowIdx int64
if low != UndefinedValue {
if low, ok := low.(*Int); ok {
if low, ok := low.(Int); ok {
lowIdx = low.Value
} else {
v.err = fmt.Errorf("invalid slice index type: %s",
@ -391,7 +391,7 @@ func (v *VM) run() {
var highIdx int64
if high == UndefinedValue {
highIdx = numElements
} else if high, ok := high.(*Int); ok {
} else if high, ok := high.(Int); ok {
highIdx = high.Value
} else {
v.err = fmt.Errorf("invalid slice index type: %s",
@ -428,7 +428,7 @@ func (v *VM) run() {
var highIdx int64
if high == UndefinedValue {
highIdx = numElements
} else if high, ok := high.(*Int); ok {
} else if high, ok := high.(Int); ok {
highIdx = high.Value
} else {
v.err = fmt.Errorf("invalid slice index type: %s",
@ -465,7 +465,7 @@ func (v *VM) run() {
var highIdx int64
if high == UndefinedValue {
highIdx = numElements
} else if high, ok := high.(*Int); ok {
} else if high, ok := high.(Int); ok {
highIdx = high.Value
} else {
v.err = fmt.Errorf("invalid slice index type: %s",
@ -502,7 +502,7 @@ func (v *VM) run() {
var highIdx int64
if high == UndefinedValue {
highIdx = numElements
} else if high, ok := high.(*Int); ok {
} else if high, ok := high.(Int); ok {
highIdx = high.Value
} else {
v.err = fmt.Errorf("invalid slice index type: %s",
@ -628,8 +628,7 @@ func (v *VM) run() {
v.framesIndex++
v.sp = v.sp - numArgs + callee.NumLocals
} else {
var args []Object
args = append(args, v.stack[v.sp-numArgs:v.sp]...)
args := v.stack[v.sp-numArgs : v.sp]
ret, e := value.Call(args...)
v.sp -= numArgs + 1

View file

@ -5,7 +5,6 @@ import (
"fmt"
"math"
"math/rand"
"reflect"
_runtime "runtime"
"strings"
"testing"
@ -2094,7 +2093,7 @@ func TestIncDec(t *testing.T) {
}
type StringDict struct {
tengo.ObjectImpl
tengo.PtrObjectImpl
Value map[string]string
}
@ -2136,7 +2135,7 @@ func (o *StringDict) IndexSet(index, value tengo.Object) error {
}
type StringCircle struct {
tengo.ObjectImpl
tengo.PtrObjectImpl
Value []string
}
@ -2149,7 +2148,7 @@ func (o *StringCircle) String() string {
}
func (o *StringCircle) IndexGet(index tengo.Object) (tengo.Object, error) {
intIdx, ok := index.(*tengo.Int)
intIdx, ok := index.(tengo.Int)
if !ok {
return nil, tengo.ErrInvalidIndexType
}
@ -2163,7 +2162,7 @@ func (o *StringCircle) IndexGet(index tengo.Object) (tengo.Object, error) {
}
func (o *StringCircle) IndexSet(index, value tengo.Object) error {
intIdx, ok := index.(*tengo.Int)
intIdx, ok := index.(tengo.Int)
if !ok {
return tengo.ErrInvalidIndexType
}
@ -2184,7 +2183,7 @@ func (o *StringCircle) IndexSet(index, value tengo.Object) error {
}
type StringArray struct {
tengo.ObjectImpl
tengo.PtrObjectImpl
Value []string
}
@ -2242,7 +2241,7 @@ func (o *StringArray) TypeName() string {
}
func (o *StringArray) IndexGet(index tengo.Object) (tengo.Object, error) {
intIdx, ok := index.(*tengo.Int)
intIdx, ok := index.(tengo.Int)
if ok {
if intIdx.Value >= 0 && intIdx.Value < int64(len(o.Value)) {
return &tengo.String{Value: o.Value[intIdx.Value]}, nil
@ -2255,7 +2254,7 @@ func (o *StringArray) IndexGet(index tengo.Object) (tengo.Object, error) {
if ok {
for vidx, str := range o.Value {
if strIdx.Value == str {
return &tengo.Int{Value: int64(vidx)}, nil
return tengo.Int{Value: int64(vidx)}, nil
}
}
@ -2271,7 +2270,7 @@ func (o *StringArray) IndexSet(index, value tengo.Object) error {
return tengo.ErrInvalidIndexValueType
}
intIdx, ok := index.(*tengo.Int)
intIdx, ok := index.(tengo.Int)
if ok {
if intIdx.Value >= 0 && intIdx.Value < int64(len(o.Value)) {
o.Value[intIdx.Value] = strVal
@ -2302,7 +2301,7 @@ func (o *StringArray) Call(
for i, v := range o.Value {
if v == s1 {
return &tengo.Int{Value: int64(i)}, nil
return tengo.Int{Value: int64(i)}, nil
}
}
@ -2423,7 +2422,7 @@ func TestInteger(t *testing.T) {
}
type StringArrayIterator struct {
tengo.ObjectImpl
tengo.PtrObjectImpl
strArr *StringArray
idx int
}
@ -2442,7 +2441,7 @@ func (i *StringArrayIterator) Next() bool {
}
func (i *StringArrayIterator) Key() tengo.Object {
return &tengo.Int{Value: int64(i.idx - 1)}
return tengo.Int{Value: int64(i.idx - 1)}
}
func (i *StringArrayIterator) Value() tengo.Object {
@ -2573,7 +2572,7 @@ func TestBuiltin(t *testing.T) {
Name: "abs",
Value: func(a ...tengo.Object) (tengo.Object, error) {
v, _ := tengo.ToFloat64(a[0])
return &tengo.Float{Value: math.Abs(v)}, nil
return tengo.Float{Value: math.Abs(v)}, nil
},
},
},
@ -2779,7 +2778,7 @@ func TestModuleBlockScopes(t *testing.T) {
Name: "abs",
Value: func(a ...tengo.Object) (tengo.Object, error) {
v, _ := tengo.ToInt64(a[0])
return &tengo.Int{Value: rand.Int63n(v)}, nil
return tengo.Int{Value: rand.Int63n(v)}, nil
},
},
},
@ -3873,7 +3872,7 @@ func formatGlobals(globals []tengo.Object) (formatted []string) {
return
}
formatted = append(formatted, fmt.Sprintf("[% 3d] %s (%s|%p)",
idx, global.String(), reflect.TypeOf(global).Elem().Name(), global))
idx, global.String(), global.TypeName(), global))
}
return
}
@ -3899,20 +3898,20 @@ func toObject(v interface{}) tengo.Object {
case string:
return &tengo.String{Value: v}
case int64:
return &tengo.Int{Value: v}
return tengo.Int{Value: v}
case int: // for convenience
return &tengo.Int{Value: int64(v)}
return tengo.Int{Value: int64(v)}
case bool:
if v {
return tengo.TrueValue
}
return tengo.FalseValue
case rune:
return &tengo.Char{Value: v}
return tengo.Char{Value: v}
case byte: // for convenience
return &tengo.Char{Value: rune(v)}
return tengo.Char{Value: rune(v)}
case float64:
return &tengo.Float{Value: v}
return tengo.Float{Value: v}
case []byte:
return &tengo.Bytes{Value: v}
case MAP:
@ -3950,14 +3949,14 @@ func toObject(v interface{}) tengo.Object {
func objectZeroCopy(o tengo.Object) tengo.Object {
switch o.(type) {
case *tengo.Int:
return &tengo.Int{}
case *tengo.Float:
return &tengo.Float{}
case *tengo.Bool:
return &tengo.Bool{}
case *tengo.Char:
return &tengo.Char{}
case tengo.Int:
return tengo.Int{}
case tengo.Float:
return tengo.Float{}
case tengo.Bool:
return tengo.Bool{}
case tengo.Char:
return tengo.Char{}
case *tengo.String:
return &tengo.String{}
case *tengo.Array: