Merge branch 'nanoant-patch/fix-3496-generic-tmpl-args' into devel
This commit is contained in:
commit
ad1b34dc30
3 changed files with 107 additions and 11 deletions
|
|
@ -47,7 +47,7 @@ type
|
||||||
efLValue, efWantIterator, efInTypeof,
|
efLValue, efWantIterator, efInTypeof,
|
||||||
efWantStmt, efAllowStmt, efDetermineType,
|
efWantStmt, efAllowStmt, efDetermineType,
|
||||||
efAllowDestructor, efWantValue, efOperand, efNoSemCheck,
|
efAllowDestructor, efWantValue, efOperand, efNoSemCheck,
|
||||||
efNoProcvarCheck, efFromHlo
|
efNoProcvarCheck, efNoEvaluateGeneric, efInCall, efFromHlo
|
||||||
TExprFlags* = set[TExprFlag]
|
TExprFlags* = set[TExprFlag]
|
||||||
|
|
||||||
TTypeAttachedOp* = enum
|
TTypeAttachedOp* = enum
|
||||||
|
|
|
||||||
|
|
@ -717,6 +717,34 @@ proc resolveIndirectCall(c: PContext; n, nOrig: PNode;
|
||||||
initCandidate(c, result, t)
|
initCandidate(c, result, t)
|
||||||
matches(c, n, nOrig, result)
|
matches(c, n, nOrig, result)
|
||||||
|
|
||||||
|
proc bracketedMacro(n: PNode): PSym =
|
||||||
|
if n.len >= 1 and n[0].kind == nkSym:
|
||||||
|
result = n[0].sym
|
||||||
|
if result.kind notin {skMacro, skTemplate}:
|
||||||
|
result = nil
|
||||||
|
|
||||||
|
proc semBracketedMacro(c: PContext; outer, inner: PNode; s: PSym;
|
||||||
|
flags: TExprFlags): PNode =
|
||||||
|
# We received untransformed bracket expression coming from macroOrTmpl[].
|
||||||
|
# Transform it to macro or template call, where first come normal
|
||||||
|
# arguments, next come generic template arguments.
|
||||||
|
var sons = newSeq[PNode]()
|
||||||
|
sons.add inner.sons[0]
|
||||||
|
# Normal arguments:
|
||||||
|
for i in 1..<outer.len:
|
||||||
|
sons.add outer.sons[i]
|
||||||
|
# Generic template arguments from bracket expression:
|
||||||
|
for i in 1..<inner.len:
|
||||||
|
sons.add inner.sons[i]
|
||||||
|
shallowCopy(outer.sons, sons)
|
||||||
|
# FIXME: Shouldn't we check sfImmediate and call semDirectOp?
|
||||||
|
# However passing to semDirectOp doesn't work here.
|
||||||
|
case s.kind
|
||||||
|
of skMacro: result = semMacroExpr(c, outer, outer, s, flags)
|
||||||
|
of skTemplate: result = semTemplateExpr(c, outer, s, flags)
|
||||||
|
else: assert(false)
|
||||||
|
return
|
||||||
|
|
||||||
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
|
|
@ -732,10 +760,15 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
|
for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
|
||||||
return semExpr(c, result, flags)
|
return semExpr(c, result, flags)
|
||||||
else:
|
else:
|
||||||
n.sons[0] = semExpr(c, n.sons[0])
|
n.sons[0] = semExpr(c, n.sons[0], {efInCall})
|
||||||
let t = n.sons[0].typ
|
let t = n.sons[0].typ
|
||||||
if t != nil and t.kind == tyVar:
|
if t != nil and t.kind == tyVar:
|
||||||
n.sons[0] = newDeref(n.sons[0])
|
n.sons[0] = newDeref(n.sons[0])
|
||||||
|
elif n.sons[0].kind == nkBracketExpr:
|
||||||
|
let s = bracketedMacro(n.sons[0])
|
||||||
|
if s != nil:
|
||||||
|
return semBracketedMacro(c, n, n.sons[0], s, flags)
|
||||||
|
|
||||||
let nOrig = n.copyTree
|
let nOrig = n.copyTree
|
||||||
semOpAux(c, n)
|
semOpAux(c, n)
|
||||||
var t: PType = nil
|
var t: PType = nil
|
||||||
|
|
@ -965,8 +998,20 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
else: result = newSymNode(s, n.info)
|
else: result = newSymNode(s, n.info)
|
||||||
else:
|
else:
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
of skMacro: result = semMacroExpr(c, n, n, s, flags)
|
of skMacro:
|
||||||
of skTemplate: result = semTemplateExpr(c, n, s, flags)
|
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0:
|
||||||
|
markUsed(n.info, s)
|
||||||
|
styleCheckUse(n.info, s)
|
||||||
|
result = newSymNode(s, n.info)
|
||||||
|
else:
|
||||||
|
result = semMacroExpr(c, n, n, s, flags)
|
||||||
|
of skTemplate:
|
||||||
|
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0:
|
||||||
|
markUsed(n.info, s)
|
||||||
|
styleCheckUse(n.info, s)
|
||||||
|
result = newSymNode(s, n.info)
|
||||||
|
else:
|
||||||
|
result = semTemplateExpr(c, n, s, flags)
|
||||||
of skParam:
|
of skParam:
|
||||||
markUsed(n.info, s)
|
markUsed(n.info, s)
|
||||||
styleCheckUse(n.info, s)
|
styleCheckUse(n.info, s)
|
||||||
|
|
@ -1193,7 +1238,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result.add(x[0])
|
result.add(x[0])
|
||||||
return
|
return
|
||||||
checkMinSonsLen(n, 2)
|
checkMinSonsLen(n, 2)
|
||||||
n.sons[0] = semExprWithType(c, n.sons[0], {efNoProcvarCheck})
|
# make sure we don't evaluate generic macros/templates
|
||||||
|
n.sons[0] = semExprWithType(c, n.sons[0],
|
||||||
|
{efNoProcvarCheck, efNoEvaluateGeneric})
|
||||||
let arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
|
let arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
|
||||||
case arr.kind
|
case arr.kind
|
||||||
of tyArray, tyOpenArray, tyVarargs, tyArrayConstr, tySequence, tyString,
|
of tyArray, tyOpenArray, tyVarargs, tyArrayConstr, tySequence, tyString,
|
||||||
|
|
@ -1236,12 +1283,30 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
let s = if n.sons[0].kind == nkSym: n.sons[0].sym
|
let s = if n.sons[0].kind == nkSym: n.sons[0].sym
|
||||||
elif n[0].kind in nkSymChoices: n.sons[0][0].sym
|
elif n[0].kind in nkSymChoices: n.sons[0][0].sym
|
||||||
else: nil
|
else: nil
|
||||||
if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}:
|
if s != nil:
|
||||||
# type parameters: partial generic specialization
|
case s.kind
|
||||||
n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
|
of skProc, skMethod, skConverter, skIterator:
|
||||||
result = explicitGenericInstantiation(c, n, s)
|
# type parameters: partial generic specialization
|
||||||
elif s != nil and s.kind == skType:
|
n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
|
||||||
result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
|
result = explicitGenericInstantiation(c, n, s)
|
||||||
|
of skMacro, skTemplate:
|
||||||
|
if efInCall in flags:
|
||||||
|
# We are processing macroOrTmpl[] in macroOrTmpl[](...) call.
|
||||||
|
# Return as is, so it can be transformed into complete macro or
|
||||||
|
# template call in semIndirectOp caller.
|
||||||
|
result = n
|
||||||
|
else:
|
||||||
|
# We are processing macroOrTmpl[] not in call. Transform it to the
|
||||||
|
# macro or template call with generic arguments here.
|
||||||
|
n.kind = nkCall
|
||||||
|
case s.kind
|
||||||
|
of skMacro: result = semMacroExpr(c, n, n, s, flags)
|
||||||
|
of skTemplate: result = semTemplateExpr(c, n, s, flags)
|
||||||
|
else: discard
|
||||||
|
of skType:
|
||||||
|
result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
|
||||||
|
else:
|
||||||
|
c.p.bracketExpr = n.sons[0]
|
||||||
else:
|
else:
|
||||||
c.p.bracketExpr = n.sons[0]
|
c.p.bracketExpr = n.sons[0]
|
||||||
|
|
||||||
|
|
|
||||||
31
tests/generics/tgenerictmpl2.nim
Normal file
31
tests/generics/tgenerictmpl2.nim
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
discard """
|
||||||
|
output: '''1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
999
|
||||||
|
999
|
||||||
|
999
|
||||||
|
2'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
# test if we can pass explicit generic arguments to generic templates
|
||||||
|
# based on bug report #3496
|
||||||
|
|
||||||
|
proc tproc[T](t: T = 999) = echo t
|
||||||
|
template ttmpl[T](t: T = 999) = echo t
|
||||||
|
|
||||||
|
tproc(1)
|
||||||
|
tproc[int](1)
|
||||||
|
ttmpl(1)
|
||||||
|
ttmpl[int](1) #<- crash case #1
|
||||||
|
|
||||||
|
tproc[int]()
|
||||||
|
discard tproc[int]
|
||||||
|
ttmpl[int]() #<- crash case #2
|
||||||
|
ttmpl[int] #<- crash case #3
|
||||||
|
|
||||||
|
# but still allow normal use of [] on non-generic templates
|
||||||
|
|
||||||
|
template tarr: expr = [1, 2, 3, 4]
|
||||||
|
echo tarr[1]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue