Browse Source

[PATCH 2/2] Work on signatures for all callables.

Beoran 4 years ago
parent
commit
b211839902
4 changed files with 114 additions and 99 deletions
  1. 4 4
      builtin.go
  2. 80 0
      signature.go
  3. 3 3
      value.go
  4. 27 92
      vm.go

+ 4 - 4
builtin.go

@@ -427,12 +427,12 @@ func (door * Door) Position() *Position {
 	return &Position{"builtin.go", 427, 8}
 }
 
-type ValueCallable interface {
+type CallableValue interface {
 	Callable
 	Value
 }
 
-func Redispatch(from ValueCallable, vm *VM, args...Value) []Value {
+func Redispatch(from CallableValue, vm *VM, args...Value) []Value {
 	if len(args) < 1 {
 		return EmptyValueArray()		
 	}
@@ -451,8 +451,8 @@ func (door * Door) Call(vm *VM, args...Value) []Value {
 
 var doorSignature = NewSignature(WordTypeValue) 
 
-func (door * Door) Signature() *Signature {
-    return &doorSignature
+func (door * Door) Signature() Signature {
+    return doorSignature
 }
 
 var _ Callable = &Door{}

+ 80 - 0
signature.go

@@ -0,0 +1,80 @@
+package muesli
+
+/*
+	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
+
+/* Parameter describes the name and type of a parameter of a command. */
+type Parameter struct {
+	Name WordValue
+	Type TypeValue
+}
+
+// Signature describes the types of the arguments that a callable takes. */
+type Signature struct {
+	Types [TypesInSignature]TypeValue
+    Names [TypesInSignature]WordValue
+}
+
+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 NewSignature(types ... TypeValue) Signature {
+    signature := Signature{}
+    for i := 0 ; i < len(types) && i < len(signature.Types) ; i ++ {
+        signature.Types[i] = types[i]
+    }
+    return signature
+}
+
+// NoSignature is the default signature which means the VM will not do 
+// any argument type checking when the callable is called.
+func NoSignature() Signature { 
+	return Signature{}
+}
+
+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
+}
+

+ 3 - 3
value.go

@@ -6,9 +6,9 @@ import "fmt"
 type Value interface {
 	String() string
 	Type() TypeValue
-	// Convert the value to a normal go value which must be passed 
-	// in as a pointer to which the value mmust be set, 
-	// or return an error if the concversion is not possible.
+	// Convert the value to a different go value which must be passed 
+	// in as a pointer to which the value must be set, 
+	// or return an error if the conversion is not possible.
 	Convert(to interface{}) error
 }
 

+ 27 - 92
vm.go

@@ -18,10 +18,10 @@ func (handler *Handler) Call(vm *VM, arguments ...Value) []Value {
 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 is the source code position where it was defined. Needed for tracebacks.
 	Position() *Position
-    // Callable has a signature.. but not yet!
-    // Signature() *Signature
+    // Signature are the types of the parameters of this function.
+    Signature() Signature
 }
 
 // A helper Value has a help text available.
@@ -34,26 +34,32 @@ type Helper interface {
 
 
 // Callable value types
-type CallableValue struct {
+type BasicCallable struct {
 	// Name of the callable
 	Name string
 	// Help string for the callable.
 	HelpText string
+	// Signature of the callable
+	signature Signature 
+}
+
+func (val BasicCallable) Signature() Signature {
+	return val.signature
 }
 
 // Implement Helper interface
-func (val CallableValue) Help() string {
+func (val BasicCallable) Help() string {
 	return val.HelpText
 }
 
 // Implement Helper interface
-func (val * CallableValue) SetHelp(help string) string {
+func (val * BasicCallable) SetHelp(help string) string {
 	val.HelpText = help
 	return val.HelpText
 }
 
 // Implement Helper interface
-func (val CallableValue) HelperName() string {
+func (val BasicCallable) HelperName() string {
 	return val.Name
 }
 
@@ -68,32 +74,33 @@ func ClearHelp(helper Helper, extra string) string {
 }
 
 
-func (val CallableValue) String() string {
+func (val BasicCallable) String() string {
 	return val.Name
 }
 
-func (val CallableValue) Type() TypeValue {
+func (val BasicCallable) Type() TypeValue {
 	return TypeValue("Callable")
 }
 
-func (from CallableValue) Convert(to interface{}) error {
+func (from BasicCallable) 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 {
+func (val *BasicCallable) Call(vm *VM, arguments ...Value) []Value {
 	panic("Not implemented")
 }
 
 // A struct to store a built in function
 type BuiltinValue struct {
-	CallableValue
+	BasicCallable
 	Handler
 }
 
-func NewCallableValue(name string) CallableValue {
-	return CallableValue{name, ""}
+func NewBasicCallable(name string) BasicCallable {
+	return BasicCallable{name, "", NoSignature()}
 }
 
+
 func NewBuiltinValue(name string, handler Handler) *BuiltinValue {
 	result := &BuiltinValue{}
 	result.Name = name
@@ -103,7 +110,7 @@ func NewBuiltinValue(name string, handler Handler) *BuiltinValue {
 
 // A block in a script.
 type BlockValue struct {
-	CallableValue
+	BasicCallable
 	Ast *Ast
 }
 
@@ -137,22 +144,14 @@ func (defined * DefinedValue) Position() *Position {
 	return defined.Body.Position()
 }
 
-func (cv CallableValue) Position() *Position {
+func (cv BasicCallable) 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
+	BasicCallable
 	Body *BlockValue
 	Parameters []*Parameter
 }
@@ -186,7 +185,7 @@ func (defined *DefinedValue) Call(vm *VM, arguments ...Value) []Value {
 }
 
 func (defined *DefinedValue) Help() string {
-	help := defined.CallableValue.Help()
+	help := defined.BasicCallable.Help()
 	extra := "["
 	for _, parameter := range defined.Parameters {
 		extra = fmt.Sprintf("%s %s %s", extra, parameter.Name, parameter.Type)
@@ -196,70 +195,6 @@ func (defined *DefinedValue) Help() string {
 }
 
 
-/*
-	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
-
-/* Signature describes the types that a callable takes. */
-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 NewSignature(types ... TypeValue) Signature {
-    signature := Signature{}
-    for i := 0 ; i < len(types) && i < len(signature.Types) ; i ++ {
-        signature.Types[i] = types[i]
-    }
-    return signature
-}
-
-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 {
@@ -272,7 +207,7 @@ the types of the arguments, in particular the first one. The individual
 callable functions are the overloads
 */
 type CoverValue struct {
-	CallableValue
+	BasicCallable
 	Overloads map[Signature]Overload
 }
 
@@ -294,7 +229,7 @@ func NewCoverValue(name string) *CoverValue {
 
 
 func (cover *CoverValue) Help() string {
-	help := cover.CallableValue.Help()
+	help := cover.BasicCallable.Help()
 	extra := "\n"
 	for signature, overload := range cover.Overloads {
 		// fmt.Printf("overload: %v", signature)