Merge pull request #1240 from Varriount/fix-1172
Fixed #1172 (for real)
This commit is contained in:
commit
0d65550abb
6 changed files with 28 additions and 13 deletions
|
|
@ -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 =
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -66,10 +66,16 @@ 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:
|
||||||
localError(n.info, errXCannotBePassedToProcVar, s.name.s)
|
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) =
|
proc semProcvarCheck(c: PContext, n: PNode) =
|
||||||
let n = n.skipConv
|
let n = n.skipConv
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue