// vm, the virtual low level machine that runs MUESLI. package muesli import "fmt" // Handler function type Handler func(vm *VM, arguments ...Value) []Value func (handler *Handler) Call(vm *VM, arguments ...Value) []Value { return (*handler)(vm, arguments...) } // A callable Value must implement the Callable interface type Callable interface { // Callable can be called Call(vm *VM, arguments ...Value) []Value // Callable has a position here it was defined. Needed for tracebacks. Position() *Position } // A helper Value has a help text available. // This help text can be set as well. type Helper interface { HelperName() string Help() string SetHelp(string) string } // Callable value types type CallableValue struct { // Name of the callable Name string // Help string for the callable. HelpText string } // Implement Helper interface func (val CallableValue) Help() string { return val.HelpText } // Implement Helper interface func (val * CallableValue) SetHelp(help string) string { val.HelpText = help return val.HelpText } // Implement Helper interface func (val CallableValue) HelperName() string { return val.Name } // AppendHelp appends help to an existing helper. func AppendHelp(helper Helper, extra string) string { return helper.SetHelp( helper.Help() + extra) } // ClearHelp rresets the help text to an empty string. func ClearHelp(helper Helper, extra string) string { return helper.SetHelp("") } func (val CallableValue) String() string { return val.Name } func (val CallableValue) Type() TypeValue { return TypeValue("Callable") } func (from CallableValue) Convert(to interface{}) error { return NewErrorValuef("Cannot convert the callable value %v to %v", from, to) } func (val *CallableValue) Call(vm *VM, arguments ...Value) []Value { panic("Not implemented") } // A struct to store a built in function type BuiltinValue struct { CallableValue Handler } func NewCallableValue(name string) CallableValue { return CallableValue{name, ""} } func NewBuiltinValue(name string, handler Handler) *BuiltinValue { result := &BuiltinValue{} result.Name = name result.Handler = handler return result } // A block in a script. type BlockValue struct { CallableValue Ast *Ast } func NewBlockValue(definition *Ast) *BlockValue { result := &BlockValue{} result.Name = fmt.Sprintf("", definition.String()) result.Ast = definition return result } func (block * BlockValue) Position() *Position { if block == nil { return nil } if block.Ast == nil { return nil } pos := block.Ast.Token().Position return &pos } func (defined * DefinedValue) Position() *Position { if defined == nil { return nil } if defined.Body == nil { return nil } return defined.Body.Position() } func (cv CallableValue) Position() *Position { pos := Position{cv.Name, 1, 1} return &pos } /* Parameters for a defined value */ type Parameter struct { Name WordValue Type TypeValue } // A script defined function type DefinedValue struct { CallableValue Body *BlockValue Parameters []*Parameter } func NewDefinedValue(name string, params []*Parameter, body *BlockValue) *DefinedValue { result := &DefinedValue{} result.Name = name result.Body = body result.Parameters = params return result } func (defined *DefinedValue) Call(vm *VM, arguments ...Value) []Value { // vm.Logf("Call defined value: %v", defined) 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 } func (defined *DefinedValue) Help() string { help := defined.CallableValue.Help() extra := "[" for _, parameter := range defined.Parameters { extra = fmt.Sprintf("%s %s %s", extra, parameter.Name, parameter.Type) } extra = extra + "]:" return extra + help } /* Amount of types that will be considered inside a signature. Limited mosty to allow hashability, that is, Signature is a map key. */ const TypesInSignature = 32 /* A signature describes the desired types of an overloaded function call. */ type Signature struct { Types [TypesInSignature]TypeValue } func (s Signature) String() string { res := "[" sep := "" for _, typ := range s.Types { if typ != ZeroTypeValue { res = res + sep + typ.String() sep = " " } } res = res + "]" return res } func CalculateSignature(arguments ...Value) Signature { signature := Signature{} for i := 0; i < len(signature.Types); i++ { if i < len(arguments) { signature.Types[i] = arguments[i].Type() } else { signature.Types[i] = AnyTypeValue } } return signature } func (tv TypeValue) IsMatch(other TypeValue) bool { if tv == AnyTypeValue || other == AnyTypeValue { return true } if tv == ZeroTypeValue || other == ZeroTypeValue { return true } return tv == other } func (signature Signature) IsMatch(other Signature) bool { for i, kind := range signature.Types { t1 := kind t2 := other.Types[i] if !t1.IsMatch(t2) { return false } } return true } /* An overload is an overloaded value that can be called. */ type Overload struct { Name string Callable } /* A cover is a callable that dispatches to other callables depending on the types of the arguments, in particular the first one. The individual callable functions are the overloads */ type CoverValue struct { CallableValue Overloads map[Signature]Overload } func (cv CoverValue) String() string { res := fmt.Sprintf("cover %s [ ", cv.Name) for k, v := range cv.Overloads { res = fmt.Sprintf("%s [%v] %s", res, k, v.Name) } res = fmt.Sprintf("%s].", res) return res; } func NewCoverValue(name string) *CoverValue { result := &CoverValue{} result.Name = name result.Overloads = make(map[Signature]Overload) return result } func (cover *CoverValue) Help() string { help := cover.CallableValue.Help() extra := "\n" for signature, overload := range cover.Overloads { // fmt.Printf("overload: %v", signature) extra = extra + fmt.Sprintf("* %v -> %s\n", signature.String(), overload.Name) } return help + extra } func (cover *CoverValue) Call(vm *VM, arguments ...Value) []Value { signature := CalculateSignature(arguments...) if overload, ok := cover.Overloads[signature]; ok { return overload.Call(vm, arguments...) } else { for overloadSignature, overload := range cover.Overloads { if signature.IsMatch(overloadSignature) { return overload.Call(vm, arguments...) } } } vm.Fail() return Fail(NewErrorValuef("Could not match cover %s with arguments: %s<->%v", cover.String(), signature, arguments)) } 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) } func (from BuiltinValue) Convert(to interface{}) error { return NewErrorValuef("Cannot convert the builtin value %v to %v", from, to) } 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(name string, callable Callable, tv ... TypeValue) error { // fmt.Printf("AddOverload: %v\n", tv) signature := Signature{} length := len(tv) if length > len(signature.Types) { length = len(signature.Types) } for i := 0; i < length; i++ { signature.Types[i] = tv[i] } cv.Overloads[signature] = Overload { Name: name, Callable: callable } // fmt.Printf("Overloads: %v\n", cv.Overloads) return nil } func (vm * VM) AddOverload(from, target string, level int, tv... TypeValue) error { var cover *CoverValue var callable Callable var ok bool lookup := vm.Lookup(from) if lookup == nil { cover = vm.RegisterCover(from, level) } else if cover, ok = lookup.(*CoverValue) ; !ok { 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.(Callable) ; !ok { return fmt.Errorf("%s is not a callable value", target) } res := cover.AddOverload(target, callable, tv...) // fmt.Printf("AddOverload: %v %v\n", lookup, cover) return res } type OverloadDescription struct { Target string Types []TypeValue Level int } func (vm * VM) AddOverloads(from string, descriptions ... OverloadDescription) error { for _, od := range descriptions { err := vm.AddOverload(from, od.Target, od.Level, od.Types...) if err != nil { panic(fmt.Errorf("internal error: could not register overloads: %s", err)) } } return nil } func Over(target string, level int, types ... TypeValue) OverloadDescription { return OverloadDescription { Target: target, Level: level, Types: types} } 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 } // Scope of symbols defined in the VM, hierarchical type Scope struct { parent *Scope children []*Scope symbols map[string]Value } func NewScope(parent *Scope) *Scope { return &Scope{parent, make([]*Scope, 0), make(map[string]Value)} } func (scope *Scope) Lookup(name string) Value { value, ok := scope.symbols[name] if ok { return value } if scope.parent != nil { return scope.parent.Lookup(name) } return NilValue } func (scope *Scope) Register(name string, value Value) Value { scope.symbols[name] = value return value } func (scope * Scope) Known(filter func(string, Value) bool) map[string]Value { res := make(map[string]Value) if scope.parent != nil { res = scope.parent.Known(filter) } for k, v := range scope.symbols { if (filter == nil) || filter(k, v) { res[k] = v } } return res } func (scope * Scope) ForEachDefined(do func(string, Value) (bool, error)) (bool, error) { var res bool = true var err error if (do == nil) { return false, fmt.Errorf("do may not be nil") } if scope.parent != nil { res, err = scope.parent.ForEachDefined(do) } if res == false || err != nil { return res, err } for k, v := range scope.symbols { res, err = do(k, v) if res == false || err != nil { return res, err } } return res, err } func (scope* Scope) DefinedHelpers() []Helper { res := []Helper{} scope.ForEachDefined(func (k string, v Value) (bool, error) { helper, hok := v.(Helper) if hok { res = append(res, helper) } return true, nil }) return res } // Frame of execution of a function type Frame struct { parent *Frame arguments []Value results []Value failed bool returned bool position *Position } func NewFrame(parent *Frame, position *Position) *Frame { return &Frame{parent, EmptyValueArray(), EmptyValueArray(), false, false, position} } type Tracer interface { Trace(vm VM, ast Ast, values ...Value) bool } // Virtual machine type VM struct { TopScope *Scope // Top level scope TopFrame *Frame // Top level scope *Scope // Current Scope *Frame // Current frame Tracer // Tracer to emit tracing info to, could be used for logging or debugging ExitStatus int } func NewVM() *VM { vm := &VM{NewScope(nil), NewFrame(nil, nil), nil, nil, nil, 0} vm.Scope = vm.TopScope vm.Frame = vm.TopFrame return vm } func (vm *VM) PushNewFrame(position *Position) *Frame { frame := NewFrame(vm.Frame, position) vm.Frame = frame return frame } func (vm *VM) PushNewScope() *Scope { scope := NewScope(vm.Scope) vm.Scope = scope return scope } func (vm *VM) Return(results ...Value) []Value { return results } func (vm *VM) PopFrame() *Frame { if (vm.Frame != vm.TopFrame) && (vm.Frame.parent != nil) { frame := vm.Frame vm.Frame = frame.parent return frame } return nil } func (vm *VM) PopScope() *Scope { if (vm.Scope != vm.TopScope) && (vm.Scope.parent != nil) { scope := vm.Scope vm.Scope = scope.parent return scope } return nil } func (block * BlockValue) Call(vm *VM, arguments ...Value) []Value { ast := block.Ast // Now, don't run the bloc itself but the Statements node // that should be in it. children := ast.Children() if len(children) < 1 { return Fail(fmt.Errorf("Block has no statements.")) } if len(children) > 1 { return Fail(fmt.Errorf("Block has too many statements.")) } statements := children[0] arr := vm.RunAst(*statements, arguments...) return arr } func (builtin * BuiltinValue) Call(vm *VM, arguments ...Value) []Value { handler := builtin.Handler return handler.Call(vm, arguments...) } /* func (vm *VM) CallDefined(ast *Ast, arguments ...Value) []Value { arr := vm.RunChildren(*ast, arguments...) 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...) } func (vm *VM) CallCover(cover * CoverValue, arguments ...Value) []Value { return cover.Call(vm, arguments...) } */ func (vm *VM) AddTrace(err error) error { res := "" for frame := vm.Frame; frame != nil; frame = frame.parent { if frame.position == nil { res = fmt.Sprintf("%s\nIn frame %v", res, frame) } else { res = fmt.Sprintf("%s\nIn %s", res, frame.position.String()) } } return fmt.Errorf("%s: %s", res, err) } func (vm *VM) CallCallable(callable Callable, arguments ...Value) []Value { defer vm.PopFrame() defer vm.PopScope() vm.PushNewFrame(callable.Position()) vm.PushNewScope() result := callable.Call(vm, arguments...) return result } func (vm *VM) CallNamed(name string, arguments ...Value) []Value { value := vm.Lookup(name) if value == nil { return ReturnError(vm.AddTrace(NewErrorValuef("Cannot call %s: not found.", name))) } if callable, ok := value.(Callable) ; ok { return vm.CallCallable(callable, arguments...) } else { return ReturnError(vm.AddTrace(NewErrorValuef("Cannot call %s: %v. Not callable", name, value))) } } /* func (vm * VM) CallNamedFramed(name string, arguments ...) []Value { frame := vm.PushNewFrame() } */ // ScopeUp Returns the levelth scope up from the current one where 0 is the // current scope. Returns the toplevel scope if l is greather than the current // scope stack depth. func (vm * VM) ScopeUp(level int) *Scope { scope := vm.Scope for now := 0; now < level; now++ { if scope.parent == nil { return scope } scope = scope.parent } return scope } // RegisterUp registers in klevel scopes up from the current scope, // or at toplevel if the level is greater than the total depth func (vm *VM) RegisterUp(name string, value Value, level int) Value { scope := vm.ScopeUp(level) return scope.Register(name, value) } func (vm *VM) Register(name string, value Value) Value { return vm.Scope.Register(name, value) } func (vm *VM) RegisterCover(name string, level int) *CoverValue { value := NewCoverValue(name) vm.RegisterUp(name, value, level) return value } func (vm *VM) RegisterBuiltin(name string, handler Handler) Value { value := NewBuiltinValue(name, handler) return vm.Register(name, value) } func (vm *VM) RegisterDefined(name string, params []*Parameter, block *BlockValue, level int) Value { value := NewDefinedValue(name, params, block) return vm.RegisterUp(name, value, level) } // RegisterBuiltinWithHelp 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 } /* func (vm *VM) RunChildren(ast Ast, args ...Value) []Value { if ast.CountChildren() < 1 { return ReturnEmpty() } result := []Value{} for _, child := range ast.Children() { val := child.Run(vm, args...) if vm.Frame.returned || vm.Frame.failed { return vm.Frame.results } // skip empty results if len(val) < 1 { continue } first := val[0] if _, isEmpty := first.(EmptyValue); isEmpty { continue } last := val[len(val) -1] // errors in the results at the last position take precendence and are propagated upwards. if _, isErr := last.(ErrorValue); isErr { return val } result = append(result, val...) } return result } func (vm *VM) RunChildrenLastResult(ast Ast, args ...Value) Value { var result Value = EmptyValue{} for _, child := range ast.Children() { val := child.Run(vm, args...) if vm.Frame.returned || vm.Frame.failed { res := vm.Frame.results return res[len(res)-1] } // skip empty results if len(val) < 1 { continue } first := val[0] if _, isEmpty := first.(EmptyValue); isEmpty { continue } last := val[len(val) -1] // errors in the results at the last position take precendence and are propagated upwards. if _, isErr := last.(ErrorValue); isErr { return last } result = last } // The last non empty result is the result of this function. return result } func (vm *VM) RunChildrenFirstResult(ast Ast, args ...Value) Value { var result Value = EmptyValue{} for _, child := range ast.Children() { val := child.Run(vm, args...) if vm.Frame.returned || vm.Frame.failed { res := vm.Frame.results return res[0] } // skip empty results if len(val) < 1 { continue } first := val[0] if _, isEmpty := first.(EmptyValue); isEmpty { continue } // otherwise if non empty return the result. return val[0] } return result } */ func (vm *VM) RunAst(ast Ast, args ...Value) []Value { var result []Value /*pos := ast.Token().Position vm.PushNewFrame(&pos) defer vm.PopFrame() */ // vm.Logf("RunAst: %s\n", ast.Kind().String()) // Leaf nodes, both declared and in practice are self evaluating. if ast.Kind().IsLeaf() || ast.CountChildren() < 1 { result = ast.Eval(vm) if vm.Frame.returned || vm.Frame.failed { result = vm.Frame.results } } else { var subResult = []Value{} // Depth first recursion. for _, child := range ast.Children() { sub := vm.RunAst(*child) subResult = append(subResult, sub...) /* if frame.failed && frame.parent != nil { // failures are like panics and propagate up the call tree frame.parent.failed = true frame.parent.results = frame.results } */ if vm.Frame.returned || vm.Frame.failed { subResult = vm.Frame.results break; } } // vm.Logf("RunAst subResult: %v\n", subResult) result = ast.Eval(vm, subResult...) } // vm.Logf("RunAst result: %v\n", result) return result } func (vm *VM) DefinedHelpers() []Helper { return vm.Scope.DefinedHelpers() } /* func (vm *VM) RunProgram(ast *BasicAst) ListValue { return vm.RunChildren(ast, (*VM).RunStatements) } func (vm *VM) RunStatements(ast *BasicAst) ListValue { return vm.RunChildren(ast, (*VM).RunStatement) } func (vm *VM) RunStatement(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunSet(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunGet(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunTarget(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunCommand(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunArguments(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunArgument(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunExpression(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunBlock(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunParenthesis(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunList(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunCapture(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunWordValue(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunWord(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunType(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunValue(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunEnd(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) RunError(ast *BasicAst) ListValue { return NewListValue() } func (vm *VM) Run(ast *BasicAst) ListValue { switch ast.AstKind { case AstKindProgram: return vm.RunProgram(ast) case AstKindStatements: return vm.RunStatements(ast) case AstKindStatement: return vm.RunStatement(ast) case AstKindSet: return vm.RunSet(ast) case AstKindGet: return vm.RunGet(ast) case AstKindTarget: return vm.RunTarget(ast) case AstKindCommand: return vm.RunCommand(ast) case AstKindArguments: return vm.RunArguments(ast) case AstKindArgument: return vm.RunArgument(ast) case AstKindExpression: return vm.RunExpression(ast) case AstKindBlock: return vm.RunBlock(ast) case AstKindParenthesis: return vm.RunParenthesis(ast) case AstKindList: return vm.RunList(ast) case AstKindCapture: return vm.RunCapture(ast) case AstKindWordValue: return vm.RunWordValue(ast) case AstKindWord: return vm.RunWord(ast) case AstKindType: return vm.RunType(ast) case AstKindValue: return vm.RunValue(ast) case AstKindEnd: return vm.RunEnd(ast) case AstKindError: return vm.RunError(ast) default: return ListValue{[]Value{NewErrorValuef("Unknown ast node type: %d", ast.AstKind)}} } } */