summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-09-17 23:43:07 +0200
committerAraq <rumpf_a@web.de>2013-09-17 23:43:07 +0200
commit9de3bc8ef64fbd2fa1e336b05a09ad8f898a5d45 (patch)
tree90fa96e12b363ec40af0ddcb5a0f7c5e3c173630 /compiler
parent823cb494a5dbba2100d1dcaa675f97dd20e28d15 (diff)
downloadNim-9de3bc8ef64fbd2fa1e336b05a09ad8f898a5d45.tar.gz
improvements for TR macros
Diffstat (limited to 'compiler')
-rw-r--r--compiler/hlo.nim21
-rw-r--r--compiler/patterns.nim9
-rw-r--r--compiler/semdata.nim1
-rw-r--r--compiler/semstmts.nim11
-rw-r--r--compiler/transf.nim30
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: