fixes #194
This commit is contained in:
parent
e741583f7b
commit
043921c7a7
6 changed files with 65 additions and 4 deletions
|
|
@ -234,10 +234,12 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||||
result = SemStmtAndGenerateGenerics(c, n)
|
result = SemStmtAndGenerateGenerics(c, n)
|
||||||
else:
|
else:
|
||||||
let oldContextLen = msgs.getInfoContextLen()
|
let oldContextLen = msgs.getInfoContextLen()
|
||||||
|
let oldInGenericInst = c.InGenericInst
|
||||||
try:
|
try:
|
||||||
result = SemStmtAndGenerateGenerics(c, n)
|
result = SemStmtAndGenerateGenerics(c, n)
|
||||||
except ERecoverableError:
|
except ERecoverableError:
|
||||||
RecoverContext(c)
|
RecoverContext(c)
|
||||||
|
c.InGenericInst = oldInGenericInst
|
||||||
result = ast.emptyNode
|
result = ast.emptyNode
|
||||||
msgs.setInfoContextLen(oldContextLen)
|
msgs.setInfoContextLen(oldContextLen)
|
||||||
if gCmd == cmdIdeTools: findSuggest(c, n)
|
if gCmd == cmdIdeTools: findSuggest(c, n)
|
||||||
|
|
@ -261,7 +263,7 @@ proc myClose(context: PPassContext, n: PNode): PNode =
|
||||||
popOwner()
|
popOwner()
|
||||||
popProcCon(c)
|
popProcCon(c)
|
||||||
|
|
||||||
proc semPass(): TPass =
|
proc semPass(): TPass =
|
||||||
initPass(result)
|
initPass(result)
|
||||||
result.open = myOpen
|
result.open = myOpen
|
||||||
result.openCached = myOpenCached
|
result.openCached = myOpenCached
|
||||||
|
|
|
||||||
|
|
@ -63,12 +63,15 @@ type
|
||||||
tab*: TSymTab # each module has its own symbol table
|
tab*: TSymTab # each module has its own symbol table
|
||||||
AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
|
AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
|
||||||
# store this info in the syms themselves!)
|
# store this info in the syms themselves!)
|
||||||
InGenericContext*: int # > 0 if we are in a generic
|
InGenericContext*: int # > 0 if we are in a generic type
|
||||||
InUnrolledContext*: int # > 0 if we are unrolling a loop
|
InUnrolledContext*: int # > 0 if we are unrolling a loop
|
||||||
InCompilesContext*: int # > 0 if we are in a ``compiles`` magic
|
InCompilesContext*: int # > 0 if we are in a ``compiles`` magic
|
||||||
|
InGenericInst*: int # > 0 if we are instantiating a generic
|
||||||
converters*: TSymSeq # sequence of converters
|
converters*: TSymSeq # sequence of converters
|
||||||
patterns*: TSymSeq # sequence of pattern matchers
|
patterns*: TSymSeq # sequence of pattern matchers
|
||||||
optionStack*: TLinkedList
|
optionStack*: TLinkedList
|
||||||
|
symMapping*: TIdTable # every gensym'ed symbol needs to be mapped
|
||||||
|
# to some new symbol in a generic instantiation
|
||||||
libs*: TLinkedList # all libs used by this module
|
libs*: TLinkedList # all libs used by this module
|
||||||
semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
||||||
semExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
semExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
||||||
|
|
|
||||||
|
|
@ -1211,6 +1211,7 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
|
|
||||||
let oldInGenericContext = c.InGenericContext
|
let oldInGenericContext = c.InGenericContext
|
||||||
let oldInUnrolledContext = c.InUnrolledContext
|
let oldInUnrolledContext = c.InUnrolledContext
|
||||||
|
let oldInGenericInst = c.InGenericInst
|
||||||
let oldProcCon = c.p
|
let oldProcCon = c.p
|
||||||
c.generics = newGenericsCache()
|
c.generics = newGenericsCache()
|
||||||
try:
|
try:
|
||||||
|
|
@ -1222,6 +1223,7 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
c.generics = oldGenerics
|
c.generics = oldGenerics
|
||||||
c.InGenericContext = oldInGenericContext
|
c.InGenericContext = oldInGenericContext
|
||||||
c.InUnrolledContext = oldInUnrolledContext
|
c.InUnrolledContext = oldInUnrolledContext
|
||||||
|
c.InGenericInst = oldInGenericInst
|
||||||
c.p = oldProcCon
|
c.p = oldProcCon
|
||||||
msgs.setInfoContextLen(oldContextLen)
|
msgs.setInfoContextLen(oldContextLen)
|
||||||
setlen(gOwners, oldOwnerLen)
|
setlen(gOwners, oldOwnerLen)
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,14 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
var s = QualifiedLookUp(c, n, luf)
|
var s = QualifiedLookUp(c, n, luf)
|
||||||
if s != nil: result = semGenericStmtSymbol(c, n, s)
|
if s != nil: result = semGenericStmtSymbol(c, n, s)
|
||||||
# XXX for example: ``result.add`` -- ``add`` needs to be looked up here...
|
# XXX for example: ``result.add`` -- ``add`` needs to be looked up here...
|
||||||
of nkEmpty, nkSym..nkNilLit:
|
of nkEmpty, nkSym..nkNilLit:
|
||||||
|
# see tests/compile/tgensymgeneric.nim:
|
||||||
|
# We need to open the gensym'ed symbol again so that the instantiation
|
||||||
|
# creates a fresh copy; but this is wrong the very first reason for gensym
|
||||||
|
# is that scope rules cannot be used! So simply removing 'sfGenSym' does
|
||||||
|
# not work. Copying the symbol does not work either because we're already
|
||||||
|
# the owner of the symbol! What we need to do is to copy the symbol
|
||||||
|
# in the generic instantiation process...
|
||||||
nil
|
nil
|
||||||
of nkBind:
|
of nkBind:
|
||||||
result = semGenericStmt(c, n.sons[0], flags+{withinBind}, toBind)
|
result = semGenericStmt(c, n.sons[0], flags+{withinBind}, toBind)
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,18 @@ proc removeDefaultParamValues(n: PNode) =
|
||||||
# not possible... XXX We don't solve this issue here.
|
# not possible... XXX We don't solve this issue here.
|
||||||
a.sons[L-1] = ast.emptyNode
|
a.sons[L-1] = ast.emptyNode
|
||||||
|
|
||||||
|
proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) =
|
||||||
|
# we need to create a fresh set of gensym'ed symbols:
|
||||||
|
if n.kind == nkSym and sfGenSym in n.sym.flags:
|
||||||
|
var x = PSym(IdTableGet(symMap, n.sym))
|
||||||
|
if x == nil:
|
||||||
|
x = copySym(n.sym, false)
|
||||||
|
x.owner = owner
|
||||||
|
IdTablePut(symMap, n.sym, x)
|
||||||
|
n.sym = x
|
||||||
|
else:
|
||||||
|
for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, symMap)
|
||||||
|
|
||||||
proc instantiateBody(c: PContext, n: PNode, result: PSym) =
|
proc instantiateBody(c: PContext, n: PNode, result: PSym) =
|
||||||
if n.sons[bodyPos].kind != nkEmpty:
|
if n.sons[bodyPos].kind != nkEmpty:
|
||||||
# add it here, so that recursive generic procs are possible:
|
# add it here, so that recursive generic procs are possible:
|
||||||
|
|
@ -77,7 +89,11 @@ proc instantiateBody(c: PContext, n: PNode, result: PSym) =
|
||||||
if result.kind in {skProc, skMethod, skConverter, skMacro}:
|
if result.kind in {skProc, skMethod, skConverter, skMacro}:
|
||||||
addResult(c, result.typ.sons[0], n.info, result.kind)
|
addResult(c, result.typ.sons[0], n.info, result.kind)
|
||||||
addResultNode(c, n)
|
addResultNode(c, n)
|
||||||
var b = semStmtScope(c, n.sons[bodyPos])
|
var b = n.sons[bodyPos]
|
||||||
|
var symMap: TIdTable
|
||||||
|
InitIdTable symMap
|
||||||
|
freshGenSyms(b, result, symMap)
|
||||||
|
b = semStmtScope(c, b)
|
||||||
b = hloBody(c, b)
|
b = hloBody(c, b)
|
||||||
n.sons[bodyPos] = transformBody(c.module, b, result)
|
n.sons[bodyPos] = transformBody(c.module, b, result)
|
||||||
#echo "code instantiated ", result.name.s
|
#echo "code instantiated ", result.name.s
|
||||||
|
|
|
||||||
31
tests/compile/tgensymgeneric.nim
Normal file
31
tests/compile/tgensymgeneric.nim
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# We need to open the gensym'ed symbol again so that the instantiation
|
||||||
|
# creates a fresh copy; but this is wrong the very first reason for gensym
|
||||||
|
# is that scope rules cannot be used! So simply removing 'sfGenSym' does
|
||||||
|
# not work. Copying the symbol does not work either because we're already
|
||||||
|
# the owner of the symbol! What we need to do is to copy the symbol
|
||||||
|
# in the generic instantiation process...
|
||||||
|
|
||||||
|
type
|
||||||
|
TA = object
|
||||||
|
x: int
|
||||||
|
TB = object
|
||||||
|
x: string
|
||||||
|
|
||||||
|
template genImpl() =
|
||||||
|
var gensymed: T
|
||||||
|
when T is TB:
|
||||||
|
gensymed.x = "abc"
|
||||||
|
else:
|
||||||
|
gensymed.x = 123
|
||||||
|
shallowCopy(result, gensymed)
|
||||||
|
|
||||||
|
proc gen[T](x: T): T =
|
||||||
|
genImpl()
|
||||||
|
|
||||||
|
var
|
||||||
|
a: TA
|
||||||
|
b: TB
|
||||||
|
let x = gen(a)
|
||||||
|
let y = gen(b)
|
||||||
|
|
||||||
|
echo x.x, " ", y.x
|
||||||
Loading…
Add table
Add a link
Reference in a new issue