mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-24 09:25:21 +00:00
vm: implement Array <-> Struct conversion
Reference VM implementation supports convertation from Struct to Array via NEWARRAY and vice versa. https://github.com/neo-project/neo-vm/pull/91
This commit is contained in:
parent
8fac66d4af
commit
bcc8234155
2 changed files with 106 additions and 6 deletions
32
pkg/vm/vm.go
32
pkg/vm/vm.go
|
@ -569,14 +569,34 @@ func (v *VM) execute(ctx *Context, op Instruction) {
|
||||||
|
|
||||||
// Object operations.
|
// Object operations.
|
||||||
case NEWARRAY:
|
case NEWARRAY:
|
||||||
n := v.estack.Pop().BigInt().Int64()
|
item := v.estack.Pop()
|
||||||
items := make([]StackItem, n)
|
switch t := item.value.(type) {
|
||||||
v.estack.PushVal(&ArrayItem{items})
|
case *BigIntegerItem:
|
||||||
|
n := t.value.Int64()
|
||||||
|
items := make([]StackItem, n)
|
||||||
|
v.estack.PushVal(&ArrayItem{items})
|
||||||
|
case *StructItem:
|
||||||
|
v.estack.PushVal(&ArrayItem{t.value})
|
||||||
|
case *ArrayItem:
|
||||||
|
v.estack.PushVal(t)
|
||||||
|
default:
|
||||||
|
panic("NEWARRAY: invalid operand")
|
||||||
|
}
|
||||||
|
|
||||||
case NEWSTRUCT:
|
case NEWSTRUCT:
|
||||||
n := v.estack.Pop().BigInt().Int64()
|
item := v.estack.Pop()
|
||||||
items := make([]StackItem, n)
|
switch t := item.value.(type) {
|
||||||
v.estack.PushVal(&StructItem{items})
|
case *BigIntegerItem:
|
||||||
|
n := t.value.Int64()
|
||||||
|
items := make([]StackItem, n)
|
||||||
|
v.estack.PushVal(&StructItem{items})
|
||||||
|
case *ArrayItem:
|
||||||
|
v.estack.PushVal(&StructItem{t.value})
|
||||||
|
case *StructItem:
|
||||||
|
v.estack.PushVal(t)
|
||||||
|
default:
|
||||||
|
panic("NEWSTRUCT: invalid operand")
|
||||||
|
}
|
||||||
|
|
||||||
case APPEND:
|
case APPEND:
|
||||||
itemElem := v.estack.Pop()
|
itemElem := v.estack.Pop()
|
||||||
|
|
|
@ -216,6 +216,86 @@ func TestINC(t *testing.T) {
|
||||||
assert.Equal(t, big.NewInt(2), vm.estack.Pop().BigInt())
|
assert.Equal(t, big.NewInt(2), vm.estack.Pop().BigInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNEWARRAYInteger(t *testing.T) {
|
||||||
|
prog := makeProgram(NEWARRAY)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, &ArrayItem{make([]StackItem, 1)}, vm.estack.Pop().value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNEWARRAYStruct(t *testing.T) {
|
||||||
|
prog := makeProgram(NEWARRAY)
|
||||||
|
vm := load(prog)
|
||||||
|
arr := []StackItem{makeStackItem(42)}
|
||||||
|
vm.estack.Push(&Element{value: &StructItem{arr}})
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNEWARRAYArray(t *testing.T) {
|
||||||
|
prog := makeProgram(NEWARRAY)
|
||||||
|
vm := load(prog)
|
||||||
|
arr := []StackItem{makeStackItem(42)}
|
||||||
|
vm.estack.Push(&Element{value: &ArrayItem{arr}})
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, &ArrayItem{arr}, vm.estack.Pop().value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNEWARRAYWrongType(t *testing.T) {
|
||||||
|
prog := makeProgram(NEWARRAY)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.Push(NewElement([]byte{}))
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNEWSTRUCTInteger(t *testing.T) {
|
||||||
|
prog := makeProgram(NEWSTRUCT)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.PushVal(1)
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, &StructItem{make([]StackItem, 1)}, vm.estack.Pop().value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNEWSTRUCTArray(t *testing.T) {
|
||||||
|
prog := makeProgram(NEWSTRUCT)
|
||||||
|
vm := load(prog)
|
||||||
|
arr := []StackItem{makeStackItem(42)}
|
||||||
|
vm.estack.Push(&Element{value: &ArrayItem{arr}})
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNEWSTRUCTStruct(t *testing.T) {
|
||||||
|
prog := makeProgram(NEWSTRUCT)
|
||||||
|
vm := load(prog)
|
||||||
|
arr := []StackItem{makeStackItem(42)}
|
||||||
|
vm.estack.Push(&Element{value: &StructItem{arr}})
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, false, vm.state.HasFlag(faultState))
|
||||||
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
|
assert.Equal(t, &StructItem{arr}, vm.estack.Pop().value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNEWSTRUCTWrongType(t *testing.T) {
|
||||||
|
prog := makeProgram(NEWSTRUCT)
|
||||||
|
vm := load(prog)
|
||||||
|
vm.estack.Push(NewElement([]byte{}))
|
||||||
|
vm.Run()
|
||||||
|
assert.Equal(t, true, vm.state.HasFlag(faultState))
|
||||||
|
}
|
||||||
|
|
||||||
func TestAppCall(t *testing.T) {
|
func TestAppCall(t *testing.T) {
|
||||||
prog := []byte{byte(APPCALL)}
|
prog := []byte{byte(APPCALL)}
|
||||||
hash := util.Uint160{}
|
hash := util.Uint160{}
|
||||||
|
|
Loading…
Reference in a new issue