diff options
Diffstat (limited to 'rod/procfind.nim')
-rwxr-xr-x | rod/procfind.nim | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/rod/procfind.nim b/rod/procfind.nim new file mode 100755 index 000000000..bd5b3841f --- /dev/null +++ b/rod/procfind.nim @@ -0,0 +1,86 @@ +# +# +# The Nimrod Compiler +# (c) Copyright 2009 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# This module implements the searching for procs and iterators. +# This is needed for proper handling of forward declarations. + +import + ast, astalgo, msgs, semdata, types, trees + +proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym + # Searchs for the fn in the symbol table. If the parameter lists are exactly + # the same the sym in the symbol table is returned, else nil. +proc SearchForBorrowProc*(c: PContext, fn: PSym, tos: int): PSym + # Searchs 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. +# implementation + +proc equalGenericParams(procA, procB: PNode): bool = + var a, b: PSym + result = procA == procB + if result: return + if (procA == nil) or (procB == nil): return + if sonsLen(procA) != sonsLen(procB): return + for i in countup(0, sonsLen(procA) - 1): + if procA.sons[i].kind != nkSym: + InternalError(procA.info, "equalGenericParams") + if procB.sons[i].kind != nkSym: + InternalError(procB.info, "equalGenericParams") + a = procA.sons[i].sym + b = procB.sons[i].sym + if (a.name.id != b.name.id) or not sameTypeOrNil(a.typ, b.typ): return + if (a.ast != nil) and (b.ast != nil): + if not ExprStructuralEquivalent(a.ast, b.ast): return + result = true + +proc SearchForProc(c: PContext, fn: PSym, tos: int): PSym = + var it: TIdentIter + result = initIdentIter(it, c.tab.stack[tos], fn.Name) + while result != nil: + if (result.Kind == fn.kind): + if equalGenericParams(result.ast.sons[genericParamsPos], + fn.ast.sons[genericParamsPos]): + case equalParams(result.typ.n, fn.typ.n) + of paramsEqual: + return + of paramsIncompatible: + liMessage(fn.info, errNotOverloadable, fn.name.s) + return + of paramsNotEqual: + nil + result = NextIdentIter(it, c.tab.stack[tos]) + +proc paramsFitBorrow(a, b: PNode): bool = + var + length: int + m, n: PSym + length = sonsLen(a) + result = false + if length == sonsLen(b): + for i in countup(1, length - 1): + m = a.sons[i].sym + n = b.sons[i].sym + assert((m.kind == skParam) and (n.kind == skParam)) + if not equalOrDistinctOf(m.typ, n.typ): return + if not equalOrDistinctOf(a.sons[0].typ, b.sons[0].typ): return + result = true + +proc SearchForBorrowProc(c: PContext, fn: PSym, tos: int): PSym = + # Searchs 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 + for scope in countdown(tos, 0): + result = initIdentIter(it, c.tab.stack[scope], 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 paramsFitBorrow(fn.typ.n, result.typ.n): return + result = NextIdentIter(it, c.tab.stack[scope]) |