// 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 Caller interface type Caller interface { Call(vm *VM, arguments ...Value) []Value } // Callable value types type CallableValue struct { Name string } func (val CallableValue) String() string { return val.Name } func (val *CallableValue) Call(vm *VM, arguments ...Value) ListValue { 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 } func (builtin *BuiltinValue) Call(vm *VM, arguments ...Value) []Value { return vm.CallBuiltin(builtin.Handler, arguments...) } // A script defined function type DefinedValue struct { CallableValue Definition *Ast } func NewDefinedValue(name string, definition *Ast) DefinedValue { result := DefinedValue{} result.Name = name result.Definition = definition return result } func (defined *DefinedValue) Call(vm *VM, arguments ...Value) []Value { return vm.CallDefined(defined.Definition, arguments...) } /* Amount of types that will be considered inside a signature. Limited mosty to allow hashability. */ const TypesInSignature = 8 /* A signature describes the desired types of an overloaded function call. */ type Signature struct { Types [TypesInSignature]TypeValue } func CalculateSignature(arguments ...Value) Signature { signature := Signature{} for i := 0; i < cap(signature.Types); i++ { if i > len(arguments) { signature.Types[i] = AnyTypeValue } else { signature.Types[i] = arguments[i].Type() } } return signature } func (signature *Signature) IsMatch(arguments ...Value) bool { for i, kind := range signature.Types { if i > len(arguments) || arguments[i] == nil { return false } if kind != arguments[i].Type() && kind != AnyTypeValue { return false } } return true } /* An overload is an overloaded callable value that can be called. */ type Overload struct { CallableValue } /* 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 (cover *CoverValue) Call(vm *VM, arguments ...Value) ListValue { signature := CalculateSignature(arguments...) if overload, ok := cover.Overloads[signature]; ok { return overload.Call(vm, arguments...) } else { for signature, overload := range cover.Overloads { if signature.IsMatch(arguments...) { return overload.Call(vm, arguments...) } } } vm.Fail() return NewListValue(NewErrorValuef("Could not match cover %s with arguments.", cover.Name)) } const ( CoverTypeValue = TypeValue("Cover") BuiltinTypeValue = TypeValue("Builtin") DefinedTypeValue = TypeValue("Defined") ) func (v CoverValue) Type() TypeValue { return CoverTypeValue } func (v BuiltinValue) Type() TypeValue { return BuiltinTypeValue } func (v DefinedValue) Type() TypeValue { return DefinedTypeValue } // 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) Parent(level int) *Scope { if level < 1 { return scope } parent := scope.parent for parent != nil && level > 1 { level-- parent = parent.parent } return parent } 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 } // Frame of execution of a function type Frame struct { parent *Frame arguments []Value results []Value failed bool } func NewFrame(parent *Frame) *Frame { return &Frame{parent, EmptyValueArray(), EmptyValueArray(), false} } // Virtual machine type VM struct { TopScope *Scope // Top level scope TopFrame *Frame // Top level scope *Scope // Current Scope *Frame // Current frame } func NewVM() *VM { vm := &VM{NewScope(nil), NewFrame(nil), nil, nil} vm.Scope = vm.TopScope vm.Frame = vm.TopFrame return vm } func (vm *VM) PushNewFrame() *Frame { frame := NewFrame(vm.Frame) vm.Frame = frame return frame } func (vm *VM) PushNewScope() *Scope { scope := NewScope(vm.Scope) vm.Scope = scope return scope } 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 (vm *VM) CallDefined(ast *Ast, arguments ...Value) []Value { return ast.Run(vm, arguments) } func (vm *VM) CallBuiltin(handler Handler, arguments ...Value) []Value { return handler.Call(vm, arguments...) } func (vm *VM) CallNamed(name string, arguments ...Value) []Value { value := vm.Lookup(name) switch toCall := value.(type) { case BuiltinValue: return vm.CallBuiltin(toCall.Handler, arguments...) case DefinedValue: return vm.CallDefined(toCall.Definition, arguments...) default: return NewValueArray(NewErrorValuef("Cannot call %s: %v", name, value)) } } /* func (vm * VM) CallNamedFramed(name string, arguments ...) []Value { frame := vm.PushNewFrame() } */ func (vm *VM) Register(name string, value Value) Value { return vm.Scope.Register(name, 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, ast *Ast) Value { value := NewDefinedValue(name, ast) return vm.Register(name, value) } func (vm *VM) Fail() { vm.Frame.failed = true } func (vm *VM) RunChildren(ast Ast, args ...Value) []Value { result := NewValueArray() for _, child := range ast.Children() { val := child.Run(vm, args) result = append(result, val...) } return result } /* 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)}} } } */