Merge pull request #967 from nspcc-dev/fix-pickitem-and-vm-cli-2.x

Fix pickitem and vm cli 2.x
This commit is contained in:
Roman Khimov 2020-05-21 13:37:35 +03:00 committed by GitHub
commit d0853c0471
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 85 additions and 43 deletions

View file

@ -87,6 +87,16 @@ var commands = []*ishell.Cmd{
> load /path/to/file.go`, > load /path/to/file.go`,
Func: handleLoadGo, Func: handleLoadGo,
}, },
{
Name: "push",
Help: "Push given item to the estack",
LongHelp: `Usage: push <parameter>
<parameter> is mandatory, example:
> push methodstring
See run command help for parameter syntax.`,
Func: handlePush,
},
{ {
Name: "run", Name: "run",
Help: "Execute the current loaded script", Help: "Execute the current loaded script",
@ -270,6 +280,20 @@ func handleLoadGo(c *ishell.Context) {
changePrompt(c, v) changePrompt(c, v)
} }
func handlePush(c *ishell.Context) {
v := getVMFromContext(c)
if len(c.Args) == 0 {
c.Err(errors.New("missing parameter"))
return
}
param, err := parseArg(c.Args[0])
if err != nil {
c.Err(err)
return
}
v.Estack().PushVal(param)
}
func handleRun(c *ishell.Context) { func handleRun(c *ishell.Context) {
v := getVMFromContext(c) v := getVMFromContext(c)
if len(c.Args) != 0 { if len(c.Args) != 0 {
@ -297,7 +321,13 @@ func runVMWithHandling(c *ishell.Context, v *vm.VM) {
c.Err(err) c.Err(err)
return return
} }
checkAndPrintVMState(c, v)
}
// checkAndPrintVMState checks VM state and outputs it to the user if it's
// failed, halted or at breakpoint. No message is printed if VM is running
// normally.
func checkAndPrintVMState(c *ishell.Context, v *vm.VM) {
var message string var message string
switch { switch {
case v.HasFailed(): case v.HasFailed():
@ -340,8 +370,17 @@ func handleStep(c *ishell.Context) {
return return
} }
} }
v.AddBreakPointRel(n) for i := 0; i < n; i++ {
runVMWithHandling(c, v) err := v.Step()
if err != nil {
c.Err(err)
return
}
checkAndPrintVMState(c, v)
}
ctx := v.Context()
i, op := ctx.CurrInstr()
c.Printf("at %d (%s)\n", i, op.String())
changePrompt(c, v) changePrompt(c, v)
} }
@ -408,7 +447,19 @@ func isMethodArg(s string) bool {
func parseArgs(args []string) ([]vm.StackItem, error) { func parseArgs(args []string) ([]vm.StackItem, error) {
items := make([]vm.StackItem, len(args)) items := make([]vm.StackItem, len(args))
for i, arg := range args { for i, arg := range args {
item, err := parseArg(arg)
if err != nil {
return nil, err
}
items[i] = item
}
return items, nil
}
func parseArg(arg string) (vm.StackItem, error) {
var typ, value string var typ, value string
var item vm.StackItem
typeAndVal := strings.Split(arg, ":") typeAndVal := strings.Split(arg, ":")
if len(typeAndVal) < 2 { if len(typeAndVal) < 2 {
if typeAndVal[0] == boolFalse || typeAndVal[0] == boolTrue { if typeAndVal[0] == boolFalse || typeAndVal[0] == boolTrue {
@ -427,9 +478,9 @@ func parseArgs(args []string) ([]vm.StackItem, error) {
switch typ { switch typ {
case boolType: case boolType:
if value == boolFalse { if value == boolFalse {
items[i] = vm.NewBoolItem(false) item = vm.NewBoolItem(false)
} else if value == boolTrue { } else if value == boolTrue {
items[i] = vm.NewBoolItem(true) item = vm.NewBoolItem(true)
} else { } else {
return nil, errors.New("failed to parse bool parameter") return nil, errors.New("failed to parse bool parameter")
} }
@ -438,13 +489,11 @@ func parseArgs(args []string) ([]vm.StackItem, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
items[i] = vm.NewBigIntegerItem(val) item = vm.NewBigIntegerItem(val)
case stringType: case stringType:
items[i] = vm.NewByteArrayItem([]byte(value)) item = vm.NewByteArrayItem([]byte(value))
} }
} return item, nil
return items, nil
} }
func printLogo(c *ishell.Shell) { func printLogo(c *ishell.Shell) {

View file

@ -1029,12 +1029,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
} }
v.estack.Push(&Element{value: t.value[index].Value.Dup()}) v.estack.Push(&Element{value: t.value[index].Value.Dup()})
default: default:
arr := obj.Bytes() panic("PICKITEM: unknown type")
if index < 0 || index >= len(arr) {
panic("PICKITEM: invalid index")
}
item := arr[index]
v.estack.PushVal(int(item))
} }
case opcode.SETITEM: case opcode.SETITEM:

View file

@ -1367,9 +1367,7 @@ func TestPICKITEMByteArray(t *testing.T) {
vm := load(prog) vm := load(prog)
vm.estack.PushVal([]byte{1, 2}) vm.estack.PushVal([]byte{1, 2})
vm.estack.PushVal(1) vm.estack.PushVal(1)
runVM(t, vm) checkVMFailed(t, vm)
assert.Equal(t, 1, vm.estack.Len())
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
} }
func TestPICKITEMDupArray(t *testing.T) { func TestPICKITEMDupArray(t *testing.T) {