diff options
-rw-r--r-- | compiler/ast.nim | 5 | ||||
-rw-r--r-- | compiler/condsyms.nim | 1 | ||||
-rw-r--r-- | compiler/semtypes.nim | 8 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 25 | ||||
-rw-r--r-- | compiler/types.nim | 4 | ||||
-rw-r--r-- | lib/system.nim | 48 | ||||
-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.xml | 2 | ||||
-rw-r--r-- | tests/typerel/tvarargsexpr.nim | 14 | ||||
-rw-r--r-- | todo.txt | 3 |
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 |