|
@@ -15,11 +15,44 @@ type Caller interface {
|
|
|
Call(vm *VM, arguments ...Value) []Value
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+type Helper interface {
|
|
|
+ Help() string
|
|
|
+ SetHelp(string) string
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
|
|
|
type CallableValue struct {
|
|
|
+
|
|
|
Name string
|
|
|
+
|
|
|
+ HelpText string
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func (val CallableValue) Help() string {
|
|
|
+ return val.HelpText
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func (val * CallableValue) SetHelp(help string) string {
|
|
|
+ val.HelpText = help
|
|
|
+ return val.HelpText
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func AppendHelp(helper Helper, extra string) string {
|
|
|
+ return helper.SetHelp( helper.Help() + extra)
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+func ClearHelp(helper Helper, extra string) string {
|
|
|
+ return helper.SetHelp("")
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
func (val CallableValue) String() string {
|
|
|
return val.Name
|
|
|
}
|
|
@@ -43,7 +76,7 @@ type BuiltinValue struct {
|
|
|
}
|
|
|
|
|
|
func NewCallableValue(name string) CallableValue {
|
|
|
- return CallableValue{name}
|
|
|
+ return CallableValue{name, ""}
|
|
|
}
|
|
|
|
|
|
func NewBuiltinValue(name string, handler Handler) *BuiltinValue {
|
|
@@ -57,21 +90,67 @@ func (builtin *BuiltinValue) Call(vm *VM, arguments ...Value) []Value {
|
|
|
return vm.CallBuiltin(builtin.Handler, arguments...)
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+type BlockValue struct {
|
|
|
+ CallableValue
|
|
|
+ Ast *Ast
|
|
|
+}
|
|
|
+
|
|
|
+func NewBlockValue(definition *Ast) *BlockValue {
|
|
|
+ result := &BlockValue{}
|
|
|
+ result.Name = fmt.Sprintf("<block:%s>", definition.String())
|
|
|
+ result.Ast = definition
|
|
|
+ return result
|
|
|
+}
|
|
|
+
|
|
|
+func (block *BlockValue) Call(vm *VM, arguments ...Value) []Value {
|
|
|
+ res := vm.CallBlock(block.Ast, arguments...)
|
|
|
+ return res
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+type Parameter struct {
|
|
|
+ Name WordValue
|
|
|
+ Type TypeValue
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
|
|
|
type DefinedValue struct {
|
|
|
CallableValue
|
|
|
- Definition *Ast
|
|
|
+ Body *BlockValue
|
|
|
+ Parameters []*Parameter
|
|
|
}
|
|
|
|
|
|
-func NewDefinedValue(name string, definition *Ast) *DefinedValue {
|
|
|
+func NewDefinedValue(name string, params []*Parameter, body *BlockValue) *DefinedValue {
|
|
|
result := &DefinedValue{}
|
|
|
result.Name = name
|
|
|
- result.Definition = definition
|
|
|
+ result.Body = body
|
|
|
+ result.Parameters = params
|
|
|
return result
|
|
|
}
|
|
|
|
|
|
func (defined *DefinedValue) Call(vm *VM, arguments ...Value) []Value {
|
|
|
- return vm.CallDefined(defined.Definition, arguments...)
|
|
|
+ defer vm.PopFrame()
|
|
|
+ defer vm.PopScope()
|
|
|
+ vm.PushNewFrame()
|
|
|
+ vm.PushNewScope()
|
|
|
+ for i , arg := range arguments {
|
|
|
+ if i >= len(defined.Parameters) {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ param := defined.Parameters[i]
|
|
|
+ expectedType := param.Type
|
|
|
+ if !expectedType.IsMatch(arg.Type()) {
|
|
|
+ return Fail(NewErrorValuef("Argument %d type mismatch: %s<->%s", i, expectedType, arg.Type()))
|
|
|
+ }
|
|
|
+ vm.Register(param.Name.String(), arg)
|
|
|
+ }
|
|
|
+
|
|
|
+ res := defined.Body.Call(vm, arguments...)
|
|
|
+ return res
|
|
|
+
|
|
|
}
|
|
|
|
|
|
|
|
@@ -167,11 +246,13 @@ const (
|
|
|
CoverTypeValue = TypeValue("Cover")
|
|
|
BuiltinTypeValue = TypeValue("Builtin")
|
|
|
DefinedTypeValue = TypeValue("Defined")
|
|
|
+ BlockTypeValue = TypeValue("Block")
|
|
|
)
|
|
|
|
|
|
func (v CoverValue) Type() TypeValue { return CoverTypeValue }
|
|
|
func (v BuiltinValue) Type() TypeValue { return BuiltinTypeValue }
|
|
|
func (v DefinedValue) Type() TypeValue { return DefinedTypeValue }
|
|
|
+func (v BlockValue) Type() TypeValue { return BlockTypeValue }
|
|
|
|
|
|
func (from CoverValue) Convert(to interface{}) error {
|
|
|
return NewErrorValuef("Cannot convert the cover value %v to %v", from, to)
|
|
@@ -185,8 +266,17 @@ func (from DefinedValue) Convert(to interface{}) error {
|
|
|
return NewErrorValuef("Cannot convert the defined value %v to %v", from, to)
|
|
|
}
|
|
|
|
|
|
+func (from BlockValue) Convert(to interface{}) error {
|
|
|
+ if toValue, isOk := to.(*BlockValue) ; isOk {
|
|
|
+ (*toValue) = from
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ return NewErrorValuef("Cannot convert the block value %v to %v", from, to)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
func (cv * CoverValue) AddOverload(callable Caller, tv ... TypeValue) error {
|
|
|
- fmt.Printf("AddOverload: %v\n", tv)
|
|
|
+
|
|
|
|
|
|
signature := Signature{}
|
|
|
length := len(tv)
|
|
@@ -200,7 +290,7 @@ func (cv * CoverValue) AddOverload(callable Caller, tv ... TypeValue) error {
|
|
|
|
|
|
cv.Overloads[signature] = Overload { callable }
|
|
|
|
|
|
- fmt.Printf("Overloads: %v\n", cv.Overloads)
|
|
|
+
|
|
|
|
|
|
return nil
|
|
|
}
|
|
@@ -216,24 +306,38 @@ func (vm * VM) AddOverload(from, target string, tv... TypeValue) error {
|
|
|
return fmt.Errorf("%s exists and is not a cover value", from)
|
|
|
}
|
|
|
|
|
|
- fmt.Printf("AddOverload: %v %v\n", lookup, cover)
|
|
|
+
|
|
|
|
|
|
lookup = vm.Lookup(target)
|
|
|
if lookup == nil {
|
|
|
return fmt.Errorf("target %s is not defined", target)
|
|
|
}
|
|
|
- fmt.Printf("AddOverload lookup: %v\n", lookup)
|
|
|
+
|
|
|
|
|
|
if callable, ok = lookup.(Caller) ; !ok {
|
|
|
return fmt.Errorf("%s is not a callable value", target)
|
|
|
}
|
|
|
res := cover.AddOverload(callable, tv...)
|
|
|
|
|
|
- fmt.Printf("AddOverload: %v %v\n", lookup, cover)
|
|
|
+
|
|
|
|
|
|
return res
|
|
|
}
|
|
|
|
|
|
+func (vm * VM) SetHelp(target, help string) error {
|
|
|
+ var helper Helper
|
|
|
+ var ok bool
|
|
|
+ lookup := vm.Lookup(target)
|
|
|
+ if lookup == nil {
|
|
|
+ return fmt.Errorf("%s not found", target)
|
|
|
+ } else if helper, ok = lookup.(Helper) ; !ok {
|
|
|
+ return fmt.Errorf("%s exists but cannot set help text.", target)
|
|
|
+ }
|
|
|
+ helper.SetHelp(help)
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
|
|
|
type Scope struct {
|
|
|
parent *Scope
|
|
@@ -296,10 +400,11 @@ type VM struct {
|
|
|
*Scope
|
|
|
*Frame
|
|
|
Tracer
|
|
|
+ ExitStatus int
|
|
|
}
|
|
|
|
|
|
func NewVM() *VM {
|
|
|
- vm := &VM{NewScope(nil), NewFrame(nil), nil, nil, nil}
|
|
|
+ vm := &VM{NewScope(nil), NewFrame(nil), nil, nil, nil, 0}
|
|
|
vm.Scope = vm.TopScope
|
|
|
vm.Frame = vm.TopFrame
|
|
|
return vm
|
|
@@ -340,6 +445,11 @@ func (vm *VM) CallDefined(ast *Ast, arguments ...Value) []Value {
|
|
|
return arr
|
|
|
}
|
|
|
|
|
|
+func (vm *VM) CallBlock(ast *Ast, arguments ...Value) []Value {
|
|
|
+ arr := vm.RunChildren(*ast, arguments...)
|
|
|
+ return arr
|
|
|
+}
|
|
|
+
|
|
|
func (vm *VM) CallBuiltin(handler Handler, arguments ...Value) []Value {
|
|
|
return handler.Call(vm, arguments...)
|
|
|
}
|
|
@@ -355,9 +465,11 @@ func (vm *VM) CallNamed(name string, arguments ...Value) []Value {
|
|
|
case *BuiltinValue:
|
|
|
return vm.CallBuiltin(toCall.Handler, arguments...)
|
|
|
case *DefinedValue:
|
|
|
- return vm.CallDefined(toCall.Definition, arguments...)
|
|
|
+ return vm.CallDefined(toCall.Body.Ast, arguments...)
|
|
|
case *CoverValue:
|
|
|
return vm.CallCover(toCall, arguments...)
|
|
|
+ case *BlockValue:
|
|
|
+ return vm.CallBlock(toCall.Ast, arguments...)
|
|
|
default:
|
|
|
return ReturnError(NewErrorValuef("Cannot call %s: %v", name, value))
|
|
|
}
|
|
@@ -385,11 +497,18 @@ func (vm *VM) RegisterBuiltin(name string, handler Handler) Value {
|
|
|
return vm.Register(name, value)
|
|
|
}
|
|
|
|
|
|
-func (vm *VM) RegisterDefined(name string, ast *Ast) Value {
|
|
|
- value := NewDefinedValue(name, ast)
|
|
|
+func (vm *VM) RegisterDefined(name string, params []*Parameter, block *BlockValue) Value {
|
|
|
+ value := NewDefinedValue(name, params, block)
|
|
|
return vm.Register(name, value)
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+func (vm *VM) RegisterBuiltinWithHelp(name string, handler Handler, help string) Value {
|
|
|
+ res := vm.RegisterBuiltin(name, handler)
|
|
|
+ vm.SetHelp(name, help)
|
|
|
+ return res
|
|
|
+}
|
|
|
+
|
|
|
func (vm *VM) Fail() {
|
|
|
vm.Frame.failed = true
|
|
|
}
|