procfind.nim 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2013 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # This module implements the searching for procs and iterators.
  10. # This is needed for proper handling of forward declarations.
  11. import
  12. ast, astalgo, msgs, semdata, types, trees, strutils
  13. proc equalGenericParams(procA, procB: PNode): bool =
  14. if procA.len != procB.len: return false
  15. for i in 0..<procA.len:
  16. if procA[i].kind != nkSym:
  17. return false
  18. if procB[i].kind != nkSym:
  19. return false
  20. let a = procA[i].sym
  21. let b = procB[i].sym
  22. if a.name.id != b.name.id or
  23. not sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}): return
  24. if a.ast != nil and b.ast != nil:
  25. if not exprStructuralEquivalent(a.ast, b.ast): return
  26. result = true
  27. proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym =
  28. # Searches for a forward declaration or a "twin" symbol of fn
  29. # in the symbol table. If the parameter lists are exactly
  30. # the same the sym in the symbol table is returned, else nil.
  31. var it: TIdentIter
  32. result = initIdentIter(it, scope.symbols, fn.name)
  33. if isGenericRoutine(fn):
  34. # we simply check the AST; this is imprecise but nearly the best what
  35. # can be done; this doesn't work either though as type constraints are
  36. # not kept in the AST ..
  37. while result != nil:
  38. if result.kind == fn.kind and isGenericRoutine(result):
  39. let genR = result.ast[genericParamsPos]
  40. let genF = fn.ast[genericParamsPos]
  41. if exprStructuralEquivalent(genR, genF) and
  42. exprStructuralEquivalent(result.ast[paramsPos],
  43. fn.ast[paramsPos]) and
  44. equalGenericParams(genR, genF):
  45. return
  46. result = nextIdentIter(it, scope.symbols)
  47. else:
  48. while result != nil:
  49. if result.kind == fn.kind and not isGenericRoutine(result):
  50. case equalParams(result.typ.n, fn.typ.n)
  51. of paramsEqual:
  52. return
  53. of paramsIncompatible:
  54. localError(c.config, fn.info, "overloaded '$1' leads to ambiguous calls" % fn.name.s)
  55. return
  56. of paramsNotEqual:
  57. discard
  58. result = nextIdentIter(it, scope.symbols)
  59. proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
  60. const flags = {ExactGenericParams, ExactTypeDescValues,
  61. ExactConstraints, IgnoreCC}
  62. var it: TIdentIter
  63. result = initIdentIter(it, scope.symbols, fn.name)
  64. while result != nil:
  65. if result.kind == fn.kind: #and sameType(result.typ, fn.typ, flags):
  66. case equalParams(result.typ.n, fn.typ.n)
  67. of paramsEqual:
  68. if (sfExported notin result.flags) and (sfExported in fn.flags):
  69. let message = ("public implementation '$1' has non-public " &
  70. "forward declaration at $2") %
  71. [getProcHeader(c.config, result, getDeclarationPath = false), c.config$result.info]
  72. localError(c.config, fn.info, message)
  73. return
  74. of paramsIncompatible:
  75. localError(c.config, fn.info, "overloaded '$1' leads to ambiguous calls" % fn.name.s)
  76. return
  77. of paramsNotEqual:
  78. discard
  79. result = nextIdentIter(it, scope.symbols)
  80. proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
  81. result = searchForProcNew(c, scope, fn)
  82. when false:
  83. let old = searchForProcOld(c, scope, fn)
  84. if old != result:
  85. echo "Mismatch in searchForProc: ", fn.info
  86. debug fn.typ
  87. debug if result != nil: result.typ else: nil
  88. debug if old != nil: old.typ else: nil
  89. when false:
  90. proc paramsFitBorrow(child, parent: PNode): bool =
  91. result = false
  92. if child.len == parent.len:
  93. for i in 1..<child.len:
  94. var m = child[i].sym
  95. var n = parent[i].sym
  96. assert((m.kind == skParam) and (n.kind == skParam))
  97. if not compareTypes(m.typ, n.typ, dcEqOrDistinctOf): return
  98. if not compareTypes(child[0].typ, parent[0].typ,
  99. dcEqOrDistinctOf): return
  100. result = true
  101. proc searchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym =
  102. # Searches for the fn in the symbol table. If the parameter lists are suitable
  103. # for borrowing the sym in the symbol table is returned, else nil.
  104. var it: TIdentIter
  105. for scope in walkScopes(startScope):
  106. result = initIdentIter(it, scope.symbols, fn.Name)
  107. while result != nil:
  108. # watchout! result must not be the same as fn!
  109. if (result.Kind == fn.kind) and (result.id != fn.id):
  110. if equalGenericParams(result.ast[genericParamsPos],
  111. fn.ast[genericParamsPos]):
  112. if paramsFitBorrow(fn.typ.n, result.typ.n): return
  113. result = NextIdentIter(it, scope.symbols)