summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-02-12 14:56:42 +0100
committerAraq <rumpf_a@web.de>2015-02-12 14:56:57 +0100
commitc4eddb3fdafe3494fa1b1300bcbf1314b7540490 (patch)
tree87ebc8d8f759efedf09f127f0c2acebc0c87bf0e
parent41385f3aaf4da7a13df64ec98a2b0b713c88c1d6 (diff)
downloadNim-c4eddb3fdafe3494fa1b1300bcbf1314b7540490.tar.gz
ordinary parameters can follow a varargs parameter
-rw-r--r--compiler/sigmatch.nim22
-rw-r--r--tests/overload/tparams_after_varargs.nim17
-rw-r--r--todo.txt2
-rw-r--r--web/news.txt12
4 files changed, 44 insertions, 9 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 9a99d5200..544011f2d 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1441,13 +1441,14 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
         return
       checkConstraint(n.sons[a].sons[1])
       if m.baseTypeMatch: 
-        assert(container == nil)
+        #assert(container == nil)
         container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
         addSon(container, arg)
         setSon(m.call, formal.position + 1, container)
         if f != formalLen - 1: container = nil
-      else: 
+      else:
         setSon(m.call, formal.position + 1, arg)
+      inc f
     else:
       # unnamed param
       if f >= formalLen:
@@ -1466,7 +1467,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
           var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
                                     n.sons[a], nOrig.sons[a])
-          if (arg != nil) and m.baseTypeMatch and (container != nil):
+          if arg != nil and m.baseTypeMatch and container != nil:
             addSon(container, arg)
             incrIndexType(container.typ)
           else:
@@ -1480,7 +1481,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           internalError(n.sons[a].info, "matches")
           return
         formal = m.callee.n.sons[f].sym
-        if containsOrIncl(marker, formal.position): 
+        if containsOrIncl(marker, formal.position) and container.isNil:
           # already in namedParams:
           localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
           m.state = csNoMatch
@@ -1493,17 +1494,22 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           m.state = csNoMatch
           return
         if m.baseTypeMatch:
-          assert(container == nil)
-          container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
+          #assert(container == nil)
+          if container.isNil:
+            container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
           addSon(container, arg)
           setSon(m.call, formal.position + 1, 
                  implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
-          if f != formalLen - 1: container = nil
+          #if f != formalLen - 1: container = nil
+
+          # pick the formal from the end, so that 'x, y, varargs, z' works:
+          f = max(f, formalLen - n.len + a + 1)
         else:
           setSon(m.call, formal.position + 1, arg)
+          inc(f)
+          container = nil
       checkConstraint(n.sons[a])
     inc(a)
-    inc(f)
 
 proc semFinishOperands*(c: PContext, n: PNode) =
   # this needs to be called to ensure that after overloading resolution every
diff --git a/tests/overload/tparams_after_varargs.nim b/tests/overload/tparams_after_varargs.nim
new file mode 100644
index 000000000..a93e280b9
--- /dev/null
+++ b/tests/overload/tparams_after_varargs.nim
@@ -0,0 +1,17 @@
+discard """
+  output: '''a 1 b 2 x @[3, 4, 5] y 6 z 7
+yay
+12'''
+"""
+
+proc test(a, b: int, x: varargs[int]; y, z: int) =
+  echo "a ", a, " b ", b, " x ", @x, " y ", y, " z ", z
+
+test 1, 2, 3, 4, 5, 6, 7
+
+template takesBlock(a, b: int, x: varargs[expr]; blck: stmt) =
+  blck
+  echo a, b
+
+takesBlock 1, 2, "some", 0.90, "random stuff":
+  echo "yay"
diff --git a/todo.txt b/todo.txt
index 57cfea017..15521eae1 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,8 +1,8 @@
 version 0.10.4
 ==============
 
-- make 'nil' work for 'add' and 'len'
 - improve GC-unsafety warnings
+- make 'nil' work for 'add' and 'len'
 - get rid of 'mget'; aka priority of 'var' needs to be 'var{lvalue}'
 
 
diff --git a/web/news.txt b/web/news.txt
index 5cc3a6ed6..7ead5a70e 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -43,6 +43,18 @@ News
       foo = {"ah": "finally", "this": "is", "possible.": "nice!"}.toTable()
 
 
+  - Ordinary parameters can follow after a varargs parameter. This means the
+    following is finally accepted by the compiler:
+
+  .. code-block:: nim  
+    template takesBlock(a, b: int, x: varargs[expr]; blck: stmt) =
+      blck
+      echo a, b
+
+    takesBlock 1, 2, "some", 0.90, "random stuff":
+      echo "yay"
+  
+
 2014-12-29 Version 0.10.2 released
 ==================================