Browse Source

Signatures for all callables. Think about type system.

Beoran 4 years ago
parent
commit
027d3a2f29
27 changed files with 1006 additions and 819 deletions
  1. 1 1
      ast.go
  2. 1 0
      block.go
  3. 39 0
      bool.go
  4. 34 84
      builtin.go
  5. 1 0
      callable.go
  6. 8 1
      cmd/muesli/main.go
  7. 62 0
      cover.go
  8. 1 0
      defined.go
  9. 94 0
      door.go
  10. 24 0
      empty.go
  11. 43 0
      error.go
  12. 46 0
      float.go
  13. 1 0
      help.go
  14. 45 0
      int.go
  15. 144 0
      keyword.go
  16. 0 8
      lexer.go
  17. 96 0
      list.go
  18. 60 0
      map.go
  19. 36 33
      parser.go
  20. 51 0
      redispatch.go
  21. 38 1
      signature.go
  22. 28 0
      string.go
  23. 9 0
      token.go
  24. 43 0
      type.go
  25. 4 426
      value.go
  26. 72 265
      vm.go
  27. 25 0
      word.go

+ 1 - 1
ast.go

@@ -220,7 +220,7 @@ func (astkind AstMetaKindParenthesis) Eval(vm *VM, ast Ast, val ...Value) []Valu
 }
 
 func (astkind AstMetaKindList) Eval(vm *VM, ast Ast, val ...Value) []Value {	
-	list := &ListValue{List:val}
+	list := NewListValue(val...)
 	return []Value{list}
 }
 

+ 1 - 0
block.go

@@ -0,0 +1 @@
+package muesli

+ 39 - 0
bool.go

@@ -0,0 +1,39 @@
+package muesli
+
+const BoolType   		= TypeValue("Bool")
+
+// IntValue are Muesli booleans
+type BoolValue bool
+
+const (
+	// TrueValue is the Muesli side equvalent to true
+	TrueValue       = BoolValue(true)
+	// FalseValue is the Muesli side equvalent to false
+	FalseValue      = BoolValue(false)
+)
+
+func (val BoolValue) String() string {
+	if bool(val) {
+		return "true"
+	} else {
+		return "false"
+	}
+}
+
+func (v BoolValue) Type() TypeValue   { return BoolType }
+
+
+func (from BoolValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *bool:			 
+			(*toPtr) = bool(from) 		
+		case *BoolValue:
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from												
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+

+ 34 - 84
builtin.go

@@ -253,10 +253,9 @@ func cover(vm *VM, args ...Value) []Value {
 
 func types(vm *VM, args ...Value) []Value {
 	result := []Value{}
-	for i, arg := range args {
+	for _, arg := range args {
 		typ := arg.Type() 
 		result = append(result, typ)
-		fmt.Printf("Type %d: %s\n", i, typ.String())
 	}
 	return Ok(NewListValue(result...))
 }
@@ -292,6 +291,19 @@ func get(vm *VM, val ...Value) []Value {
 	return Ok(vm.Lookup(target))
 }
 
+func addl(vm *VM, args ...Value) []Value {	
+	var value Value
+	var list *ListValue
+	_, err := ParseArgs(args, &list, &value)
+	if err != nil {
+		return Fail(err)
+	}
+	list.Append(value)    
+	return Ok(list)	
+}
+
+
+
 func fetchl(vm *VM, args ...Value) []Value {
 	var index int
 	var list *ListValue
@@ -413,91 +425,32 @@ func exit(vm *VM, val ...Value) [] Value {
 	return Ok()
 }
 
-type Door struct {
-	name string
-	locked bool
-	opened bool
-}
-
-// Implement callable ... 
-func (door * Door) Position() *Position {
-	return &Position{"builtin.go", 427, 8}
-}
-
-
-func (door * Door) Call(vm *VM, args...Value) []Value {
-	return Redispatch(door, vm, args...)
-}
-
-var doorSignature = NewSignature(WordType) 
-
-func (door * Door) Signature() Signature {
-    return doorSignature
-}
-
-var _ Callable = &Door{}
-
-const DoorType = TypeValue("Door")
 
-func (door * Door) String() string {
-	return fmt.Sprintf("Door: %s %v %v", door.name, door.locked, door.opened)
+func (vm *VM) RegisterBuiltinTypes() {
+	vm.RegisterTop("Int", IntType)
+	vm.RegisterTop("Float", FloatType)
+	vm.RegisterTop("String",StringType)
+	vm.RegisterTop("Bool", BoolType)
+	vm.RegisterTop("Word", WordType)
+	vm.RegisterTop("Error", ErrorType)
+	vm.RegisterTop("Type", TypeType)
+	vm.RegisterTop("Empty", EmptyType)
+	vm.RegisterTop("List", ListType)
+	vm.RegisterTop("Map", MapType)
+	vm.RegisterTop("Any", AnyType)	
+	vm.RegisterTop("ZeroType", ZeroType)
 }
 
 
-func (*Door) Type() TypeValue {
-	return DoorType
-}
-
-func (from * Door) Convert(to interface{}) error {
-	switch toPtr := to.(type) {
-		case **Door:
-			(*toPtr) = from
-		case *Door:
-			(*toPtr) = *from
-		case *Value:
-			(*toPtr) = from
-		default:
-			return NewErrorValuef("Cannot convert DoorValue value %v to %v", from, to)
-	}
-	return nil
-}
-
-func door(vm *VM, val ...Value) [] Value {
-	var name string
-	var locked bool
-	_, err := ParseOptArgs(val, 1, &name, &locked)
-	if err != nil {
-		return Fail(err)
-	}
-	return Ok(&Door{name: name, locked: locked, opened:false})
-}
-
-func (door * Door) Open() {
-	door.opened = true
-}
-
-func openDoor(vm *VM, val ...Value) [] Value {
-	var door *Door
-	_, err := ParseArgs(val, &door)
-	if err != nil {
-		return Fail(err)
-	}
-	if door == nil {
-		return Fail(NewErrorValuef("Door may not be nil."))
-	}	
-	
-	fmt.Printf("Door: %v %s", door, door)
-	door.Open()
-	return Ok(door)
-}
-
 func (vm *VM) RegisterBuiltins() {
+	vm.RegisterBuiltinTypes()
+	vm.RegisterBuiltinWithHelp("addl", addl, "adds an element to a list").Takes(ListType, AnyType).Returns(ListType)
 	vm.RegisterBuiltinWithHelp("addi", addi, `adds two integers together`).Takes(IntType, IntType).Returns(BoolType)
 	vm.RegisterBuiltinWithHelp("addf", addf, `adds two floats together`).Takes(IntType, IntType).Returns(IntType)
 	vm.RegisterBuiltinWithHelp("andb", andb, `returns true if all it's arguments are true`).Takes(BoolType, BoolType).Returns(BoolType)
 	vm.RegisterBuiltin("cover", cover)
-	vm.RegisterBuiltin("fetchl", fetchl)
-	vm.RegisterBuiltin("fetchm", fetchm)
+	vm.RegisterBuiltin("fetchl", fetchl).Takes(ListType, IntType).Returns(AnyType)
+	vm.RegisterBuiltin("fetchm", fetchm).Takes(MapType, AnyType).Returns(AnyType)
 	vm.RegisterBuiltin("sumi", sumi).Takes(IntType, IntType).Returns(IntType)
 	vm.RegisterBuiltin("sumf", sumf).Takes(FloatType, FloatType).Returns(FloatType)
 	vm.RegisterBuiltin("subi", subi).Takes(IntType, IntType).Returns(IntType)
@@ -512,8 +465,8 @@ func (vm *VM) RegisterBuiltins() {
 	vm.RegisterBuiltin("p", p)
 	vm.RegisterBuiltin("println", println)
 	vm.RegisterBuiltin("printf", printf)	
-	vm.RegisterBuiltin("storel", storel)
-	vm.RegisterBuiltin("storem", storem)
+	vm.RegisterBuiltin("storel", storel).Takes(ListType, IntType).Returns(AnyType)
+	vm.RegisterBuiltin("storem", storem).Takes(MapType, AnyType).Returns(AnyType)
 	vm.RegisterBuiltin("trace", trace)
 	vm.RegisterBuiltin("to", to)
 	vm.RegisterBuiltin("types", types)
@@ -524,10 +477,6 @@ func (vm *VM) RegisterBuiltins() {
 	vm.RegisterBuiltin("help", help)
 	vm.RegisterBuiltin("explain", explain)
 	vm.RegisterBuiltin("exit", exit)
-	vm.RegisterBuiltin("door", door)
-	vm.RegisterBuiltin("openDoor", openDoor)
-    vm.Register("Door", DoorType)
-	vm.AddOverloads("open", Over("openDoor", 0, DoorType))
 	
 	vm.AddOverloads("mul", 
 			Over("mulf", 0, FloatType, FloatType),
@@ -555,6 +504,7 @@ func (vm *VM) RegisterBuiltins() {
 		)
 	vm.SetHelp("store", " storage, index, value. Store value in storage at given index.")
 	*/
+	RegisterDoor(vm)
 }
 
 

+ 1 - 0
callable.go

@@ -0,0 +1 @@
+package muesli

+ 8 - 1
cmd/muesli/main.go

@@ -11,6 +11,13 @@ import "github.com/peterh/liner"
 
 func runLine(vm *muesli.VM, in string) error {	
 	parser := muesli.NewParserFromString(in)
+	kw := vm.LoadKeywords() 
+	if kw != nil {
+		parser.AddKeywords(kw)
+	} else {
+		parser.AddKeywords(muesli.DefaultKeywords)
+		vm.StoreKeywords(muesli.DefaultKeywords)
+	}
 	ast := parser.Parse()
 	err := ast.ToError()
 	if err != nil {
@@ -26,7 +33,7 @@ func runLine(vm *muesli.VM, in string) error {
 			}
 		}
 	}
-	
+		
 	return nil
 }
 

+ 62 - 0
cover.go

@@ -0,0 +1,62 @@
+package muesli
+
+import "fmt"
+
+/* 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 {
+	BasicCallable
+	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.BasicCallable.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))
+}

+ 1 - 0
defined.go

@@ -0,0 +1 @@
+package muesli

+ 94 - 0
door.go

@@ -0,0 +1,94 @@
+package muesli
+
+import "fmt"
+
+// Door is an example of how to wrap a custom type in Muesli.
+type Door struct {
+	RedispatchCallable
+	name string
+	locked bool
+	opened bool
+}
+
+var _ Callable = &Door{}
+
+const DoorType = TypeValue("Door")
+
+func (door * Door) String() string {
+	return fmt.Sprintf("Door: %s %v %v", door.name, door.locked, door.opened)
+}
+
+
+func (*Door) Type() TypeValue {
+	return DoorType
+}
+
+func (from * Door) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case **Door:
+			(*toPtr) = from
+		case *Door:
+			(*toPtr) = *from
+		case *Value:
+			(*toPtr) = from
+		default:
+			return NewErrorValuef("Cannot convert DoorValue value %v to %v", from, to)
+	}
+	return nil
+}
+
+func door(vm *VM, val ...Value) [] Value {
+	var name string
+	var locked bool
+	_, err := ParseOptArgs(val, 1, &name, &locked)
+	if err != nil {
+		return Fail(err)
+	}
+	d := &Door{name: name, locked: locked, opened:false}
+	d.RedispatchCallable = NewRedispatchCallable("Door", d)
+	return Ok(d)
+}
+
+func (door * Door) Open() {
+	door.opened = true
+}
+
+func openDoor(vm *VM, val ...Value) [] Value {
+	var door *Door
+	_, err := ParseArgs(val, &door)
+	if err != nil {
+		return Fail(err)
+	}
+	if door == nil {
+		return Fail(NewErrorValuef("Door may not be nil."))
+	}		
+	door.Open()
+	return Ok(door)
+}
+
+func nameDoor(vm *VM, val ...Value) [] Value {
+	var door *Door
+	var name string
+	_, err := ParseArgs(val, &door, &name)
+	if err != nil {
+		return Fail(err)
+	}
+	if door == nil {
+		return Fail(NewErrorValuef("Door may not be nil."))
+	}		
+	if name == "" {
+		return Fail(NewErrorValuef("Name may not be empty."))
+	}	
+		
+	door.name = name
+	return Ok(door)
+}
+
+func RegisterDoor(vm * VM) {
+	vm.RegisterBuiltin("door", door)
+	vm.RegisterBuiltin("openDoor", openDoor).Takes(DoorType).Returns(DoorType)
+	vm.RegisterBuiltin("nameDoor", nameDoor).Takes(DoorType).Returns(DoorType)
+    vm.Register("Door", DoorType)
+	vm.AddOverloadByName("open", "openDoor", 0)
+	vm.AddOverloads("name", Over("nameDoor", 0, DoorType))
+}

+ 24 - 0
empty.go

@@ -0,0 +1,24 @@
+package muesli
+
+// EmptyValue is a Muesli value without contents
+type EmptyValue struct {
+}
+
+// EmptyType is the type of !nil values
+const EmptyType  		= TypeValue("Empty")
+
+// NilValue is the value of !nil in Muesli
+var NilValue = Value(nil)
+
+
+func (val EmptyValue) String() string {
+	return "<empty>"
+}
+	
+func (v EmptyValue) Type() TypeValue  { return EmptyType }
+
+
+func (from EmptyValue) Convert(to interface{}) error {
+	return NewErrorValuef("Cannot convert the empty value %v to %v", from, to)
+}
+

+ 43 - 0
error.go

@@ -0,0 +1,43 @@
+package muesli
+
+import "fmt"
+
+// ErrorValue are Muesli errors
+type ErrorValue struct {
+	error
+}
+
+func (v ErrorValue) Type() TypeValue  { return ErrorType }
+
+func (val ErrorValue) String() string {
+	return fmt.Sprintf("%s", val.Error())
+}
+
+const ErrorType  		= TypeValue("Error")
+
+
+func NewErrorValuef(format string, args ...interface{}) ErrorValue {
+	err := fmt.Errorf(format, args...)
+	return ErrorValue{err}
+}
+
+
+
+
+
+func (from ErrorValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		case *error:
+			(*toPtr) = from.error
+		case *ErrorValue:
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from			
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+

+ 46 - 0
float.go

@@ -0,0 +1,46 @@
+package muesli
+
+import "fmt"
+
+const FloatType  		= TypeValue("Float")
+
+// FloatValue are Muesli floating point values
+type FloatValue float64
+
+func (val FloatValue) String() string {
+	return fmt.Sprintf("%f", float64(val))
+}
+
+
+func (v FloatValue) Type() TypeValue  { return FloatType }
+
+func (from FloatValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		case *int8:
+			(*toPtr) = int8(from)
+		case *int16:
+			(*toPtr) = int16(from)
+		case *int32:
+			(*toPtr) = int32(from)
+		case *int64:
+			(*toPtr) = int64(from)
+		case *int:
+			(*toPtr) = int(from)
+		case *bool:			 
+			(*toPtr) = (from != 0) 		
+		case *float32:
+			(*toPtr) = float32(from)
+		case *float64:
+			(*toPtr) = float64(from)
+		case *FloatValue:
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from
+		default:
+			return NewErrorValuef("Cannot convert FloatValue value %v to %v", from, to)
+	}
+	return nil
+}
+

+ 1 - 0
help.go

@@ -0,0 +1 @@
+package muesli

+ 45 - 0
int.go

@@ -0,0 +1,45 @@
+package muesli
+
+import "fmt"
+
+// IntValue are Muesli integer values
+type IntValue int64
+// IntType is the type of IntValue
+const IntType    		= TypeValue("Int")
+
+func (val IntValue) String() string {
+	return fmt.Sprintf("%d", int64(val))
+}
+
+func (v IntValue) Type() TypeValue    { return IntType }
+
+func (from IntValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		case *int8:
+			(*toPtr) = int8(from)
+		case *int16:
+			(*toPtr) = int16(from)
+		case *int32:
+			(*toPtr) = int32(from)
+		case *int64:
+			(*toPtr) = int64(from)
+		case *int:
+			(*toPtr) = int(from)
+		case *bool:			 
+			(*toPtr) = (from != 0)
+		case *float32:
+			(*toPtr) = float32(from)
+		case *float64:
+			(*toPtr) = float64(from)
+		case *IntValue:
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from			
+		default:
+			return NewErrorValuef("Cannot convert IntValue value %v to %v", from, to)
+	}
+	return nil
+}
+

+ 144 - 0
keyword.go

@@ -0,0 +1,144 @@
+package muesli
+
+import "fmt"
+
+/* Muesli has no key words by default, but they can be defined if desired
+ * for ease of use. A key word is replaced by a token during lexing. */
+type Keyword struct {
+	Name string
+	TokenKind
+	Value 
+} 
+
+
+var DefaultKeywords []*Keyword = []*Keyword{
+	&Keyword { "true", TokenKindBoolean, TrueValue },
+	&Keyword { "false", TokenKindBoolean, FalseValue },
+	&Keyword { "nil", TokenKindNil, NilValue },
+	&Keyword { "do", TokenKindOpenBlock, StringValue("{") },
+	&Keyword { "end", TokenKindCloseBlock, StringValue("}") },
+	&Keyword { "as", TokenKindOpenParen, StringValue("(") },
+	&Keyword { "so", TokenKindCloseParen, StringValue(")") },
+	&Keyword { "list", TokenKindOpenList, StringValue("[") },
+	&Keyword { "done", TokenKindCloseList, StringValue("]") },
+    &Keyword { "the", TokenKindGet, StringValue("$") },
+	&Keyword { "a", TokenKindGet, StringValue("$") },
+	&Keyword { "an", TokenKindGet, StringValue("$") },
+}
+
+var DefaultKeywordsFR []*Keyword = []*Keyword{
+	&Keyword { "vrai", TokenKindBoolean, TrueValue },
+	&Keyword { "faux", TokenKindBoolean, FalseValue },
+	&Keyword { "nul", TokenKindNil, NilValue },
+	&Keyword { "fais", TokenKindOpenBlock, StringValue("{") },
+	&Keyword { "fin", TokenKindCloseBlock, StringValue("}") },
+	&Keyword { "comme", TokenKindOpenParen, StringValue("(") },
+	&Keyword { "ça", TokenKindCloseParen, StringValue(")") },
+	&Keyword { "liste", TokenKindOpenList, StringValue("[") },
+	&Keyword { "fini", TokenKindCloseList, StringValue("]") },
+    &Keyword { "le", TokenKindGet, StringValue("$") },
+    &Keyword { "la", TokenKindGet, StringValue("$") },
+}
+
+
+var _ Value = &Keyword{}
+
+const KeywordType = TypeValue("Keyword")
+
+func (kw * Keyword) String() string {
+	return fmt.Sprintf("Keyword: %s %v %v", kw.Name, kw.TokenKind, kw.Value)
+}
+
+func (*Keyword) Type() TypeValue {
+	return KeywordType
+}
+
+func (from * Keyword) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case **Keyword:
+			(*toPtr) = from
+		case *Keyword:
+			(*toPtr) = *from
+		case *Value:
+			(*toPtr) = from
+		default:
+			return NewErrorValuef("Cannot convert Keyword value %v to %v", from, to)
+	}
+	return nil
+}
+
+func (vm * VM) AddKeyword(kw *Keyword) *Keyword {
+    found := vm.Lookup(KeywordName)
+    list, ok := found.(*ListValue)
+    if !ok || list == nil  {
+        list = NewListValue()
+        vm.Register(KeywordName, list)
+    }
+    list.Append(kw)
+    return kw
+}
+
+
+func keyword(vm *VM, val ...Value) []Value {
+	var name string = val[0].String()
+	var tokenName string = val[1].String()
+    var value = val[2]
+    tokenkind, ok := NamesTokenKind[tokenName]
+    if ! ok {
+        return Fail(NewErrorValuef("Token kind unknown: %s", tokenName))
+    }
+    
+    kw := &Keyword{ Name: name, TokenKind: tokenkind, Value: value }
+	return Ok(vm.AddKeyword(kw))
+}
+
+func keywords(vm *VM, val ...Value) []Value {
+    kws := []Value{}
+    for i := 2 ; i < len(val) ; i += 3 {
+    	var name string = val[i-2].String()
+        var tokenName string = val[i-1].String()
+        var value = val[i]
+        tokenkind, ok := NamesTokenKind[tokenName]
+        if !ok {
+            return Fail(NewErrorValuef("Token kind unknown: %s", tokenName))
+        }
+        kw := &Keyword{ Name: name, TokenKind: tokenkind, Value: value }
+        kws = append(kws, kw)
+    }
+    
+    listValue := NewListValue(kws...)    
+    vm.RegisterTop(KeywordName, listValue)
+    return Ok(listValue)
+}
+
+
+const KeywordName = "muesli__keywords__"
+
+func (vm * VM) StoreKeywords(keywords []*Keyword) *ListValue {
+    vm.Register("Keyword", KeywordType) 
+    vm.RegisterBuiltin("keyword", keyword).Takes(StringType, StringType, AnyType).Returns(KeywordType)
+    vm.RegisterBuiltin("keywords", keyword).Takes(StringType, StringType, AnyType).Returns(ListType)
+    list := NewValueArray()
+    for _, kw := range keywords {
+        list = append(list, kw)
+    }    
+    listValue := NewListValue(list...)
+    vm.RegisterTop(KeywordName, listValue)
+    return listValue
+}
+
+
+func (vm * VM) LoadKeywords() ([]*Keyword) {
+    found := vm.Lookup(KeywordName)
+    list, ok := found.(*ListValue)
+    if !ok || list == nil {
+        return nil
+    }
+    
+    result := []*Keyword{}
+    for _, kw := range list.List {
+        result = append(result, kw.(*Keyword))
+    }
+    return result
+}
+

+ 0 - 8
lexer.go

@@ -18,14 +18,6 @@ import (
 	// _ "gitlab.com/beoran/woe/monolog"
 )
 
-
-/* Muesli has no key words by default, but they can be defined if desired
- * for ease of use. A key word is replaced by a token during lexing. */
-type Keyword struct {
-	Name string
-	TokenKind
-	Value 
-} 
   
 
 /* A Lexer splits scanned input into tokens.

+ 96 - 0
list.go

@@ -0,0 +1,96 @@
+package muesli
+
+// ListValue is a Muesli value with a list of other values.
+// Lists in Muesli are heterogenous, and can contain other Values of any type.
+type ListValue struct {
+    RedispatchCallable
+	List []Value
+}
+
+const ListType   		= TypeValue("List")
+
+func (v ListValue) Type() TypeValue   { return ListType }
+
+func (val ListValue) String() string {
+	res := "["
+	sep := ""
+	for _, elt := range val.List {
+        if elt == nil {
+            res = res + sep + "nil"
+        } else   { 
+            res = res + sep + elt.String()
+        }
+        sep = ", "
+	}
+	res += "]"
+	return res
+}
+
+func (from * ListValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *[]Value:
+			(*toPtr) = from.List
+		case **ListValue:
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+
+func NewListValue(elements ...Value) *ListValue {
+	l := &ListValue{ List: elements }
+	l.RedispatchCallable = NewRedispatchCallable("List", l)
+	return l    
+}
+
+func (list *ListValue) Append(elements ...Value) {
+	list.List = append(list.List, elements...)
+}
+
+func (list *ListValue) AppendList(toAppend ListValue) {
+	list.List = append(list.List, toAppend.List...)
+}
+
+func (list ListValue) Length() int {
+	return len(list.List)
+}
+
+func (list *ListValue) Fetch(i int) Value {
+	if i >= len(list.List) {
+		return NilValue
+	}
+	return list.List[i]
+}
+
+func (list *ListValue) Place(i int, v Value) Value {
+	if i >= len(list.List) {
+		return NilValue
+	}
+	list.List[i] = v
+	return list.List[i]
+}
+
+func (list *ListValue) First() Value {
+	return list.Fetch(0)
+}
+
+func (list *ListValue) Last() Value {
+	return list.Fetch(list.Length()-1)
+}
+
+
+func EmptyListValue() ListValue {
+	lv := NewListValue()
+	return *lv
+}
+
+func EmptyValueArray() []Value {
+	return make([]Value, 0)
+}
+
+func NewValueArray(elements ...Value) []Value {
+	return elements
+}

+ 60 - 0
map.go

@@ -0,0 +1,60 @@
+package muesli
+
+// MapValue is a Muesli value with a hash map.
+// Maps in Muesli are heterogenous, and can contain other Values of any type.
+// Furtehmore any Value can be used as the hash map key.
+type MapValue struct {
+	RedispatchCallable
+	Map map[Value]Value
+}
+
+const MapType    		= TypeValue("Map")
+
+func (v MapValue) Type() TypeValue    { return MapType }
+
+func (val MapValue) String() string {
+	res := "{"
+	sep := ""
+	for k, v := range val.Map {
+		res = res + sep + k.String() + "=>" + v.String()
+		sep = ", "
+	}
+	res += "}"
+	return res
+}
+
+
+func NewMapValue(elements map[Value]Value) * MapValue {
+	mv :=  &MapValue{Map:elements}
+	mv.RedispatchCallable = NewRedispatchCallable("List", mv)
+	return mv
+}
+
+func (m *MapValue) Fetch(key Value) Value {
+	var res Value
+	var ok bool
+	if res, ok = m.Map[key] ; !ok {
+		return NilValue
+	}
+	return res
+}
+
+func (m *MapValue) Place(key Value, value Value) Value {
+	m.Map[key] = value
+	return m.Map[key]
+}
+
+func (from * MapValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *map[Value]Value:
+			(*toPtr) = from.Map
+		case **MapValue:
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from			
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+

+ 36 - 33
parser.go

@@ -37,6 +37,27 @@ GETTER -> get ORIGIN .
 ORIGIN -> word | SETTER | GETTER .
 
 
+Or with methods variant
+
+PROGRAM -> STATEMENTS.
+CLOSED -> BLOCK | LIST | PARENTHESIS .
+STATEMENTS -> STATEMENT STATEMENTS | .
+STATEMENT -> CLOSED | EXPRESSION eos | eos .
+COMMAND -> word PARAMETERS.
+PARAMETERS -> PARAMETER PARAMETERS | .
+PARAMETER -> WORDVALUE | GETTER | SETTER | CLOSED .
+EXPRESSION -> COMMAND | GETTER | SETTER | METHODCALL .
+PARENTHESIS -> closeparen EXPRESSION openparen .
+BLOCK -> openblock STATEMENTS closeblock .
+LIST -> openlist PARAMETERS closelist .
+VALUE -> string | int | float | symbol | type .
+WORDVALUE -> word | VALUE.
+SETTER -> set TARGET . 
+TARGET -> word PARAMETER | GETTER PARAMETER .
+GETTER -> get ORIGIN .
+ORIGIN -> word | SETTER | GETTER .
+METHODCALL -> VALUE word PARAMETERS .
+
  *
  * program -> statements
  * statements -> statement+
@@ -194,11 +215,15 @@ func (parser *Parser) ParseArgument() *Ast {
 	}
 }
 
-func (parser *Parser) ParseArguments() *Ast {
+func (parser *Parser) ParseArguments(extra ... *Ast) *Ast {
     parser.LogDebug("ParseArguments: %s\n", parser.current.String())
     
     ast := NewAstWithToken(AstKindArguments,  parser.current)
     var children []*Ast
+    for _, arg := range extra {
+		children = append(children, arg)
+	}
+    
     for parser.NextIsArgument() {
 		child := parser.ParseArgument()
 		children = append(children, child)
@@ -378,6 +403,15 @@ func (parser *Parser) ParseClosed() *Ast {
 	}
 }
 
+func (parser *Parser) ParseMethodCall() *Ast {
+	value := parser.ParseValue()
+	word := parser.Require(TokenKindWord, TokenKindType)
+	command := NewAstWithToken(AstKindCommand, word)
+	arguments := parser.ParseArguments(value)	
+	command.AppendChild(arguments)
+	return command
+}
+
 func (parser *Parser) ParseExpression() *Ast {
     parser.LogDebug("ParseExpression: %s\n", parser.current.String())
     
@@ -385,7 +419,7 @@ func (parser *Parser) ParseExpression() *Ast {
 		case parser.NextIsWord(): return parser.ParseCommand()
 		case parser.NextIsSet(): return parser.ParseSet()
 		case parser.NextIsGet(): return parser.ParseGet()
-		case parser.NextIsValue(): return parser.ParseValue()
+		case parser.NextIsValue(): return parser.ParseMethodCall()
 		default: 
 			parser.Panicf("Syntax error in expression, expected word, $, =, value")
 			return nil
@@ -550,7 +584,6 @@ func (parser *Parser) Parse() (ast *Ast) {
 
 func NewParser(lexer *Lexer) *Parser {
 	parser := &Parser{Lexer: lexer, current: NoToken(), LoggerWrapper: LoggerWrapper{nil}}
-	parser.AddDefaultKeywords()
 	return parser
 }
 
@@ -581,36 +614,6 @@ func (parser * Parser) AddKeywords(keywords []*Keyword) {
 	}	
 }
 
-var DefaultKeywords []*Keyword = []*Keyword{
-	&Keyword { "true", TokenKindBoolean, TrueValue },
-	&Keyword { "false", TokenKindBoolean, FalseValue },
-	&Keyword { "nil", TokenKindNil, NilValue },
-	&Keyword { "do", TokenKindOpenBlock, StringValue("{") },
-	&Keyword { "end", TokenKindCloseBlock, StringValue("}") },
-	&Keyword { "as", TokenKindOpenParen, StringValue("(") },
-	&Keyword { "so", TokenKindCloseParen, StringValue(")") },
-	&Keyword { "list", TokenKindOpenList, StringValue("[") },
-	&Keyword { "done", TokenKindCloseList, StringValue("]") },
-    &Keyword { "the", TokenKindGet, StringValue("$") },
-	&Keyword { "a", TokenKindGet, StringValue("$") },
-	&Keyword { "an", TokenKindGet, StringValue("$") },
-}
-
-var DefaultKeywordsFR []*Keyword = []*Keyword{
-	&Keyword { "vrai", TokenKindBoolean, TrueValue },
-	&Keyword { "faux", TokenKindBoolean, FalseValue },
-	&Keyword { "nul", TokenKindNil, NilValue },
-	&Keyword { "fais", TokenKindOpenBlock, StringValue("{") },
-	&Keyword { "fin", TokenKindCloseBlock, StringValue("}") },
-	&Keyword { "comme", TokenKindOpenParen, StringValue("(") },
-	&Keyword { "ça", TokenKindCloseParen, StringValue(")") },
-	&Keyword { "liste", TokenKindOpenList, StringValue("[") },
-	&Keyword { "fini", TokenKindCloseList, StringValue("]") },
-    &Keyword { "le", TokenKindGet, StringValue("$") },
-    &Keyword { "la", TokenKindGet, StringValue("$") },
-}
-
-
 func (parser * Parser) AddDefaultKeywords() {
 	parser.AddKeywords(DefaultKeywords)
 }

+ 51 - 0
redispatch.go

@@ -0,0 +1,51 @@
+package muesli
+
+// CallableValue is is both a Value and a Callable.
+type CallableValue interface {
+	Callable
+	Value
+}
+
+// Redispath takes the first argument i args, and if that is a word,
+// calls the command named by that word, replacing the target CalableValue
+// as the first argument. This allows some OOP style trickery where
+// custom_value foo gets called as foo custom_value where custom_value is 
+// of CustomType. 
+// In this case foo should the be an overloaded command that takes CustomType.  
+func Redispatch(target CallableValue, vm *VM, args...Value) []Value {
+	if len(args) < 1 {
+		return EmptyValueArray()		
+	}
+	var word WordValue 
+	_, err := ParseOptArgs(args, 1, &word)
+	if err != nil {
+		return Fail(err)
+	}	
+	args[0] = target
+	vm.Trace("Redispatching with args %v\n", args)
+	return vm.CallNamed(string(word), args...)
+} 
+
+
+// RedispatchCallable can be embedded into a type to allow it to 
+// become redispatchable, that is, it can support OOP style
+// calling of pseudo methods by rearranging the command.  
+type RedispatchCallable struct {
+    target CallableValue
+    BasicCallable    
+}
+
+func (rc * RedispatchCallable) Call(vm *VM, args...Value) []Value {
+	if (rc.target == nil) {
+		return Fail(NewErrorValuef("Cannot redispatch call due to nil target."))
+	}
+	return Redispatch(rc.target, vm, args...)
+}
+
+var _ Callable = &RedispatchCallable{}
+
+func NewRedispatchCallable(name string, value CallableValue) RedispatchCallable {
+    return RedispatchCallable{target: value, BasicCallable: NewBasicCallable(name)}
+}
+
+var _ Callable = &ListValue{}

+ 38 - 1
signature.go

@@ -34,8 +34,16 @@ type Returned NamedWithType
 /* Signature describes the types of the arguments that a callable takes,
 as well as the returned values.*/
 type Signature struct {
+    // Parameters the callable takes.
 	Parameters [ParametersPerSignature]Parameter
+    // Returns results of the given types and names.
     Returns [ReturnsPerSignature]Returned
+    // RequiresAtLeast is the required amount of parameters. 
+    // The callable may accept more than this amount, but not less.
+    RequiresAtLeast int
+    // ReturnsAtLeast is the minimal amount of return values for the 
+    // callable. The callable may return more than this amount, but not less.
+    ReturnsAtLeast int
 }
 
 func (s Signature) String() string {
@@ -89,6 +97,7 @@ func (signature * Signature) SetReturns(types ... TypeValue) {
         signature.Returns[i].Type = types[i]
         signature.Returns[i].Name = WordValue(fmt.Sprintf("res%d", i))
     }
+    signature.ReturnsAtLeast = len(types)
 }
 
 func (signature * Signature) SetParameters(types ... TypeValue) {
@@ -96,6 +105,7 @@ func (signature * Signature) SetParameters(types ... TypeValue) {
         signature.Parameters[i].Type = types[i]
         signature.Parameters[i].Name = WordValue(fmt.Sprintf("arg%d", i))
     }
+    signature.RequiresAtLeast = len(types)
 }
 
 func NewSignature(types ... TypeValue) Signature {
@@ -122,6 +132,7 @@ func NewSignatureWithNames(param ...Value) (Signature, error) {
 		sign.Parameters[j].Type = tv
 		sign.Parameters[j].Name = nv
         j++
+        sign.RequiresAtLeast++
 	}
 	return sign, nil
 }
@@ -141,6 +152,7 @@ func CalculateSignature(arguments ...Value) Signature {
 			signature.Parameters[i].Type = AnyType
 		}
 	}
+    signature.RequiresAtLeast = len(arguments)
 	return signature
 }
 
@@ -155,7 +167,7 @@ func (tv TypeValue) IsMatch(other TypeValue) bool {
 }
 
 func (signature Signature) IsMatch(other Signature) bool {
-	for i, param := range signature.Parameters {
+    for i, param := range signature.Parameters {
 		t1 := param.Type
 		t2 := other.Parameters[i].Type
 		if !t1.IsMatch(t2) {
@@ -165,3 +177,28 @@ func (signature Signature) IsMatch(other Signature) bool {
 	return true
 }
 
+// TypeCheck checks if the arguments match the signature.
+// Returns nil if so, or an error if not.
+func (signature Signature) TypeCheck(arguments ...Value) error {
+    if len(arguments) < signature.RequiresAtLeast {
+        return fmt.Errorf("Too few arguments, expected %d: for %d", signature.RequiresAtLeast, len(arguments))
+    }
+    
+	for i , arg := range arguments {
+		if i >= len(signature.Parameters) {
+			break
+		}
+		param := signature.Parameters[i]
+		expectedType := param.Type
+		
+		if arg == nil {
+			return fmt.Errorf("Nil argument %d, expected %s: %v for %v", i, expectedType, arguments, signature)
+		}
+
+        if !expectedType.IsMatch(arg.Type()) {
+			return fmt.Errorf("Argument %d type mismatch: %s<->%s", i, expectedType, arg.Type())
+		}
+	}
+    return nil
+}
+

+ 28 - 0
string.go

@@ -0,0 +1,28 @@
+package muesli
+
+// StringValue are Muesli strings
+type StringValue string
+
+const StringType 		= TypeValue("String")
+
+func (val StringValue) String() string {
+	return string(val)
+}
+
+func (from StringValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		case *StringValue:
+			(*toPtr) = from	
+		case *Value:
+			(*toPtr) = from	
+		default:
+			return NewErrorValuef("Cannot convert StringValue %v to %v", from, to)
+	}
+	return nil
+}
+
+func (v StringValue) Type() TypeValue { return StringType }
+
+

+ 9 - 0
token.go

@@ -65,6 +65,15 @@ var TokenKindNames map[TokenKind]string = map[TokenKind]string{
 	TokenKindEOF:        "EOF",
 }
 
+/* Reverse map of the names of the different token types. */
+var NamesTokenKind map[string] TokenKind = map[string]TokenKind{}
+
+func init () {
+	for k, v := range TokenKindNames {
+		NamesTokenKind[v] = k
+	}
+}
+
 /* Transforms a token kind to a String */
 func (kind TokenKind) String() string {
 	name, ok := TokenKindNames[kind]

+ 43 - 0
type.go

@@ -0,0 +1,43 @@
+package muesli
+
+// TypeValue is used to model the type of a value in the Muesli type system.
+// This is simply a string so this can be used as a hash key, however, 
+// the name of a type must always begin with an upper case letter.
+type TypeValue string
+const (
+    // TypeType is the type of TypeValue itself.
+    TypeType   		= TypeValue("Type")
+	// AnyType is not really a type, but a wildcard that matches any type
+	AnyType    		= TypeValue("Any")
+	// ZeroType in not really a type, but means that the type is missing, 
+	// and is conventiently the zero value for TypeValue
+	ZeroType   		= TypeValue("")
+)
+
+
+
+func (val TypeValue) String() string {
+	return string(val)
+}
+
+func (v TypeValue) Type() TypeValue   { return TypeType }
+
+var _ Value = TypeValue("")
+
+
+func (from TypeValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		case *TypeValue:
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from
+		default:
+			return NewErrorValuef("Cannot convert value %v to %v", from, to)
+	}
+	return nil
+}
+
+
+

+ 4 - 426
value.go

@@ -1,10 +1,11 @@
 package muesli
 
-import "fmt"
-
-/* Run time values */
+// Value interface type for Muesli run time values that the language works with.
 type Value interface {
+	// String because a value must be convertible to string.
+	// This string is then used as the hash key in MapValue and for debugging.
 	String() string
+	// Type returns the type of the value. Muesli has typed values.
 	Type() TypeValue
 	// Convert the value to a different go value which must be passed 
 	// in as a pointer to which the value must be set, 
@@ -12,368 +13,6 @@ type Value interface {
 	Convert(to interface{}) error
 }
 
-type IntValue int64
-type FloatValue float64
-type StringValue string
-type BoolValue bool
-type WordValue string
-type TypeValue string
-
-type ErrorValue struct {
-	error
-}
-
-type EmptyValue struct {
-}
-
-type ListValue struct {
-    RedispatchCallable
-	List []Value
-}
-
-type MapValue struct { 
-	Map map[Value]Value
-}
-
-// Values is simply a shorthand alias for []Value
-type Values = []Value
-
-const (
-	TrueValue       = BoolValue(true)
-	FalseValue      = BoolValue(false)
-	IntType    = TypeValue("Int")
-	FloatType  = TypeValue("Float")
-	StringType = TypeValue("String")
-	BoolType   = TypeValue("Bool")
-	WordType   = TypeValue("Word")
-	ErrorType  = TypeValue("Error")
-	TypeType   = TypeValue("Type")
-	EmptyType  = TypeValue("Empty")
-	ListType   = TypeValue("List")
-	MapType    = TypeValue("Map")
-	AnyType    = TypeValue("Any")
-	ZeroType   = TypeValue("")
-)
-
-var NilValue = Value(nil)
-
-func (val IntValue) String() string {
-	return fmt.Sprintf("%d", int64(val))
-}
-
-func (val FloatValue) String() string {
-	return fmt.Sprintf("%f", float64(val))
-}
-
-func (val BoolValue) String() string {
-	if bool(val) {
-		return "true"
-	} else {
-		return "false"
-	}
-}
-
-func (val StringValue) String() string {
-	return string(val)
-}
-
-func (val WordValue) String() string {
-	return string(val)
-}
-
-func (val TypeValue) String() string {
-	return string(val)
-}
-
-func (val ErrorValue) String() string {
-	return fmt.Sprintf("%s", val.Error())
-}
-
-func (val EmptyValue) String() string {
-	return "<empty>"
-}
-
-func (val ListValue) String() string {
-	res := "["
-	sep := ""
-	for _, elt := range val.List {
-        if elt == nil {
-            res = res + sep + "nil"
-        } else   { 
-            res = res + sep + elt.String()
-        }
-        sep = ", "
-	}
-	res += "]"
-	return res
-}
-
-func (val MapValue) String() string {
-	res := "{"
-	sep := ""
-	for k, v := range val.Map {
-		res = res + sep + k.String() + "=>" + v.String()
-		sep = ", "
-	}
-	res += "}"
-	return res
-}
-
-
-func (v IntValue) Type() TypeValue    { return IntType }
-func (v FloatValue) Type() TypeValue  { return FloatType }
-func (v StringValue) Type() TypeValue { return StringType }
-func (v BoolValue) Type() TypeValue   { return BoolType }
-func (v WordValue) Type() TypeValue   { return WordType }
-func (v TypeValue) Type() TypeValue   { return TypeType }
-func (v ErrorValue) Type() TypeValue  { return ErrorType }
-func (v EmptyValue) Type() TypeValue  { return EmptyType }
-func (v ListValue) Type() TypeValue   { return ListType }
-func (v MapValue) Type() TypeValue    { return MapType }
-
-func NewErrorValuef(format string, args ...interface{}) ErrorValue {
-	err := fmt.Errorf(format, args...)
-	return ErrorValue{err}
-}
-
-func NewListValue(elements ...Value) * ListValue {
-	return &ListValue{ NewRedispatchCallable(), elements}
-}
-
-func (list *ListValue) Append(elements ...Value) {
-	list.List = append(list.List, elements...)
-}
-
-func (list *ListValue) AppendList(toAppend ListValue) {
-	list.List = append(list.List, toAppend.List...)
-}
-
-func (list ListValue) Length() int {
-	return len(list.List)
-}
-
-func (list *ListValue) Fetch(i int) Value {
-	if i >= len(list.List) {
-		return NilValue
-	}
-	return list.List[i]
-}
-
-func (list *ListValue) Place(i int, v Value) Value {
-	if i >= len(list.List) {
-		return NilValue
-	}
-	list.List[i] = v
-	return list.List[i]
-}
-
-func (list *ListValue) First() Value {
-	return list.Fetch(0)
-}
-
-func (list *ListValue) Last() Value {
-	return list.Fetch(list.Length()-1)
-}
-
-
-func EmptyListValue() ListValue {
-	return ListValue{NewRedispatchCallable(), make([]Value, 0)}
-}
-
-func EmptyValueArray() []Value {
-	return make([]Value, 0)
-}
-
-func NewValueArray(elements ...Value) []Value {
-	return elements
-}
-
-func NewMapValue(elements map[Value]Value) * MapValue {
-	return &MapValue{elements}
-}
-
-func (m *MapValue) Fetch(key Value) Value {
-	var res Value
-	var ok bool
-	if res, ok = m.Map[key] ; !ok {
-		return NilValue
-	}
-	return res
-}
-
-func (m *MapValue) Place(key Value, value Value) Value {
-	m.Map[key] = value
-	return m.Map[key]
-}
-
-
-func (from IntValue) Convert(to interface{}) error {
-	switch toPtr := to.(type) {
-		case *string:
-			(*toPtr) = from.String()
-		case *int8:
-			(*toPtr) = int8(from)
-		case *int16:
-			(*toPtr) = int16(from)
-		case *int32:
-			(*toPtr) = int32(from)
-		case *int64:
-			(*toPtr) = int64(from)
-		case *int:
-			(*toPtr) = int(from)
-		case *bool:			 
-			(*toPtr) = (from != 0)
-		case *float32:
-			(*toPtr) = float32(from)
-		case *float64:
-			(*toPtr) = float64(from)
-		case *IntValue:
-			(*toPtr) = from
-		case *Value:
-			(*toPtr) = from			
-		default:
-			return NewErrorValuef("Cannot convert IntValue value %v to %v", from, to)
-	}
-	return nil
-}
-
-func (from FloatValue) Convert(to interface{}) error {
-	switch toPtr := to.(type) {
-		case *string:
-			(*toPtr) = from.String()
-		case *int8:
-			(*toPtr) = int8(from)
-		case *int16:
-			(*toPtr) = int16(from)
-		case *int32:
-			(*toPtr) = int32(from)
-		case *int64:
-			(*toPtr) = int64(from)
-		case *int:
-			(*toPtr) = int(from)
-		case *bool:			 
-			(*toPtr) = (from != 0) 		
-		case *float32:
-			(*toPtr) = float32(from)
-		case *float64:
-			(*toPtr) = float64(from)
-		case *FloatValue:
-			(*toPtr) = from
-		case *Value:
-			(*toPtr) = from
-		default:
-			return NewErrorValuef("Cannot convert FloatValue value %v to %v", from, to)
-	}
-	return nil
-}
-	
-func (from StringValue) Convert(to interface{}) error {
-	switch toPtr := to.(type) {
-		case *string:
-			(*toPtr) = from.String()
-		case *StringValue:
-			(*toPtr) = from	
-		case *Value:
-			(*toPtr) = from	
-		default:
-			return NewErrorValuef("Cannot convert StringValue %v to %v", from, to)
-	}
-	return nil
-}
-
-func (from WordValue) Convert(to interface{}) error {
-	switch toPtr := to.(type) {
-		case *string:
-			(*toPtr) = from.String()
-		case *WordValue:
-			(*toPtr) = from
-		case *Value:
-			(*toPtr) = from			
-		default:
-			return NewErrorValuef("Cannot convert WordValue %v to %v", from, to)
-	}
-	return nil
-}
-
-
-func (from TypeValue) Convert(to interface{}) error {
-	switch toPtr := to.(type) {
-		case *string:
-			(*toPtr) = from.String()
-		case *TypeValue:
-			(*toPtr) = from
-		case *Value:
-			(*toPtr) = from
-		default:
-			return NewErrorValuef("Cannot convert value %v to %v", from, to)
-	}
-	return nil
-}
-
-
-func (from BoolValue) Convert(to interface{}) error {
-	switch toPtr := to.(type) {
-		case *bool:			 
-			(*toPtr) = bool(from) 		
-		case *BoolValue:
-			(*toPtr) = from
-		case *Value:
-			(*toPtr) = from												
-		default:
-			return NewErrorValuef("Cannot convert value %v to %v", from, to)
-	}
-	return nil
-}
-
-func (from ErrorValue) Convert(to interface{}) error {
-	switch toPtr := to.(type) {
-		case *string:
-			(*toPtr) = from.String()
-		case *error:
-			(*toPtr) = from.error
-		case *ErrorValue:
-			(*toPtr) = from
-		case *Value:
-			(*toPtr) = from			
-		default:
-			return NewErrorValuef("Cannot convert value %v to %v", from, to)
-	}
-	return nil
-}
-
-func (from EmptyValue) Convert(to interface{}) error {
-	return NewErrorValuef("Cannot convert the empty value %v to %v", from, to)
-}
-
-func (from * ListValue) Convert(to interface{}) error {
-	switch toPtr := to.(type) {
-		case *[]Value:
-			(*toPtr) = from.List
-		case **ListValue:
-			(*toPtr) = from
-		case *Value:
-			(*toPtr) = from
-		default:
-			return NewErrorValuef("Cannot convert value %v to %v", from, to)
-	}
-	return nil
-}
-
-func (from * MapValue) Convert(to interface{}) error {
-	switch toPtr := to.(type) {
-		case *map[Value]Value:
-			(*toPtr) = from.Map
-		case **MapValue:
-			(*toPtr) = from
-		case *Value:
-			(*toPtr) = from			
-		default:
-			return NewErrorValuef("Cannot convert value %v to %v", from, to)
-	}
-	return nil
-}
-
-
 /* Helpers to easily convert Muesli values to "normal" Go values. */
 func From(from Value, to interface{}) error {
 	return from.Convert(to)
@@ -541,66 +180,5 @@ func FloatOk(f float64) []Value{
 }
 
 
-// CallableValue is is both a Value and a Callable.
-type CallableValue interface {
-	Callable
-	Value
-}
-
-// Redispath takes the first argument i args, and if that is a word,
-// calls the command named by that word, replacing the from CalableValue
-// as the first argument. This allows some OOP style trickery where
-// custom_value foo gets called as foo custom_value where custom_value is 
-// of CustomType. 
-// In this case foo should the be an overloaded command that takes CustomType.  
-func Redispatch(from CallableValue, vm *VM, args...Value) []Value {
-	if len(args) < 1 {
-		return EmptyValueArray()		
-	}
-	var word WordValue 
-	_, err := ParseOptArgs(args, 1, &word)
-	if err != nil {
-		return Fail(err)
-	}
-	args[0] = from
-	return vm.CallNamed(string(word), args...)
-} 
-
-
-// RedispatchCallable can be embedded into a type to allow it to 
-// become redispatchable, that is, it can support OOP style
-// calling of pseudo methods by rearranging the command.  
-type RedispatchCallable struct {
-    BasicCallable
-}
-
-func (rc * RedispatchCallable) Call(vm *VM, args...Value) []Value {
-	return Redispatch(rc, vm, args...)
-}
-
-var _ Callable = &RedispatchCallable{}
-
-func NewRedispatchCallable() RedispatchCallable {
-    return RedispatchCallable{}
-}
-
-// Implement callable ... 
-/*
-func (list * ListValue) Position() *Position {
-	return &Position{"value.go", 572, 8}
-}
-
-
-func (list * ListValue) Call(vm *VM, args...Value) []Value {
-	return Redispatch(list, vm, args...)
-}
-
-var listSignature = NewSignature(WordType, IntType) 
-
-func (list * ListValue) Signature() Signature {
-    return listSignature
-}
-*/
 
-var _ Callable = &ListValue{}
 

+ 72 - 265
vm.go

@@ -33,7 +33,8 @@ type Helper interface {
 }
 
 
-// Callable value types
+// BasicCallable is an embeddable struct that makes it easier to 
+// implement the Caller and Helper interface.
 type BasicCallable struct {
 	// Name of the callable
 	Name string
@@ -80,8 +81,9 @@ func (bc * BasicCallable) Takes(arguments ...TypeValue) *BasicCallable {
 	return bc
 }
 
-func (bc * BasicCallable) Returns(arguments ...TypeValue) {
+func (bc * BasicCallable) Returns(arguments ...TypeValue) *BasicCallable {
 	bc.signature.SetReturns(arguments...)
+	return bc
 }
 
 
@@ -94,7 +96,7 @@ func (val BasicCallable) Type() TypeValue {
 }
 
 func (from BasicCallable) Convert(to interface{}) error {
-	return NewErrorValuef("Cannot convert the callable value %v to %v", from, to)
+	return NewErrorValuef("Cannot convert the callable value %v to %v: Not implemented.", from, to)
 }
 
 func (val *BasicCallable) Call(vm *VM, arguments ...Value) []Value {
@@ -207,64 +209,6 @@ func (defined *DefinedValue) Help() string {
 // Assert that DefinedValue is callable.
 var _ Callable = &DefinedValue{}
 
-/* 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 {
-	BasicCallable
-	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.BasicCallable.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")
@@ -298,10 +242,18 @@ func (from BlockValue) Convert(to interface{}) error {
 	return NewErrorValuef("Cannot convert the block value %v to %v", from, to)
 }
 
+func (cv * CoverValue) AddOverloadWithSignature(name string, callable Callable, signature Signature) Overload {
+	ov := Overload { Name: name, Callable: callable }
+	cv.Overloads[signature] = ov
+	return ov
+}
+
+
+func (cv * CoverValue) AddOverloadCallable(name string, callable Callable) Overload {	
+	return cv.AddOverloadWithSignature(name, callable, callable.Signature())
+}
 
 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.Parameters) {
@@ -311,17 +263,13 @@ func (cv * CoverValue) AddOverload(name string, callable Callable, tv ... TypeVa
 	for i := 0; i < length; i++ {
 		signature.Parameters[i].Type = tv[i]
 	}
-		
-	cv.Overloads[signature] = Overload { Name: name, Callable: callable } 
-	
-	// fmt.Printf("Overloads: %v\n", cv.Overloads)
 	
+	cv.AddOverloadWithSignature(name, callable, signature)
 	return nil
 }
 
-func (vm * VM) AddOverload(from, target string, level int, tv... TypeValue) error {
+func (vm * VM) AddOverloadCallable(from, target string, level int, callable Callable) error {
 	var cover *CoverValue
-	var callable Callable
 	var ok bool	
 	lookup := vm.Lookup(from)
 	if lookup == nil { 
@@ -329,23 +277,57 @@ func (vm * VM) AddOverload(from, target string, level int, tv... TypeValue) erro
 	} 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)
+
+	cover.AddOverloadCallable(target, callable)
+	return nil
+}
+
+
+func (vm *VM) LookupCallable(target string) (Callable, error) {
+	var callable Callable
+	var ok bool
+	lookup := vm.Lookup(target)
 	if lookup == nil { 
-		return fmt.Errorf("target %s is not defined", target)
+		return nil, fmt.Errorf("%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)
+		return nil, fmt.Errorf("%s is not a callable value", target)
+	}
+	return callable, nil
+}
+
+// AddOverloadByName overloads the from command to call the target command 
+// if the argument list matches the signature based on the given type values
+func (vm * VM) AddOverload(from, target string, level int, tv... TypeValue) error {
+	var cover *CoverValue
+	var callable Callable
+	var ok bool	
+	var err error
+
+	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)
 	}
-	res := cover.AddOverload(target, callable, tv...)
 	
-	// fmt.Printf("AddOverload: %v %v\n", lookup, cover)
+	callable, err = vm.LookupCallable(target)
+	if err != nil {
+		return err
+	}
 	
-	return res
+	return cover.AddOverload(target, callable, tv...)	
+}
+
+// AddOverloadByName overloads the from command to call the target command 
+// if the argment lists matches the signature of the target command.
+func (vm * VM) AddOverloadByName(from, target string, level int) error {
+	callable, err := vm.LookupCallable(target)
+	if err != nil {
+		return err
+	}
+	return vm.AddOverloadCallable(from, target, level, callable)
 }
 
 type OverloadDescription struct {
@@ -560,17 +542,9 @@ func (block * BlockValue) Call(vm *VM, arguments ...Value) []Value {
 }
 
 func (builtin * BuiltinValue) Call(vm *VM, arguments ...Value) []Value {
-	for i , arg := range arguments {
-		if i >= len(builtin.signature.Parameters) {
-			break
-		}
-		param := builtin.signature.Parameters[i]
-		expectedType := param.Type
-		vm.Trace("Signature check: %d %v", i, param)
-
-        if !expectedType.IsMatch(arg.Type()) {
-			return Fail(NewErrorValuef("Argument %d type mismatch: %s<->%s", i, expectedType, arg.Type()))
-		}
+	err := builtin.signature.TypeCheck(arguments...)
+	if err != nil { 
+		return Fail(ErrorValue{err})
 	}
     handler := builtin.Handler
 	return handler.Call(vm, arguments...)
@@ -632,6 +606,12 @@ func (vm * VM) ScopeUp(level int) *Scope {
 	return scope
 }
 
+// RegisterTop registers a value at top level scope.
+func (vm *VM) RegisterTop(name string, value Value) Value {
+	scope := vm.TopScope
+	return scope.Register(name, value)
+}
+
 // RegisterUp registers in level 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 {
@@ -672,100 +652,6 @@ 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
@@ -790,7 +676,8 @@ func (vm *VM) RunAst(ast Ast, args ...Value) []Value {
             vm.Trace("RunAst: %d %v %v %v\n", i, child, sub, vm.Frame)
             /*
             if frame.failed && frame.parent != nil {
-                // failures are like panics and propagate up the call tree
+                // XXX failures are like panics and propagate up the call tree
+                * // Or should they? 
                 frame.parent.failed = true
                 frame.parent.results = frame.results 
             }
@@ -849,83 +736,3 @@ func (vm * VM) BackTrace() string {
 	return strings.Join(vm.BackTraceStrings(), "\n")
 }
 
-
-/*
-
-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)}}
-	}
-}
-*/

+ 25 - 0
word.go

@@ -0,0 +1,25 @@
+package muesli
+
+const WordType   		= TypeValue("Word")
+// WordValue are Muesli command words
+type WordValue string
+
+func (val WordValue) String() string {
+	return string(val)
+}
+
+func (v WordValue) Type() TypeValue   { return WordType }
+
+func (from WordValue) Convert(to interface{}) error {
+	switch toPtr := to.(type) {
+		case *string:
+			(*toPtr) = from.String()
+		case *WordValue:
+			(*toPtr) = from
+		case *Value:
+			(*toPtr) = from			
+		default:
+			return NewErrorValuef("Cannot convert WordValue %v to %v", from, to)
+	}
+	return nil
+}