summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorSaem Ghani <saemghani+github@gmail.com>2021-03-22 04:46:34 -0700
committerGitHub <noreply@github.com>2021-03-22 12:46:34 +0100
commite5873b3a9300897443f0f2e2db128e3463089003 (patch)
treecce53a09190b9cc2ee5bdec6fdb50338507a550e
parentc8dda867f2a2607d4049759d09593a66b1697d02 (diff)
downloadNim-e5873b3a9300897443f0f2e2db128e3463089003.tar.gz
semTemplateDef and t17433 clean-ups (#17448)
- use `doAssert` in t17433
- use setGenericParamsMisc in semTemplateDef akin to semProcAux
- pragma handling in semTemplateDef inline with semProcAux
-rw-r--r--compiler/sem.nim24
-rw-r--r--compiler/semstmts.nim18
-rw-r--r--compiler/semtempl.nim38
-rw-r--r--tests/template/t17433.nim6
4 files changed, 44 insertions, 42 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 5593f8b02..bb42b5c1b 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -485,11 +485,31 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode =
   if result.kind != nkIntLit:
     localError(c.config, n.info, errConstExprExpected)
 
-
 proc semGenericStmt(c: PContext, n: PNode): PNode
 proc semConceptBody(c: PContext, n: PNode): PNode
 
-include semtypes, semtempl, semgnrc, semstmts, semexprs
+include semtypes
+
+proc setGenericParamsMisc(c: PContext; n: PNode) =
+  ## used by call defs (procs, templates, macros, ...) to analyse their generic
+  ## params, and store the originals in miscPos for better error reporting.
+  let orig = n[genericParamsPos]
+
+  doAssert orig.kind in {nkEmpty, nkGenericParams}
+
+  if n[genericParamsPos].kind == nkEmpty:
+    n[genericParamsPos] = newNodeI(nkGenericParams, n.info)
+  else:
+    # we keep the original params around for better error messages, see
+    # issue https://github.com/nim-lang/Nim/issues/1713
+    n[genericParamsPos] = semGenericParamList(c, orig)
+
+  if n[miscPos].kind == nkEmpty:
+    n[miscPos] = newTree(nkBracket, c.graph.emptyNode, orig)
+  else:
+    n[miscPos][1] = orig
+
+include semtempl, semgnrc, semstmts, semexprs
 
 proc addCodeForGenerics(c: PContext, n: PNode) =
   for i in c.lastGenericIdx..<c.generics.len:
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index a98103478..ff8f68ed0 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1769,23 +1769,6 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
     else:
       localError(c.config, n.info, "'method' needs a parameter that has an object type")
 
-proc setGenericParamsMisc(c: PContext; n: PNode) =
-  let orig = n[genericParamsPos]
-
-  doAssert orig.kind in {nkEmpty, nkGenericParams}
-
-  if n[genericParamsPos].kind == nkEmpty:
-    n[genericParamsPos] = newNodeI(nkGenericParams, n.info)
-  else:
-    # we keep the original params around for better error messages, see
-    # issue https://github.com/nim-lang/Nim/issues/1713
-    n[genericParamsPos] = semGenericParamList(c, orig)
-
-  if n[miscPos].kind == nkEmpty:
-    n[miscPos] = newTree(nkBracket, c.graph.emptyNode, orig)
-  else:
-    n[miscPos][1] = orig
-
 proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
                 validPragmas: TSpecialWords, flags: TExprFlags = {}): PNode =
   result = semProcAnnotation(c, n, validPragmas)
@@ -1839,7 +1822,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
 
   if n[paramsPos].kind != nkEmpty:
     semParamList(c, n[paramsPos], n[genericParamsPos], s)
-    # we maybe have implicit type parameters:
   else:
     s.typ = newProcType(c, n.info)
 
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index 4bb9f3e6b..40502daf4 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -595,12 +595,14 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
       result[i] = semTemplBodyDirty(c, n[i])
 
 proc semTemplateDef(c: PContext, n: PNode): PNode =
+  result = n
   var s: PSym
   if isTopLevel(c):
-    s = semIdentVis(c, skTemplate, n[0], {sfExported})
+    s = semIdentVis(c, skTemplate, n[namePos], {sfExported})
     incl(s.flags, sfGlobal)
   else:
-    s = semIdentVis(c, skTemplate, n[0], {})
+    s = semIdentVis(c, skTemplate, n[namePos], {})
+  assert s.kind == skTemplate
 
   if s.owner != nil:
     const names = ["!=", ">=", ">", "incl", "excl", "in", "notin", "isnot"]
@@ -608,26 +610,23 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
        s.owner.name.s == "vm" and s.name.s == "stackTrace":
       incl(s.flags, sfCallsite)
 
+  s.ast = n
+
   styleCheckDef(c.config, s)
-  onDef(n[0].info, s)
+  onDef(n[namePos].info, s)
   # check parameter list:
   #s.scope = c.currentScope
   pushOwner(c, s)
   openScope(c)
-  n[namePos] = newSymNode(s, n[namePos].info)
-  if n[pragmasPos].kind != nkEmpty:
-    pragma(c, s, n[pragmasPos], templatePragmas)
-
-  var gp: PNode
-  if n[genericParamsPos].kind != nkEmpty:
-    n[genericParamsPos] = semGenericParamList(c, n[genericParamsPos])
-    gp = n[genericParamsPos]
-  else:
-    gp = newNodeI(nkGenericParams, n.info)
+  n[namePos] = newSymNode(s)
+  pragmaCallable(c, s, n, templatePragmas)
+  implicitPragmas(c, s, n.info, templatePragmas)
+
+  setGenericParamsMisc(c, n)
   # process parameters:
   var allUntyped = true
   if n[paramsPos].kind != nkEmpty:
-    semParamList(c, n[paramsPos], gp, s)
+    semParamList(c, n[paramsPos], n[genericParamsPos], 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 absence of the sfGenSym flag:
@@ -636,18 +635,21 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
       param.flags.incl sfTemplateParam
       param.flags.excl sfGenSym
       if param.typ.kind != tyUntyped: allUntyped = false
-    if gp.len > 0 and n[genericParamsPos].kind == nkEmpty:
-      # we have a list of implicit type parameters:
-      n[genericParamsPos] = gp
   else:
     s.typ = newTypeS(tyProc, c)
     # XXX why do we need tyTyped as a return type again?
     s.typ.n = newNodeI(nkFormalParams, n.info)
     rawAddSon(s.typ, newTypeS(tyTyped, c))
     s.typ.n.add newNodeIT(nkType, n.info, s.typ[0])
+  if n[genericParamsPos].safeLen == 0:
+    # restore original generic type params as no explicit or implicit were found
+    n[genericParamsPos] = n[miscPos][1]
+    n[miscPos] = c.graph.emptyNode
   if allUntyped: incl(s.flags, sfAllUntyped)
+  
   if n[patternPos].kind != nkEmpty:
     n[patternPos] = semPattern(c, n[patternPos])
+  
   var ctx: TemplCtx
   ctx.toBind = initIntSet()
   ctx.toMixin = initIntSet()
@@ -662,8 +664,6 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
   semIdeForTemplateOrGeneric(c, n[bodyPos], ctx.cursorInBody)
   closeScope(c)
   popOwner(c)
-  s.ast = n
-  result = n
   if sfCustomPragma in s.flags:
     if n[bodyPos].kind != nkEmpty:
       localError(c.config, n[bodyPos].info, errImplOfXNotAllowed % s.name.s)
diff --git a/tests/template/t17433.nim b/tests/template/t17433.nim
index 121f3c471..053d33ff0 100644
--- a/tests/template/t17433.nim
+++ b/tests/template/t17433.nim
@@ -7,10 +7,10 @@
 from std/macros import expandMacros
 
 proc bar(a: typedesc): a = default(a)
-assert bar(float) == 0.0
-assert bar(string) == ""
+doAssert bar(float) == 0.0
+doAssert bar(string) == ""
 
 template main =
   proc baz(a: typedesc): a = default(a)
-  assert baz(float) == 0.0
+  doAssert baz(float) == 0.0
 main()