mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-18 23:11:36 +00:00
fixes #1809; implements overloading based on 'var T'
This commit is contained in:
@@ -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]
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user