mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-23 07:45:23 +00:00
implements varargs[untyped]; refs #2545; to be documented
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -89,3 +89,4 @@ proc initDefines*() =
|
||||
defineSymbol("nimlocks")
|
||||
defineSymbol("nimnode")
|
||||
defineSymbol("nimnomagic64")
|
||||
defineSymbol("nimvarargstyped")
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user