summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2018-12-12 10:15:25 +0100
committerGitHub <noreply@github.com>2018-12-12 10:15:25 +0100
commitd9ae9201c442f2e1427140283f3eab77b4f8c70c (patch)
tree5c3d7de95238b830969bf2e6f698fb2074d4a725
parent3a70d18b84d777b9c38f33692d3bf2aa1c0d1a85 (diff)
parent1d16676dd6a31de03bfc87a5dfdee482b27b51b5 (diff)
downloadNim-d9ae9201c442f2e1427140283f3eab77b4f8c70c.tar.gz
Merge pull request #9937 from cooldome/pragmablock_custom_pragma
Language feature: implement custom pragmas in pragma blocks
-rw-r--r--changelog.md3
-rw-r--r--compiler/pragmas.nim4
-rw-r--r--compiler/semstmts.nim12
-rw-r--r--tests/pragmas/tcustom_pragma.nim22
4 files changed, 32 insertions, 9 deletions
diff --git a/changelog.md b/changelog.md
index 9c1b218f5..62450d58e 100644
--- a/changelog.md
+++ b/changelog.md
@@ -113,6 +113,9 @@ proc enumToString*(enums: openArray[enum]): string =
 - There is a new pragma block `noSideEffect` that works like
   the `gcsafe` pragma block.
 - added os.getCurrentProcessId()
+- User defined pragmas are now allowed in the pragma blocks
+- Pragma blocks are now longer eliminated from the typed AST tree to preserve
+  pragmas for further analysis by macros
 
 ### Language changes
 
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 247f6ad54..f67e74f11 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -1111,8 +1111,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
         else: sym.flags.incl sfUsed
       of wLiftLocals: discard
       else: invalidPragma(c, it)
-    elif sym != nil and sym.kind in {skVar, skLet, skParam, skField, skProc,
-                                     skFunc, skConverter, skMethod, skType}:
+    elif sym == nil or (sym != nil and sym.kind in {skVar, skLet, skParam, 
+                      skField, skProc, skFunc, skConverter, skMethod, skType}):
       n.sons[i] = semCustomPragma(c, it)
     elif sym != nil:
       illegalCustomPragma(c, it, sym)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 04fe91cfb..aec03b492 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1876,18 +1876,16 @@ proc setLine(n: PNode, info: TLineInfo) =
   n.info = info
 
 proc semPragmaBlock(c: PContext, n: PNode): PNode =
+  checkSonsLen(n, 2, c.config)
   let pragmaList = n.sons[0]
   pragma(c, nil, pragmaList, exprPragmas)
-  result = semExpr(c, n.sons[1])
-  n.sons[1] = result
+  n[1] = semExpr(c, n[1])
+  result = n
+  result.typ = n[1].typ
   for i in 0 ..< pragmaList.len:
     case whichPragma(pragmaList.sons[i])
     of wLine: setLine(result, pragmaList.sons[i].info)
-    of wLocks, wGcSafe, wNosideeffect:
-      result = n
-      result.typ = n.sons[1].typ
-    of wNoRewrite:
-      incl(result.flags, nfNoRewrite)
+    of wNoRewrite: incl(result.flags, nfNoRewrite)
     else: discard
 
 proc semStaticStmt(c: PContext, n: PNode): PNode =
diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim
index ae0f39631..0bc4d2f18 100644
--- a/tests/pragmas/tcustom_pragma.nim
+++ b/tests/pragmas/tcustom_pragma.nim
@@ -174,3 +174,25 @@ type
 var foo: Something
 foo.cardinal = north
 doAssert foo.b.hasCustomPragma(thingy) == true
+
+
+proc myproc(s: string): int = 
+  {.thingy.}:
+    s.len
+
+doAssert myproc("123") == 3
+
+let xx = compiles:
+  proc myproc_bad(s: string): int = 
+    {.not_exist.}:
+      s.len
+doAssert: xx == false
+
+
+macro checkSym(s: typed{nkSym}): untyped = 
+  let body = s.getImpl.body
+  doAssert body[1].kind == nnkPragmaBlock
+  doAssert body[1][0].kind == nnkPragma
+  doAssert body[1][0][0] == bindSym"thingy"
+
+checkSym(myproc)
\ No newline at end of file