procfind.nim 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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 sonsLen(procA) != sonsLen(procB): return
  15. for i in countup(0, sonsLen(procA) - 1):
  16. if procA.sons[i].kind != nkSym:
  17. internalError(procA.info, "equalGenericParams")
  18. return
  19. if procB.sons[i].kind != nkSym:
  20. internalError(procB.info, "equalGenericParams")
  21. return
  22. let a = procA.sons[i].sym
  23. let b = procB.sons[i].sym
  24. if a.name.id != b.name.id or
  25. not sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}): return
  26. if a.ast != nil and b.ast != nil:
  27. if not exprStructuralEquivalent(a.ast, b.ast): return
  28. result = true
  29. proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym =
  30. # Searchs for a forward declaration or a "twin" symbol of fn
  31. # in the symbol table. If the parameter lists are exactly
  32. # the same the sym in the symbol table is returned, else nil.
  33. var it: TIdentIter
  34. result = initIdentIter(it, scope.symbols, fn.name)
  35. if isGenericRoutine(fn):
  36. # we simply check the AST; this is imprecise but nearly the best what
  37. # can be done; this doesn't work either though as type constraints are
  38. # not kept in the AST ..
  39. while result != nil:
  40. if result.kind == fn.kind and isGenericRoutine(result):
  41. let genR = result.ast.sons[genericParamsPos]
  42. let genF = fn.ast.sons[genericParamsPos]
  43. if exprStructuralEquivalent(genR, genF) and
  44. exprStructuralEquivalent(result.ast.sons[paramsPos],
  45. fn.ast.sons[paramsPos]) and
  46. equalGenericParams(genR, genF):
  47. return
  48. result = nextIdentIter(it, scope.symbols)
  49. else:
  50. while result != nil:
  51. if result.kind == fn.kind and not isGenericRoutine(result):
  52. case equalParams(result.typ.n, fn.typ.n)
  53. of paramsEqual:
  54. return
  55. of paramsIncompatible:
  56. localError(fn.info, errNotOverloadable, fn.name.s)
  57. return
  58. of paramsNotEqual:
  59. discard
  60. result = nextIdentIter(it, scope.symbols)
  61. proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
  62. const flags = {ExactGenericParams, ExactTypeDescValues,
  63. ExactConstraints, IgnoreCC}
  64. var it: TIdentIter
  65. result = initIdentIter(it, scope.symbols, fn.name)
  66. while result != nil:
  67. if result.kind == fn.kind and sameType(result.typ, fn.typ, flags):
  68. case equalParams(result.typ.n, fn.typ.n)
  69. of paramsEqual:
  70. if (sfExported notin result.flags) and (sfExported in fn.flags):
  71. let message = ("public implementation '$1' has non-public " &
  72. "forward declaration in $2") %
  73. [getProcHeader(result), $result.info]
  74. localError(fn.info, errGenerated, message)
  75. return
  76. of paramsIncompatible:
  77. localError(fn.info, errNotOverloadable, fn.name.s)
  78. return
  79. of paramsNotEqual:
  80. discard
  81. result = nextIdentIter(it, scope.symbols)
  82. return nil
  83. proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
  84. result = searchForProcNew(c, scope, fn)
  85. when false:
  86. let old = searchForProcOld(c, scope, fn)
  87. if old != result:
  88. echo "Mismatch in searchForProc: ", fn.info
  89. debug fn.typ
  90. debug if result != nil: result.typ else: nil
  91. debug if old != nil: old.typ else: nil
  92. when false:
  93. proc paramsFitBorrow(child, parent: PNode): bool =
  94. var length = sonsLen(child)
  95. result = false
  96. if length == sonsLen(parent):
  97. for i in countup(1, length - 1):
  98. var m = child.sons[i].sym
  99. var n = parent.sons[i].sym
  100. assert((m.kind == skParam) and (n.kind == skParam))
  101. if not compareTypes(m.typ, n.typ, dcEqOrDistinctOf): return
  102. if not compareTypes(child.sons[0].typ, parent.sons[0].typ,
  103. dcEqOrDistinctOf): return
  104. result = true
  105. proc searchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym =
  106. # Searchs for the fn in the symbol table. If the parameter lists are suitable
  107. # for borrowing the sym in the symbol table is returned, else nil.
  108. var it: TIdentIter
  109. for scope in walkScopes(startScope):
  110. result = initIdentIter(it, scope.symbols, fn.Name)
  111. while result != nil:
  112. # watchout! result must not be the same as fn!
  113. if (result.Kind == fn.kind) and (result.id != fn.id):
  114. if equalGenericParams(result.ast.sons[genericParamsPos],
  115. fn.ast.sons[genericParamsPos]):
  116. if paramsFitBorrow(fn.typ.n, result.typ.n): return
  117. result = NextIdentIter(it, scope.symbols)