diff options
Diffstat (limited to 'compiler/procfind.nim')
-rw-r--r-- | compiler/procfind.nim | 109 |
1 files changed, 34 insertions, 75 deletions
diff --git a/compiler/procfind.nim b/compiler/procfind.nim index 137765ddb..c2cc6e71f 100644 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -11,119 +11,78 @@ # This is needed for proper handling of forward declarations. import - ast, astalgo, msgs, semdata, types, trees, strutils + ast, astalgo, msgs, semdata, types, trees, lookups + +import std/strutils proc equalGenericParams(procA, procB: PNode): bool = - if sonsLen(procA) != sonsLen(procB): return - for i in countup(0, sonsLen(procA) - 1): - if procA.sons[i].kind != nkSym: - internalError(procA.info, "equalGenericParams") - return - if procB.sons[i].kind != nkSym: - internalError(procB.info, "equalGenericParams") - return - let a = procA.sons[i].sym - let b = procB.sons[i].sym + if procA.len != procB.len: return false + for i in 0..<procA.len: + if procA[i].kind != nkSym: + return false + if procB[i].kind != nkSym: + return false + let a = procA[i].sym + let b = procB[i].sym if a.name.id != b.name.id or not sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}): return if a.ast != nil and b.ast != nil: if not exprStructuralEquivalent(a.ast, b.ast): return result = true -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. - var it: TIdentIter - result = initIdentIter(it, scope.symbols, fn.name) - if isGenericRoutine(fn): - # we simply check the AST; this is imprecise but nearly the best what - # can be done; this doesn't work either though as type constraints are - # not kept in the AST .. - while result != nil: - if result.kind == fn.kind and isGenericRoutine(result): - let genR = result.ast.sons[genericParamsPos] - let genF = fn.ast.sons[genericParamsPos] - if exprStructuralEquivalent(genR, genF) and - exprStructuralEquivalent(result.ast.sons[paramsPos], - fn.ast.sons[paramsPos]) and - equalGenericParams(genR, genF): - return - result = nextIdentIter(it, scope.symbols) - else: - while result != nil: - if result.kind == fn.kind and not isGenericRoutine(result): - case equalParams(result.typ.n, fn.typ.n) - of paramsEqual: - return - of paramsIncompatible: - localError(fn.info, errNotOverloadable, fn.name.s) - return - of paramsNotEqual: - discard - result = nextIdentIter(it, scope.symbols) - -proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym = +proc searchForProcAux(c: PContext, scope: PScope, fn: PSym): PSym = const flags = {ExactGenericParams, ExactTypeDescValues, ExactConstraints, IgnoreCC} - - var it: TIdentIter - + var it: TIdentIter = default(TIdentIter) result = initIdentIter(it, scope.symbols, fn.name) while result != nil: - if result.kind == fn.kind and sameType(result.typ, fn.typ, flags): + if result.kind == fn.kind: #and sameType(result.typ, fn.typ, flags): case equalParams(result.typ.n, fn.typ.n) of paramsEqual: if (sfExported notin result.flags) and (sfExported in fn.flags): let message = ("public implementation '$1' has non-public " & - "forward declaration in $2") % - [getProcHeader(result), $result.info] - localError(fn.info, errGenerated, message) + "forward declaration at $2") % + [getProcHeader(c.config, result, getDeclarationPath = false), c.config$result.info] + localError(c.config, fn.info, message) return of paramsIncompatible: - localError(fn.info, errNotOverloadable, fn.name.s) + localError(c.config, fn.info, "overloaded '$1' leads to ambiguous calls" % fn.name.s) return of paramsNotEqual: discard - 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 +proc searchForProc*(c: PContext, scope: PScope, fn: PSym): tuple[proto: PSym, comesFromShadowScope: bool] = + var scope = scope + result = (searchForProcAux(c, scope, fn), false) + while result.proto == nil and scope.isShadowScope: + scope = scope.parent + result.proto = searchForProcAux(c, scope, fn) + result.comesFromShadowScope = true when false: proc paramsFitBorrow(child, parent: PNode): bool = - var length = sonsLen(child) result = false - if length == sonsLen(parent): - for i in countup(1, length - 1): - var m = child.sons[i].sym - var n = parent.sons[i].sym + if child.len == parent.len: + for i in 1..<child.len: + var m = child[i].sym + var n = parent[i].sym assert((m.kind == skParam) and (n.kind == skParam)) if not compareTypes(m.typ, n.typ, dcEqOrDistinctOf): return - if not compareTypes(child.sons[0].typ, parent.sons[0].typ, + if not compareTypes(child[0].typ, parent[0].typ, dcEqOrDistinctOf): return result = true proc searchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym = - # Searchs for the fn in the symbol table. If the parameter lists are suitable + # Searches for the fn in the symbol table. If the parameter lists are suitable # for borrowing the sym in the symbol table is returned, else nil. - var it: TIdentIter + var it: TIdentIter = default(TIdentIter) for scope in walkScopes(startScope): result = initIdentIter(it, scope.symbols, fn.Name) while result != nil: # watchout! result must not be the same as fn! if (result.Kind == fn.kind) and (result.id != fn.id): - if equalGenericParams(result.ast.sons[genericParamsPos], - fn.ast.sons[genericParamsPos]): + if equalGenericParams(result.ast[genericParamsPos], + fn.ast[genericParamsPos]): if paramsFitBorrow(fn.typ.n, result.typ.n): return result = NextIdentIter(it, scope.symbols) |