Skip to content

Commit

Permalink
test template default values using other params
Browse files Browse the repository at this point in the history
  • Loading branch information
metagn committed Sep 10, 2024
1 parent baec195 commit 9646bfa
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 1 deletion.
13 changes: 13 additions & 0 deletions compiler/evaltempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
let x = param
if x.kind == nkArgList:
for y in items(x): result.add(y)
elif nfDefaultRefsParam in x.flags:
# value of default param needs to be evaluated
# if it contains other template params
var res: PNode
if isAtom(x):
res = newNodeI(nkPar, x.info)
evalTemplateAux(x, actual, c, res)
if res.len == 1: res = res[0]
else:
res = copyNode(x)
for i in 0..<x.safeLen:
evalTemplateAux(x[i], actual, c, res)
result.add res
else:
result.add copyTree(x)

Expand Down
2 changes: 1 addition & 1 deletion compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ proc isUnresolvedSym(s: PSym): bool =
result = s.kind == skGenericParam
if not result and s.typ != nil:
result = tfInferrableStatic in s.typ.flags or
(s.kind == skParam and s.typ.isMetaType) or
(s.kind == skParam and (s.typ.isMetaType or sfTemplateParam in s.flags)) or
(s.kind == skType and
s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} != {})

Expand Down
10 changes: 10 additions & 0 deletions compiler/semtempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,16 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
c: c,
owner: s
)
for i in 1..<s.typ.n.len:
let param = s.typ.n[i].sym
if param.ast != nil:
# param default values need to be treated like template body:
if sfDirty in s.flags:
param.ast = semTemplBodyDirty(ctx, param.ast)
else:
param.ast = semTemplBody(ctx, param.ast)
if param.ast.referencesAnotherParam(s):
param.ast.flags.incl nfDefaultRefsParam
if sfDirty in s.flags:
n[bodyPos] = semTemplBodyDirty(ctx, n[bodyPos])
else:
Expand Down
3 changes: 3 additions & 0 deletions compiler/semtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
"either use ';' (semicolon) or explicitly write each default value")
message(c.config, a.info, warnImplicitDefaultValue, msg)
block determineType:
if kind == skTemplate and hasUnresolvedArgs(c, def):
def.typ = makeTypeFromExpr(c, def.copyTree)
break determineType
let isGeneric = isCurrentlyGeneric()
inc c.inGenericContext, ord(isGeneric)
def = semExprWithType(c, def, {efDetermineType, efAllowSymChoice}, typ)
Expand Down
15 changes: 15 additions & 0 deletions tests/template/tdefaultparam.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
block:
template foo(a: untyped, b: untyped = a(0)): untyped =
let x = a(0)
let y = b
(x, y)
proc bar(x: int): int = x + 1
doAssert foo(bar, b = bar(0)) == (1, 1)
doAssert foo(bar) == (1, 1)

block: # issue #23506
var a: string
template foo(x: int; y = x) =
a = $($x, $y)
foo(1)
doAssert a == "(\"1\", \"1\")"

0 comments on commit 9646bfa

Please sign in to comment.