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"
This commit is contained in:
Adam Strzelecki
2015-06-02 21:29:28 +02:00
parent 79c92603f5
commit 13b57dbc2f
5 changed files with 11 additions and 4 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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 =

View File

@@ -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",