summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2019-02-18 15:23:43 +0100
committerAndreas Rumpf <rumpf_a@web.de>2019-02-18 15:23:43 +0100
commitc8cb5679381b7e00fdfbdfd4fdd24b8794fdb84d (patch)
treedf54e0b909b09dc124e941faa6774bcd331dfdc2
parent739dc8094e4a4f6dd2f0eb0fb2eb8ce8191cb001 (diff)
parent2deb1e354fb7eba063c125579af04911f14382ed (diff)
downloadNim-c8cb5679381b7e00fdfbdfd4fdd24b8794fdb84d.tar.gz
Merge branch 'devel' of github.com:nim-lang/Nim into devel
-rw-r--r--compiler/pragmas.nim28
-rw-r--r--compiler/semstmts.nim41
-rw-r--r--koch.nim8
-rw-r--r--lib/core/macros.nim2
-rw-r--r--tests/macros/tmacrotypes.nim34
-rw-r--r--tests/pragmas/tcustom_pragma.nim7
6 files changed, 85 insertions, 35 deletions
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 3b6f82c40..9b3c66104 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -719,26 +719,34 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
     result = qualifiedLookUp(c, n, {checkUndeclared})
 
 proc semCustomPragma(c: PContext, n: PNode): PNode =
+  var callNode: PNode
+
   if n.kind == nkIdent:
-    result = newTree(nkCall, n)
+    # pragma -> pragma()
+    callNode = newTree(nkCall, n)
   elif n.kind == nkExprColonExpr:
     # pragma: arg -> pragma(arg)
-    result = newTree(nkCall, n[0], n[1])
+    callNode = newTree(nkCall, n[0], n[1])
   elif n.kind in nkPragmaCallKinds:
-    result = n
+    callNode = n
   else:
     invalidPragma(c, n)
     return n
 
-  let r = c.semOverloadedCall(c, result, n, {skTemplate}, {efNoUndeclared})
+  let r = c.semOverloadedCall(c, callNode, n, {skTemplate}, {efNoUndeclared})
+
   if r.isNil or sfCustomPragma notin r[0].sym.flags:
     invalidPragma(c, n)
-  else:
-    result = r
-    if n.kind == nkIdent:
-      result = result[0]
-    elif n.kind == nkExprColonExpr:
-      result.kind = n.kind # pragma(arg) -> pragma: arg
+    return n
+
+  result = r
+  # Transform the nkCall node back to its original form if possible
+  if n.kind == nkIdent and r.len == 1:
+    # pragma() -> pragma
+    result = result[0]
+  elif n.kind == nkExprColonExpr and r.len == 2:
+    # pragma(arg) -> pragma: arg
+    result.kind = n.kind
 
 proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
                   validPragmas: TSpecialWords, comesFromPush: bool) : bool =
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 5b7556b2e..cd570caad 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1136,7 +1136,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       # its evaluated result here so that we don't execute it once again in the
       # final pass
       if a[2].kind in nkCallKinds:
-        a[2] = newNodeIT(nkType, a[2].info, t)
+        incl a[2].flags, nfSem # bug #10548
     if sfExportc in s.flags and s.typ.kind == tyAlias:
       localError(c.config, name.info, "{.exportc.} not allowed for type aliases")
     let aa = a.sons[2]
@@ -1191,24 +1191,27 @@ proc typeSectionFinalPass(c: PContext, n: PNode) =
     # compute the type's size and check for illegal recursions:
     if a.sons[1].kind == nkEmpty:
       var x = a[2]
-      while x.kind in {nkStmtList, nkStmtListExpr} and x.len > 0:
-        x = x.lastSon
-      if x.kind notin {nkObjectTy, nkDistinctTy, nkEnumTy, nkEmpty} and
-          s.typ.kind notin {tyObject, tyEnum}:
-        # type aliases are hard:
-        var t = semTypeNode(c, x, nil)
-        assert t != nil
-        if s.typ != nil and s.typ.kind notin {tyAlias, tySink}:
-          if t.kind in {tyProc, tyGenericInst} and not t.isMetaType:
-            assignType(s.typ, t)
-            s.typ.id = t.id
-          elif t.kind in {tyObject, tyEnum, tyDistinct}:
-            assert s.typ != nil
-            assignType(s.typ, t)
-            s.typ.id = t.id     # same id
-      checkConstructedType(c.config, s.info, s.typ)
-      if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil:
-        checkForMetaFields(c, s.typ.n)
+      if x.kind in nkCallKinds and nfSem in x.flags:
+        discard "already semchecked, see line marked with bug #10548"
+      else:
+        while x.kind in {nkStmtList, nkStmtListExpr} and x.len > 0:
+          x = x.lastSon
+        if x.kind notin {nkObjectTy, nkDistinctTy, nkEnumTy, nkEmpty} and
+            s.typ.kind notin {tyObject, tyEnum}:
+          # type aliases are hard:
+          var t = semTypeNode(c, x, nil)
+          assert t != nil
+          if s.typ != nil and s.typ.kind notin {tyAlias, tySink}:
+            if t.kind in {tyProc, tyGenericInst} and not t.isMetaType:
+              assignType(s.typ, t)
+              s.typ.id = t.id
+            elif t.kind in {tyObject, tyEnum, tyDistinct}:
+              assert s.typ != nil
+              assignType(s.typ, t)
+              s.typ.id = t.id     # same id
+        checkConstructedType(c.config, s.info, s.typ)
+        if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil:
+          checkForMetaFields(c, s.typ.n)
   instAllTypeBoundOp(c, n.info)
 
 
diff --git a/koch.nim b/koch.nim
index 5deda5ecd..ac95c1566 100644
--- a/koch.nim
+++ b/koch.nim
@@ -291,13 +291,14 @@ proc boot(args: string) =
                       hostOs & "_" & hostCpu
 
   let nimStart = findStartNim()
-  copyExe(nimStart, 0.thVersion)
   for i in 0..2:
     let defaultCommand = if useCpp: "cpp" else: "c"
     let bootOptions = if args.len == 0 or args.startsWith("-"): defaultCommand else: ""
     echo "iteration: ", i+1
     var extraOption = ""
+    var nimi = i.thVersion
     if i == 0:
+      nimi = nimStart
       extraOption.add " --skipUserCfg --skipParentCfg"
         # The configs are skipped for bootstrap
         # (1st iteration) to prevent newer flags from breaking bootstrap phase.
@@ -307,8 +308,9 @@ proc boot(args: string) =
       if version.startsWith "Nim Compiler Version 0.19.0":
         extraOption.add " -d:nimBoostrapCsources0_19_0"
         # remove this when csources get updated
-    exec i.thVersion & " $# $# $# --nimcache:$# compiler" / "nim.nim" %
-      [bootOptions, extraOption, args, smartNimcache]
+
+    exec "$# $# $# $# --nimcache:$# compiler" / "nim.nim" %
+      [nimi, bootOptions, extraOption, args, smartNimcache]
     if sameFileContent(output, i.thVersion):
       copyExe(output, finalDest)
       echo "executables are equal: SUCCESS!"
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 43e61d660..7ec1eefc6 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -1515,7 +1515,7 @@ macro getCustomPragmaVal*(n: typed, cp: typed{nkSym}): untyped =
       else:
         let def = p[0].getImpl[3]
         result = newTree(nnkPar)
-        for i in 1..<p.len:
+        for i in 1 ..< def.len:
           let key = def[i][0]
           let val = p[i]
           result.add newTree(nnkExprColonExpr, key, val)
diff --git a/tests/macros/tmacrotypes.nim b/tests/macros/tmacrotypes.nim
index b4d708240..ab8bcfa95 100644
--- a/tests/macros/tmacrotypes.nim
+++ b/tests/macros/tmacrotypes.nim
@@ -14,10 +14,10 @@ macro checkType(ex: typed; expected: string): untyped =
 macro checkProcType(fn: typed): untyped =
   let fn_sym = if fn.kind == nnkProcDef: fn[0] else: fn
   echo fn_sym, "; ", fn_sym.typeKind, "; ", fn_sym.getType.repr, "; ", fn_sym.getTypeImpl.repr
-  
+
 
 proc voidProc = echo "hello"
-proc intProc(a: int, b: float): int {.checkProcType.} = 10 
+proc intProc(a: int, b: float): int {.checkProcType.} = 10
 
 checkType(voidProc(), "void")
 checkType(intProc(10, 20.0), "int")
@@ -38,3 +38,33 @@ block:
     Club = Blub
 
   static: doAssert(c == 1)
+
+# bug #10702
+type
+  VectorElementType = SomeNumber | bool
+  Vec*[N : static[int], T: VectorElementType] = object
+    arr*: array[N, T]
+
+type
+  Vec4*[T: VectorElementType] = Vec[4,T]
+  Vec3*[T: VectorElementType] = Vec[3,T]
+  Vec2*[T: VectorElementType] = Vec[2,T]
+
+template vecGen(U:untyped,V:typed):typed=
+  ## ``U`` suffix
+  ## ``V`` valType
+  ##
+  type
+    `Vec2 U`* {.inject.} = Vec2[V]
+    `Vec3 U`* {.inject.} = Vec3[V]
+    `Vec4 U`* {.inject.} = Vec4[V]
+
+vecGen(f, float32)
+
+macro foobar(arg: typed): untyped =
+  let typ = arg.getTypeInst
+  doAssert typ.getImpl[^1].kind == nnkCall
+
+var x: Vec2f
+
+foobar(x)
diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim
index 0dc85cf67..9f2fc024b 100644
--- a/tests/pragmas/tcustom_pragma.nim
+++ b/tests/pragmas/tcustom_pragma.nim
@@ -233,3 +233,10 @@ block:
   doAssert ps.first == ps[0] and ps.first == "one"
   doAssert ps.second == ps[1] and ps.second == 2
   doAssert ps.third == ps[2] and ps.third == 3.0
+
+# pragma with implicit&explicit generic types
+block:
+  template fooBar[T](x: T; c: static[int] = 42; m: char) {.pragma.}
+  var e {.fooBar("foo", 123, 'u').}: int
+  doAssert(hasCustomPragma(e, fooBar))
+  doAssert(getCustomPragmaVal(e, fooBar).c == 123)