summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2014-06-03 00:22:44 +0200
committerAndreas Rumpf <rumpf_a@web.de>2014-06-03 00:22:44 +0200
commit0d65550abb7da0e4ee79c30ef3d4245e77f0af43 (patch)
tree2c80599ca1f8bd0b95e019c2052b3199e6746ca5
parentcbe25a41b031ea8c36dce1b47c26fd7682e40a82 (diff)
parent93fa75bb07b11dfb5346d2598210bc10162ce804 (diff)
downloadNim-0d65550abb7da0e4ee79c30ef3d4245e77f0af43.tar.gz
Merge pull request #1240 from Varriount/fix-1172
Fixed #1172 (for real)
-rw-r--r--compiler/sem.nim10
-rw-r--r--compiler/semdata.nim4
-rw-r--r--compiler/seminst.nim8
-rw-r--r--compiler/semstmts.nim10
-rw-r--r--compiler/suggest.nim7
-rw-r--r--lib/pure/collections/queues.nim2
6 files changed, 28 insertions, 13 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim
index bdc2a0b3c..0c793eeba 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -268,11 +268,15 @@ include hlo, seminst, semcall
 
 proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
                        flags: TExprFlags): PNode =
+  ## Semantically check the output of a macro.
+  ## This involves processes such as re-checking the macro output for type
+  ## coherence, making sure that variables declared with 'let' aren't
+  ## reassigned, and binding the unbound identifiers that the macro output
+  ## contains.
   inc(evalTemplateCounter)
   if evalTemplateCounter > 100:
     globalError(s.info, errTemplateInstantiationTooNested)
-  let oldFriend = c.friendModule
-  c.friendModule = s.owner.getModule
+  c.friendModules.add(s.owner.getModule)
 
   result = n
   if s.typ.sons[0] == nil:
@@ -296,7 +300,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
       result = fitNode(c, s.typ.sons[0], result)
       #GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
   dec(evalTemplateCounter)
-  c.friendModule = oldFriend
+  discard c.friendModules.pop()
 
 proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
                   flags: TExprFlags = {}): PNode =
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 987a70a41..d2b2f90cd 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -52,7 +52,7 @@ type
     importTable*: PScope       # scope for all imported symbols
     topLevelScope*: PScope     # scope for all top-level symbols
     p*: PProcCon               # procedure context
-    friendModule*: PSym        # current friend module; may access private data;
+    friendModules*: seq[PSym]  # friend modules; may access private data;
                                # this is used so that generic instantiations
                                # can access private object fields
     instCounter*: int          # to prevent endless instantiations
@@ -168,7 +168,7 @@ proc newContext(module: PSym): PContext =
   initLinkedList(result.libs)
   append(result.optionStack, newOptionEntry())
   result.module = module
-  result.friendModule = module
+  result.friendModules = @[module]
   result.converters = @[]
   result.patterns = @[]
   result.includedFiles = initIntSet()
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index f7d5fa6f8..b93d7ca15 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -190,6 +190,9 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
 
 proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
                       info: TLineInfo): PSym =
+  ## Generates a new instance of a generic procedure.
+  ## The `pt` parameter is a type-unsafe mapping table used to link generic
+  ## parameters to their concrete types within the generic instance.
   # no need to instantiate generic templates/macros:
   if fn.kind in {skTemplate, skMacro}: return fn
   # generates an instantiated proc
@@ -199,8 +202,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   var n = copyTree(fn.ast)
   # NOTE: for access of private fields within generics from a different module
   # we set the friend module:
-  var oldFriend = c.friendModule
-  c.friendModule = getModule(fn)
+  c.friendModules.add(getModule(fn))
   #let oldScope = c.currentScope
   #c.currentScope = fn.scope
   result = copySym(fn, false)
@@ -236,6 +238,6 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   closeScope(c)           # close scope for parameters
   popOwner()
   #c.currentScope = oldScope
-  c.friendModule = oldFriend
+  discard c.friendModules.pop()
   dec(c.instCounter)
   if result.kind == skMethod: finishMethod(c, result)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 43c7bf3fe..d17351988 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -66,10 +66,16 @@ proc toCover(t: PType): BiggestInt =
     result = lengthOrd(skipTypes(t, abstractVar-{tyTypeDesc}))
 
 proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
+  ## Checks that the given symbol is a proper procedure variable, meaning
+  ## that it 
   var smoduleId = getModule(s).id
   if sfProcvar notin s.flags and s.typ.callConv == ccDefault and
-      smoduleId != c.module.id and smoduleId != c.friendModule.id: 
-    localError(n.info, errXCannotBePassedToProcVar, s.name.s)
+      smoduleId != c.module.id:
+    block outer:
+      for module in c.friendModules:
+        if smoduleId == module.id:
+          break outer
+      localError(n.info, errXCannotBePassedToProcVar, s.name.s)
 
 proc semProcvarCheck(c: PContext, n: PNode) =
   let n = n.skipConv
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index fc6ba2f77..a46c6a082 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -63,8 +63,11 @@ proc filterSym(s: PSym): bool {.inline.} =
 
 proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} =
   let fmoduleId = getModule(f).id
-  result = sfExported in f.flags or fmoduleId == c.module.id or
-      fmoduleId == c.friendModule.id
+  result = sfExported in f.flags or fmoduleId == c.module.id
+  for module in c.friendModules:
+    if fmoduleId == module.id:
+      result = true
+      break
 
 proc suggestField(c: PContext, s: PSym, outputs: var int) = 
   if filterSym(s) and fieldVisible(c, s):
diff --git a/lib/pure/collections/queues.nim b/lib/pure/collections/queues.nim
index db1d50569..5481272f0 100644
--- a/lib/pure/collections/queues.nim
+++ b/lib/pure/collections/queues.nim
@@ -59,7 +59,7 @@ proc enqueue*[T](q: var TQueue[T], item: T) =
 
 proc dequeue*[T](q: var TQueue[T]): T =
   ## removes and returns the first element of the queue `q`.
-  assert q.len > 0
+  assert q.count > 0
   dec q.count
   result = q.data[q.rd]
   q.rd = (q.rd + 1) and q.mask