Skip to content

Commit e338512

Browse files
authored
fix: do not invert token.Less to token.Greater in compiler (#391)
* fix: do not invert token.Less to token.Great in compiler * unittest: do not invert token.Less to token.Great in compiler
1 parent 6fc8053 commit e338512

File tree

3 files changed

+77
-29
lines changed

3 files changed

+77
-29
lines changed

compiler.go

+5-19
Original file line numberDiff line numberDiff line change
@@ -141,25 +141,7 @@ func (c *Compiler) Compile(node parser.Node) error {
141141
if node.Token == token.LAnd || node.Token == token.LOr {
142142
return c.compileLogical(node)
143143
}
144-
if node.Token == token.Less {
145-
if err := c.Compile(node.RHS); err != nil {
146-
return err
147-
}
148-
if err := c.Compile(node.LHS); err != nil {
149-
return err
150-
}
151-
c.emit(node, parser.OpBinaryOp, int(token.Greater))
152-
return nil
153-
} else if node.Token == token.LessEq {
154-
if err := c.Compile(node.RHS); err != nil {
155-
return err
156-
}
157-
if err := c.Compile(node.LHS); err != nil {
158-
return err
159-
}
160-
c.emit(node, parser.OpBinaryOp, int(token.GreaterEq))
161-
return nil
162-
}
144+
163145
if err := c.Compile(node.LHS); err != nil {
164146
return err
165147
}
@@ -182,6 +164,10 @@ func (c *Compiler) Compile(node parser.Node) error {
182164
c.emit(node, parser.OpBinaryOp, int(token.Greater))
183165
case token.GreaterEq:
184166
c.emit(node, parser.OpBinaryOp, int(token.GreaterEq))
167+
case token.Less:
168+
c.emit(node, parser.OpBinaryOp, int(token.Less))
169+
case token.LessEq:
170+
c.emit(node, parser.OpBinaryOp, int(token.LessEq))
185171
case token.Equal:
186172
c.emit(node, parser.OpEqual)
187173
case token.NotEqual:

compiler_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,12 @@ func TestCompiler_Compile(t *testing.T) {
107107
concatInsts(
108108
tengo.MakeInstruction(parser.OpConstant, 0),
109109
tengo.MakeInstruction(parser.OpConstant, 1),
110-
tengo.MakeInstruction(parser.OpBinaryOp, 39),
110+
tengo.MakeInstruction(parser.OpBinaryOp, 38),
111111
tengo.MakeInstruction(parser.OpPop),
112112
tengo.MakeInstruction(parser.OpSuspend)),
113113
objectsArray(
114-
intObject(2),
115-
intObject(1))))
114+
intObject(1),
115+
intObject(2))))
116116

117117
expectCompile(t, `1 >= 2`,
118118
bytecode(
@@ -131,12 +131,12 @@ func TestCompiler_Compile(t *testing.T) {
131131
concatInsts(
132132
tengo.MakeInstruction(parser.OpConstant, 0),
133133
tengo.MakeInstruction(parser.OpConstant, 1),
134-
tengo.MakeInstruction(parser.OpBinaryOp, 44),
134+
tengo.MakeInstruction(parser.OpBinaryOp, 43),
135135
tengo.MakeInstruction(parser.OpPop),
136136
tengo.MakeInstruction(parser.OpSuspend)),
137137
objectsArray(
138-
intObject(2),
139-
intObject(1))))
138+
intObject(1),
139+
intObject(2))))
140140

141141
expectCompile(t, `1 == 2`,
142142
bytecode(
@@ -929,9 +929,9 @@ func() {
929929
concatInsts(
930930
tengo.MakeInstruction(parser.OpConstant, 0),
931931
tengo.MakeInstruction(parser.OpSetGlobal, 0),
932-
tengo.MakeInstruction(parser.OpConstant, 1),
933932
tengo.MakeInstruction(parser.OpGetGlobal, 0),
934-
tengo.MakeInstruction(parser.OpBinaryOp, 39),
933+
tengo.MakeInstruction(parser.OpConstant, 1),
934+
tengo.MakeInstruction(parser.OpBinaryOp, 38),
935935
tengo.MakeInstruction(parser.OpJumpFalsy, 31),
936936
tengo.MakeInstruction(parser.OpGetGlobal, 0),
937937
tengo.MakeInstruction(parser.OpConstant, 2),
@@ -978,9 +978,9 @@ func() {
978978
tengo.MakeInstruction(parser.OpConstant, 1),
979979
tengo.MakeInstruction(parser.OpNotEqual),
980980
tengo.MakeInstruction(parser.OpOrJump, 34),
981-
tengo.MakeInstruction(parser.OpConstant, 1),
982981
tengo.MakeInstruction(parser.OpGetGlobal, 0),
983-
tengo.MakeInstruction(parser.OpBinaryOp, 39),
982+
tengo.MakeInstruction(parser.OpConstant, 1),
983+
tengo.MakeInstruction(parser.OpBinaryOp, 38),
984984
tengo.MakeInstruction(parser.OpPop),
985985
tengo.MakeInstruction(parser.OpSuspend)),
986986
objectsArray(

script_test.go

+62
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77
"math/rand"
8+
"strconv"
89
"strings"
910
"sync"
1011
"testing"
@@ -479,6 +480,67 @@ func TestCompiled_RunContext(t *testing.T) {
479480
require.Equal(t, context.DeadlineExceeded, err)
480481
}
481482

483+
func TestCompiled_CustomObject(t *testing.T) {
484+
c := compile(t, `r := (t<130)`, M{"t": &customNumber{value: 123}})
485+
compiledRun(t, c)
486+
compiledGet(t, c, "r", true)
487+
488+
c = compile(t, `r := (t>13)`, M{"t": &customNumber{value: 123}})
489+
compiledRun(t, c)
490+
compiledGet(t, c, "r", true)
491+
}
492+
493+
// customNumber is a user defined object that can compare to tengo.Int
494+
// very shitty implementation, just to test that token.Less and token.Greater in BinaryOp works
495+
type customNumber struct {
496+
tengo.ObjectImpl
497+
value int64
498+
}
499+
500+
func (n *customNumber) TypeName() string {
501+
return "Number"
502+
}
503+
504+
func (n *customNumber) String() string {
505+
return strconv.FormatInt(n.value, 10)
506+
}
507+
508+
func (n *customNumber) BinaryOp(op token.Token, rhs tengo.Object) (tengo.Object, error) {
509+
tengoInt, ok := rhs.(*tengo.Int)
510+
if !ok {
511+
return nil, tengo.ErrInvalidOperator
512+
}
513+
return n.binaryOpInt(op, tengoInt)
514+
}
515+
516+
func (n *customNumber) binaryOpInt(op token.Token, rhs *tengo.Int) (tengo.Object, error) {
517+
i := n.value
518+
519+
switch op {
520+
case token.Less:
521+
if i < rhs.Value {
522+
return tengo.TrueValue, nil
523+
}
524+
return tengo.FalseValue, nil
525+
case token.Greater:
526+
if i > rhs.Value {
527+
return tengo.TrueValue, nil
528+
}
529+
return tengo.FalseValue, nil
530+
case token.LessEq:
531+
if i <= rhs.Value {
532+
return tengo.TrueValue, nil
533+
}
534+
return tengo.FalseValue, nil
535+
case token.GreaterEq:
536+
if i >= rhs.Value {
537+
return tengo.TrueValue, nil
538+
}
539+
return tengo.FalseValue, nil
540+
}
541+
return nil, tengo.ErrInvalidOperator
542+
}
543+
482544
func compile(t *testing.T, input string, vars M) *tengo.Compiled {
483545
s := tengo.NewScript([]byte(input))
484546
for vn, vv := range vars {

0 commit comments

Comments
 (0)