diff options
author | Adam Strzelecki <ono@java.pl> | 2015-06-02 21:29:28 +0200 |
---|---|---|
committer | Adam Strzelecki <ono@java.pl> | 2015-06-02 21:38:53 +0200 |
commit | 13b57dbc2f686ba9beb410ad9fef848926de38c5 (patch) | |
tree | 4f876def309e15da3baf0ad9f141e5f34b587995 /compiler | |
parent | 79c92603f505c388d370c5ef0dd8890e4e17e4e0 (diff) | |
download | Nim-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.nim | 1 | ||||
-rw-r--r-- | compiler/patterns.nim | 4 | ||||
-rw-r--r-- | compiler/pragmas.nim | 4 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | compiler/wordrecg.nim | 4 |
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", |