diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/parampatterns.nim | 41 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 21 |
2 files changed, 28 insertions, 34 deletions
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim index 8db786a25..58b5c5681 100644 --- a/compiler/parampatterns.nim +++ b/compiler/parampatterns.nim @@ -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}: + 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: + if result != arNone and sfDiscriminant in n.sons[1].sym.flags: result = arDiscriminant - of nkBracketExpr: + of nkBracketExpr: 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: + 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] - + diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index f1fd84326..e56d82a5b 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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 |