implements varargs[untyped]; refs #2545; to be documented

This commit is contained in:
Araq 2015-07-02 16:18:11 +02:00
commit cabbcd411d
11 changed files with 75 additions and 37 deletions

View file

@ -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

View file

@ -89,3 +89,4 @@ proc initDefines*() =
defineSymbol("nimlocks") defineSymbol("nimlocks")
defineSymbol("nimnode") defineSymbol("nimnode")
defineSymbol("nimnomagic64") defineSymbol("nimnomagic64")
defineSymbol("nimvarargstyped")

View file

@ -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))

View file

@ -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,

View file

@ -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:

View file

@ -2302,7 +2302,8 @@ elif hasAlloc:
inc(i) inc(i)
{.pop.} {.pop.}
proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect], when defined(nimvarargstyped):
proc echo*(x: varargs[typed, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
benign, sideEffect.} benign, sideEffect.}
## Writes and flushes the parameters to the standard output. ## Writes and flushes the parameters to the standard output.
## ##
@ -2318,11 +2319,16 @@ proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
## <manual.html#pragmas-nosideeffect-pragma>`_ you can use `debugEcho <#debugEcho>`_ ## <manual.html#pragmas-nosideeffect-pragma>`_ you can use `debugEcho <#debugEcho>`_
## instead. ## 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

View file

@ -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

View file

@ -1,5 +1,7 @@
discard """ discard """
output: '''success''' output: '''success
true
true'''
""" """
#bug #913 #bug #913
@ -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)

View file

@ -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