diff options
Diffstat (limited to 'compiler/sigmatch.nim')
-rw-r--r-- | compiler/sigmatch.nim | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 2a9d15b5a..ef1c01b7a 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -47,6 +47,7 @@ type coerceDistincts*: bool # this is an explicit coercion that can strip away # a distrinct type typedescMatched*: bool + isNoCall*: bool # misused for generic type instantiations C[T] inheritancePenalty: int # to prefer closest father object type errors*: CandidateErrors # additional clarifications to be displayed to the # user if overload resolution fails @@ -158,11 +159,15 @@ proc sumGeneric(t: PType): int = t = t.sons[0] inc result inc isvar + of tyTypeDesc: + t = t.lastSon + if t.kind == tyEmpty: break + inc result of tyGenericInvocation, tyTuple: result += ord(t.kind == tyGenericInvocation) for i in 0 .. <t.len: result += t.sons[i].sumGeneric break - of tyGenericParam, tyExpr, tyStatic, tyStmt, tyTypeDesc: break + of tyGenericParam, tyExpr, tyStatic, tyStmt: break of tyBool, tyChar, tyEnum, tyObject, tyProc, tyPointer, tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128, tyUInt..tyUInt64: @@ -218,12 +223,12 @@ proc cmpCandidates*(a, b: TCandidate): int = result = complexDisambiguation(a.callee, b.callee) proc writeMatches*(c: TCandidate) = - writeln(stdout, "exact matches: " & $c.exactMatches) - writeln(stdout, "generic matches: " & $c.genericMatches) - writeln(stdout, "subtype matches: " & $c.subtypeMatches) - writeln(stdout, "intconv matches: " & $c.intConvMatches) - writeln(stdout, "conv matches: " & $c.convMatches) - writeln(stdout, "inheritance: " & $c.inheritancePenalty) + writeLine(stdout, "exact matches: " & $c.exactMatches) + writeLine(stdout, "generic matches: " & $c.genericMatches) + writeLine(stdout, "subtype matches: " & $c.subtypeMatches) + writeLine(stdout, "intconv matches: " & $c.intConvMatches) + writeLine(stdout, "conv matches: " & $c.convMatches) + writeLine(stdout, "inheritance: " & $c.inheritancePenalty) proc argTypeToString(arg: PNode; prefer: TPreferedDesc): string = if arg.kind in nkSymChoices: @@ -264,6 +269,9 @@ proc concreteType(c: TCandidate, t: PType): PType = addSonSkipIntLit(result, t.sons[1]) # XXX: semantic checking for the type? of tyNil: result = nil # what should it be? + of tyTypeDesc: + if c.isNoCall: result = t + else: result = nil of tySequence, tySet: if t.sons[0].kind == tyEmpty: result = nil else: result = t @@ -727,8 +735,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)) @@ -748,6 +760,13 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = result = isConvertible elif typeRel(c, base(f), a.sons[0]) >= isGeneric: result = isConvertible + of tyString: + if f.kind == tyOpenArray: + if f.sons[0].kind == tyChar: + result = isConvertible + elif f.sons[0].kind == tyGenericParam and a.len > 0 and + typeRel(c, base(f), base(a)) >= isGeneric: + result = isConvertible else: discard of tySequence: case a.kind @@ -1091,6 +1110,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: @@ -1281,7 +1302,10 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, result = implicitConv(nkHiddenStdConv, f, arg, m, c) of isSubtype: inc(m.subtypeMatches) - result = implicitConv(nkHiddenSubConv, f, arg, m, c) + if f.kind == tyTypeDesc: + result = arg + else: + result = implicitConv(nkHiddenSubConv, f, arg, m, c) of isSubrange: inc(m.subtypeMatches) if f.kind == tyVar: @@ -1291,6 +1315,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, of isInferred, isInferredConvertible: if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds: result = c.semInferredLambda(c, m.bindings, arg) + elif arg.kind != nkSym: + return nil else: let inferred = c.semGenerateInstance(c, arg.sym, m.bindings, arg.info) result = newSymNode(inferred, arg.info) @@ -1454,6 +1480,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.} = @@ -1482,10 +1512,17 @@ 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: + if container.isNil: + container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, n.info)) + setSon(m.call, formal.position + 1, container) + else: + incrIndexType(container.typ) + addSon(container, n.sons[a]) + elif n.sons[a].kind == nkExprEqExpr: # named param # check if m.callee has such a param: prepareNamedParam(n.sons[a]) @@ -1507,7 +1544,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, n.sons[a].sons[1] = prepareOperand(c, formal.typ, n.sons[a].sons[1]) n.sons[a].typ = n.sons[a].sons[1].typ var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ, - n.sons[a].sons[1], nOrig.sons[a].sons[1]) + n.sons[a].sons[1], n.sons[a].sons[1]) if arg == nil: m.state = csNoMatch return @@ -1536,7 +1573,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, |