implements auto-deref for the first argument (requires .experimental)
This commit is contained in:
parent
defaf5d400
commit
603f36bc86
2 changed files with 38 additions and 8 deletions
|
|
@ -126,7 +126,8 @@ proc gatherUsedSyms(c: PContext, usedSyms: var seq[PNode]) =
|
||||||
for s in scope.usingSyms: usedSyms.safeAdd(s)
|
for s in scope.usingSyms: usedSyms.safeAdd(s)
|
||||||
|
|
||||||
proc resolveOverloads(c: PContext, n, orig: PNode,
|
proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
filter: TSymKinds): TCandidate =
|
filter: TSymKinds;
|
||||||
|
errors: var CandidateErrors): TCandidate =
|
||||||
var initialBinding: PNode
|
var initialBinding: PNode
|
||||||
var alt: TCandidate
|
var alt: TCandidate
|
||||||
var f = n.sons[0]
|
var f = n.sons[0]
|
||||||
|
|
@ -137,7 +138,6 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
else:
|
else:
|
||||||
initialBinding = nil
|
initialBinding = nil
|
||||||
|
|
||||||
var errors: CandidateErrors
|
|
||||||
var usedSyms: seq[PNode]
|
var usedSyms: seq[PNode]
|
||||||
|
|
||||||
template pickBest(headSymbol: expr) =
|
template pickBest(headSymbol: expr) =
|
||||||
|
|
@ -207,7 +207,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
|
|
||||||
errors = @[]
|
errors = @[]
|
||||||
pickBest(f)
|
pickBest(f)
|
||||||
notFoundError(c, n, errors)
|
#notFoundError(c, n, errors)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -293,12 +293,32 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
|
||||||
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
||||||
result.typ = finalCallee.typ.sons[0]
|
result.typ = finalCallee.typ.sons[0]
|
||||||
|
|
||||||
|
proc canDeref(n: PNode): bool {.inline.} =
|
||||||
|
result = n.len >= 2 and (let t = n[1].typ;
|
||||||
|
t != nil and t.skipTypes({tyGenericInst}).kind in {tyPtr, tyRef})
|
||||||
|
|
||||||
|
proc tryDeref(n: PNode): PNode =
|
||||||
|
result = newNodeI(nkHiddenDeref, n.info)
|
||||||
|
result.typ = n.typ.skipTypes(abstractInst).sons[0]
|
||||||
|
result.addSon(n)
|
||||||
|
|
||||||
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||||
filter: TSymKinds): PNode =
|
filter: TSymKinds): PNode =
|
||||||
var r = resolveOverloads(c, n, nOrig, filter)
|
var errors: CandidateErrors
|
||||||
|
|
||||||
|
var r = resolveOverloads(c, n, nOrig, filter, errors)
|
||||||
if r.state == csMatch: result = semResolvedCall(c, n, r)
|
if r.state == csMatch: result = semResolvedCall(c, n, r)
|
||||||
|
elif experimentalMode(c) and canDeref(n):
|
||||||
|
# try to deref the first argument and then try overloading resolution again:
|
||||||
|
n.sons[1] = n.sons[1].tryDeref
|
||||||
|
var r = resolveOverloads(c, n, nOrig, filter, errors)
|
||||||
|
if r.state == csMatch: result = semResolvedCall(c, n, r)
|
||||||
|
else:
|
||||||
|
notFoundError(c, n, errors)
|
||||||
|
else:
|
||||||
|
notFoundError(c, n, errors)
|
||||||
# else: result = errorNode(c, n)
|
# else: result = errorNode(c, n)
|
||||||
|
|
||||||
proc explicitGenericInstError(n: PNode): PNode =
|
proc explicitGenericInstError(n: PNode): PNode =
|
||||||
localError(n.info, errCannotInstantiateX, renderTree(n))
|
localError(n.info, errCannotInstantiateX, renderTree(n))
|
||||||
result = n
|
result = n
|
||||||
|
|
|
||||||
|
|
@ -750,6 +750,18 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||||
incl(c.p.owner.flags, sfSideEffect)
|
incl(c.p.owner.flags, sfSideEffect)
|
||||||
|
|
||||||
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode
|
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||||
|
|
||||||
|
proc resolveIndirectCall(c: PContext; n, nOrig: PNode;
|
||||||
|
t: PType): TCandidate =
|
||||||
|
initCandidate(c, result, t)
|
||||||
|
matches(c, n, nOrig, result)
|
||||||
|
if result.state != csMatch:
|
||||||
|
# try to deref the first argument:
|
||||||
|
if experimentalMode(c) and canDeref(n):
|
||||||
|
n.sons[1] = n.sons[1].tryDeref
|
||||||
|
initCandidate(c, result, t)
|
||||||
|
matches(c, n, nOrig, result)
|
||||||
|
|
||||||
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
|
|
@ -773,9 +785,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
|
t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
|
||||||
if t != nil and t.kind == tyProc:
|
if t != nil and t.kind == tyProc:
|
||||||
# This is a proc variable, apply normal overload resolution
|
# This is a proc variable, apply normal overload resolution
|
||||||
var m: TCandidate
|
let m = resolveIndirectCall(c, n, nOrig, t)
|
||||||
initCandidate(c, m, t)
|
|
||||||
matches(c, n, nOrig, m)
|
|
||||||
if m.state != csMatch:
|
if m.state != csMatch:
|
||||||
if c.inCompilesContext > 0:
|
if c.inCompilesContext > 0:
|
||||||
# speed up error generation:
|
# speed up error generation:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue