diff options
author | Araq <rumpf_a@web.de> | 2013-09-17 23:43:07 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-09-17 23:43:07 +0200 |
commit | 9de3bc8ef64fbd2fa1e336b05a09ad8f898a5d45 (patch) | |
tree | 90fa96e12b363ec40af0ddcb5a0f7c5e3c173630 /compiler | |
parent | 823cb494a5dbba2100d1dcaa675f97dd20e28d15 (diff) | |
download | Nim-9de3bc8ef64fbd2fa1e336b05a09ad8f898a5d45.tar.gz |
improvements for TR macros
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/hlo.nim | 21 | ||||
-rw-r--r-- | compiler/patterns.nim | 9 | ||||
-rw-r--r-- | compiler/semdata.nim | 1 | ||||
-rw-r--r-- | compiler/semstmts.nim | 11 | ||||
-rw-r--r-- | compiler/transf.nim | 30 |
5 files changed, 53 insertions, 19 deletions
diff --git a/compiler/hlo.nim b/compiler/hlo.nim index 152fd4414..f19f6dd92 100644 --- a/compiler/hlo.nim +++ b/compiler/hlo.nim @@ -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) diff --git a/compiler/patterns.nim b/compiler/patterns.nim index ff7f18ac0..b7792100f 100644 --- a/compiler/patterns.nim +++ b/compiler/patterns.nim @@ -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 diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 4c066f5fa..121bf297d 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -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 diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 0ce58ba5c..ed6787a16 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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: diff --git a/compiler/transf.nim b/compiler/transf.nim index a81457b39..206c21c3d 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -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: |