Browse Source

[PATCH 3/4] Signatures for all callables. Makes type checking possible and help better structured.

Beoran 4 years ago
parent
commit
c7e120218f
3 changed files with 36 additions and 32 deletions
  1. 9 6
      builtin.go
  2. 15 14
      signature.go
  3. 12 12
      vm.go

+ 9 - 6
builtin.go

@@ -222,23 +222,26 @@ func to(vm *VM, args ...Value) []Value {
 		return Fail(NewErrorValuef("Not a block: %v", last))
 	}
 	param := rest[0:len(rest)-1]
-	defpars := []*Parameter{}
+	sign := &Signature{}
 	for i := 1 ; i < len(param) ; i += 2 {
-		par := &Parameter{}
 		name := param[i-1]
 		typ  := param[i]
 		var ok bool
-		if par.Name, ok = name.(WordValue); !ok {
+		var nv WordValue
+		var tv TypeValue
+		
+		if nv, ok = name.(WordValue); !ok {
 			return Fail(NewErrorValuef("Not a word value: %v", name))
 		}
-		if par.Type, ok = typ.(TypeValue); !ok {
+		if tv, ok = typ.(TypeValue); !ok {
 			return Fail(NewErrorValuef("Not a type value: %v", typ))
 		}
-		defpars = append(defpars, par) 
+		sign.Parameters[i].Type = tv
+		sign.Parameters[i].Name = nv
 	}
 	
 	// To must register one level up.
-	return Ok(vm.RegisterDefined(name, defpars, block, 1))
+	return Ok(vm.RegisterDefined(name, sign, block, 1))
 }
 
 func cover(vm *VM, args ...Value) []Value {

+ 15 - 14
signature.go

@@ -1,10 +1,11 @@
 package muesli
 
 /*
-	Amount of types that will be considered inside a signature.
-	Limited mosty to allow hashability, that is, Signature is a map key.
+ParametersPerSignature is the amount of parameters that will be
+checked when type checking a signature.	Limited mosty to allow hashability, 
+that is, Signature is a map key.
 */
-const TypesInSignature = 32
+const ParametersPerSignature = 32
 
 /* Parameter describes the name and type of a parameter of a command. */
 type Parameter struct {
@@ -14,14 +15,14 @@ type Parameter struct {
 
 // Signature describes the types of the arguments that a callable takes. */
 type Signature struct {
-	Types [TypesInSignature]TypeValue
-    Names [TypesInSignature]WordValue
+	Parameters [ParametersPerSignature]Parameter
 }
 
 func (s Signature) String() string {
 	res := "["
 	sep := ""
-	for _, typ := range s.Types {
+	for _, param := range s.Parameters {
+        typ := param.Type
 		if typ != ZeroTypeValue { 
 			res = res + sep + typ.String()
 			sep = " "
@@ -33,8 +34,8 @@ func (s Signature) String() string {
 
 func NewSignature(types ... TypeValue) Signature {
     signature := Signature{}
-    for i := 0 ; i < len(types) && i < len(signature.Types) ; i ++ {
-        signature.Types[i] = types[i]
+    for i := 0 ; i < len(types) && i < len(signature.Parameters) ; i ++ {
+        signature.Parameters[i].Type = types[i]
     }
     return signature
 }
@@ -47,11 +48,11 @@ func NoSignature() Signature {
 
 func CalculateSignature(arguments ...Value) Signature {
 	signature := Signature{}
-	for i := 0; i < len(signature.Types); i++ {
+	for i := 0; i < len(signature.Parameters); i++ {
 		if i < len(arguments) {
-			signature.Types[i] = arguments[i].Type()
+			signature.Parameters[i].Type = arguments[i].Type()
 		} else {			
-			signature.Types[i] = AnyTypeValue
+			signature.Parameters[i].Type = AnyTypeValue
 		}
 	}
 	return signature
@@ -68,9 +69,9 @@ func (tv TypeValue) IsMatch(other TypeValue) bool {
 }
 
 func (signature Signature) IsMatch(other Signature) bool {
-	for i, kind := range signature.Types {
-		t1 := kind
-		t2 := other.Types[i]
+	for i, param := range signature.Parameters {
+		t1 := param.Type
+		t2 := other.Parameters[i].Type
 		if !t1.IsMatch(t2) {
 			return false
 		}

+ 12 - 12
vm.go

@@ -153,24 +153,24 @@ func (cv BasicCallable) Position() *Position {
 type DefinedValue struct {	
 	BasicCallable
 	Body *BlockValue
-	Parameters []*Parameter
+	Signature *Signature
 }
 
-func NewDefinedValue(name string, params []*Parameter, body *BlockValue) *DefinedValue {
+func NewDefinedValue(name string, signature *Signature, body *BlockValue) *DefinedValue {
 	result := &DefinedValue{}
 	result.Name = name
 	result.Body = body
-	result.Parameters = params
+	result.Signature = signature
 	return result
 }
 
 func (defined *DefinedValue) Call(vm *VM, arguments ...Value) []Value {
-	vm.Trace("Call defined value: %v %v %v", defined, defined.Parameters, arguments)
+	vm.Trace("Call defined value: %v %v %v", defined, defined.Signature, arguments)
     for i , arg := range arguments {
-		if i >= len(defined.Parameters) {
+		if i >= len(defined.Signature.Parameters) {
 			break
 		}
-		param := defined.Parameters[i]
+		param := defined.Signature.Parameters[i]
 		expectedType := param.Type
 		if !expectedType.IsMatch(arg.Type()) {
 			return Fail(NewErrorValuef("Argument %d type mismatch: %s<->%s", i, expectedType, arg.Type()))
@@ -187,7 +187,7 @@ func (defined *DefinedValue) Call(vm *VM, arguments ...Value) []Value {
 func (defined *DefinedValue) Help() string {
 	help := defined.BasicCallable.Help()
 	extra := "["
-	for _, parameter := range defined.Parameters {
+	for _, parameter := range defined.Signature.Parameters {
 		extra = fmt.Sprintf("%s %s %s", extra, parameter.Name, parameter.Type)
 	}
 	extra = extra + "]:"
@@ -293,12 +293,12 @@ func (cv * CoverValue) AddOverload(name string, callable Callable, tv ... TypeVa
 	
 	signature := Signature{}
 	length := len(tv)
-	if length > len(signature.Types) {
-		length = len(signature.Types)
+	if length > len(signature.Parameters) {
+		length = len(signature.Parameters)
 	}
 	
 	for i := 0; i < length; i++ {
-		signature.Types[i] = tv[i]
+		signature.Parameters[i].Type = tv[i]
 	}
 		
 	cv.Overloads[signature] = Overload { Name: name, Callable: callable } 
@@ -651,8 +651,8 @@ func (vm *VM) RegisterBuiltin(name string, handler Handler) Value {
 	return vm.Register(name, value)
 }
 
-func (vm *VM) RegisterDefined(name string, params []*Parameter, block *BlockValue, level int) Value {
-	value := NewDefinedValue(name, params, block)
+func (vm *VM) RegisterDefined(name string, signature *Signature, block *BlockValue, level int) Value {
+	value := NewDefinedValue(name, signature, block)
 	return vm.RegisterUp(name, value, level)
 }