summary refs log tree commit diff stats
path: root/compiler/procfind.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/procfind.nim')
-rw-r--r--compiler/procfind.nim92
1 files changed, 29 insertions, 63 deletions
diff --git a/compiler/procfind.nim b/compiler/procfind.nim
index 3f47e7e8a..c2cc6e71f 100644
--- a/compiler/procfind.nim
+++ b/compiler/procfind.nim
@@ -11,60 +11,29 @@
 # This is needed for proper handling of forward declarations.
 
 import
-  ast, astalgo, msgs, semdata, types, trees, strutils
+  ast, astalgo, msgs, semdata, types, trees, lookups
+
+import std/strutils
 
 proc equalGenericParams(procA, procB: PNode): bool =
-  if sonsLen(procA) != sonsLen(procB): return false
-  for i in countup(0, sonsLen(procA) - 1):
-    if procA.sons[i].kind != nkSym:
+  if procA.len != procB.len: return false
+  for i in 0..<procA.len:
+    if procA[i].kind != nkSym:
       return false
-    if procB.sons[i].kind != nkSym:
+    if procB[i].kind != nkSym:
       return false
-    let a = procA.sons[i].sym
-    let b = procB.sons[i].sym
+    let a = procA[i].sym
+    let b = procB[i].sym
     if a.name.id != b.name.id or
         not sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}): return
     if a.ast != nil and b.ast != nil:
       if not exprStructuralEquivalent(a.ast, b.ast): return
   result = true
 
-proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym =
-  # Searchs for a forward declaration or a "twin" symbol of fn
-  # in the symbol table. If the parameter lists are exactly
-  # the same the sym in the symbol table is returned, else nil.
-  var it: TIdentIter
-  result = initIdentIter(it, scope.symbols, fn.name)
-  if isGenericRoutine(fn):
-    # we simply check the AST; this is imprecise but nearly the best what
-    # can be done; this doesn't work either though as type constraints are
-    # not kept in the AST ..
-    while result != nil:
-      if result.kind == fn.kind and isGenericRoutine(result):
-        let genR = result.ast.sons[genericParamsPos]
-        let genF = fn.ast.sons[genericParamsPos]
-        if exprStructuralEquivalent(genR, genF) and
-           exprStructuralEquivalent(result.ast.sons[paramsPos],
-                                    fn.ast.sons[paramsPos]) and
-           equalGenericParams(genR, genF):
-            return
-      result = nextIdentIter(it, scope.symbols)
-  else:
-    while result != nil:
-      if result.kind == fn.kind and not isGenericRoutine(result):
-        case equalParams(result.typ.n, fn.typ.n)
-        of paramsEqual:
-          return
-        of paramsIncompatible:
-          localError(c.config, fn.info, "overloaded '$1' leads to ambiguous calls" % fn.name.s)
-          return
-        of paramsNotEqual:
-          discard
-      result = nextIdentIter(it, scope.symbols)
-
-proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
+proc searchForProcAux(c: PContext, scope: PScope, fn: PSym): PSym =
   const flags = {ExactGenericParams, ExactTypeDescValues,
                  ExactConstraints, IgnoreCC}
-  var it: TIdentIter
+  var it: TIdentIter = default(TIdentIter)
   result = initIdentIter(it, scope.symbols, fn.name)
   while result != nil:
     if result.kind == fn.kind: #and sameType(result.typ, fn.typ, flags):
@@ -72,8 +41,8 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
       of paramsEqual:
         if (sfExported notin result.flags) and (sfExported in fn.flags):
           let message = ("public implementation '$1' has non-public " &
-                         "forward declaration in $2") %
-                        [getProcHeader(c.config, result), c.config$result.info]
+                         "forward declaration at $2") %
+                        [getProcHeader(c.config, result, getDeclarationPath = false), c.config$result.info]
           localError(c.config, fn.info, message)
         return
       of paramsIncompatible:
@@ -83,40 +52,37 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
         discard
     result = nextIdentIter(it, scope.symbols)
 
-proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
-  result = searchForProcNew(c, scope, fn)
-  when false:
-    let old = searchForProcOld(c, scope, fn)
-    if old != result:
-      echo "Mismatch in searchForProc: ", fn.info
-      debug fn.typ
-      debug if result != nil: result.typ else: nil
-      debug if old != nil: old.typ else: nil
+proc searchForProc*(c: PContext, scope: PScope, fn: PSym): tuple[proto: PSym, comesFromShadowScope: bool] =
+  var scope = scope
+  result = (searchForProcAux(c, scope, fn), false)
+  while result.proto == nil and scope.isShadowScope:
+    scope = scope.parent
+    result.proto = searchForProcAux(c, scope, fn)
+    result.comesFromShadowScope = true
 
 when false:
   proc paramsFitBorrow(child, parent: PNode): bool =
-    var length = sonsLen(child)
     result = false
-    if length == sonsLen(parent):
-      for i in countup(1, length - 1):
-        var m = child.sons[i].sym
-        var n = parent.sons[i].sym
+    if child.len == parent.len:
+      for i in 1..<child.len:
+        var m = child[i].sym
+        var n = parent[i].sym
         assert((m.kind == skParam) and (n.kind == skParam))
         if not compareTypes(m.typ, n.typ, dcEqOrDistinctOf): return
-      if not compareTypes(child.sons[0].typ, parent.sons[0].typ,
+      if not compareTypes(child[0].typ, parent[0].typ,
                           dcEqOrDistinctOf): return
       result = true
 
   proc searchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym =
-    # Searchs for the fn in the symbol table. If the parameter lists are suitable
+    # Searches for the fn in the symbol table. If the parameter lists are suitable
     # for borrowing the sym in the symbol table is returned, else nil.
-    var it: TIdentIter
+    var it: TIdentIter = default(TIdentIter)
     for scope in walkScopes(startScope):
       result = initIdentIter(it, scope.symbols, fn.Name)
       while result != nil:
         # watchout! result must not be the same as fn!
         if (result.Kind == fn.kind) and (result.id != fn.id):
-          if equalGenericParams(result.ast.sons[genericParamsPos],
-                                fn.ast.sons[genericParamsPos]):
+          if equalGenericParams(result.ast[genericParamsPos],
+                                fn.ast[genericParamsPos]):
             if paramsFitBorrow(fn.typ.n, result.typ.n): return
         result = NextIdentIter(it, scope.symbols)