improvements for TR macros

This commit is contained in:
Araq
2013-09-17 23:43:07 +02:00
parent 823cb494a5
commit 9de3bc8ef6
6 changed files with 53 additions and 21 deletions

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2012 Andreas Rumpf
# (c) Copyright 2013 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -30,8 +30,6 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
if optHints in gOptions and hintPattern in gNotes:
Message(orig.info, hintPattern, rule & " --> '" &
renderTree(result, {renderNoComments}) & "'")
# check the resulting AST for optimization rules again:
result = hlo(c, result)
proc applyPatterns(c: PContext, n: PNode): PNode =
result = n
@@ -44,11 +42,12 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
let x = applyRule(c, pattern, result)
if not isNil(x):
assert x.kind in {nkStmtList, nkCall}
# better be safe than sorry, so check evalTemplateCounter too:
inc(evalTemplateCounter)
if evalTemplateCounter > 100:
GlobalError(n.info, errTemplateInstantiationTooNested)
# deactivate this pattern:
c.patterns[i] = nil
#c.patterns[i] = nil
if x.kind == nkStmtList:
assert x.len == 3
x.sons[1] = evalPattern(c, x.sons[1], result)
@@ -57,9 +56,12 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
result = evalPattern(c, x, result)
dec(evalTemplateCounter)
# activate this pattern again:
c.patterns[i] = pattern
#c.patterns[i] = pattern
proc hlo(c: PContext, n: PNode): PNode =
inc(c.hloLoopDetector)
# simply stop and do not perform any further transformations:
if c.hloLoopDetector > 300: result = n
case n.kind
of nkMacroDef, nkTemplateDef, procDefs:
# already processed (special cases in semstmts.nim)
@@ -74,18 +76,23 @@ proc hlo(c: PContext, n: PNode): PNode =
if h != a: result.sons[i] = h
else:
# perform type checking, so that the replacement still fits:
if n.typ == nil and (result.typ == nil or
result.typ.kind in {tyStmt, tyEmpty}):
if isEmptyType(n.typ) and isEmptyType(result.typ):
nil
else:
result = fitNode(c, n.typ, result)
# optimization has been applied so check again:
result = commonOptimizations(c.module, result)
result = hlo(c, result)
result = commonOptimizations(c.module, result)
proc hloBody(c: PContext, n: PNode): PNode =
# fast exit:
if c.patterns.len == 0 or optPatterns notin gOptions: return n
c.hloLoopDetector = 0
result = hlo(c, n)
proc hloStmt(c: PContext, n: PNode): PNode =
# fast exit:
if c.patterns.len == 0 or optPatterns notin gOptions: return n
c.hloLoopDetector = 0
result = hlo(c, n)

View File

@@ -237,15 +237,6 @@ proc addToArgList(result, n: PNode) =
else:
for i in 0 .. <n.len: result.add(n.sons[i])
when false:
proc procPatternMatches*(c: PContext, s: PSym, n: PNode): bool =
## for AST-based overloading:
var ctx: TPatternContext
ctx.owner = s
ctx.c = c
ctx.formals = sonsLen(s.typ)-1
result = matches(ctx, s.ast.sons[patternPos], n)
proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
## returns a tree to semcheck if the rule triggered; nil otherwise
var ctx: TPatternContext

View File

@@ -85,6 +85,7 @@ type
# naming it multiple times
generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile
lastGenericIdx*: int # used for the generics stack
hloLoopDetector*: int # used to prevent endless loops in the HLO
proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
result.genericSym = s

View File

@@ -574,9 +574,14 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
fc.c = c
semForObjectFields(fc, tupleTypeA.n, n, stmts)
Dec(c.p.nestedLoopCounter)
var b = newNodeI(nkBreakStmt, n.info)
b.add(ast.emptyNode)
stmts.add(b)
# for TR macros this 'while true: ...; break' loop is pretty bad, so
# we avoid it now if we can:
if hasSonWith(stmts, nkBreakStmt):
var b = newNodeI(nkBreakStmt, n.info)
b.add(ast.emptyNode)
stmts.add(b)
else:
result = stmts
proc addForVarDecl(c: PContext, v: PSym) =
if warnShadowIdent in gNotes:

View File

@@ -588,6 +588,36 @@ proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} =
result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkBracket} and
cnst.len != 0
proc commonOptimizations*(c: PSym, n: PNode): PNode =
result = n
for i in 0 .. < n.safeLen:
result.sons[i] = commonOptimizations(c, n.sons[i])
var op = getMergeOp(n)
if (op != nil) and (op.magic != mNone) and (sonsLen(n) >= 3):
result = newNodeIT(nkCall, n.info, n.typ)
add(result, n.sons[0])
var args = newNode(nkArgList)
flattenTreeAux(args, n, op)
var j = 0
while j < sonsLen(args):
var a = args.sons[j]
inc(j)
if isConstExpr(a):
while j < sonsLen(args):
let b = args.sons[j]
if not isConstExpr(b): break
a = evalOp(op.magic, result, a, b, nil)
inc(j)
add(result, a)
if len(result) == 2: result = result[1]
else:
var cnst = getConstExpr(c, n)
# we inline constants if they are not complex constants:
if cnst != nil and not dontInlineConstant(n, cnst):
result = cnst
else:
result = n
proc transform(c: PTransf, n: PNode): PTransNode =
case n.kind
of nkSym:

View File

@@ -12,8 +12,6 @@ version 0.9.4
- special rule for ``[]=``
- ``=`` should be overloadable; requires specialization for ``=``; general
lift mechanism in the compiler is already implemented for 'fields'
- mocking support with ``tyProxy`` that does: fallback for ``.`` operator
- overloading of ``.``? Special case ``.=``?
- built-in 'getImpl'
- optimize 'genericReset'; 'newException' leads to code bloat
- stack-less GC