mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-12 11:10:35 +00:00
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:
commit
d0853c0471
3 changed files with 85 additions and 43 deletions
|
@ -87,6 +87,16 @@ var commands = []*ishell.Cmd{
|
|||
> load /path/to/file.go`,
|
||||
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",
|
||||
Help: "Execute the current loaded script",
|
||||
|
@ -270,6 +280,20 @@ func handleLoadGo(c *ishell.Context) {
|
|||
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) {
|
||||
v := getVMFromContext(c)
|
||||
if len(c.Args) != 0 {
|
||||
|
@ -297,7 +321,13 @@ func runVMWithHandling(c *ishell.Context, v *vm.VM) {
|
|||
c.Err(err)
|
||||
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
|
||||
switch {
|
||||
case v.HasFailed():
|
||||
|
@ -340,8 +370,17 @@ func handleStep(c *ishell.Context) {
|
|||
return
|
||||
}
|
||||
}
|
||||
v.AddBreakPointRel(n)
|
||||
runVMWithHandling(c, v)
|
||||
for i := 0; i < n; i++ {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -408,43 +447,53 @@ func isMethodArg(s string) bool {
|
|||
func parseArgs(args []string) ([]vm.StackItem, error) {
|
||||
items := make([]vm.StackItem, len(args))
|
||||
for i, arg := range args {
|
||||
var typ, value string
|
||||
typeAndVal := strings.Split(arg, ":")
|
||||
if len(typeAndVal) < 2 {
|
||||
if typeAndVal[0] == boolFalse || typeAndVal[0] == boolTrue {
|
||||
typ = boolType
|
||||
} else if _, err := strconv.Atoi(typeAndVal[0]); err == nil {
|
||||
typ = intType
|
||||
} else {
|
||||
typ = stringType
|
||||
}
|
||||
value = typeAndVal[0]
|
||||
} else {
|
||||
typ = typeAndVal[0]
|
||||
value = typeAndVal[1]
|
||||
item, err := parseArg(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items[i] = item
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
switch typ {
|
||||
case boolType:
|
||||
if value == boolFalse {
|
||||
items[i] = vm.NewBoolItem(false)
|
||||
} else if value == boolTrue {
|
||||
items[i] = vm.NewBoolItem(true)
|
||||
} else {
|
||||
return nil, errors.New("failed to parse bool parameter")
|
||||
}
|
||||
case intType:
|
||||
val, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items[i] = vm.NewBigIntegerItem(val)
|
||||
case stringType:
|
||||
items[i] = vm.NewByteArrayItem([]byte(value))
|
||||
func parseArg(arg string) (vm.StackItem, error) {
|
||||
var typ, value string
|
||||
var item vm.StackItem
|
||||
|
||||
typeAndVal := strings.Split(arg, ":")
|
||||
if len(typeAndVal) < 2 {
|
||||
if typeAndVal[0] == boolFalse || typeAndVal[0] == boolTrue {
|
||||
typ = boolType
|
||||
} else if _, err := strconv.Atoi(typeAndVal[0]); err == nil {
|
||||
typ = intType
|
||||
} else {
|
||||
typ = stringType
|
||||
}
|
||||
value = typeAndVal[0]
|
||||
} else {
|
||||
typ = typeAndVal[0]
|
||||
value = typeAndVal[1]
|
||||
}
|
||||
|
||||
return items, nil
|
||||
switch typ {
|
||||
case boolType:
|
||||
if value == boolFalse {
|
||||
item = vm.NewBoolItem(false)
|
||||
} else if value == boolTrue {
|
||||
item = vm.NewBoolItem(true)
|
||||
} else {
|
||||
return nil, errors.New("failed to parse bool parameter")
|
||||
}
|
||||
case intType:
|
||||
val, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item = vm.NewBigIntegerItem(val)
|
||||
case stringType:
|
||||
item = vm.NewByteArrayItem([]byte(value))
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func printLogo(c *ishell.Shell) {
|
||||
|
|
|
@ -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()})
|
||||
default:
|
||||
arr := obj.Bytes()
|
||||
if index < 0 || index >= len(arr) {
|
||||
panic("PICKITEM: invalid index")
|
||||
}
|
||||
item := arr[index]
|
||||
v.estack.PushVal(int(item))
|
||||
panic("PICKITEM: unknown type")
|
||||
}
|
||||
|
||||
case opcode.SETITEM:
|
||||
|
|
|
@ -1367,9 +1367,7 @@ func TestPICKITEMByteArray(t *testing.T) {
|
|||
vm := load(prog)
|
||||
vm.estack.PushVal([]byte{1, 2})
|
||||
vm.estack.PushVal(1)
|
||||
runVM(t, vm)
|
||||
assert.Equal(t, 1, vm.estack.Len())
|
||||
assert.Equal(t, makeStackItem(2), vm.estack.Pop().value)
|
||||
checkVMFailed(t, vm)
|
||||
}
|
||||
|
||||
func TestPICKITEMDupArray(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue