This commit is contained in:
Araq 2015-02-25 20:32:32 +01:00
commit f2cdbc92eb
3 changed files with 41 additions and 11 deletions

View file

@ -80,10 +80,6 @@ proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) =
let s = n.sym let s = n.sym
var x = PSym(idTableGet(symMap, s)) var x = PSym(idTableGet(symMap, s))
if x == nil: if x == nil:
if s.kind == skParam:
x = owner.typ.n[s.position+1].sym
internalAssert x.kind == skParam
else:
x = copySym(s, false) x = copySym(s, false)
x.owner = owner x.owner = owner
idTablePut(symMap, s, x) idTablePut(symMap, s, x)
@ -104,13 +100,18 @@ proc addProcDecls(c: PContext, fn: PSym) =
maybeAddResult(c, fn, fn.ast) maybeAddResult(c, fn, fn.ast)
proc instantiateBody(c: PContext, n: PNode, result: PSym) = proc instantiateBody(c: PContext, n, params: PNode, result: PSym) =
if n.sons[bodyPos].kind != nkEmpty: if n.sons[bodyPos].kind != nkEmpty:
inc c.inGenericInst inc c.inGenericInst
# add it here, so that recursive generic procs are possible: # add it here, so that recursive generic procs are possible:
var b = n.sons[bodyPos] var b = n.sons[bodyPos]
var symMap: TIdTable var symMap: TIdTable
initIdTable symMap initIdTable symMap
if params != nil:
for i in 1 .. <params.len:
let param = params[i].sym
if sfGenSym in param.flags:
idTablePut(symMap, params[i].sym, result.typ.n[param.position+1].sym)
freshGenSyms(b, result, symMap) freshGenSyms(b, result, symMap)
b = semProcBody(c, b) b = semProcBody(c, b)
b = hloBody(c, b) b = hloBody(c, b)
@ -127,7 +128,7 @@ proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
openScope(c) openScope(c)
var n = oldPrc.ast var n = oldPrc.ast
n.sons[bodyPos] = copyTree(s.getBody) n.sons[bodyPos] = copyTree(s.getBody)
instantiateBody(c, n, oldPrc) instantiateBody(c, n, nil, oldPrc)
closeScope(c) closeScope(c)
popInfoContext() popInfoContext()
@ -249,7 +250,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
pragma(c, result, n.sons[pragmasPos], allRoutinePragmas) pragma(c, result, n.sons[pragmasPos], allRoutinePragmas)
if isNil(n.sons[bodyPos]): if isNil(n.sons[bodyPos]):
n.sons[bodyPos] = copyTree(fn.getBody) n.sons[bodyPos] = copyTree(fn.getBody)
instantiateBody(c, n, result) instantiateBody(c, n, fn.typ.n, result)
sideEffectsCheck(c, result) sideEffectsCheck(c, result)
paramsTypeCheck(c, result.typ) paramsTypeCheck(c, result.typ)
else: else:

View file

@ -494,7 +494,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
semParamList(c, n.sons[paramsPos], gp, s) semParamList(c, n.sons[paramsPos], gp, s)
# a template's parameters are not gensym'ed even if that was originally the # a template's parameters are not gensym'ed even if that was originally the
# case as we determine whether it's a template parameter in the template # case as we determine whether it's a template parameter in the template
# body by the absence of the skGenSym flag: # body by the absence of the sfGenSym flag:
for i in 1 .. s.typ.n.len-1: for i in 1 .. s.typ.n.len-1:
s.typ.n.sons[i].sym.flags.excl sfGenSym s.typ.n.sons[i].sym.flags.excl sfGenSym
if sonsLen(gp) > 0: if sonsLen(gp) > 0:

View file

@ -31,3 +31,32 @@ var x: Something
testB(x) testB(x)
# bug #2215
# Test that templates in generics still work (regression to fix the
# regression...)
template forStatic(index: expr, slice: Slice[int], predicate: stmt):
stmt {.immediate.} =
const a = slice.a
const b = slice.b
when a <= b:
template iteration(i: int) =
block:
const index = i
predicate
template iterateStartingFrom(i: int): stmt =
when i <= b:
iteration i
iterateStartingFrom i + 1
iterateStartingFrom a
proc concreteProc(x: int) =
forStatic i, 0..3:
echo i
proc genericProc(x: any) =
forStatic i, 0..3:
echo i
concreteProc(7) # This works
genericProc(7) # This doesn't compile