vm: implement NOTEQUAL opcode
This commit is contained in:
parent
70f0c656b0
commit
9081211f12
4 changed files with 27 additions and 9 deletions
|
@ -616,8 +616,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
case n.Op == token.NEQ:
|
case n.Op == token.NEQ:
|
||||||
// VM has separate opcodes for number and string equality
|
// VM has separate opcodes for number and string equality
|
||||||
if isStringType(c.typeInfo.Types[n.X].Type) {
|
if isStringType(c.typeInfo.Types[n.X].Type) {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.EQUAL)
|
emit.Opcode(c.prog.BinWriter, opcode.NOTEQUAL)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NOT)
|
|
||||||
} else {
|
} else {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NUMNOTEQUAL)
|
emit.Opcode(c.prog.BinWriter, opcode.NUMNOTEQUAL)
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,11 +98,12 @@ const (
|
||||||
RIGHT Opcode = 0x81
|
RIGHT Opcode = 0x81
|
||||||
|
|
||||||
// Bitwise logic
|
// Bitwise logic
|
||||||
INVERT Opcode = 0x90
|
INVERT Opcode = 0x90
|
||||||
AND Opcode = 0x91
|
AND Opcode = 0x91
|
||||||
OR Opcode = 0x92
|
OR Opcode = 0x92
|
||||||
XOR Opcode = 0x93
|
XOR Opcode = 0x93
|
||||||
EQUAL Opcode = 0x97
|
EQUAL Opcode = 0x97
|
||||||
|
NOTEQUAL Opcode = 0x98
|
||||||
|
|
||||||
// Arithmetic
|
// Arithmetic
|
||||||
SIGN Opcode = 0x99
|
SIGN Opcode = 0x99
|
||||||
|
|
|
@ -748,7 +748,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
a := v.estack.Pop().BigInt()
|
a := v.estack.Pop().BigInt()
|
||||||
v.estack.PushVal(new(big.Int).Xor(b, a))
|
v.estack.PushVal(new(big.Int).Xor(b, a))
|
||||||
|
|
||||||
case opcode.EQUAL:
|
case opcode.EQUAL, opcode.NOTEQUAL:
|
||||||
b := v.estack.Pop()
|
b := v.estack.Pop()
|
||||||
if b == nil {
|
if b == nil {
|
||||||
panic("no top-level element found")
|
panic("no top-level element found")
|
||||||
|
@ -757,7 +757,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
if a == nil {
|
if a == nil {
|
||||||
panic("no second-to-the-top element found")
|
panic("no second-to-the-top element found")
|
||||||
}
|
}
|
||||||
v.estack.PushVal(a.value.Equals(b.value))
|
v.estack.PushVal(a.value.Equals(b.value) == (op == opcode.EQUAL))
|
||||||
|
|
||||||
// Numeric operations.
|
// Numeric operations.
|
||||||
case opcode.SIGN:
|
case opcode.SIGN:
|
||||||
|
|
|
@ -1319,6 +1319,24 @@ func TestEQUALMapFalse(t *testing.T) {
|
||||||
assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value)
|
assert.Equal(t, &BoolItem{false}, vm.estack.Pop().value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTestFuncForVM(prog []byte, result interface{}, args ...interface{}) func(t *testing.T) {
|
||||||
|
return func(t *testing.T) {
|
||||||
|
v := load(prog)
|
||||||
|
for i := range args {
|
||||||
|
v.estack.PushVal(args[i])
|
||||||
|
}
|
||||||
|
runVM(t, v)
|
||||||
|
require.Equal(t, 1, v.estack.Len())
|
||||||
|
require.Equal(t, makeStackItem(result), v.estack.Pop().value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNOTEQUALByteArray(t *testing.T) {
|
||||||
|
prog := makeProgram(opcode.NOTEQUAL)
|
||||||
|
t.Run("True", getTestFuncForVM(prog, true, []byte{1, 2}, []byte{0, 1, 2}))
|
||||||
|
t.Run("False", getTestFuncForVM(prog, false, []byte{1, 2}, []byte{1, 2}))
|
||||||
|
}
|
||||||
|
|
||||||
func TestNumEqual(t *testing.T) {
|
func TestNumEqual(t *testing.T) {
|
||||||
prog := makeProgram(opcode.NUMEQUAL)
|
prog := makeProgram(opcode.NUMEQUAL)
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
|
|
Loading…
Reference in a new issue