summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorClay Sweetser <clay.sweetser@gmail.com>2014-06-01 17:40:06 -0400
committerClay Sweetser <clay.sweetser@gmail.com>2014-06-01 17:40:06 -0400
commit93fa75bb07b11dfb5346d2598210bc10162ce804 (patch)
tree2c80599ca1f8bd0b95e019c2052b3199e6746ca5 /compiler
parentcbe25a41b031ea8c36dce1b47c26fd7682e40a82 (diff)
downloadNim-93fa75bb07b11dfb5346d2598210bc10162ce804.tar.gz
Fixed #1172 (for real)
Diffstat (limited to 'compiler')
-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
5 files changed, 27 insertions, 12 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):
a> 41 42 43 44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117