summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAdam Strzelecki <ono@java.pl>2015-06-02 21:29:28 +0200
committerAdam Strzelecki <ono@java.pl>2015-06-02 21:38:53 +0200
commit13b57dbc2f686ba9beb410ad9fef848926de38c5 (patch)
tree4f876def309e15da3baf0ad9f141e5f34b587995 /compiler
parent79c92603f505c388d370c5ef0dd8890e4e17e4e0 (diff)
downloadNim-13b57dbc2f686ba9beb410ad9fef848926de38c5.tar.gz
Introduce {.noRewrite.} expr pragma disabling TR
Term rewriting macros/templates are currently greedy and they will rewrite as
long as there is a match. So there was no way to ensure some rewrite happens
only once, eg. when rewriting term to same term plus extra content.

With new macro we can actually prevent further rewriting on marked expr or
stmts, eg. with given example echo(...) will be rewritten just once:

  template pwnEcho{echo(x)}(x: expr) =
    {.noRewrite.}: echo("pwned!")

  echo "ab"
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim1
-rw-r--r--compiler/patterns.nim4
-rw-r--r--compiler/pragmas.nim4
-rw-r--r--compiler/semstmts.nim2
-rw-r--r--compiler/wordrecg.nim4
5 files changed, 11 insertions, 4 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 64cb1b1bc..52ba93565 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -423,6 +423,7 @@ type
                 # but unfortunately it has measurable impact for compilation
                 # efficiency
     nfTransf,   # node has been transformed
+    nfNoRewrite # node should not be transformed anymore
     nfSem       # node has been checked for semantics
     nfLL        # node has gone through lambda lifting
     nfDotField  # the call can use a dot operator
diff --git a/compiler/patterns.nim b/compiler/patterns.nim
index 368b0b37b..3f8b05940 100644
--- a/compiler/patterns.nim
+++ b/compiler/patterns.nim
@@ -130,7 +130,9 @@ proc matchNested(c: PPatternContext, p, n: PNode, rpn: bool): bool =
 
 proc matches(c: PPatternContext, p, n: PNode): bool =
   # hidden conversions (?)
-  if isPatternParam(c, p):
+  if nfNoRewrite in n.flags:
+    result = false
+  elif isPatternParam(c, p):
     result = bindOrCheck(c, p.sym, n)
   elif n.kind == nkSym and p.kind == nkIdent:
     result = p.ident.id == n.sym.name.id
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index c048d78e9..6f37fe756 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -37,7 +37,7 @@ const
     wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
     wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
     wTags, wLocks, wGcSafe}
-  exprPragmas* = {wLine, wLocks}
+  exprPragmas* = {wLine, wLocks, wNoRewrite}
   stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
     wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
     wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
@@ -859,6 +859,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
             c.module.flags.incl sfExperimental
           else:
             localError(it.info, "'experimental' pragma only valid as toplevel statement")
+        of wNoRewrite:
+          noVal(it)
         else: invalidPragma(it)
       else: invalidPragma(it)
   else: processNote(c, it)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index c355a5bf1..43cdca866 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1268,6 +1268,8 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
     of wLocks:
       result = n
       result.typ = n.sons[1].typ
+    of wNoRewrite:
+      incl(result.flags, nfNoRewrite)
     else: discard
 
 proc semStaticStmt(c: PContext, n: PNode): PNode =
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 63fd995c4..deb12536f 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -55,7 +55,7 @@ type
     wFloatchecks, wNanChecks, wInfChecks,
     wAssertions, wPatterns, wWarnings,
     wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags,
-    wDeadCodeElim, wSafecode, wNoForward,
+    wDeadCodeElim, wSafecode, wNoForward, wNoRewrite,
     wPragma,
     wCompileTime, wNoInit,
     wPassc, wPassl, wBorrow, wDiscardable,
@@ -139,7 +139,7 @@ const
 
     "assertions", "patterns", "warnings", "hints",
     "optimization", "raises", "writes", "reads", "size", "effects", "tags",
-    "deadcodeelim", "safecode", "noforward",
+    "deadcodeelim", "safecode", "noforward", "norewrite",
     "pragma",
     "compiletime", "noinit",
     "passc", "passl", "borrow", "discardable", "fieldchecks",