summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-07-02 16:18:11 +0200
committerAraq <rumpf_a@web.de>2015-07-02 16:18:11 +0200
commitcabbcd411d93ab1787414715b68b5239a9cee2ae (patch)
tree2b63596d3d669a7d5465f9de39d9b619c09efd2d
parentde5113805a67e6e2a1aa647af6e7529713ecd418 (diff)
downloadNim-cabbcd411d93ab1787414715b68b5239a9cee2ae.tar.gz
implements varargs[untyped]; refs #2545; to be documented
-rw-r--r--compiler/ast.nim5
-rw-r--r--compiler/condsyms.nim1
-rw-r--r--compiler/semtypes.nim8
-rw-r--r--compiler/sigmatch.nim25
-rw-r--r--compiler/types.nim4
-rw-r--r--lib/system.nim48
-rw-r--r--tests/generics/moverloading_typedesc.nim (renamed from tests/generics/mgenericprocmatcher.nim)0
-rw-r--r--tests/generics/toverloading_typedesc.nim (renamed from tests/generics/tgenericprocmatcher.nim)4
-rw-r--r--tests/testdata/doc1.xml2
-rw-r--r--tests/typerel/tvarargsexpr.nim14
-rw-r--r--todo.txt3
11 files changed, 76 insertions, 38 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 95aae035d..0a7fc28f4 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -522,6 +522,9 @@ const
   tfUnion* = tfNoSideEffect
   tfGcSafe* = tfThread
   tfObjHasKids* = tfEnumHasHoles
+  tfOldSchoolExprStmt* = tfVarargs # for now used to distinguish \
+    # 'varargs[expr]' from 'varargs[untyped]'. Eventually 'expr' will be
+    # deprecated and this mess can be cleaned up.
   skError* = skUnknown
 
   # type flags that are essential for type equality:
@@ -618,7 +621,7 @@ const
   # thus cannot be overloaded (also documented in the spec!):
   SpecialSemMagics* = {
     mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf,
-    mEcho, mShallowCopy, mExpandToAst, mParallel, mSpawn, mAstToStr}
+    mShallowCopy, mExpandToAst, mParallel, mSpawn, mAstToStr}
 
 type
   PNode* = ref TNode
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 34322471f..aecbde66e 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -89,3 +89,4 @@ proc initDefines*() =
   defineSymbol("nimlocks")
   defineSymbol("nimnode")
   defineSymbol("nimnomagic64")
+  defineSymbol("nimvarargstyped")
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 8c7bd7243..5c3880fa5 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1326,8 +1326,12 @@ proc processMagicType(c: PContext, m: PSym) =
     rawAddSon(m.typ, newTypeS(tyEmpty, c))
   of mIntSetBaseType: setMagicType(m, tyRange, intSize)
   of mNil: setMagicType(m, tyNil, ptrSize)
-  of mExpr: setMagicType(m, tyExpr, 0)
-  of mStmt: setMagicType(m, tyStmt, 0)
+  of mExpr:
+    setMagicType(m, tyExpr, 0)
+    if m.name.s == "expr": m.typ.flags.incl tfOldSchoolExprStmt
+  of mStmt:
+    setMagicType(m, tyStmt, 0)
+    if m.name.s == "stmt": m.typ.flags.incl tfOldSchoolExprStmt
   of mTypeDesc:
     setMagicType(m, tyTypeDesc, 0)
     rawAddSon(m.typ, newTypeS(tyNone, c))
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 88a2155dc..902b3bd61 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -727,8 +727,12 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         result = isNone
     else: discard
   of tyOpenArray, tyVarargs:
-    # varargs[expr] is special
-    if f.kind == tyVarargs and f.sons[0].kind == tyExpr: return
+    # varargs[expr] is special too but handled earlier. So we only need to
+    # handle varargs[stmt] which is the same as varargs[typed]:
+    if f.kind == tyVarargs:
+      if tfOldSchoolExprStmt in f.sons[0].flags:
+        if f.sons[0].kind == tyExpr: return
+      elif f.sons[0].kind == tyStmt: return
     case a.kind
     of tyOpenArray, tyVarargs:
       result = typeRel(c, base(f), base(a))
@@ -752,7 +756,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       if f.kind == tyOpenArray:
         if f.sons[0].kind == tyChar:
           result = isConvertible
-        elif f.sons[0].kind == tyGenericParam and typeRel(c, base(f), base(a)) >= isGeneric:
+        elif f.sons[0].kind == tyGenericParam and a.len > 0 and
+            typeRel(c, base(f), base(a)) >= isGeneric:
           result = isConvertible
     else: discard
   of tySequence:
@@ -1097,6 +1102,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       result = isNone
 
   of tyStmt:
+    if aOrig != nil and tfOldSchoolExprStmt notin f.flags:
+      put(c.bindings, f, aOrig)
     result = isGeneric
 
   of tyProxy:
@@ -1465,6 +1472,10 @@ proc incrIndexType(t: PType) =
   assert t.kind == tyArrayConstr
   inc t.sons[0].n.sons[1].intVal
 
+template isVarargsUntyped(x): expr =
+  x.kind == tyVarargs and x.sons[0].kind == tyExpr and
+    tfOldSchoolExprStmt notin x.sons[0].flags
+
 proc matchesAux(c: PContext, n, nOrig: PNode,
                 m: var TCandidate, marker: var IntSet) =
   template checkConstraint(n: expr) {.immediate, dirty.} =
@@ -1493,10 +1504,12 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
   var formalLen = m.callee.n.len
   addSon(m.call, copyTree(n.sons[0]))
   var container: PNode = nil # constructed container
-  var formal: PSym = nil
+  var formal: PSym = if formalLen > 1: m.callee.n.sons[1].sym else: nil
 
   while a < n.len:
-    if n.sons[a].kind == nkExprEqExpr:
+    if a >= formalLen-1 and formal != nil and formal.typ.isVarargsUntyped:
+      discard
+    elif n.sons[a].kind == nkExprEqExpr:
       # named param
       # check if m.callee has such a param:
       prepareNamedParam(n.sons[a])
@@ -1547,7 +1560,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
             addSon(m.call, copyTree(n.sons[a]))
         elif formal != nil and formal.typ.kind == tyVarargs:
           # beware of the side-effects in 'prepareOperand'! So only do it for
-          # varags matching. See tests/metatype/tstatic_overloading.
+          # varargs matching. See tests/metatype/tstatic_overloading.
           m.baseTypeMatch = false
           n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
           var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
diff --git a/compiler/types.nim b/compiler/types.nim
index e205f5722..af103bc3c 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -395,7 +395,7 @@ proc rangeToStr(n: PNode): string =
 
 const
   typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
-    "Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc",
+    "Array Constructor [$1]", "nil", "untyped", "typed", "typeDesc",
     "GenericInvocation", "GenericBody", "GenericInst", "GenericParam",
     "distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
     "set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
@@ -481,7 +481,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     result = "not " & typeToString(t.sons[0])
   of tyExpr:
     internalAssert t.len == 0
-    result = "expr"
+    result = "untyped"
   of tyFromExpr, tyFieldAccessor:
     result = renderTree(t.n)
   of tyArray:
diff --git a/lib/system.nim b/lib/system.nim
index e11722ae0..2677e4990 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2302,27 +2302,33 @@ elif hasAlloc:
       inc(i)
   {.pop.}
 
-proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
-  benign, sideEffect.}
-  ## Writes and flushes the parameters to the standard output.
-  ##
-  ## Special built-in that takes a variable number of arguments. Each argument
-  ## is converted to a string via ``$``, so it works for user-defined
-  ## types that have an overloaded ``$`` operator.
-  ## It is roughly equivalent to ``writeLine(stdout, x); flushFile(stdout)``, but
-  ## available for the JavaScript target too.
-  ##
-  ## Unlike other IO operations this is guaranteed to be thread-safe as
-  ## ``echo`` is very often used for debugging convenience. If you want to use
-  ## ``echo`` inside a `proc without side effects
-  ## <manual.html#pragmas-nosideeffect-pragma>`_ you can use `debugEcho <#debugEcho>`_
-  ## instead.
-
-proc debugEcho*(x: varargs[expr, `$`]) {.magic: "Echo", noSideEffect,
-                                           tags: [], raises: [].}
-  ## Same as `echo <#echo>`_, but as a special semantic rule, ``debugEcho``
-  ## pretends to be free of side effects, so that it can be used for debugging
-  ## routines marked as `noSideEffect <manual.html#pragmas-nosideeffect-pragma>`_.
+when defined(nimvarargstyped):
+  proc echo*(x: varargs[typed, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
+    benign, sideEffect.}
+    ## Writes and flushes the parameters to the standard output.
+    ##
+    ## Special built-in that takes a variable number of arguments. Each argument
+    ## is converted to a string via ``$``, so it works for user-defined
+    ## types that have an overloaded ``$`` operator.
+    ## It is roughly equivalent to ``writeLine(stdout, x); flushFile(stdout)``, but
+    ## available for the JavaScript target too.
+    ##
+    ## Unlike other IO operations this is guaranteed to be thread-safe as
+    ## ``echo`` is very often used for debugging convenience. If you want to use
+    ## ``echo`` inside a `proc without side effects
+    ## <manual.html#pragmas-nosideeffect-pragma>`_ you can use `debugEcho <#debugEcho>`_
+    ## instead.
+
+  proc debugEcho*(x: varargs[typed, `$`]) {.magic: "Echo", noSideEffect,
+                                            tags: [], raises: [].}
+    ## Same as `echo <#echo>`_, but as a special semantic rule, ``debugEcho``
+    ## pretends to be free of side effects, so that it can be used for debugging
+    ## routines marked as `noSideEffect <manual.html#pragmas-nosideeffect-pragma>`_.
+else:
+  proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
+    benign, sideEffect.}
+  proc debugEcho*(x: varargs[expr, `$`]) {.magic: "Echo", noSideEffect,
+                                             tags: [], raises: [].}
 
 template newException*(exceptn: typedesc, message: string): expr =
   ## creates an exception object of type ``exceptn`` and sets its ``msg`` field
diff --git a/tests/generics/mgenericprocmatcher.nim b/tests/generics/moverloading_typedesc.nim
index e0980bf4a..e0980bf4a 100644
--- a/tests/generics/mgenericprocmatcher.nim
+++ b/tests/generics/moverloading_typedesc.nim
diff --git a/tests/generics/tgenericprocmatcher.nim b/tests/generics/toverloading_typedesc.nim
index dfffdb87c..065f7c75d 100644
--- a/tests/generics/tgenericprocmatcher.nim
+++ b/tests/generics/toverloading_typedesc.nim
@@ -1,7 +1,7 @@
 discard """
   exitcode: 0
 """
-import mgenericprocmatcher
+import moverloading_typedesc
 import tables
 
 type
@@ -10,7 +10,7 @@ type
 
 
 when isMainModule:
-  doAssert FBar.new() == 3
+  #  doAssert FBar.new() == 3
 
   proc new(_: typedesc[LFoo]): int = 0
   proc new[T](_: typedesc[T]): int = 1
diff --git a/tests/testdata/doc1.xml b/tests/testdata/doc1.xml
index 2895cc32f..4e77481aa 100644
--- a/tests/testdata/doc1.xml
+++ b/tests/testdata/doc1.xml
@@ -3,7 +3,7 @@
   <tag>
     <test arg="blah" arg2="test"/>
     <test2>
-      bla ah absy hsh 
+      bla ah absy hsh
       hsh
       sjj
     </test2>
diff --git a/tests/typerel/tvarargsexpr.nim b/tests/typerel/tvarargsexpr.nim
index fcb49af61..c6a59fb20 100644
--- a/tests/typerel/tvarargsexpr.nim
+++ b/tests/typerel/tvarargsexpr.nim
@@ -1,12 +1,14 @@
 discard """
-  output: '''success'''
+  output: '''success
+true
+true'''
 """
 
 #bug #913
 
 import macros
 
-macro thirteen(args: varargs[expr]): expr = 
+macro thirteen(args: varargs[expr]): expr =
   result = newIntLitNode(13)
 
 doAssert(13==thirteen([1,2])) # works
@@ -16,3 +18,11 @@ doAssert(13==thirteen(1,[2])) # does not work
 doAssert(13==thirteen([1], 2)) # does not work
 
 echo "success"
+
+# bug #2545
+
+import macros
+macro test(e: varargs[untyped]): expr = bindSym"true"
+
+echo test(a)
+echo test(fake=90, arguments=80, also="false", possible=true)
diff --git a/todo.txt b/todo.txt
index 1d9d1c8d6..839d568c8 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,6 +1,8 @@
 version 0.11.4
 ==============
 
+- document special cased varargs[untyped] and varargs[typed]
+
 - The remaining bugs of the lambda lifting pass that is responsible to enable
   closures and closure iterators need to be fixed.
 - ``concept`` needs to be refined, a nice name for the feature is not enough.
@@ -10,7 +12,6 @@ version 0.11.4
 
 - Finish the implementation of the 'parallel' statement.
 - Deprecate ``immediate`` for templates and macros
-- special case varargs[untyped] and varargs[typed]
 - make 'nil' work for 'add':
   - resizeString
   - incrSeq