summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-09-20 23:44:52 +0200
committerAraq <rumpf_a@web.de>2012-09-20 23:44:52 +0200
commit043921c7a7d7ba50872c3a48f063a5d7b9d6b6b0 (patch)
tree261349a336b2fd948ab5e6b97038d51a08e96e57 /compiler
parente741583f7b01fecefef9c61ed70dcb6f234b9a07 (diff)
downloadNim-043921c7a7d7ba50872c3a48f063a5d7b9d6b6b0.tar.gz
fixes #194
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/sem.nim4
-rwxr-xr-xcompiler/semdata.nim5
-rwxr-xr-xcompiler/semexprs.nim2
-rwxr-xr-xcompiler/semgnrc.nim9
-rwxr-xr-xcompiler/seminst.nim18
5 files changed, 34 insertions, 4 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 16dd2d107..e1f2fb21c 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -234,10 +234,12 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
     result = SemStmtAndGenerateGenerics(c, n)
   else:
     let oldContextLen = msgs.getInfoContextLen()
+    let oldInGenericInst = c.InGenericInst
     try:
       result = SemStmtAndGenerateGenerics(c, n)
     except ERecoverableError:
       RecoverContext(c)
+      c.InGenericInst = oldInGenericInst
       result = ast.emptyNode
       msgs.setInfoContextLen(oldContextLen)
       if gCmd == cmdIdeTools: findSuggest(c, n)
@@ -261,7 +263,7 @@ proc myClose(context: PPassContext, n: PNode): PNode =
   popOwner()
   popProcCon(c)
 
-proc semPass(): TPass = 
+proc semPass(): TPass =
   initPass(result)
   result.open = myOpen
   result.openCached = myOpenCached
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 02768c90b..fe6f43f44 100755
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -63,12 +63,15 @@ type
     tab*: TSymTab              # each module has its own symbol table
     AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
                                # store this info in the syms themselves!)
-    InGenericContext*: int     # > 0 if we are in a generic
+    InGenericContext*: int     # > 0 if we are in a generic type
     InUnrolledContext*: int    # > 0 if we are unrolling a loop
     InCompilesContext*: int    # > 0 if we are in a ``compiles`` magic
+    InGenericInst*: int        # > 0 if we are instantiating a generic
     converters*: TSymSeq       # sequence of converters
     patterns*: TSymSeq         # sequence of pattern matchers
     optionStack*: TLinkedList
+    symMapping*: TIdTable      # every gensym'ed symbol needs to be mapped
+                               # to some new symbol in a generic instantiation
     libs*: TLinkedList         # all libs used by this module
     semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
     semExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.}      # for the pragmas
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index a08d50307..8a42a7090 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1211,6 +1211,7 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
   
   let oldInGenericContext = c.InGenericContext
   let oldInUnrolledContext = c.InUnrolledContext
+  let oldInGenericInst = c.InGenericInst
   let oldProcCon = c.p
   c.generics = newGenericsCache()
   try:
@@ -1222,6 +1223,7 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
   c.generics = oldGenerics
   c.InGenericContext = oldInGenericContext
   c.InUnrolledContext = oldInUnrolledContext
+  c.InGenericInst = oldInGenericInst
   c.p = oldProcCon
   msgs.setInfoContextLen(oldContextLen)
   setlen(gOwners, oldOwnerLen)
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index 434dd7155..2751aa1e1 100755
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -91,7 +91,14 @@ proc semGenericStmt(c: PContext, n: PNode,
     var s = QualifiedLookUp(c, n, luf)
     if s != nil: result = semGenericStmtSymbol(c, n, s)
     # XXX for example: ``result.add`` -- ``add`` needs to be looked up here...
-  of nkEmpty, nkSym..nkNilLit: 
+  of nkEmpty, nkSym..nkNilLit:
+    # see tests/compile/tgensymgeneric.nim:
+    # We need to open the gensym'ed symbol again so that the instantiation
+    # creates a fresh copy; but this is wrong the very first reason for gensym
+    # is that scope rules cannot be used! So simply removing 'sfGenSym' does
+    # not work. Copying the symbol does not work either because we're already
+    # the owner of the symbol! What we need to do is to copy the symbol
+    # in the generic instantiation process...
     nil
   of nkBind: 
     result = semGenericStmt(c, n.sons[0], flags+{withinBind}, toBind)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index ffda48fba..135f9bba9 100755
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -69,6 +69,18 @@ proc removeDefaultParamValues(n: PNode) =
         # not possible... XXX We don't solve this issue here.
         a.sons[L-1] = ast.emptyNode
 
+proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) =
+  # we need to create a fresh set of gensym'ed symbols:
+  if n.kind == nkSym and sfGenSym in n.sym.flags:
+    var x = PSym(IdTableGet(symMap, n.sym))
+    if x == nil:
+      x = copySym(n.sym, false)
+      x.owner = owner
+      IdTablePut(symMap, n.sym, x)
+    n.sym = x
+  else:
+    for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, symMap)
+
 proc instantiateBody(c: PContext, n: PNode, result: PSym) =
   if n.sons[bodyPos].kind != nkEmpty:
     # add it here, so that recursive generic procs are possible:
@@ -77,7 +89,11 @@ proc instantiateBody(c: PContext, n: PNode, result: PSym) =
     if result.kind in {skProc, skMethod, skConverter, skMacro}: 
       addResult(c, result.typ.sons[0], n.info, result.kind)
       addResultNode(c, n)
-    var b = semStmtScope(c, n.sons[bodyPos])
+    var b = n.sons[bodyPos]
+    var symMap: TIdTable
+    InitIdTable symMap
+    freshGenSyms(b, result, symMap)
+    b = semStmtScope(c, b)
     b = hloBody(c, b)
     n.sons[bodyPos] = transformBody(c.module, b, result)
     #echo "code instantiated ", result.name.s