mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 01:14:41 +00:00
make the current PContext accessible through TCandidate
the goal here is to remove all the hacks from ParamTypeMatch and to handle all type matching in typeRel (the context there is required to evaluate any static params and to run the compilation tests of user-defined type classes)
This commit is contained in:
@@ -47,14 +47,14 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||
var z: TCandidate
|
||||
|
||||
if sym == nil: return
|
||||
initCandidate(best, sym, initialBinding, symScope)
|
||||
initCandidate(alt, sym, initialBinding, symScope)
|
||||
initCandidate(c, best, sym, initialBinding, symScope)
|
||||
initCandidate(c, alt, sym, initialBinding, symScope)
|
||||
best.state = csNoMatch
|
||||
|
||||
while sym != nil:
|
||||
if sym.kind in filter:
|
||||
determineType(c, sym)
|
||||
initCandidate(z, sym, initialBinding, o.lastOverloadScope)
|
||||
initCandidate(c, z, sym, initialBinding, o.lastOverloadScope)
|
||||
z.calleeSym = sym
|
||||
matches(c, n, orig, z)
|
||||
if errors != nil:
|
||||
@@ -199,15 +199,15 @@ proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) =
|
||||
|
||||
proc IndexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode =
|
||||
var m: TCandidate
|
||||
initCandidate(m, f)
|
||||
result = paramTypesMatch(c, m, f, a, arg, nil)
|
||||
initCandidate(c, m, f)
|
||||
result = paramTypesMatch(m, f, a, arg, nil)
|
||||
if m.genericConverter and result != nil:
|
||||
instGenericConvertersArg(c, result, m)
|
||||
|
||||
proc ConvertTo*(c: PContext, f: PType, n: PNode): PNode =
|
||||
var m: TCandidate
|
||||
initCandidate(m, f)
|
||||
result = paramTypesMatch(c, m, f, n.typ, n, nil)
|
||||
initCandidate(c, m, f)
|
||||
result = paramTypesMatch(m, f, n.typ, n, nil)
|
||||
if m.genericConverter and result != nil:
|
||||
instGenericConvertersArg(c, result, m)
|
||||
|
||||
@@ -243,9 +243,9 @@ proc explicitGenericInstError(n: PNode): PNode =
|
||||
result = n
|
||||
|
||||
proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
|
||||
var x: TCandidate
|
||||
initCandidate(x, s, n)
|
||||
var newInst = generateInstance(c, s, x.bindings, n.info)
|
||||
var m: TCandidate
|
||||
initCandidate(c, m, s, n)
|
||||
var newInst = generateInstance(c, s, m.bindings, n.info)
|
||||
markUsed(n, s)
|
||||
result = newSymNode(newInst, n.info)
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ proc checkConversionBetweenObjects(castDest, src: PType): TConvStatus =
|
||||
const
|
||||
IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
|
||||
|
||||
proc checkConvertible(castDest, src: PType): TConvStatus =
|
||||
proc checkConvertible(c: PContext, castDest, src: PType): TConvStatus =
|
||||
result = convOK
|
||||
if sameType(castDest, src) and castDest.sym == src.sym:
|
||||
# don't annoy conversions that may be needed on another processor:
|
||||
@@ -163,7 +163,7 @@ proc checkConvertible(castDest, src: PType): TConvStatus =
|
||||
# accept conversion between integral types
|
||||
else:
|
||||
# we use d, s here to speed up that operation a bit:
|
||||
case cmpTypes(d, s)
|
||||
case cmpTypes(c, d, s)
|
||||
of isNone, isGeneric:
|
||||
if not compareTypes(castDest, src, dcEqIgnoreDistinct):
|
||||
result = convNotLegal
|
||||
@@ -202,7 +202,7 @@ proc semConv(c: PContext, n: PNode): PNode =
|
||||
var op = result.sons[1]
|
||||
|
||||
if not isSymChoice(op):
|
||||
let status = checkConvertible(result.typ, op.typ)
|
||||
let status = checkConvertible(c, result.typ, op.typ)
|
||||
case status
|
||||
of convOK: nil
|
||||
of convNotNeedeed:
|
||||
@@ -213,7 +213,7 @@ proc semConv(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
for i in countup(0, sonsLen(op) - 1):
|
||||
let it = op.sons[i]
|
||||
let status = checkConvertible(result.typ, it.typ)
|
||||
let status = checkConvertible(c, result.typ, it.typ)
|
||||
if status == convOK:
|
||||
markUsed(n, it.sym)
|
||||
markIndirect(c, it.sym)
|
||||
@@ -324,15 +324,15 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
|
||||
case t2.kind
|
||||
of tyTypeClasses:
|
||||
var m: TCandidate
|
||||
InitCandidate(m, t2)
|
||||
InitCandidate(c, m, t2)
|
||||
match = matchUserTypeClass(c, m, emptyNode, t2, t1) != nil
|
||||
of tyOrdinal:
|
||||
var m: TCandidate
|
||||
InitCandidate(m, t2)
|
||||
InitCandidate(c, m, t2)
|
||||
match = isOrdinalType(t1)
|
||||
of tySequence, tyArray, tySet:
|
||||
var m: TCandidate
|
||||
InitCandidate(m, t2)
|
||||
InitCandidate(c, m, t2)
|
||||
match = typeRel(m, t2, t1) != isNone
|
||||
else:
|
||||
match = sameType(t1, t2)
|
||||
@@ -707,7 +707,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if t != nil and t.kind == tyProc:
|
||||
# This is a proc variable, apply normal overload resolution
|
||||
var m: TCandidate
|
||||
initCandidate(m, t)
|
||||
initCandidate(c, m, t)
|
||||
matches(c, n, nOrig, m)
|
||||
if m.state != csMatch:
|
||||
if c.inCompilesContext > 0:
|
||||
|
||||
@@ -838,7 +838,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
|
||||
else:
|
||||
internalAssert s.typ.kind == tyGenericBody
|
||||
|
||||
var m = newCandidate(s, n)
|
||||
var m = newCandidate(c, s, n)
|
||||
matches(c, n, copyTree(n), m)
|
||||
|
||||
if m.state != csMatch:
|
||||
|
||||
@@ -21,7 +21,8 @@ type
|
||||
TCandidateState* = enum
|
||||
csEmpty, csMatch, csNoMatch
|
||||
|
||||
TCandidate* {.final.} = object
|
||||
TCandidate* {.final.} = object
|
||||
c*: PContext
|
||||
exactMatches*: int # also misused to prefer iters over procs
|
||||
genericMatches: int # also misused to prefer constraints
|
||||
subtypeMatches: int
|
||||
@@ -58,7 +59,9 @@ const
|
||||
|
||||
proc markUsed*(n: PNode, s: PSym)
|
||||
|
||||
proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} =
|
||||
proc initCandidateAux(ctx: PContext,
|
||||
c: var TCandidate, callee: PType) {.inline.} =
|
||||
c.c = ctx
|
||||
c.exactMatches = 0
|
||||
c.subtypeMatches = 0
|
||||
c.convMatches = 0
|
||||
@@ -71,17 +74,17 @@ proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} =
|
||||
c.genericConverter = false
|
||||
c.inheritancePenalty = 0
|
||||
|
||||
proc initCandidate*(c: var TCandidate, callee: PType) =
|
||||
initCandidateAux(c, callee)
|
||||
proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PType) =
|
||||
initCandidateAux(ctx, c, callee)
|
||||
c.calleeSym = nil
|
||||
initIdTable(c.bindings)
|
||||
|
||||
proc put(t: var TIdTable, key, val: PType) {.inline.} =
|
||||
IdTablePut(t, key, val)
|
||||
|
||||
proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode,
|
||||
calleeScope = -1) =
|
||||
initCandidateAux(c, callee.typ)
|
||||
proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
|
||||
binding: PNode, calleeScope = -1) =
|
||||
initCandidateAux(ctx, c, callee.typ)
|
||||
c.calleeSym = callee
|
||||
c.calleeScope = calleeScope
|
||||
initIdTable(c.bindings)
|
||||
@@ -93,10 +96,12 @@ proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode,
|
||||
#debug(formalTypeParam)
|
||||
put(c.bindings, formalTypeParam, binding[i].typ)
|
||||
|
||||
proc newCandidate*(callee: PSym, binding: PNode, calleeScope = -1): TCandidate =
|
||||
initCandidate(result, callee, binding, calleeScope)
|
||||
proc newCandidate*(ctx: PContext, callee: PSym,
|
||||
binding: PNode, calleeScope = -1): TCandidate =
|
||||
initCandidate(ctx, result, callee, binding, calleeScope)
|
||||
|
||||
proc copyCandidate(a: var TCandidate, b: TCandidate) =
|
||||
a.c = b.c
|
||||
a.exactMatches = b.exactMatches
|
||||
a.subtypeMatches = b.subtypeMatches
|
||||
a.convMatches = b.convMatches
|
||||
@@ -762,10 +767,10 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
|
||||
result = isEqual
|
||||
else: internalError("typeRel: " & $f.kind)
|
||||
|
||||
proc cmpTypes*(f, a: PType): TTypeRelation =
|
||||
var c: TCandidate
|
||||
InitCandidate(c, f)
|
||||
result = typeRel(c, f, a)
|
||||
proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation =
|
||||
var m: TCandidate
|
||||
InitCandidate(c, m, f)
|
||||
result = typeRel(m, f, a)
|
||||
|
||||
proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
|
||||
f: PType): PType =
|
||||
@@ -887,13 +892,14 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
||||
result = arg
|
||||
put(m.bindings, f, a)
|
||||
|
||||
proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
|
||||
proc ParamTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||
argSemantized, argOrig: PNode): PNode =
|
||||
var
|
||||
r: TTypeRelation
|
||||
arg = argSemantized
|
||||
|
||||
let
|
||||
c = m.c
|
||||
a0 = if c.InTypeClass > 0: argType.skipTypes({tyTypeDesc})
|
||||
else: argType
|
||||
a = if a0 != nil: a0.skipTypes({tyStatic}) else: a0
|
||||
@@ -1007,19 +1013,20 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
|
||||
else:
|
||||
result = userConvMatch(c, m, base(f), a, arg)
|
||||
|
||||
proc ParamTypesMatch*(c: PContext, m: var TCandidate, f, a: PType,
|
||||
proc ParamTypesMatch*(m: var TCandidate, f, a: PType,
|
||||
arg, argOrig: PNode): PNode =
|
||||
if arg == nil or arg.kind notin nkSymChoices:
|
||||
result = ParamTypesMatchAux(c, m, f, a, arg, argOrig)
|
||||
result = ParamTypesMatchAux(m, f, a, arg, argOrig)
|
||||
else:
|
||||
# CAUTION: The order depends on the used hashing scheme. Thus it is
|
||||
# incorrect to simply use the first fitting match. However, to implement
|
||||
# this correctly is inefficient. We have to copy `m` here to be able to
|
||||
# roll back the side effects of the unification algorithm.
|
||||
let c = m.c
|
||||
var x, y, z: TCandidate
|
||||
initCandidate(x, m.callee)
|
||||
initCandidate(y, m.callee)
|
||||
initCandidate(z, m.callee)
|
||||
initCandidate(c, x, m.callee)
|
||||
initCandidate(c, y, m.callee)
|
||||
initCandidate(c, z, m.callee)
|
||||
x.calleeSym = m.calleeSym
|
||||
y.calleeSym = m.calleeSym
|
||||
z.calleeSym = m.calleeSym
|
||||
@@ -1051,7 +1058,7 @@ proc ParamTypesMatch*(c: PContext, m: var TCandidate, f, a: PType,
|
||||
else:
|
||||
# only one valid interpretation found:
|
||||
markUsed(arg, arg.sons[best].sym)
|
||||
result = ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best],
|
||||
result = ParamTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best],
|
||||
argOrig)
|
||||
|
||||
proc setSon(father: PNode, at: int, son: PNode) =
|
||||
@@ -1142,7 +1149,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
m.baseTypeMatch = false
|
||||
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(c, m, formal.typ, n.sons[a].typ,
|
||||
var arg = ParamTypesMatch(m, formal.typ, n.sons[a].typ,
|
||||
n.sons[a].sons[1], nOrig.sons[a].sons[1])
|
||||
if arg == nil:
|
||||
m.state = csNoMatch
|
||||
@@ -1172,7 +1179,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
elif formal != nil:
|
||||
m.baseTypeMatch = false
|
||||
n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
|
||||
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
|
||||
var arg = ParamTypesMatch(m, formal.typ, n.sons[a].typ,
|
||||
n.sons[a], nOrig.sons[a])
|
||||
if (arg != nil) and m.baseTypeMatch and (container != nil):
|
||||
addSon(container, arg)
|
||||
@@ -1195,7 +1202,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
return
|
||||
m.baseTypeMatch = false
|
||||
n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
|
||||
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
|
||||
var arg = ParamTypesMatch(m, formal.typ, n.sons[a].typ,
|
||||
n.sons[a], nOrig.sons[a])
|
||||
if arg == nil:
|
||||
m.state = csNoMatch
|
||||
@@ -1249,8 +1256,8 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||
|
||||
proc argtypeMatches*(c: PContext, f, a: PType): bool =
|
||||
var m: TCandidate
|
||||
initCandidate(m, f)
|
||||
let res = paramTypesMatch(c, m, f, a, ast.emptyNode, nil)
|
||||
initCandidate(c, m, f)
|
||||
let res = paramTypesMatch(m, f, a, ast.emptyNode, nil)
|
||||
#instantiateGenericConverters(c, res, m)
|
||||
# XXX this is used by patterns.nim too; I think it's better to not
|
||||
# instantiate generic converters for that
|
||||
@@ -1312,7 +1319,7 @@ tests:
|
||||
|
||||
setup:
|
||||
var c: TCandidate
|
||||
InitCandidate(c, nil)
|
||||
InitCandidate(nil, c, nil)
|
||||
|
||||
template yes(x, y) =
|
||||
test astToStr(x) & " is " & astToStr(y):
|
||||
|
||||
@@ -119,7 +119,7 @@ proc argsFit(c: PContext, candidate: PSym, n, nOrig: PNode): bool =
|
||||
case candidate.kind
|
||||
of OverloadableSyms:
|
||||
var m: TCandidate
|
||||
initCandidate(m, candidate, nil)
|
||||
initCandidate(c, m, candidate, nil)
|
||||
sigmatch.partialMatch(c, n, nOrig, m)
|
||||
result = m.state != csNoMatch
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user