diff options
author | Zahary Karadjov <zahary@gmail.com> | 2013-12-30 02:13:50 +0200 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2013-12-30 10:57:12 +0200 |
commit | e3f53409f64a74e2f672a1624de17efc84be55ed (patch) | |
tree | beecf302214524b1d808426750cf6f25259e0d2b /compiler | |
parent | fa3bb8d66bfa18c3a497db2945df43703d809adc (diff) | |
download | Nim-e3f53409f64a74e2f672a1624de17efc84be55ed.tar.gz |
proc redefinition search based on the type system instead of on sloppy AST matching
This will work the same for procs/templates/macros/etc, having arbitrary mix of implicit and explicit generics (as long as the symbols are equivalent for the purposes of overload resolution, they will be detected as redefinitions) fixes tgeneric
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/procfind.nim | 26 | ||||
-rw-r--r-- | compiler/semtypes.nim | 16 | ||||
-rw-r--r-- | compiler/types.nim | 36 |
3 files changed, 48 insertions, 30 deletions
diff --git a/compiler/procfind.nim b/compiler/procfind.nim index f02e7aed4..eb0cbca3f 100644 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -30,7 +30,7 @@ proc equalGenericParams(procA, procB: PNode): bool = if not exprStructuralEquivalent(a.ast, b.ast): return result = true -proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym = +proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym = # Searchs for a forward declaration or a "twin" symbol of fn # in the symbol table. If the parameter lists are exactly # the same the sym in the symbol table is returned, else nil. @@ -63,6 +63,30 @@ proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym = nil result = nextIdentIter(it, scope.symbols) +proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym = + const flags = {ExactGenericParams, ExactTypeDescValues, + ExactConstraints, IgnoreCC} + + var it: TIdentIter + result = initIdentIter(it, scope.symbols, fn.name) + while result != nil: + if result.kind in skProcKinds and + sameType(result.typ, fn.typ, flags): return + + result = nextIdentIter(it, scope.symbols) + + return nil + +proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym = + result = searchForProcNew(c, scope, fn) + when false: + let old = searchForProcOld(c, scope, fn) + if old != result: + echo "Mismatch in searchForProc: ", fn.info + debug fn.typ + debug if result != nil: result.typ else: nil + debug if old != nil: old.typ else: nil + when false: proc paramsFitBorrow(child, parent: PNode): bool = var length = sonsLen(child) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 03d8b7095..175901057 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -827,22 +827,6 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType = dec(c.p.nestedBlockCounter) proc semGenericParamInInvokation(c: PContext, n: PNode): PType = - # XXX hack 1022 for generics ... would have been nice if the compiler had - # been designed with them in mind from start ... - when false: - if n.kind == nkSym: - # for generics we need to lookup the type var again: - var s = searchInScopes(c, n.sym.name) - if s != nil: - if s.kind == skType and s.typ != nil: - var t = n.sym.typ - echo "came here" - return t - else: - echo "s is crap:" - debug(s) - else: - echo "s is nil!!!!" result = semTypeNode(c, n, nil) proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = diff --git a/compiler/types.nim b/compiler/types.nim index 024cf4549..7403e29f9 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -606,8 +606,10 @@ type TTypeCmpFlag* = enum IgnoreTupleFields + IgnoreCC ExactTypeDescValues ExactGenericParams + ExactConstraints AllowCommonBase TTypeCmpFlags* = set[TTypeCmpFlag] @@ -637,15 +639,17 @@ proc sameTypeOrNilAux(a, b: PType, c: var TSameTypeClosure): bool = if a == nil or b == nil: result = false else: result = sameTypeAux(a, b, c) +proc sameType*(a, b: PType, flags: TTypeCmpFlags = {}): bool = + var c = initSameTypeClosure() + c.flags = flags + result = sameTypeAux(a, b, c) + proc sameTypeOrNil*(a, b: PType, flags: TTypeCmpFlags = {}): bool = if a == b: result = true - else: + else: if a == nil or b == nil: result = false - else: - var c = initSameTypeClosure() - c.flags = flags - result = sameTypeAux(a, b, c) + else: result = sameType(a, b, flags) proc equalParam(a, b: PSym): TParamsEquality = if sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}) and @@ -661,7 +665,15 @@ proc equalParam(a, b: PSym): TParamsEquality = result = paramsIncompatible else: result = paramsNotEqual - + +proc sameConstraints(a, b: PNode): bool = + internalAssert a.len == b.len + for i in 1 .. <a.len: + if not exprStructuralEquivalent(a[i].sym.constraint, + b[i].sym.constraint): + return false + return true + proc equalParams(a, b: PNode): TParamsEquality = result = paramsEqual var length = sonsLen(a) @@ -860,8 +872,9 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = else: result = sameFlags(a, b) of tyGenericParam: - result = if ExactGenericParams in c.flags: a.id == b.id - else: sameChildrenAux(a, b, c) and sameFlags(a, b) + result = sameChildrenAux(a, b, c) and sameFlags(a, b) + if result and ExactGenericParams in c.flags: + result = a.sym.position == b.sym.position of tyGenericInvokation, tyGenericBody, tySequence, tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr, tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter, @@ -869,7 +882,8 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = cycleCheck() result = sameChildrenAux(a, b, c) and sameFlags(a, b) if result and a.kind == tyProc: - result = a.callConv == b.callConv + result = ((IgnoreCC in c.flags) or a.callConv == b.callConv) and + ((ExactConstraints notin c.flags) or sameConstraints(a.n, b.n)) of tyRange: cycleCheck() result = sameTypeOrNilAux(a.sons[0], b.sons[0], c) and @@ -877,10 +891,6 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = sameValue(a.n.sons[1], b.n.sons[1]) of tyNone: result = false -proc sameType*(x, y: PType): bool = - var c = initSameTypeClosure() - result = sameTypeAux(x, y, c) - proc sameBackendType*(x, y: PType): bool = var c = initSameTypeClosure() c.flags.incl IgnoreTupleFields |