summary refs log tree commit diff stats
path: root/rod/procfind.nim
diff options
context:
space:
mode:
Diffstat (limited to 'rod/procfind.nim')
-rwxr-xr-xrod/procfind.nim86
1 files changed, 86 insertions, 0 deletions
diff --git a/rod/procfind.nim b/rod/procfind.nim
new file mode 100755
index 000000000..bd5b3841f
--- /dev/null
+++ b/rod/procfind.nim
@@ -0,0 +1,86 @@
+#
+#
+#           The Nimrod Compiler
+#        (c) Copyright 2009 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+# This module implements the searching for procs and iterators.
+# This is needed for proper handling of forward declarations.
+
+import 
+  ast, astalgo, msgs, semdata, types, trees
+
+proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym
+  # Searchs for the fn in the symbol table. If the parameter lists are exactly
+  # the same the sym in the symbol table is returned, else nil.
+proc SearchForBorrowProc*(c: PContext, fn: PSym, tos: int): PSym
+  # Searchs 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.
+# implementation
+
+proc equalGenericParams(procA, procB: PNode): bool = 
+  var a, b: PSym
+  result = procA == procB
+  if result: return 
+  if (procA == nil) or (procB == nil): return 
+  if sonsLen(procA) != sonsLen(procB): return 
+  for i in countup(0, sonsLen(procA) - 1): 
+    if procA.sons[i].kind != nkSym: 
+      InternalError(procA.info, "equalGenericParams")
+    if procB.sons[i].kind != nkSym: 
+      InternalError(procB.info, "equalGenericParams")
+    a = procA.sons[i].sym
+    b = procB.sons[i].sym
+    if (a.name.id != b.name.id) or not sameTypeOrNil(a.typ, b.typ): return 
+    if (a.ast != nil) and (b.ast != nil): 
+      if not ExprStructuralEquivalent(a.ast, b.ast): return 
+  result = true
+
+proc SearchForProc(c: PContext, fn: PSym, tos: int): PSym = 
+  var it: TIdentIter
+  result = initIdentIter(it, c.tab.stack[tos], fn.Name)
+  while result != nil: 
+    if (result.Kind == fn.kind): 
+      if equalGenericParams(result.ast.sons[genericParamsPos], 
+                            fn.ast.sons[genericParamsPos]): 
+        case equalParams(result.typ.n, fn.typ.n)
+        of paramsEqual: 
+          return 
+        of paramsIncompatible: 
+          liMessage(fn.info, errNotOverloadable, fn.name.s)
+          return 
+        of paramsNotEqual: 
+          nil
+    result = NextIdentIter(it, c.tab.stack[tos])
+
+proc paramsFitBorrow(a, b: PNode): bool = 
+  var 
+    length: int
+    m, n: PSym
+  length = sonsLen(a)
+  result = false
+  if length == sonsLen(b): 
+    for i in countup(1, length - 1): 
+      m = a.sons[i].sym
+      n = b.sons[i].sym
+      assert((m.kind == skParam) and (n.kind == skParam))
+      if not equalOrDistinctOf(m.typ, n.typ): return 
+    if not equalOrDistinctOf(a.sons[0].typ, b.sons[0].typ): return 
+    result = true
+
+proc SearchForBorrowProc(c: PContext, fn: PSym, tos: int): PSym = 
+  # Searchs 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
+  for scope in countdown(tos, 0): 
+    result = initIdentIter(it, c.tab.stack[scope], 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 paramsFitBorrow(fn.typ.n, result.typ.n): return 
+      result = NextIdentIter(it, c.tab.stack[scope])