mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-07 04:14:19 +00:00
fixes #1915
This commit is contained in:
@@ -1977,7 +1977,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
of skParam:
|
||||
if sym.loc.r == nil or sym.loc.t == nil:
|
||||
#echo "FAILED FOR PRCO ", p.prc.name.s
|
||||
internalError(n.info, "expr: param not init " & sym.name.s & "_" & $sym.id)
|
||||
#debug p.prc.typ.n
|
||||
#echo renderTree(p.prc.ast, {renderIds})
|
||||
internalError(n.info, "expr: param not init " & sym.name.s & "_" & $sym.id)
|
||||
putLocIntoDest(p, d, sym.loc)
|
||||
else: internalError(n.info, "expr(" & $sym.kind & "); unknown symbol")
|
||||
of nkNilLit:
|
||||
|
||||
@@ -29,7 +29,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||
of nkSym:
|
||||
var s = templ.sym
|
||||
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]
|
||||
if x.kind == nkArgList:
|
||||
for y in items(x): result.add(y)
|
||||
|
||||
@@ -35,6 +35,7 @@ type
|
||||
inTryStmt*: int # whether we are in a try statement; works also
|
||||
# in standalone ``except`` and ``finally``
|
||||
next*: PProcCon # used for stacking procedure contexts
|
||||
wasForwarded*: bool # whether the current proc has a separate header
|
||||
|
||||
TInstantiationPair* = object
|
||||
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 sfGlobal in s.flags:
|
||||
incl(c.p.owner.flags, sfSideEffect)
|
||||
elif s.kind == skParam and s.typ.kind == tyStatic and s.typ.n != nil:
|
||||
# XXX see the hack in sigmatch.nim ...
|
||||
return s.typ.n
|
||||
elif s.kind == skParam:
|
||||
if s.typ.kind == tyStatic and s.typ.n != nil:
|
||||
# XXX see the hack in sigmatch.nim ...
|
||||
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)
|
||||
# We cannot check for access to outer vars for example because it's still
|
||||
# not sure the symbol really ends up being used:
|
||||
|
||||
@@ -982,7 +982,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
# process parameters:
|
||||
if n.sons[paramsPos].kind != nkEmpty:
|
||||
semParamList(c, n.sons[paramsPos], gp, s)
|
||||
if sonsLen(gp) > 0:
|
||||
if sonsLen(gp) > 0:
|
||||
if n.sons[genericParamsPos].kind == nkEmpty:
|
||||
# we have a list of implicit type parameters:
|
||||
n.sons[genericParamsPos] = gp
|
||||
@@ -1049,6 +1049,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
|
||||
if not usePseudoGenerics: paramsTypeCheck(c, s.typ)
|
||||
pushProcCon(c, s)
|
||||
c.p.wasForwarded = proto != nil
|
||||
maybeAddResult(c, s, n)
|
||||
if sfImportc notin s.flags:
|
||||
# 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.} =
|
||||
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
|
||||
|
||||
@@ -246,8 +246,8 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
|
||||
n.sons[i] = semTemplBody(c, n.sons[i])
|
||||
closeScope(c)
|
||||
|
||||
proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind) =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind; start=0) =
|
||||
for i in countup(start, sonsLen(n) - 1):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
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])
|
||||
of nkVarSection: semTemplSomeDecl(c, n, skVar)
|
||||
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:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var a = n.sons[i]
|
||||
@@ -485,6 +489,11 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
# process parameters:
|
||||
if n.sons[paramsPos].kind != nkEmpty:
|
||||
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 n.sons[genericParamsPos].kind == nkEmpty:
|
||||
# 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
|
||||
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
|
||||
- make nimble part of the distribution
|
||||
|
||||
Reference in New Issue
Block a user