forked from TrueCloudLab/neoneo-go
VM: Implemented SIGN, NEGATE opcode (#232)
* Implemented SIGN, NEGATE opcode
This commit is contained in:
parent
d8e399f67d
commit
14e0ab48dd
3 changed files with 95 additions and 2 deletions
|
@ -7,6 +7,8 @@ type stackInfo func(op stack.Instruction, ctx *stack.Context, istack *stack.Invo
|
||||||
var opFunc = map[stack.Instruction]stackInfo{
|
var opFunc = map[stack.Instruction]stackInfo{
|
||||||
stack.INC: Inc,
|
stack.INC: Inc,
|
||||||
stack.DEC: Dec,
|
stack.DEC: Dec,
|
||||||
|
stack.SIGN: Sign,
|
||||||
|
stack.NEGATE: Negate,
|
||||||
stack.ADD: Add,
|
stack.ADD: Add,
|
||||||
stack.SUB: Sub,
|
stack.SUB: Sub,
|
||||||
stack.PUSHBYTES1: PushNBytes,
|
stack.PUSHBYTES1: PushNBytes,
|
||||||
|
|
|
@ -46,7 +46,7 @@ func Sub(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rst
|
||||||
|
|
||||||
// Inc increments the stack Item's value by 1.
|
// Inc increments the stack Item's value by 1.
|
||||||
// Returns an error if the item cannot be casted to an integer
|
// Returns an error if the item cannot be casted to an integer
|
||||||
// or if 1 cannot be added to the item
|
// or if 1 cannot be added to the item.
|
||||||
func Inc(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
func Inc(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
i, err := ctx.Estack.PopInt()
|
i, err := ctx.Estack.PopInt()
|
||||||
|
@ -71,7 +71,7 @@ func Inc(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rst
|
||||||
|
|
||||||
// Dec decrements the stack Item's value by 1.
|
// Dec decrements the stack Item's value by 1.
|
||||||
// Returns an error if the item cannot be casted to an integer
|
// Returns an error if the item cannot be casted to an integer
|
||||||
// or if 1 cannot be subtracted to the item
|
// or if 1 cannot be subtracted to the item.
|
||||||
func Dec(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
func Dec(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
i, err := ctx.Estack.PopInt()
|
i, err := ctx.Estack.PopInt()
|
||||||
|
@ -94,6 +94,47 @@ func Dec(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rst
|
||||||
return NONE, nil
|
return NONE, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sign puts the sign of the top stack Item on top of the stack.
|
||||||
|
// If value is negative, put -1;
|
||||||
|
// If positive, put 1;
|
||||||
|
// If value is zero, put 0.
|
||||||
|
func Sign(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
|
i, err := ctx.Estack.PopInt()
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s := int64(i.Value().Sign())
|
||||||
|
sign, err := stack.NewInt(big.NewInt(s))
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Estack.Push(sign)
|
||||||
|
|
||||||
|
return NONE, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Negate flips the sign of the stack Item.
|
||||||
|
func Negate(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
|
i, err := ctx.Estack.PopInt()
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
|
||||||
|
a := big.NewInt(0).Neg(i.Value())
|
||||||
|
b, err := stack.NewInt(a)
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Estack.Push(b)
|
||||||
|
|
||||||
|
return NONE, nil
|
||||||
|
}
|
||||||
|
|
||||||
func popTwoIntegers(ctx *stack.Context) (*stack.Int, *stack.Int, error) {
|
func popTwoIntegers(ctx *stack.Context) (*stack.Int, *stack.Int, error) {
|
||||||
operandA, err := ctx.Estack.PopInt()
|
operandA, err := ctx.Estack.PopInt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -117,3 +117,53 @@ func TestSubOp(t *testing.T) {
|
||||||
assert.Equal(t, int64(-10), item.Value().Int64())
|
assert.Equal(t, int64(-10), item.Value().Int64())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSignOp(t *testing.T) {
|
||||||
|
|
||||||
|
v := VM{}
|
||||||
|
|
||||||
|
a, err := stack.NewInt(big.NewInt(-20))
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := stack.NewContext([]byte{})
|
||||||
|
ctx.Estack.Push(a)
|
||||||
|
|
||||||
|
v.executeOp(stack.SIGN, ctx)
|
||||||
|
|
||||||
|
// Stack should have one item
|
||||||
|
assert.Equal(t, 1, ctx.Estack.Len())
|
||||||
|
|
||||||
|
item, err := ctx.Estack.PopInt()
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, int64(-1), item.Value().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNegateOp(t *testing.T) {
|
||||||
|
|
||||||
|
v := VM{}
|
||||||
|
|
||||||
|
a, err := stack.NewInt(big.NewInt(-20))
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := stack.NewContext([]byte{})
|
||||||
|
ctx.Estack.Push(a)
|
||||||
|
|
||||||
|
v.executeOp(stack.NEGATE, ctx)
|
||||||
|
|
||||||
|
// Stack should have one item
|
||||||
|
assert.Equal(t, 1, ctx.Estack.Len())
|
||||||
|
|
||||||
|
item, err := ctx.Estack.PopInt()
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, int64(20), item.Value().Int64())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue