VM: Implement INC, DEC opcode (#231)

[VM]

- Implemented INC, DEC opcode
This commit is contained in:
dauTT 2019-03-27 00:15:13 +01:00 committed by decentralisedkev
parent 24cd21bd8c
commit d8e399f67d
3 changed files with 104 additions and 0 deletions

View file

@ -5,6 +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.INC: Inc,
stack.DEC: Dec,
stack.ADD: Add, stack.ADD: Add,
stack.SUB: Sub, stack.SUB: Sub,
stack.PUSHBYTES1: PushNBytes, stack.PUSHBYTES1: PushNBytes,

View file

@ -1,6 +1,8 @@
package vm package vm
import ( import (
"math/big"
"github.com/CityOfZion/neo-go/pkg/vm/stack" "github.com/CityOfZion/neo-go/pkg/vm/stack"
) )
@ -42,6 +44,56 @@ func Sub(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rst
return NONE, nil return NONE, nil
} }
// Inc increments the stack Item's value by 1.
// Returns an error if the item cannot be casted to an integer
// 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) {
i, err := ctx.Estack.PopInt()
if err != nil {
return FAULT, err
}
one, err := stack.NewInt(big.NewInt(1))
if err != nil {
return FAULT, err
}
res, err := i.Add(one)
if err != nil {
return FAULT, err
}
ctx.Estack.Push(res)
return NONE, nil
}
// Dec decrements the stack Item's value by 1.
// Returns an error if the item cannot be casted to an integer
// 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) {
i, err := ctx.Estack.PopInt()
if err != nil {
return FAULT, err
}
one, err := stack.NewInt(big.NewInt(1))
if err != nil {
return FAULT, err
}
res, err := i.Sub(one)
if err != nil {
return FAULT, err
}
ctx.Estack.Push(res)
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 {

View file

@ -8,6 +8,56 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestIncOp(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.INC, 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(21), item.Value().Int64())
}
func TestDecOp(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.DEC, 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(19), item.Value().Int64())
}
func TestAddOp(t *testing.T) { func TestAddOp(t *testing.T) {
v := VM{} v := VM{}