Compare commits
3 commits
master
...
optimizati
Author | SHA1 | Date | |
---|---|---|---|
|
fe792a9369 | ||
|
9515d2f2c0 | ||
|
e302d643a1 |
34 changed files with 881 additions and 819 deletions
53
builtins.go
53
builtins.go
|
@ -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",
|
||||
|
|
176
builtins_test.go
176
builtins_test.go
|
@ -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{
|
||||
|
|
19
bytecode.go
19
bytecode.go
|
@ -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{})
|
||||
|
|
104
bytecode_test.go
104
bytecode_test.go
|
@ -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)),
|
||||
|
|
|
@ -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("-------------------------------------")
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
18
iterator.go
18
iterator.go
|
@ -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]}
|
||||
}
|
||||
|
|
271
objects.go
271
objects.go
|
@ -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
|
||||
}
|
||||
|
|
458
objects_test.go
458
objects_test.go
|
@ -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)})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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...)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
58
stdlib/os.go
58
stdlib/os.go
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -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
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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]),
|
||||
},
|
||||
}})
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
44
tengo.go
44
tengo.go
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
27
vm.go
|
@ -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
|
||||
|
||||
|
|
55
vm_test.go
55
vm_test.go
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue