fixes #1809; implements overloading based on 'var T'

This commit is contained in:
Araq
2015-03-14 22:21:43 +01:00
parent 1592067566
commit d4bca58b7d
4 changed files with 149 additions and 154 deletions

View File

@@ -24,7 +24,7 @@ type
ppEof = 1, # end of compiled pattern
ppOr, # we could short-cut the evaluation for 'and' and 'or',
ppAnd, # but currently we don't
ppNot,
ppNot,
ppSym,
ppAtom,
ppLit,
@@ -56,7 +56,7 @@ proc whichAlias*(p: PSym): TAliasRequest =
proc compileConstraints(p: PNode, result: var TPatternCode) =
case p.kind
of nkCallKinds:
if p.sons[0].kind != nkIdent:
if p.sons[0].kind != nkIdent:
patternError(p.sons[0])
return
let op = p.sons[0].ident
@@ -168,8 +168,8 @@ proc checkForSideEffects(n: PNode): TSideEffectAnalysis =
elif ret == seUnknown and result == seNoSideEffect:
result = seUnknown
type
TAssignableResult* = enum
type
TAssignableResult* = enum
arNone, # no l-value and no discriminant
arLValue, # is an l-value
arLocalLValue, # is an l-value, but local var; must not escape
@@ -183,26 +183,26 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
of nkSym:
# don't list 'skLet' here:
if n.sym.kind in {skVar, skResult, skTemp}:
if owner != nil and owner.id == n.sym.owner.id and
if owner != nil and owner.id == n.sym.owner.id and
sfGlobal notin n.sym.flags:
result = arLocalLValue
else:
result = arLValue
of nkDotExpr:
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
{tyVar, tyPtr, tyRef}:
result = arLValue
else:
result = isAssignable(owner, n.sons[0])
if result != arNone and sfDiscriminant in n.sons[1].sym.flags:
result = arDiscriminant
of nkBracketExpr:
of nkDotExpr:
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
{tyVar, tyPtr, tyRef}:
{tyVar, tyPtr, tyRef}:
result = arLValue
else:
result = isAssignable(owner, n.sons[0])
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
if result != arNone and sfDiscriminant in n.sons[1].sym.flags:
result = arDiscriminant
of nkBracketExpr:
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
{tyVar, tyPtr, tyRef}:
result = arLValue
else:
result = isAssignable(owner, n.sons[0])
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
# Object and tuple conversions are still addressable, so we skip them
# XXX why is 'tyOpenArray' allowed here?
if skipTypes(n.typ, abstractPtrs-{tyTypeDesc}).kind in
@@ -211,9 +211,9 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
elif compareTypes(n.typ, n.sons[1].typ, dcEqIgnoreDistinct):
# types that are equal modulo distinction preserve l-value:
result = isAssignable(owner, n.sons[1])
of nkHiddenDeref, nkDerefExpr:
of nkHiddenDeref, nkDerefExpr, nkHiddenAddr:
result = arLValue
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
result = isAssignable(owner, n.sons[0])
of nkCallKinds:
# builtin slice keeps lvalue-ness:
@@ -221,24 +221,27 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
else:
discard
proc isLValue*(n: PNode): bool =
isAssignable(nil, n) in {arLValue, arLocalLValue}
proc matchNodeKinds*(p, n: PNode): bool =
# matches the parameter constraint 'p' against the concrete AST 'n'.
# matches the parameter constraint 'p' against the concrete AST 'n'.
# Efficiency matters here.
var stack {.noinit.}: array[0..MaxStackSize, bool]
# empty patterns are true:
stack[0] = true
var sp = 1
template push(x: bool) =
stack[sp] = x
inc sp
let code = p.strVal
var pc = 1
while true:
case TOpcode(code[pc])
of ppEof: break
of ppOr:
of ppOr:
stack[sp-2] = stack[sp-1] or stack[sp-2]
dec sp
of ppAnd:
@@ -264,4 +267,4 @@ proc matchNodeKinds*(p, n: PNode): bool =
of ppNoSideEffect: push checkForSideEffects(n) != seSideEffect
inc pc
result = stack[sp-1]

View File

@@ -191,21 +191,6 @@ proc complexDisambiguation(a, b: PType): int =
for i in 1 .. <a.len: x += a.sons[i].sumGeneric
for i in 1 .. <b.len: y += b.sons[i].sumGeneric
result = x - y
when false:
proc betterThan(a, b: PType): bool {.inline.} = a.sumGeneric > b.sumGeneric
if a.len > 1 and b.len > 1:
let aa = a.sons[1].sumGeneric
let bb = b.sons[1].sumGeneric
var a = a
var b = b
if aa < bb: swap(a, b)
# all must be better
for i in 2 .. <min(a.len, b.len):
if not a.sons[i].betterThan(b.sons[i]): return 0
# a must be longer or of the same length as b:
result = a.len - b.len
proc cmpCandidates*(a, b: TCandidate): int =
result = a.exactMatches - b.exactMatches
@@ -1463,6 +1448,12 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
else:
m.state = csNoMatch
return
if formal.typ.kind == tyVar:
if n.isLValue:
inc(m.genericMatches, 100)
else:
m.state = csNoMatch
return
var
# iterates over formal parameters