diff options
Diffstat (limited to 'compiler/sigmatch.nim')
-rwxr-xr-x | compiler/sigmatch.nim | 61 |
1 files changed, 36 insertions, 25 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index c21dc3c6e..ca65c670f 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -17,6 +17,7 @@ import type TCandidateState* = enum csEmpty, csMatch, csNoMatch + TCandidate* {.final.} = object exactMatches*: int subtypeMatches: int @@ -26,6 +27,7 @@ type state*: TCandidateState callee*: PType # may not be nil! calleeSym*: PSym # may be nil + calleeScope: int # may be -1 for unknown scope call*: PNode # modified call bindings*: TIdTable # maps types to types baseTypeMatch: bool # needed for conversions from T to openarray[T] @@ -35,7 +37,7 @@ type isNone, isConvertible, isIntConv, isSubtype, isGeneric, isEqual - + proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} = c.exactMatches = 0 c.subtypeMatches = 0 @@ -59,9 +61,10 @@ proc put(t: var TIdTable, key, val: PType) {.inline.} = IdentEq(val.sym.name, "TTable"): assert false -proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode) = +proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode, calleeScope = -1) = initCandidateAux(c, callee.typ) c.calleeSym = callee + c.calleeScope = calleeScope initIdTable(c.bindings) if binding != nil: var typeParams = callee.ast[genericParamsPos] @@ -93,6 +96,9 @@ proc cmpCandidates*(a, b: TCandidate): int = result = a.intConvMatches - b.intConvMatches if result != 0: return result = a.convMatches - b.convMatches + if result != 0: return + if (a.calleeScope != -1) and (b.calleeScope != -1): + result = a.calleeScope - b.calleeScope proc writeMatches(c: TCandidate) = Writeln(stdout, "exact matches: " & $c.exactMatches) @@ -101,10 +107,10 @@ proc writeMatches(c: TCandidate) = Writeln(stdout, "intconv matches: " & $c.intConvMatches) Writeln(stdout, "generic matches: " & $c.genericMatches) -proc getNotFoundError*(c: PContext, n: PNode): string = - # Gives a detailed error message; this is separated from semDirectCall, - # as semDirectCall is already pretty slow (and we need this information only - # in case of an error). +proc getNotFoundError*(c: PContext, n: PNode): string = + # Gives a detailed error message; this is separated from semOverloadedCall, + # as semOverlodedCall is already pretty slow (and we need this information + # only in case of an error). result = msgKindToString(errTypeMismatch) for i in countup(1, sonsLen(n) - 1): #debug(n.sons[i].typ) @@ -507,7 +513,10 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType, return proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType, - arg: PNode): PNode = + arg, argOrig: PNode): PNode = + if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate} and + f.kind in {tyExpr, tyStmt, tyTypeDesc}: + return argOrig var r = typeRel(m.bindings, f, a) case r of isConvertible: @@ -547,9 +556,9 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType, result = userConvMatch(c, m, base(f), a, arg) proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType, - arg: PNode): PNode = + arg, argOrig: PNode): PNode = if arg == nil or arg.kind != nkSymChoice: - result = ParamTypesMatchAux(c, m, f, a, arg) + result = ParamTypesMatchAux(c, 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 @@ -591,29 +600,29 @@ 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(c, m, f, arg.sons[best].typ, arg.sons[best], argOrig) proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode = var m: TCandidate initCandidate(m, f) - result = paramTypesMatch(c, m, f, a, arg) + result = paramTypesMatch(c, m, f, a, arg, nil) proc ConvertTo*(c: PContext, f: PType, n: PNode): PNode = var m: TCandidate initCandidate(m, f) - result = paramTypesMatch(c, m, f, n.typ, n) + result = paramTypesMatch(c, m, f, n.typ, n, nil) proc argtypeMatches*(c: PContext, f, a: PType): bool = var m: TCandidate initCandidate(m, f) - result = paramTypesMatch(c, m, f, a, ast.emptyNode) != nil + result = paramTypesMatch(c, m, f, a, ast.emptyNode, nil) != nil proc setSon(father: PNode, at: int, son: PNode) = if sonsLen(father) <= at: setlen(father.sons, at + 1) father.sons[at] = son -proc matchesAux*(c: PContext, n: PNode, m: var TCandidate, - marker: var TIntSet) = +proc matchesAux*(c: PContext, n, nOrig: PNode, + m: var TCandidate, marker: var TIntSet) = var f = 1 # iterates over formal parameters var a = 1 # iterates over the actual given arguments m.state = csMatch # until proven otherwise @@ -623,7 +632,7 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate, addSon(m.call, copyTree(n.sons[0])) var container: PNode = nil # constructed container var formal: PSym = nil - while a < sonsLen(n): + while a < n.len: if n.sons[a].kind == nkExprEqExpr: # named param # check if m.callee has such a param: @@ -642,8 +651,8 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate, m.state = csNoMatch return m.baseTypeMatch = false - var arg = ParamTypesMatch(c, m, formal.typ, - n.sons[a].typ, n.sons[a].sons[1]) + var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, + n.sons[a].sons[1], nOrig.sons[a].sons[1]) if arg == nil: m.state = csNoMatch return @@ -666,9 +675,10 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate, copyTree(n.sons[a]), m, c)) else: addSon(m.call, copyTree(n.sons[a])) - elif formal != nil: + elif formal != nil: m.baseTypeMatch = false - var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a]) + var arg = ParamTypesMatch(c, 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) else: @@ -687,7 +697,8 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate, m.state = csNoMatch return m.baseTypeMatch = false - var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a]) + var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, + n.sons[a], nOrig.sons[a]) if arg == nil: m.state = csNoMatch return @@ -703,14 +714,14 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate, inc(a) inc(f) -proc partialMatch*(c: PContext, n: PNode, m: var TCandidate) = +proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) = # for 'suggest' support: var marker = initIntSet() - matchesAux(c, n, m, marker) + matchesAux(c, n, nOrig, m, marker) -proc matches*(c: PContext, n: PNode, m: var TCandidate) = +proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) = var marker = initIntSet() - matchesAux(c, n, m, marker) + matchesAux(c, n, nOrig, m, marker) if m.state == csNoMatch: return # check that every formal parameter got a value: var f = 1 |