summary refs log tree commit diff stats
path: root/compiler/sigmatch.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/sigmatch.nim')
-rwxr-xr-xcompiler/sigmatch.nim61
1 files changed, 36 insertions, 25 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index c21dc3c6e..ca65c670f 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -17,6 +17,7 @@ import
 type
   TCandidateState* = enum 
     csEmpty, csMatch, csNoMatch
+
   TCandidate* {.final.} = object 
     exactMatches*: int
     subtypeMatches: int
@@ -26,6 +27,7 @@ type
     state*: TCandidateState
     callee*: PType           # may not be nil!
     calleeSym*: PSym         # may be nil
+    calleeScope: int         # may be -1 for unknown scope
     call*: PNode             # modified call
     bindings*: TIdTable      # maps types to types
     baseTypeMatch: bool      # needed for conversions from T to openarray[T]
@@ -35,7 +37,7 @@ type
     isNone, isConvertible, isIntConv, isSubtype, 
     isGeneric, 
     isEqual
-
+  
 proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} = 
   c.exactMatches = 0
   c.subtypeMatches = 0
@@ -59,9 +61,10 @@ proc put(t: var TIdTable, key, val: PType) {.inline.} =
         IdentEq(val.sym.name, "TTable"):
       assert false
 
-proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode) = 
+proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode, calleeScope = -1) = 
   initCandidateAux(c, callee.typ)
   c.calleeSym = callee
+  c.calleeScope = calleeScope
   initIdTable(c.bindings)
   if binding != nil:
     var typeParams = callee.ast[genericParamsPos]
@@ -93,6 +96,9 @@ proc cmpCandidates*(a, b: TCandidate): int =
   result = a.intConvMatches - b.intConvMatches
   if result != 0: return
   result = a.convMatches - b.convMatches
+  if result != 0: return
+  if (a.calleeScope != -1) and (b.calleeScope != -1):
+    result = a.calleeScope - b.calleeScope
 
 proc writeMatches(c: TCandidate) = 
   Writeln(stdout, "exact matches: " & $c.exactMatches)
@@ -101,10 +107,10 @@ proc writeMatches(c: TCandidate) =
   Writeln(stdout, "intconv matches: " & $c.intConvMatches)
   Writeln(stdout, "generic matches: " & $c.genericMatches)
 
-proc getNotFoundError*(c: PContext, n: PNode): string = 
-  # Gives a detailed error message; this is separated from semDirectCall,
-  # as semDirectCall is already pretty slow (and we need this information only
-  # in case of an error).
+proc getNotFoundError*(c: PContext, n: PNode): string =
+  # Gives a detailed error message; this is separated from semOverloadedCall,
+  # as semOverlodedCall is already pretty slow (and we need this information
+  # only in case of an error).
   result = msgKindToString(errTypeMismatch)
   for i in countup(1, sonsLen(n) - 1): 
     #debug(n.sons[i].typ)
@@ -507,7 +513,10 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
       return 
 
 proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType, 
-                        arg: PNode): PNode = 
+                        arg, argOrig: PNode): PNode =
+  if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate} and 
+     f.kind in {tyExpr, tyStmt, tyTypeDesc}:
+    return argOrig
   var r = typeRel(m.bindings, f, a)
   case r
   of isConvertible: 
@@ -547,9 +556,9 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
         result = userConvMatch(c, m, base(f), a, arg)
 
 proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType, 
-                     arg: PNode): PNode = 
+                     arg, argOrig: PNode): PNode = 
   if arg == nil or arg.kind != nkSymChoice: 
-    result = ParamTypesMatchAux(c, m, f, a, arg)
+    result = ParamTypesMatchAux(c, m, f, a, arg, argOrig)
   else: 
     # CAUTION: The order depends on the used hashing scheme. Thus it is
     # incorrect to simply use the first fitting match. However, to implement
@@ -591,29 +600,29 @@ proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
     else: 
       # only one valid interpretation found:
       markUsed(arg, arg.sons[best].sym)
-      result = ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best])
+      result = ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best], argOrig)
 
 proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode = 
   var m: TCandidate
   initCandidate(m, f)
-  result = paramTypesMatch(c, m, f, a, arg)
+  result = paramTypesMatch(c, m, f, a, arg, nil)
 
 proc ConvertTo*(c: PContext, f: PType, n: PNode): PNode = 
   var m: TCandidate
   initCandidate(m, f)
-  result = paramTypesMatch(c, m, f, n.typ, n)
+  result = paramTypesMatch(c, m, f, n.typ, n, nil)
 
 proc argtypeMatches*(c: PContext, f, a: PType): bool = 
   var m: TCandidate
   initCandidate(m, f)
-  result = paramTypesMatch(c, m, f, a, ast.emptyNode) != nil  
+  result = paramTypesMatch(c, m, f, a, ast.emptyNode, nil) != nil  
 
 proc setSon(father: PNode, at: int, son: PNode) = 
   if sonsLen(father) <= at: setlen(father.sons, at + 1)
   father.sons[at] = son
 
-proc matchesAux*(c: PContext, n: PNode, m: var TCandidate, 
-                 marker: var TIntSet) = 
+proc matchesAux*(c: PContext, n, nOrig: PNode,
+                 m: var TCandidate, marker: var TIntSet) = 
   var f = 1 # iterates over formal parameters
   var a = 1 # iterates over the actual given arguments
   m.state = csMatch           # until proven otherwise
@@ -623,7 +632,7 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
   addSon(m.call, copyTree(n.sons[0]))
   var container: PNode = nil # constructed container
   var formal: PSym = nil
-  while a < sonsLen(n): 
+  while a < n.len:
     if n.sons[a].kind == nkExprEqExpr: 
       # named param
       # check if m.callee has such a param:
@@ -642,8 +651,8 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
         m.state = csNoMatch
         return 
       m.baseTypeMatch = false
-      var arg = ParamTypesMatch(c, m, formal.typ, 
-                                      n.sons[a].typ, n.sons[a].sons[1])
+      var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
+                                n.sons[a].sons[1], nOrig.sons[a].sons[1])
       if arg == nil: 
         m.state = csNoMatch
         return 
@@ -666,9 +675,10 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
                                         copyTree(n.sons[a]), m, c))
           else: 
             addSon(m.call, copyTree(n.sons[a]))
-        elif formal != nil: 
+        elif formal != nil:
           m.baseTypeMatch = false
-          var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a])
+          var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
+                                    n.sons[a], nOrig.sons[a])
           if (arg != nil) and m.baseTypeMatch and (container != nil): 
             addSon(container, arg)
           else: 
@@ -687,7 +697,8 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
           m.state = csNoMatch
           return 
         m.baseTypeMatch = false
-        var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a])
+        var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
+                                  n.sons[a], nOrig.sons[a])
         if arg == nil: 
           m.state = csNoMatch
           return 
@@ -703,14 +714,14 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
     inc(a)
     inc(f)
 
-proc partialMatch*(c: PContext, n: PNode, m: var TCandidate) = 
+proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
   # for 'suggest' support:
   var marker = initIntSet()
-  matchesAux(c, n, m, marker)  
+  matchesAux(c, n, nOrig, m, marker)
 
-proc matches*(c: PContext, n: PNode, m: var TCandidate) = 
+proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
   var marker = initIntSet()
-  matchesAux(c, n, m, marker)
+  matchesAux(c, n, nOrig, m, marker)
   if m.state == csNoMatch: return
   # check that every formal parameter got a value:
   var f = 1