vm: implement KEYS opcode

This commit is contained in:
Evgenii Stratonikov 2019-09-24 15:41:39 +03:00
parent 0fb4bb05cf
commit 2da64267b0
3 changed files with 60 additions and 1 deletions

View file

@ -19,10 +19,18 @@ func makeStackItem(v interface{}) StackItem {
return &BigIntegerItem{ return &BigIntegerItem{
value: big.NewInt(int64(val)), value: big.NewInt(int64(val)),
} }
case int64:
return &BigIntegerItem{
value: big.NewInt(val),
}
case []byte: case []byte:
return &ByteArrayItem{ return &ByteArrayItem{
value: val, value: val,
} }
case string:
return &ByteArrayItem{
value: []byte(val),
}
case bool: case bool:
return &BoolItem{ return &BoolItem{
value: val, value: val,

View file

@ -912,12 +912,29 @@ func (v *VM) execute(ctx *Context, op Instruction) {
} }
v.estack.PushVal(sigok) v.estack.PushVal(sigok)
case KEYS, VALUES: case VALUES:
panic("unimplemented") panic("unimplemented")
case NEWMAP: case NEWMAP:
v.estack.Push(&Element{value: NewMapItem()}) v.estack.Push(&Element{value: NewMapItem()})
case KEYS:
item := v.estack.Pop()
if item == nil {
panic("no argument")
}
m, ok := item.value.(*MapItem)
if !ok {
panic("not a Map")
}
arr := make([]StackItem, 0, len(m.value))
for k := range m.value {
arr = append(arr, makeStackItem(k))
}
v.estack.PushVal(arr)
case HASKEY: case HASKEY:
key := v.estack.Pop() key := v.estack.Pop()
validateMapKey(key) validateMapKey(key)

View file

@ -673,6 +673,40 @@ func TestSIZEBool(t *testing.T) {
assert.Equal(t, makeStackItem(1), vm.estack.Pop().value) assert.Equal(t, makeStackItem(1), vm.estack.Pop().value)
} }
func TestKEYSMap(t *testing.T) {
prog := makeProgram(KEYS)
vm := load(prog)
m := NewMapItem()
m.Add(makeStackItem(5), makeStackItem(6))
m.Add(makeStackItem([]byte{0, 1}), makeStackItem(6))
vm.estack.Push(&Element{value: m})
vm.Run()
assert.Equal(t, false, vm.HasFailed())
assert.Equal(t, 1, vm.estack.Len())
top := vm.estack.Pop().value.(*ArrayItem)
assert.Equal(t, 2, len(top.value))
assert.Contains(t, top.value, makeStackItem(5))
assert.Contains(t, top.value, makeStackItem([]byte{0, 1}))
}
func TestKEYSNoArgument(t *testing.T) {
prog := makeProgram(KEYS)
vm := load(prog)
vm.Run()
assert.Equal(t, true, vm.HasFailed())
}
func TestKEYSWrongType(t *testing.T) {
prog := makeProgram(KEYS)
vm := load(prog)
vm.estack.PushVal([]StackItem{})
vm.Run()
assert.Equal(t, true, vm.HasFailed())
}
func TestHASKEYArrayTrue(t *testing.T) { func TestHASKEYArrayTrue(t *testing.T) {
prog := makeProgram(PUSH5, NEWARRAY, PUSH4, HASKEY) prog := makeProgram(PUSH5, NEWARRAY, PUSH4, HASKEY)
vm := load(prog) vm := load(prog)