fixes #1915
This commit is contained in:
parent
c87f1eb581
commit
b9079b8713
8 changed files with 46 additions and 9 deletions
|
|
@ -1977,6 +1977,8 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
of skParam:
|
of skParam:
|
||||||
if sym.loc.r == nil or sym.loc.t == nil:
|
if sym.loc.r == nil or sym.loc.t == nil:
|
||||||
#echo "FAILED FOR PRCO ", p.prc.name.s
|
#echo "FAILED FOR PRCO ", p.prc.name.s
|
||||||
|
#debug p.prc.typ.n
|
||||||
|
#echo renderTree(p.prc.ast, {renderIds})
|
||||||
internalError(n.info, "expr: param not init " & sym.name.s & "_" & $sym.id)
|
internalError(n.info, "expr: param not init " & sym.name.s & "_" & $sym.id)
|
||||||
putLocIntoDest(p, d, sym.loc)
|
putLocIntoDest(p, d, sym.loc)
|
||||||
else: internalError(n.info, "expr(" & $sym.kind & "); unknown symbol")
|
else: internalError(n.info, "expr(" & $sym.kind & "); unknown symbol")
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||||
of nkSym:
|
of nkSym:
|
||||||
var s = templ.sym
|
var s = templ.sym
|
||||||
if s.owner.id == c.owner.id:
|
if s.owner.id == c.owner.id:
|
||||||
if s.kind == skParam:
|
if s.kind == skParam and sfGenSym notin s.flags:
|
||||||
let x = actual.sons[s.position]
|
let x = actual.sons[s.position]
|
||||||
if x.kind == nkArgList:
|
if x.kind == nkArgList:
|
||||||
for y in items(x): result.add(y)
|
for y in items(x): result.add(y)
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ type
|
||||||
inTryStmt*: int # whether we are in a try statement; works also
|
inTryStmt*: int # whether we are in a try statement; works also
|
||||||
# in standalone ``except`` and ``finally``
|
# in standalone ``except`` and ``finally``
|
||||||
next*: PProcCon # used for stacking procedure contexts
|
next*: PProcCon # used for stacking procedure contexts
|
||||||
|
wasForwarded*: bool # whether the current proc has a separate header
|
||||||
|
|
||||||
TInstantiationPair* = object
|
TInstantiationPair* = object
|
||||||
genericSym*: PSym
|
genericSym*: PSym
|
||||||
|
|
|
||||||
|
|
@ -109,9 +109,16 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
# if a proc accesses a global variable, it is not side effect free:
|
# if a proc accesses a global variable, it is not side effect free:
|
||||||
if sfGlobal in s.flags:
|
if sfGlobal in s.flags:
|
||||||
incl(c.p.owner.flags, sfSideEffect)
|
incl(c.p.owner.flags, sfSideEffect)
|
||||||
elif s.kind == skParam and s.typ.kind == tyStatic and s.typ.n != nil:
|
elif s.kind == skParam:
|
||||||
|
if s.typ.kind == tyStatic and s.typ.n != nil:
|
||||||
# XXX see the hack in sigmatch.nim ...
|
# XXX see the hack in sigmatch.nim ...
|
||||||
return s.typ.n
|
return s.typ.n
|
||||||
|
elif sfGenSym in s.flags and c.p.wasForwarded:
|
||||||
|
# gensym'ed parameters that nevertheless have been forward declared
|
||||||
|
# need a special fixup:
|
||||||
|
let realParam = c.p.owner.typ.n[s.position+1]
|
||||||
|
internalAssert realParam.kind == nkSym and realParam.sym.kind == skParam
|
||||||
|
return newSymNode(c.p.owner.typ.n[s.position+1].sym, n.info)
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
# We cannot check for access to outer vars for example because it's still
|
# We cannot check for access to outer vars for example because it's still
|
||||||
# not sure the symbol really ends up being used:
|
# not sure the symbol really ends up being used:
|
||||||
|
|
|
||||||
|
|
@ -1049,6 +1049,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
|
if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
|
||||||
if not usePseudoGenerics: paramsTypeCheck(c, s.typ)
|
if not usePseudoGenerics: paramsTypeCheck(c, s.typ)
|
||||||
pushProcCon(c, s)
|
pushProcCon(c, s)
|
||||||
|
c.p.wasForwarded = proto != nil
|
||||||
maybeAddResult(c, s, n)
|
maybeAddResult(c, s, n)
|
||||||
if sfImportc notin s.flags:
|
if sfImportc notin s.flags:
|
||||||
# no semantic checking for importc:
|
# no semantic checking for importc:
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
|
||||||
|
|
||||||
proc isTemplParam(c: TemplCtx, n: PNode): bool {.inline.} =
|
proc isTemplParam(c: TemplCtx, n: PNode): bool {.inline.} =
|
||||||
result = n.kind == nkSym and n.sym.kind == skParam and
|
result = n.kind == nkSym and n.sym.kind == skParam and
|
||||||
n.sym.owner == c.owner
|
n.sym.owner == c.owner and sfGenSym notin n.sym.flags
|
||||||
|
|
||||||
proc semTemplBody(c: var TemplCtx, n: PNode): PNode
|
proc semTemplBody(c: var TemplCtx, n: PNode): PNode
|
||||||
|
|
||||||
|
|
@ -246,8 +246,8 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
|
||||||
n.sons[i] = semTemplBody(c, n.sons[i])
|
n.sons[i] = semTemplBody(c, n.sons[i])
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
|
|
||||||
proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind) =
|
proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind; start=0) =
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(start, sonsLen(n) - 1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if a.kind == nkCommentStmt: continue
|
if a.kind == nkCommentStmt: continue
|
||||||
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a)
|
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a)
|
||||||
|
|
@ -348,6 +348,10 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
a.sons[L-1] = semTemplBodyScope(c, a.sons[L-1])
|
a.sons[L-1] = semTemplBodyScope(c, a.sons[L-1])
|
||||||
of nkVarSection: semTemplSomeDecl(c, n, skVar)
|
of nkVarSection: semTemplSomeDecl(c, n, skVar)
|
||||||
of nkLetSection: semTemplSomeDecl(c, n, skLet)
|
of nkLetSection: semTemplSomeDecl(c, n, skLet)
|
||||||
|
of nkFormalParams:
|
||||||
|
checkMinSonsLen(n, 1)
|
||||||
|
n.sons[0] = semTemplBody(c, n.sons[0])
|
||||||
|
semTemplSomeDecl(c, n, skParam, 1)
|
||||||
of nkConstSection:
|
of nkConstSection:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
|
|
@ -485,6 +489,11 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||||
# process parameters:
|
# process parameters:
|
||||||
if n.sons[paramsPos].kind != nkEmpty:
|
if n.sons[paramsPos].kind != nkEmpty:
|
||||||
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
|
||||||
|
# case as we determine whether it's a template parameter in the template
|
||||||
|
# body by the absense of the skGenSym flag:
|
||||||
|
for i in 1 .. s.typ.n.len-1:
|
||||||
|
s.typ.n.sons[i].sym.flags.excl sfGenSym
|
||||||
if sonsLen(gp) > 0:
|
if sonsLen(gp) > 0:
|
||||||
if n.sons[genericParamsPos].kind == nkEmpty:
|
if n.sons[genericParamsPos].kind == nkEmpty:
|
||||||
# we have a list of implicit type parameters:
|
# we have a list of implicit type parameters:
|
||||||
|
|
|
||||||
14
tests/template/tparams_gensymed.nim
Normal file
14
tests/template/tparams_gensymed.nim
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
# bug #1915
|
||||||
|
|
||||||
|
import macros
|
||||||
|
|
||||||
|
# Test that parameters are properly gensym'ed finally:
|
||||||
|
|
||||||
|
template genNodeKind(kind, name: expr): stmt =
|
||||||
|
proc name*(children: varargs[PNimrodNode]): PNimrodNode {.compiletime.}=
|
||||||
|
result = newNimNode(kind)
|
||||||
|
for c in children:
|
||||||
|
result.add(c)
|
||||||
|
|
||||||
|
genNodeKind(nnkNone, None)
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -3,6 +3,9 @@ version 0.10
|
||||||
|
|
||||||
- The bitwise 'not' operator will be renamed to 'bnot' to
|
- The bitwise 'not' operator will be renamed to 'bnot' to
|
||||||
prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!
|
prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!
|
||||||
|
- parameter lists without type end up in 'experimental'
|
||||||
|
- iterators always require a return type
|
||||||
|
- revert tuple behaviour
|
||||||
|
|
||||||
- c2nim depends on the compiler
|
- c2nim depends on the compiler
|
||||||
- make nimble part of the distribution
|
- make nimble part of the distribution
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue