summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2013-12-30 02:13:50 +0200
committerZahary Karadjov <zahary@gmail.com>2013-12-30 10:57:12 +0200
commite3f53409f64a74e2f672a1624de17efc84be55ed (patch)
treebeecf302214524b1d808426750cf6f25259e0d2b /compiler
parentfa3bb8d66bfa18c3a497db2945df43703d809adc (diff)
downloadNim-e3f53409f64a74e2f672a1624de17efc84be55ed.tar.gz
proc redefinition search based on the type system instead of on sloppy AST matching
This will work the same for procs/templates/macros/etc, having arbitrary mix of implicit
and explicit generics (as long as the symbols are equivalent for the purposes of overload
resolution, they will be detected as redefinitions)

fixes tgeneric
Diffstat (limited to 'compiler')
-rw-r--r--compiler/procfind.nim26
-rw-r--r--compiler/semtypes.nim16
-rw-r--r--compiler/types.nim36
3 files changed, 48 insertions, 30 deletions
diff --git a/compiler/procfind.nim b/compiler/procfind.nim
index f02e7aed4..eb0cbca3f 100644
--- a/compiler/procfind.nim
+++ b/compiler/procfind.nim
@@ -30,7 +30,7 @@ proc equalGenericParams(procA, procB: PNode): bool =
       if not exprStructuralEquivalent(a.ast, b.ast): return
   result = true
 
-proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
+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.
@@ -63,6 +63,30 @@ proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
           nil
       result = nextIdentIter(it, scope.symbols)
 
+proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
+  const flags = {ExactGenericParams, ExactTypeDescValues,
+                 ExactConstraints, IgnoreCC}
+
+  var it: TIdentIter
+  result = initIdentIter(it, scope.symbols, fn.name)
+  while result != nil:
+    if result.kind in skProcKinds and
+       sameType(result.typ, fn.typ, flags): return
+
+    result = nextIdentIter(it, scope.symbols)
+  
+  return nil
+
+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
+ 
 when false:
   proc paramsFitBorrow(child, parent: PNode): bool = 
     var length = sonsLen(child)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 03d8b7095..175901057 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -827,22 +827,6 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
   dec(c.p.nestedBlockCounter)
 
 proc semGenericParamInInvokation(c: PContext, n: PNode): PType =
-  # XXX hack 1022 for generics ... would have been nice if the compiler had
-  # been designed with them in mind from start ...
-  when false:
-    if n.kind == nkSym:
-      # for generics we need to lookup the type var again:
-      var s = searchInScopes(c, n.sym.name)
-      if s != nil:
-        if s.kind == skType and s.typ != nil:
-          var t = n.sym.typ
-          echo "came here"
-          return t
-        else:
-          echo "s is crap:"
-          debug(s)
-      else:
-        echo "s is nil!!!!"
   result = semTypeNode(c, n, nil)
 
 proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = 
diff --git a/compiler/types.nim b/compiler/types.nim
index 024cf4549..7403e29f9 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -606,8 +606,10 @@ type
 
   TTypeCmpFlag* = enum
     IgnoreTupleFields
+    IgnoreCC
     ExactTypeDescValues
     ExactGenericParams
+    ExactConstraints
     AllowCommonBase
 
   TTypeCmpFlags* = set[TTypeCmpFlag]
@@ -637,15 +639,17 @@ proc sameTypeOrNilAux(a, b: PType, c: var TSameTypeClosure): bool =
     if a == nil or b == nil: result = false
     else: result = sameTypeAux(a, b, c)
 
+proc sameType*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
+  var c = initSameTypeClosure()
+  c.flags = flags
+  result = sameTypeAux(a, b, c)
+
 proc sameTypeOrNil*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
   if a == b:
     result = true
-  else: 
+  else:
     if a == nil or b == nil: result = false
-    else:
-      var c = initSameTypeClosure()
-      c.flags = flags
-      result = sameTypeAux(a, b, c)
+    else: result = sameType(a, b, flags)
 
 proc equalParam(a, b: PSym): TParamsEquality = 
   if sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}) and
@@ -661,7 +665,15 @@ proc equalParam(a, b: PSym): TParamsEquality =
       result = paramsIncompatible
   else:
     result = paramsNotEqual
-  
+
+proc sameConstraints(a, b: PNode): bool =
+  internalAssert a.len == b.len
+  for i in 1 .. <a.len:
+    if not exprStructuralEquivalent(a[i].sym.constraint,
+                                    b[i].sym.constraint):
+      return false
+  return true
+
 proc equalParams(a, b: PNode): TParamsEquality = 
   result = paramsEqual
   var length = sonsLen(a)
@@ -860,8 +872,9 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     else:
       result = sameFlags(a, b)
   of tyGenericParam:
-    result = if ExactGenericParams in c.flags: a.id == b.id
-             else: sameChildrenAux(a, b, c) and sameFlags(a, b)
+    result = sameChildrenAux(a, b, c) and sameFlags(a, b)
+    if result and ExactGenericParams in c.flags:
+      result = a.sym.position == b.sym.position
   of tyGenericInvokation, tyGenericBody, tySequence,
      tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
      tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter,
@@ -869,7 +882,8 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     cycleCheck()    
     result = sameChildrenAux(a, b, c) and sameFlags(a, b)
     if result and a.kind == tyProc:
-      result = a.callConv == b.callConv
+      result = ((IgnoreCC in c.flags) or a.callConv == b.callConv) and
+               ((ExactConstraints notin c.flags) or sameConstraints(a.n, b.n))
   of tyRange:
     cycleCheck()
     result = sameTypeOrNilAux(a.sons[0], b.sons[0], c) and
@@ -877,10 +891,6 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
         sameValue(a.n.sons[1], b.n.sons[1])
   of tyNone: result = false  
 
-proc sameType*(x, y: PType): bool =
-  var c = initSameTypeClosure()
-  result = sameTypeAux(x, y, c)
-
 proc sameBackendType*(x, y: PType): bool =
   var c = initSameTypeClosure()
   c.flags.incl IgnoreTupleFields