vm/cli: add some convenience heuristic to ease 'run' use

This commit is contained in:
Roman Khimov 2019-09-10 19:41:11 +03:00
parent c5911c2f10
commit 392a4c4f39

View file

@ -15,7 +15,14 @@ import (
"gopkg.in/abiosoft/ishell.v2" "gopkg.in/abiosoft/ishell.v2"
) )
const vmKey = "vm" const (
vmKey = "vm"
boolType = "bool"
boolFalse = "false"
boolTrue = "true"
intType = "int"
stringType = "string"
)
var commands = []*ishell.Cmd{ var commands = []*ishell.Cmd{
{ {
@ -87,12 +94,16 @@ var commands = []*ishell.Cmd{
<operation> is an operation name, passed as a first parameter to Main() (and it <operation> is an operation name, passed as a first parameter to Main() (and it
can't be 'help' at the moment) can't be 'help' at the moment)
<parameter> is a parameter (can be repeated multiple times) specified <parameter> is a parameter (can be repeated multiple times) that can be specified
as <type>:<value>, where type can be: as <type>:<value>, where type can be:
'bool': supports 'false' and 'true' values '` + boolType + `': supports '` + boolFalse + `' and '` + boolTrue + `' values
'int': supports integers as values '` + intType + `': supports integers as values
'string': supports strings as values (that are pushed as a byte array '` + stringType + `': supports strings as values (that are pushed as a byte array
values to the stack) values to the stack)
or can be just <value>, for which the type will be detected automatically
following these rules: '` + boolTrue + `' and '` + boolFalse + `' are treated as respective
boolean values, everything that can be converted to integer is treated as
integer and everything else is treated like a string.
Passing parameters without operation is not supported. Parameters are packed Passing parameters without operation is not supported. Parameters are packed
into array before they're passed to the script, so effectively 'run' only into array before they're passed to the script, so effectively 'run' only
@ -100,7 +111,7 @@ supports contracts with signatures like this:
func Main(operation string, args []interface{}) interface{} func Main(operation string, args []interface{}) interface{}
Example: Example:
> run put string:"Something to put"`, > run put ` + stringType + `:"Something to put"`,
Func: handleRun, Func: handleRun,
}, },
{ {
@ -316,30 +327,38 @@ 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 {
var typ, value string
typeAndVal := strings.Split(arg, ":") typeAndVal := strings.Split(arg, ":")
if len(typeAndVal) < 2 { if len(typeAndVal) < 2 {
return nil, errors.New("arguments need to be specified as <typ:val>") 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]
} }
typ := typeAndVal[0]
value := typeAndVal[1]
switch typ { switch typ {
case "bool": case boolType:
if value == "false" { if value == boolFalse {
items[i] = vm.NewBoolItem(false) items[i] = vm.NewBoolItem(false)
} else if value == "true" { } else if value == boolTrue {
items[i] = vm.NewBoolItem(true) items[i] = vm.NewBoolItem(true)
} else { } else {
return nil, errors.New("failed to parse bool parameter") return nil, errors.New("failed to parse bool parameter")
} }
case "int": case intType:
val, err := strconv.Atoi(value) val, err := strconv.Atoi(value)
if err != nil { if err != nil {
return nil, err return nil, err
} }
items[i] = vm.NewBigIntegerItem(val) items[i] = vm.NewBigIntegerItem(val)
case "string": case stringType:
items[i] = vm.NewByteArrayItem([]byte(value)) items[i] = vm.NewByteArrayItem([]byte(value))
} }
} }