mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 04:02:41 +00:00
Merge pull request #1240 from Varriount/fix-1172
Fixed #1172 (for real)
This commit is contained in:
@@ -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 =
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user