summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/evaltempl.nim13
-rw-r--r--compiler/semexprs.nim2
-rw-r--r--compiler/semtempl.nim11
-rw-r--r--compiler/semtypes.nim5
4 files changed, 30 insertions, 1 deletions
diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim
index 5895368bb..77c136d63 100644
--- a/compiler/evaltempl.nim
+++ b/compiler/evaltempl.nim
@@ -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 like template body
+      # 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)
 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 1307b0ab7..a83da5849 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -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} != {})
 
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index aef0ce9b3..7546d095d 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -743,6 +743,17 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
     c: c,
     owner: s
   )
+  # handle default params:
+  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:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 5faefc9aa..8cba88747 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1365,6 +1365,11 @@ 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):
+          # template default value depends on other parameter
+          # don't do any typechecking
+          def.typ = makeTypeFromExpr(c, def.copyTree)
+          break determineType
         let isGeneric = isCurrentlyGeneric()
         inc c.inGenericContext, ord(isGeneric)
         def = semExprWithType(c, def, {efDetermineType, efAllowSymChoice}, typ)