Merge pull request #1240 from Varriount/fix-1172

Fixed #1172 (for real)
This commit is contained in:
Andreas Rumpf 2014-06-03 00:22:44 +02:00
commit 0d65550abb
6 changed files with 28 additions and 13 deletions

View file

@ -268,11 +268,15 @@ include hlo, seminst, semcall
proc semAfterMacroCall(c: PContext, n: PNode, s: PSym, proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
flags: TExprFlags): PNode = 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) inc(evalTemplateCounter)
if evalTemplateCounter > 100: if evalTemplateCounter > 100:
globalError(s.info, errTemplateInstantiationTooNested) globalError(s.info, errTemplateInstantiationTooNested)
let oldFriend = c.friendModule c.friendModules.add(s.owner.getModule)
c.friendModule = s.owner.getModule
result = n result = n
if s.typ.sons[0] == nil: 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) result = fitNode(c, s.typ.sons[0], result)
#GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0])) #GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
dec(evalTemplateCounter) dec(evalTemplateCounter)
c.friendModule = oldFriend discard c.friendModules.pop()
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
flags: TExprFlags = {}): PNode = flags: TExprFlags = {}): PNode =

View file

@ -52,7 +52,7 @@ type
importTable*: PScope # scope for all imported symbols importTable*: PScope # scope for all imported symbols
topLevelScope*: PScope # scope for all top-level symbols topLevelScope*: PScope # scope for all top-level symbols
p*: PProcCon # procedure context 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 # this is used so that generic instantiations
# can access private object fields # can access private object fields
instCounter*: int # to prevent endless instantiations instCounter*: int # to prevent endless instantiations
@ -168,7 +168,7 @@ proc newContext(module: PSym): PContext =
initLinkedList(result.libs) initLinkedList(result.libs)
append(result.optionStack, newOptionEntry()) append(result.optionStack, newOptionEntry())
result.module = module result.module = module
result.friendModule = module result.friendModules = @[module]
result.converters = @[] result.converters = @[]
result.patterns = @[] result.patterns = @[]
result.includedFiles = initIntSet() result.includedFiles = initIntSet()

View file

@ -190,6 +190,9 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
info: TLineInfo): PSym = 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: # no need to instantiate generic templates/macros:
if fn.kind in {skTemplate, skMacro}: return fn if fn.kind in {skTemplate, skMacro}: return fn
# generates an instantiated proc # generates an instantiated proc
@ -199,8 +202,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
var n = copyTree(fn.ast) var n = copyTree(fn.ast)
# NOTE: for access of private fields within generics from a different module # NOTE: for access of private fields within generics from a different module
# we set the friend module: # we set the friend module:
var oldFriend = c.friendModule c.friendModules.add(getModule(fn))
c.friendModule = getModule(fn)
#let oldScope = c.currentScope #let oldScope = c.currentScope
#c.currentScope = fn.scope #c.currentScope = fn.scope
result = copySym(fn, false) result = copySym(fn, false)
@ -236,6 +238,6 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
closeScope(c) # close scope for parameters closeScope(c) # close scope for parameters
popOwner() popOwner()
#c.currentScope = oldScope #c.currentScope = oldScope
c.friendModule = oldFriend discard c.friendModules.pop()
dec(c.instCounter) dec(c.instCounter)
if result.kind == skMethod: finishMethod(c, result) if result.kind == skMethod: finishMethod(c, result)

View file

@ -66,9 +66,15 @@ proc toCover(t: PType): BiggestInt =
result = lengthOrd(skipTypes(t, abstractVar-{tyTypeDesc})) result = lengthOrd(skipTypes(t, abstractVar-{tyTypeDesc}))
proc performProcvarCheck(c: PContext, n: PNode, s: PSym) = 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 var smoduleId = getModule(s).id
if sfProcvar notin s.flags and s.typ.callConv == ccDefault and if sfProcvar notin s.flags and s.typ.callConv == ccDefault and
smoduleId != c.module.id and smoduleId != c.friendModule.id: smoduleId != c.module.id:
block outer:
for module in c.friendModules:
if smoduleId == module.id:
break outer
localError(n.info, errXCannotBePassedToProcVar, s.name.s) localError(n.info, errXCannotBePassedToProcVar, s.name.s)
proc semProcvarCheck(c: PContext, n: PNode) = proc semProcvarCheck(c: PContext, n: PNode) =

View file

@ -63,8 +63,11 @@ proc filterSym(s: PSym): bool {.inline.} =
proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} = proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} =
let fmoduleId = getModule(f).id let fmoduleId = getModule(f).id
result = sfExported in f.flags or fmoduleId == c.module.id or result = sfExported in f.flags or fmoduleId == c.module.id
fmoduleId == c.friendModule.id for module in c.friendModules:
if fmoduleId == module.id:
result = true
break
proc suggestField(c: PContext, s: PSym, outputs: var int) = proc suggestField(c: PContext, s: PSym, outputs: var int) =
if filterSym(s) and fieldVisible(c, s): if filterSym(s) and fieldVisible(c, s):

View file

@ -59,7 +59,7 @@ proc enqueue*[T](q: var TQueue[T], item: T) =
proc dequeue*[T](q: var TQueue[T]): T = proc dequeue*[T](q: var TQueue[T]): T =
## removes and returns the first element of the queue `q`. ## removes and returns the first element of the queue `q`.
assert q.len > 0 assert q.count > 0
dec q.count dec q.count
result = q.data[q.rd] result = q.data[q.rd]
q.rd = (q.rd + 1) and q.mask q.rd = (q.rd + 1) and q.mask