/rod/lookups.nim

https://github.com/comex/Nimrod · Nim · 244 lines · 190 code · 20 blank · 34 comment · 73 complexity · ee6b622b75ee43828e30a23f83625432 MD5 · raw file

  1. #
  2. #
  3. # The Nimrod Compiler
  4. # (c) Copyright 2009 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # This module implements lookup helpers.
  10. import
  11. ast, astalgo, idents, semdata, types, msgs, options, rodread, rnimsyn
  12. type
  13. TOverloadIterMode* = enum
  14. oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice
  15. TOverloadIter*{.final.} = object
  16. stackPtr*: int
  17. it*: TIdentIter
  18. m*: PSym
  19. mode*: TOverloadIterMode
  20. proc getSymRepr*(s: PSym): string
  21. proc CloseScope*(tab: var TSymTab)
  22. proc AddSym*(t: var TStrTable, n: PSym)
  23. proc addDecl*(c: PContext, sym: PSym)
  24. proc addDeclAt*(c: PContext, sym: PSym, at: Natural)
  25. proc addOverloadableSymAt*(c: PContext, fn: PSym, at: Natural)
  26. proc addInterfaceDecl*(c: PContext, sym: PSym)
  27. proc addInterfaceOverloadableSymAt*(c: PContext, sym: PSym, at: int)
  28. proc lookUp*(c: PContext, n: PNode): PSym
  29. # Looks up a symbol. Generates an error in case of nil.
  30. proc QualifiedLookUp*(c: PContext, n: PNode, ambiguousCheck: bool): PSym
  31. proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym
  32. proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym
  33. # implementation
  34. proc getSymRepr(s: PSym): string =
  35. case s.kind
  36. of skProc, skMethod, skConverter, skIterator: result = getProcHeader(s)
  37. else: result = s.name.s
  38. proc CloseScope(tab: var TSymTab) =
  39. var
  40. it: TTabIter
  41. s: PSym
  42. # check if all symbols have been used and defined:
  43. if (tab.tos > len(tab.stack)): InternalError("CloseScope")
  44. s = InitTabIter(it, tab.stack[tab.tos - 1])
  45. while s != nil:
  46. if sfForward in s.flags:
  47. liMessage(s.info, errImplOfXexpected, getSymRepr(s))
  48. elif ({sfUsed, sfInInterface} * s.flags == {}) and
  49. (optHints in s.options): # BUGFIX: check options in s!
  50. if not (s.kind in {skForVar, skParam, skMethod, skUnknown}):
  51. liMessage(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
  52. s = NextIter(it, tab.stack[tab.tos - 1])
  53. astalgo.rawCloseScope(tab)
  54. proc AddSym(t: var TStrTable, n: PSym) =
  55. if StrTableIncl(t, n): liMessage(n.info, errAttemptToRedefine, n.name.s)
  56. proc addDecl(c: PContext, sym: PSym) =
  57. if SymTabAddUnique(c.tab, sym) == Failure:
  58. liMessage(sym.info, errAttemptToRedefine, sym.Name.s)
  59. proc addDeclAt(c: PContext, sym: PSym, at: Natural) =
  60. if SymTabAddUniqueAt(c.tab, sym, at) == Failure:
  61. liMessage(sym.info, errAttemptToRedefine, sym.Name.s)
  62. proc AddInterfaceDeclAux(c: PContext, sym: PSym) =
  63. if (sfInInterface in sym.flags):
  64. # add to interface:
  65. if c.module == nil: InternalError(sym.info, "AddInterfaceDeclAux")
  66. StrTableAdd(c.module.tab, sym)
  67. if getCurrOwner().kind == skModule: incl(sym.flags, sfGlobal)
  68. proc addInterfaceDeclAt*(c: PContext, sym: PSym, at: Natural) =
  69. addDeclAt(c, sym, at)
  70. AddInterfaceDeclAux(c, sym)
  71. proc addOverloadableSymAt(c: PContext, fn: PSym, at: Natural) =
  72. if not (fn.kind in OverloadableSyms):
  73. InternalError(fn.info, "addOverloadableSymAt")
  74. var check = StrTableGet(c.tab.stack[at], fn.name)
  75. if (check != nil) and not (check.Kind in OverloadableSyms):
  76. liMessage(fn.info, errAttemptToRedefine, fn.Name.s)
  77. SymTabAddAt(c.tab, fn, at)
  78. proc addInterfaceDecl(c: PContext, sym: PSym) =
  79. # it adds the symbol to the interface if appropriate
  80. addDecl(c, sym)
  81. AddInterfaceDeclAux(c, sym)
  82. proc addInterfaceOverloadableSymAt(c: PContext, sym: PSym, at: int) =
  83. # it adds the symbol to the interface if appropriate
  84. addOverloadableSymAt(c, sym, at)
  85. AddInterfaceDeclAux(c, sym)
  86. proc lookUp(c: PContext, n: PNode): PSym =
  87. # Looks up a symbol. Generates an error in case of nil.
  88. case n.kind
  89. of nkAccQuoted:
  90. result = lookup(c, n.sons[0])
  91. of nkSym:
  92. #
  93. # result := SymtabGet(c.Tab, n.sym.name);
  94. # if result = nil then
  95. # liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s);
  96. result = n.sym
  97. of nkIdent:
  98. result = SymtabGet(c.Tab, n.ident)
  99. if result == nil: liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
  100. else: InternalError(n.info, "lookUp")
  101. if IdSetContains(c.AmbiguousSymbols, result.id):
  102. liMessage(n.info, errUseQualifier, result.name.s)
  103. if result.kind == skStub: loadStub(result)
  104. proc QualifiedLookUp(c: PContext, n: PNode, ambiguousCheck: bool): PSym =
  105. case n.kind
  106. of nkIdent:
  107. result = SymtabGet(c.Tab, n.ident)
  108. if result == nil:
  109. liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
  110. elif ambiguousCheck and IdSetContains(c.AmbiguousSymbols, result.id):
  111. liMessage(n.info, errUseQualifier, n.ident.s)
  112. of nkSym:
  113. #
  114. # result := SymtabGet(c.Tab, n.sym.name);
  115. # if result = nil then
  116. # liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s)
  117. # else
  118. result = n.sym
  119. if ambiguousCheck and IdSetContains(c.AmbiguousSymbols, result.id):
  120. liMessage(n.info, errUseQualifier, n.sym.name.s)
  121. of nkDotExpr:
  122. result = nil
  123. var m = qualifiedLookUp(c, n.sons[0], false)
  124. if (m != nil) and (m.kind == skModule):
  125. var ident: PIdent = nil
  126. if (n.sons[1].kind == nkIdent):
  127. ident = n.sons[1].ident
  128. elif (n.sons[1].kind == nkAccQuoted) and
  129. (n.sons[1].sons[0].kind == nkIdent):
  130. ident = n.sons[1].sons[0].ident
  131. if ident != nil:
  132. if m == c.module:
  133. result = StrTableGet(c.tab.stack[ModuleTablePos], ident)
  134. else:
  135. result = StrTableGet(m.tab, ident)
  136. if result == nil:
  137. liMessage(n.sons[1].info, errUndeclaredIdentifier, ident.s)
  138. else:
  139. liMessage(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1]))
  140. of nkAccQuoted:
  141. result = QualifiedLookup(c, n.sons[0], ambiguousCheck)
  142. else:
  143. result = nil #liMessage(n.info, errIdentifierExpected, '')
  144. if (result != nil) and (result.kind == skStub): loadStub(result)
  145. proc InitOverloadIter(o: var TOverloadIter, c: PContext, n: PNode): PSym =
  146. var ident: PIdent
  147. result = nil
  148. case n.kind
  149. of nkIdent:
  150. o.stackPtr = c.tab.tos
  151. o.mode = oimNoQualifier
  152. while (result == nil):
  153. dec(o.stackPtr)
  154. if o.stackPtr < 0: break
  155. result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident)
  156. while result != nil and sfFromGeneric in result.flags:
  157. result = nextOverloadIter(o, c, n)
  158. of nkSym:
  159. result = n.sym
  160. o.mode = oimDone #
  161. # o.stackPtr := c.tab.tos;
  162. # o.mode := oimNoQualifier;
  163. # while (result = nil) do begin
  164. # dec(o.stackPtr);
  165. # if o.stackPtr < 0 then break;
  166. # result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.sym.name);
  167. # end;
  168. of nkDotExpr:
  169. o.mode = oimOtherModule
  170. o.m = qualifiedLookUp(c, n.sons[0], false)
  171. if (o.m != nil) and (o.m.kind == skModule):
  172. ident = nil
  173. if (n.sons[1].kind == nkIdent):
  174. ident = n.sons[1].ident
  175. elif (n.sons[1].kind == nkAccQuoted) and
  176. (n.sons[1].sons[0].kind == nkIdent):
  177. ident = n.sons[1].sons[0].ident
  178. if ident != nil:
  179. if o.m == c.module:
  180. # a module may access its private members:
  181. result = InitIdentIter(o.it, c.tab.stack[ModuleTablePos], ident)
  182. o.mode = oimSelfModule
  183. else:
  184. result = InitIdentIter(o.it, o.m.tab, ident)
  185. else:
  186. liMessage(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1]))
  187. of nkAccQuoted:
  188. result = InitOverloadIter(o, c, n.sons[0])
  189. of nkSymChoice:
  190. o.mode = oimSymChoice
  191. result = n.sons[0].sym
  192. o.stackPtr = 1
  193. else:
  194. nil
  195. if (result != nil) and (result.kind == skStub): loadStub(result)
  196. proc nextOverloadIter(o: var TOverloadIter, c: PContext, n: PNode): PSym =
  197. case o.mode
  198. of oimDone:
  199. result = nil
  200. of oimNoQualifier:
  201. if n.kind == nkAccQuoted:
  202. result = nextOverloadIter(o, c, n.sons[0]) # BUGFIX
  203. elif o.stackPtr >= 0:
  204. result = nextIdentIter(o.it, c.tab.stack[o.stackPtr])
  205. while (result == nil):
  206. dec(o.stackPtr)
  207. if o.stackPtr < 0: break
  208. result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], o.it.name) # BUGFIX:
  209. # o.it.name <-> n.ident
  210. else:
  211. result = nil
  212. of oimSelfModule:
  213. result = nextIdentIter(o.it, c.tab.stack[ModuleTablePos])
  214. of oimOtherModule:
  215. result = nextIdentIter(o.it, o.m.tab)
  216. of oimSymChoice:
  217. if o.stackPtr < sonsLen(n):
  218. result = n.sons[o.stackPtr].sym
  219. inc(o.stackPtr)
  220. else:
  221. result = nil
  222. while result != nil and sfFromGeneric in result.flags:
  223. result = nextOverloadIter(o, c, n)
  224. if (result != nil) and (result.kind == skStub): loadStub(result)