reduce number of memory allocation in object binary operators
This commit is contained in:
parent
d581cb24e4
commit
ca128af33b
8 changed files with 193 additions and 58 deletions
|
@ -29,6 +29,9 @@ func (o *Array) BinaryOp(op token.Token, rhs Object) (Object, error) {
|
|||
if rhs, ok := rhs.(*Array); ok {
|
||||
switch op {
|
||||
case token.Add:
|
||||
if len(rhs.Value) == 0 {
|
||||
return o, nil
|
||||
}
|
||||
return &Array{Value: append(o.Value, rhs.Value...)}, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ func builtinString(args ...Object) (Object, error) {
|
|||
case *String:
|
||||
return arg, nil
|
||||
case *Undefined:
|
||||
return undefined, nil
|
||||
return UndefinedValue, nil
|
||||
default:
|
||||
return &String{Value: arg.String()}, nil
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ func builtinInt(args ...Object) (Object, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return undefined, nil
|
||||
return UndefinedValue, nil
|
||||
}
|
||||
|
||||
func builtinFloat(args ...Object) (Object, error) {
|
||||
|
@ -64,7 +64,7 @@ func builtinFloat(args ...Object) (Object, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return undefined, nil
|
||||
return UndefinedValue, nil
|
||||
}
|
||||
|
||||
func builtinBool(args ...Object) (Object, error) {
|
||||
|
@ -100,5 +100,5 @@ func builtinChar(args ...Object) (Object, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return undefined, nil
|
||||
return UndefinedValue, nil
|
||||
}
|
||||
|
|
|
@ -24,40 +24,96 @@ func (o *Float) BinaryOp(op token.Token, rhs Object) (Object, error) {
|
|||
case *Float:
|
||||
switch op {
|
||||
case token.Add:
|
||||
return &Float{o.Value + rhs.Value}, nil
|
||||
r := o.Value + rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Float{Value: r}, nil
|
||||
case token.Sub:
|
||||
return &Float{o.Value - rhs.Value}, nil
|
||||
r := o.Value - rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Float{Value: r}, nil
|
||||
case token.Mul:
|
||||
return &Float{o.Value * rhs.Value}, nil
|
||||
r := o.Value * rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Float{Value: r}, nil
|
||||
case token.Quo:
|
||||
return &Float{o.Value / rhs.Value}, nil
|
||||
r := o.Value / rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Float{Value: r}, nil
|
||||
case token.Less:
|
||||
return &Bool{o.Value < rhs.Value}, nil
|
||||
if o.Value < rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.Greater:
|
||||
return &Bool{o.Value > rhs.Value}, nil
|
||||
if o.Value > rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.LessEq:
|
||||
return &Bool{o.Value <= rhs.Value}, nil
|
||||
if o.Value <= rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.GreaterEq:
|
||||
return &Bool{o.Value >= rhs.Value}, nil
|
||||
if o.Value >= rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
}
|
||||
case *Int:
|
||||
switch op {
|
||||
case token.Add:
|
||||
return &Float{o.Value + float64(rhs.Value)}, nil
|
||||
r := o.Value + float64(rhs.Value)
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Float{Value: r}, nil
|
||||
case token.Sub:
|
||||
return &Float{o.Value - float64(rhs.Value)}, nil
|
||||
r := o.Value - float64(rhs.Value)
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Float{Value: r}, nil
|
||||
case token.Mul:
|
||||
return &Float{o.Value * float64(rhs.Value)}, nil
|
||||
r := o.Value * float64(rhs.Value)
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Float{Value: r}, nil
|
||||
case token.Quo:
|
||||
return &Float{o.Value / float64(rhs.Value)}, nil
|
||||
r := o.Value / float64(rhs.Value)
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Float{Value: r}, nil
|
||||
case token.Less:
|
||||
return &Bool{o.Value < float64(rhs.Value)}, nil
|
||||
if o.Value < float64(rhs.Value) {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.Greater:
|
||||
return &Bool{o.Value > float64(rhs.Value)}, nil
|
||||
if o.Value > float64(rhs.Value) {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.LessEq:
|
||||
return &Bool{o.Value <= float64(rhs.Value)}, nil
|
||||
if o.Value <= float64(rhs.Value) {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.GreaterEq:
|
||||
return &Bool{o.Value >= float64(rhs.Value)}, nil
|
||||
if o.Value >= float64(rhs.Value) {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
106
objects/int.go
106
objects/int.go
|
@ -23,35 +23,91 @@ func (o *Int) BinaryOp(op token.Token, rhs Object) (Object, error) {
|
|||
case *Int:
|
||||
switch op {
|
||||
case token.Add:
|
||||
return &Int{o.Value + rhs.Value}, nil
|
||||
r := o.Value + rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Int{Value: r}, nil
|
||||
case token.Sub:
|
||||
return &Int{o.Value - rhs.Value}, nil
|
||||
r := o.Value - rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Int{Value: r}, nil
|
||||
case token.Mul:
|
||||
return &Int{o.Value * rhs.Value}, nil
|
||||
r := o.Value * rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Int{Value: r}, nil
|
||||
case token.Quo:
|
||||
return &Int{o.Value / rhs.Value}, nil
|
||||
r := o.Value / rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Int{Value: r}, nil
|
||||
case token.Rem:
|
||||
return &Int{o.Value % rhs.Value}, nil
|
||||
r := o.Value % rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Int{Value: r}, nil
|
||||
case token.And:
|
||||
return &Int{o.Value & rhs.Value}, nil
|
||||
r := o.Value & rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Int{Value: r}, nil
|
||||
case token.Or:
|
||||
return &Int{o.Value | rhs.Value}, nil
|
||||
r := o.Value | rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Int{Value: r}, nil
|
||||
case token.Xor:
|
||||
return &Int{o.Value ^ rhs.Value}, nil
|
||||
r := o.Value ^ rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Int{Value: r}, nil
|
||||
case token.AndNot:
|
||||
return &Int{o.Value &^ rhs.Value}, nil
|
||||
r := o.Value &^ rhs.Value
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Int{Value: r}, nil
|
||||
case token.Shl:
|
||||
return &Int{o.Value << uint(rhs.Value)}, nil
|
||||
r := o.Value << uint64(rhs.Value)
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Int{Value: r}, nil
|
||||
case token.Shr:
|
||||
return &Int{o.Value >> uint(rhs.Value)}, nil
|
||||
r := o.Value >> uint64(rhs.Value)
|
||||
if r == o.Value {
|
||||
return o, nil
|
||||
}
|
||||
return &Int{Value: r}, nil
|
||||
case token.Less:
|
||||
return &Bool{o.Value < rhs.Value}, nil
|
||||
if o.Value < rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.Greater:
|
||||
return &Bool{o.Value > rhs.Value}, nil
|
||||
if o.Value > rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.LessEq:
|
||||
return &Bool{o.Value <= rhs.Value}, nil
|
||||
if o.Value <= rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.GreaterEq:
|
||||
return &Bool{o.Value >= rhs.Value}, nil
|
||||
if o.Value >= rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
}
|
||||
case *Float:
|
||||
switch op {
|
||||
|
@ -64,13 +120,25 @@ func (o *Int) BinaryOp(op token.Token, rhs Object) (Object, error) {
|
|||
case token.Quo:
|
||||
return &Float{float64(o.Value) / rhs.Value}, nil
|
||||
case token.Less:
|
||||
return &Bool{float64(o.Value) < rhs.Value}, nil
|
||||
if float64(o.Value) < rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.Greater:
|
||||
return &Bool{float64(o.Value) > rhs.Value}, nil
|
||||
if float64(o.Value) > rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.LessEq:
|
||||
return &Bool{float64(o.Value) <= rhs.Value}, nil
|
||||
if float64(o.Value) <= rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
case token.GreaterEq:
|
||||
return &Bool{float64(o.Value) >= rhs.Value}, nil
|
||||
if float64(o.Value) >= rhs.Value {
|
||||
return TrueValue, nil
|
||||
}
|
||||
return FalseValue, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
7
objects/objects.go
Normal file
7
objects/objects.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package objects
|
||||
|
||||
var (
|
||||
TrueValue Object = &Bool{Value: true}
|
||||
FalseValue Object = &Bool{Value: false}
|
||||
UndefinedValue Object = &Undefined{}
|
||||
)
|
|
@ -23,6 +23,9 @@ func (o *String) BinaryOp(op token.Token, rhs Object) (Object, error) {
|
|||
case *String:
|
||||
switch op {
|
||||
case token.Add:
|
||||
if rhs.Value == "" {
|
||||
return o, nil
|
||||
}
|
||||
return &String{Value: o.Value + rhs.Value}, nil
|
||||
}
|
||||
case *Char:
|
||||
|
|
|
@ -2,8 +2,6 @@ package objects
|
|||
|
||||
import "github.com/d5/tengo/compiler/token"
|
||||
|
||||
var undefined = &Undefined{}
|
||||
|
||||
type Undefined struct{}
|
||||
|
||||
func (o Undefined) TypeName() string {
|
||||
|
|
|
@ -15,9 +15,9 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
trueObj objects.Object = &objects.Bool{Value: true}
|
||||
falseObj objects.Object = &objects.Bool{Value: false}
|
||||
undefinedObj objects.Object = &objects.Undefined{}
|
||||
truePtr = &objects.TrueValue
|
||||
falsePtr = &objects.FalseValue
|
||||
undefinedPtr = &objects.UndefinedValue
|
||||
builtinFuncs []objects.Object
|
||||
)
|
||||
|
||||
|
@ -83,7 +83,7 @@ func (v *VM) Run() error {
|
|||
}
|
||||
|
||||
case compiler.OpNull:
|
||||
if err := v.push(&undefinedObj); err != nil {
|
||||
if err := v.push(undefinedPtr); err != nil {
|
||||
return err
|
||||
}
|
||||
case compiler.OpAdd:
|
||||
|
@ -223,11 +223,11 @@ func (v *VM) Run() error {
|
|||
left := v.pop()
|
||||
|
||||
if (*right).Equals(*left) {
|
||||
if err := v.push(&trueObj); err != nil {
|
||||
if err := v.push(truePtr); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := v.push(&falseObj); err != nil {
|
||||
if err := v.push(falsePtr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -236,11 +236,11 @@ func (v *VM) Run() error {
|
|||
left := v.pop()
|
||||
|
||||
if (*right).Equals(*left) {
|
||||
if err := v.push(&falseObj); err != nil {
|
||||
if err := v.push(falsePtr); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := v.push(&trueObj); err != nil {
|
||||
if err := v.push(truePtr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -271,22 +271,22 @@ func (v *VM) Run() error {
|
|||
case compiler.OpPop:
|
||||
_ = v.pop()
|
||||
case compiler.OpTrue:
|
||||
if err := v.push(&trueObj); err != nil {
|
||||
if err := v.push(truePtr); err != nil {
|
||||
return err
|
||||
}
|
||||
case compiler.OpFalse:
|
||||
if err := v.push(&falseObj); err != nil {
|
||||
if err := v.push(falsePtr); err != nil {
|
||||
return err
|
||||
}
|
||||
case compiler.OpLNot:
|
||||
operand := v.pop()
|
||||
|
||||
if (*operand).IsFalsy() {
|
||||
if err := v.push(&trueObj); err != nil {
|
||||
if err := v.push(truePtr); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := v.push(&falseObj); err != nil {
|
||||
if err := v.push(falsePtr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -528,7 +528,7 @@ func (v *VM) Run() error {
|
|||
|
||||
v.sp = frame.basePointer - 1
|
||||
|
||||
if err := v.push(&undefinedObj); err != nil {
|
||||
if err := v.push(undefinedPtr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -672,11 +672,11 @@ func (v *VM) Run() error {
|
|||
iterator := v.pop()
|
||||
b := (*iterator).(objects.Iterator).Next()
|
||||
if b {
|
||||
if err := v.push(&trueObj); err != nil {
|
||||
if err := v.push(truePtr); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := v.push(&falseObj); err != nil {
|
||||
if err := v.push(falsePtr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -783,7 +783,7 @@ func (v *VM) executeArrayIndex(arr *objects.Array, index int64) error {
|
|||
}
|
||||
|
||||
func (v *VM) executeMapIndex(map_ *objects.Map, key string) error {
|
||||
var res = undefinedObj
|
||||
var res = objects.UndefinedValue
|
||||
val, ok := map_.Value[key]
|
||||
if ok {
|
||||
res = val
|
||||
|
@ -974,7 +974,7 @@ func (v *VM) callCallable(callable objects.Callable, numArgs int) error {
|
|||
|
||||
// nil return -> undefined
|
||||
if res == nil {
|
||||
res = undefinedObj
|
||||
res = objects.UndefinedValue
|
||||
}
|
||||
|
||||
return v.push(&res)
|
||||
|
|
Loading…
Reference in a new issue