forked from TrueCloudLab/neoneo-go
VM: Implement BOOLAND, BOOLOR opcode (#251)
* Implemented BOOLAND, BOOLOR opcode
This commit is contained in:
parent
9402540c3a
commit
1fbc0af5db
4 changed files with 114 additions and 1 deletions
|
@ -30,3 +30,17 @@ func (b *Boolean) Value() bool {
|
||||||
func (b *Boolean) Not() *Boolean {
|
func (b *Boolean) Not() *Boolean {
|
||||||
return NewBoolean(!b.Value())
|
return NewBoolean(!b.Value())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// And returns a Boolean whose underlying value is obtained
|
||||||
|
// by applying the && operator to two Booleans' values.
|
||||||
|
func (b *Boolean) And(a *Boolean) *Boolean {
|
||||||
|
c := b.Value() && a.Value()
|
||||||
|
return NewBoolean(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns a Boolean whose underlying value is obtained
|
||||||
|
// by applying the || operator to two Booleans' values.
|
||||||
|
func (b *Boolean) Or(a *Boolean) *Boolean {
|
||||||
|
c := b.Value() || a.Value()
|
||||||
|
return NewBoolean(c)
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ import "github.com/CityOfZion/neo-go/pkg/vm/stack"
|
||||||
type stackInfo func(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error)
|
type stackInfo func(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error)
|
||||||
|
|
||||||
var opFunc = map[stack.Instruction]stackInfo{
|
var opFunc = map[stack.Instruction]stackInfo{
|
||||||
|
stack.BOOLAND: BoolAnd,
|
||||||
|
stack.BOOLOR: BoolOr,
|
||||||
stack.LT: Lt,
|
stack.LT: Lt,
|
||||||
stack.GT: Gt,
|
stack.GT: Gt,
|
||||||
stack.SHR: Shr,
|
stack.SHR: Shr,
|
||||||
|
|
|
@ -206,6 +206,44 @@ func Not(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rst
|
||||||
return NONE, nil
|
return NONE, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoolAnd pops two booleans off of the stack and pushes a boolean to the stack
|
||||||
|
// whose value is true iff both booleans' values are true.
|
||||||
|
// Returns an error if either items cannot be casted to an boolean
|
||||||
|
func BoolAnd(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
|
bool1, bool2, err := popTwoBooleans(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
res := bool1.And(bool2)
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Estack.Push(res)
|
||||||
|
|
||||||
|
return NONE, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolOr pops two booleans off of the stack and pushes a boolean to the stack
|
||||||
|
// whose value is true iff at least one of the two booleans' value is true.
|
||||||
|
// Returns an error if either items cannot be casted to an boolean
|
||||||
|
func BoolOr(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
|
bool1, bool2, err := popTwoBooleans(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
res := bool1.Or(bool2)
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Estack.Push(res)
|
||||||
|
|
||||||
|
return NONE, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Sign puts the sign of the top stack Item on top of the stack.
|
// Sign puts the sign of the top stack Item on top of the stack.
|
||||||
// If value is negative, put -1;
|
// If value is negative, put -1;
|
||||||
// If positive, put 1;
|
// If positive, put 1;
|
||||||
|
@ -345,3 +383,16 @@ func popTwoByteArrays(ctx *stack.Context) (*stack.ByteArray, *stack.ByteArray, e
|
||||||
}
|
}
|
||||||
return ba1, ba2, nil
|
return ba1, ba2, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func popTwoBooleans(ctx *stack.Context) (*stack.Boolean, *stack.Boolean, error) {
|
||||||
|
bool1, err := ctx.Estack.PopBoolean()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
bool2, err := ctx.Estack.PopBoolean()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return bool1, bool2, nil
|
||||||
|
}
|
||||||
|
|
|
@ -395,6 +395,52 @@ func TestShrOp(t *testing.T) {
|
||||||
assert.Equal(t, int64(2), item.Value().Int64())
|
assert.Equal(t, int64(2), item.Value().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBoolAndOp(t *testing.T) {
|
||||||
|
|
||||||
|
v := VM{}
|
||||||
|
|
||||||
|
a := stack.NewBoolean(true)
|
||||||
|
b := stack.NewBoolean(true)
|
||||||
|
|
||||||
|
ctx := stack.NewContext([]byte{})
|
||||||
|
ctx.Estack.Push(a).Push(b)
|
||||||
|
|
||||||
|
v.executeOp(stack.BOOLAND, ctx)
|
||||||
|
|
||||||
|
// Stack should have one item
|
||||||
|
assert.Equal(t, 1, ctx.Estack.Len())
|
||||||
|
|
||||||
|
item, err := ctx.Estack.PopBoolean()
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, true, item.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBoolOrOp(t *testing.T) {
|
||||||
|
|
||||||
|
v := VM{}
|
||||||
|
|
||||||
|
a := stack.NewBoolean(false)
|
||||||
|
b := stack.NewBoolean(true)
|
||||||
|
|
||||||
|
ctx := stack.NewContext([]byte{})
|
||||||
|
ctx.Estack.Push(a).Push(b)
|
||||||
|
|
||||||
|
v.executeOp(stack.BOOLOR, ctx)
|
||||||
|
|
||||||
|
// Stack should have one item
|
||||||
|
assert.Equal(t, 1, ctx.Estack.Len())
|
||||||
|
|
||||||
|
item, err := ctx.Estack.PopBoolean()
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, true, item.Value())
|
||||||
|
}
|
||||||
|
|
||||||
func TestLtOp(t *testing.T) {
|
func TestLtOp(t *testing.T) {
|
||||||
|
|
||||||
v := VM{}
|
v := VM{}
|
||||||
|
@ -452,3 +498,4 @@ func TestGtOp(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, true, item.Value())
|
assert.Equal(t, true, item.Value())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue