summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-09-04 23:57:39 +0200
committerAraq <rumpf_a@web.de>2012-09-04 23:57:39 +0200
commit30c00aba07cd8b86dc935209bcad74558bae26ad (patch)
treea083279303f3eefefd85b7eb514413f6c3c8d943
parent3a1a1976645ac9ad2c449b0afea57c7c154ec37f (diff)
downloadNim-30c00aba07cd8b86dc935209bcad74558bae26ad.tar.gz
bugfixes and improvements for term rewriting macros
-rw-r--r--compiler/parampatterns.nim2
-rw-r--r--compiler/patterns.nim29
-rwxr-xr-xcompiler/semtempl.nim6
-rw-r--r--tests/patterns/tstar.nim2
-rw-r--r--tests/patterns/tstmtlist.nim10
5 files changed, 30 insertions, 19 deletions
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim
index 83585dbd4..3b5c8f6fa 100644
--- a/compiler/parampatterns.nim
+++ b/compiler/parampatterns.nim
@@ -135,7 +135,7 @@ proc checkForSideEffects(n: PNode): TSideEffectAnalysis =
     # only calls can produce side effects:
     let op = n.sons[0]
     if op.kind == nkSym and isRoutine(op.sym):
-      let s = n.sym
+      let s = op.sym
       if sfSideEffect in s.flags:
         return seSideEffect
       # assume no side effect:
diff --git a/compiler/patterns.nim b/compiler/patterns.nim
index 110fae08a..48ad55023 100644
--- a/compiler/patterns.nim
+++ b/compiler/patterns.nim
@@ -53,15 +53,15 @@ proc sameTrees(a, b: PNode): bool =
         result = true
 
 proc inSymChoice(sc, x: PNode): bool =
-  if sc.kind == nkClosedSymChoice:
-    for i in 0.. <sc.len:
-      if sc.sons[i].sym == x.sym: return true
-  elif sc.kind == nkOpenSymChoice:
+  if sc.kind == nkOpenSymChoice:
     # same name suffices for open sym choices!
     result = sc.sons[0].sym.name.id == x.sym.name.id
+  elif sc.kind == nkClosedSymChoice:
+    for i in 0.. <sc.len:
+      if sc.sons[i].sym == x.sym: return true
 
 proc checkTypes(c: PPatternContext, p: PSym, n: PNode): bool =
-  # check param constraints first here as this quite optimized:
+  # check param constraints first here as this is quite optimized:
   if p.typ.constraint != nil:
     result = matchNodeKinds(p.typ.constraint, n)
     if not result: return
@@ -147,11 +147,20 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
         if isPatternParam(c, v) and v.sym.typ.kind == tyVarargs:
           for i in countup(0, plen - 2):
             if not matches(c, p.sons[i], n.sons[i]): return
-          var arglist = newNodeI(nkArgList, n.info, sonsLen(n) - plen + 1)
-          # f(1, 2, 3)
-          # p(X)
-          for i in countup(0, sonsLen(n) - plen):
-            arglist.sons[i] = n.sons[i + plen - 1]
+          
+          var arglist: PNode
+          if plen == sonsLen(n) and lastSon(n).kind == nkHiddenStdConv and
+              lastSon(n).sons[1].kind == nkBracket:
+            # unpack varargs:
+            let n = lastSon(n).sons[1]
+            arglist = newNodeI(nkArgList, n.info, n.len)
+            for i in 0.. <n.len: arglist.sons[i] = n.sons[i]
+          else:
+            arglist = newNodeI(nkArgList, n.info, sonsLen(n) - plen + 1)
+            # f(1, 2, 3)
+            # p(X)
+            for i in countup(0, sonsLen(n) - plen):
+              arglist.sons[i] = n.sons[i + plen - 1]
           # check or bind 'X':
           return bindOrCheck(c, v.sym, arglist)
       if plen == sonsLen(n):
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index efdfce78f..9e0e0ebab 100755
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -432,7 +432,9 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
       elif templToExpand(s):
         result = semPatternBody(c, semTemplateExpr(c.c, n, s, false))
       else:
-        result = symChoice(c.c, n, s, scOpen)
+        # we use 'scForceOpen' here so that e.g. "writeln" (which is a
+        # non ambiguous generic) will match its instantiations:
+        result = symChoice(c.c, n, s, scForceOpen)
     else:
       result = n
   
@@ -504,7 +506,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
       if s != nil:
         if Contains(c.toBind, s.id):
           return symChoice(c.c, n, s, scClosed)
-        return symChoice(c.c, n, s, scOpen)
+        return symChoice(c.c, n, s, scForceOpen)
     of nkPar:
       if n.len == 1: return semPatternBody(c, n.sons[0])
     else: nil
diff --git a/tests/patterns/tstar.nim b/tests/patterns/tstar.nim
index 6dbff3cd6..55d841c3a 100644
--- a/tests/patterns/tstar.nim
+++ b/tests/patterns/tstar.nim
@@ -15,5 +15,5 @@ template optConc{ `&&` * a }(a: expr): expr = &&a
 let space = " "
 echo "my" && (space & "awe" && "some " ) && "concat"
 
-# check that it's been properly optimized:
+# check that it's been optimized properly:
 doAssert calls == 1
diff --git a/tests/patterns/tstmtlist.nim b/tests/patterns/tstmtlist.nim
index 391c93d47..138384227 100644
--- a/tests/patterns/tstmtlist.nim
+++ b/tests/patterns/tstmtlist.nim
@@ -5,14 +5,14 @@ discard """
 """
 
 template optWrite{
-  write(stdout, x)
-  write(stdout, y)
-}(x, y: string) =
-  write(stdout, "|", x, y, "|")
+  write(f, x)
+  ((write|writeln){w})(f, y)
+}(x, y: varargs[expr], f, w: expr) =
+  w(f, "|", x, y, "|")
 
 if true:
   echo "0"
   write stdout, "1"
-  write stdout, "2"
+  writeln stdout, "2"
   write stdout, "3"
   echo "4"