Scope.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Copyright (c) 2008 Roberto Raggi <[email protected]>
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. #include "Scope.h"
  21. #include "Symbols.h"
  22. #include "Names.h"
  23. #include "Literals.h"
  24. #include "Templates.h"
  25. #include "cppassert.h"
  26. #include <cstring>
  27. using namespace CPlusPlus;
  28. class CPlusPlus::SymbolTable
  29. {
  30. SymbolTable(const SymbolTable &other);
  31. void operator =(const SymbolTable &other);
  32. public:
  33. typedef Symbol **iterator;
  34. public:
  35. /// Constructs an empty Scope.
  36. SymbolTable(Scope *owner = 0);
  37. /// Destroy this scope.
  38. ~SymbolTable();
  39. /// Returns this scope's owner Symbol.
  40. Scope *owner() const;
  41. /// Sets this scope's owner Symbol.
  42. void setOwner(Scope *owner); // ### remove me
  43. /// Adds a Symbol to this Scope.
  44. void enterSymbol(Symbol *symbol);
  45. /// Returns true if this Scope is empty; otherwise returns false.
  46. bool isEmpty() const;
  47. /// Returns the number of symbols is in the scope.
  48. unsigned symbolCount() const;
  49. /// Returns the Symbol at the given position.
  50. Symbol *symbolAt(unsigned index) const;
  51. /// Returns the first Symbol in the scope.
  52. iterator firstSymbol() const;
  53. /// Returns the last Symbol in the scope.
  54. iterator lastSymbol() const;
  55. Symbol *lookat(const Identifier *id) const;
  56. Symbol *lookat(OperatorNameId::Kind operatorId) const;
  57. private:
  58. /// Returns the hash value for the given Symbol.
  59. unsigned hashValue(Symbol *symbol) const;
  60. /// Updates the hash table.
  61. void rehash();
  62. private:
  63. enum { DefaultInitialSize = 4 };
  64. Scope *_owner;
  65. Symbol **_symbols;
  66. Symbol **_hash;
  67. int _allocatedSymbols;
  68. int _symbolCount;
  69. int _hashSize;
  70. };
  71. SymbolTable::SymbolTable(Scope *owner)
  72. : _owner(owner),
  73. _symbols(0),
  74. _hash(0),
  75. _allocatedSymbols(0),
  76. _symbolCount(-1),
  77. _hashSize(0)
  78. { }
  79. SymbolTable::~SymbolTable()
  80. {
  81. if (_symbols)
  82. free(_symbols);
  83. if (_hash)
  84. free(_hash);
  85. }
  86. void SymbolTable::enterSymbol(Symbol *symbol)
  87. {
  88. CPP_ASSERT(! symbol->_enclosingScope || symbol->enclosingScope() == _owner, return);
  89. if (++_symbolCount == _allocatedSymbols) {
  90. _allocatedSymbols <<= 1;
  91. if (! _allocatedSymbols)
  92. _allocatedSymbols = DefaultInitialSize;
  93. _symbols = reinterpret_cast<Symbol **>(realloc(_symbols, sizeof(Symbol *) * _allocatedSymbols));
  94. }
  95. symbol->_index = _symbolCount;
  96. symbol->_enclosingScope = _owner;
  97. _symbols[_symbolCount] = symbol;
  98. if (_symbolCount * 5 >= _hashSize * 3)
  99. rehash();
  100. else {
  101. const unsigned h = hashValue(symbol);
  102. symbol->_next = _hash[h];
  103. _hash[h] = symbol;
  104. }
  105. }
  106. Symbol *SymbolTable::lookat(const Identifier *id) const
  107. {
  108. if (! _hash || ! id)
  109. return 0;
  110. const unsigned h = id->hashCode() % _hashSize;
  111. Symbol *symbol = _hash[h];
  112. for (; symbol; symbol = symbol->_next) {
  113. const Name *identity = symbol->unqualifiedName();
  114. if (! identity) {
  115. continue;
  116. } else if (const Identifier *nameId = identity->asNameId()) {
  117. if (nameId->identifier()->match(id))
  118. break;
  119. } else if (const TemplateNameId *t = identity->asTemplateNameId()) {
  120. if (t->identifier()->match(id))
  121. break;
  122. } else if (const DestructorNameId *d = identity->asDestructorNameId()) {
  123. if (d->identifier()->match(id))
  124. break;
  125. } else if (identity->isQualifiedNameId()) {
  126. return 0;
  127. } else if (const SelectorNameId *selectorNameId = identity->asSelectorNameId()) {
  128. if (selectorNameId->identifier()->match(id))
  129. break;
  130. }
  131. }
  132. return symbol;
  133. }
  134. Symbol *SymbolTable::lookat(OperatorNameId::Kind operatorId) const
  135. {
  136. if (! _hash)
  137. return 0;
  138. const unsigned h = operatorId % _hashSize;
  139. Symbol *symbol = _hash[h];
  140. for (; symbol; symbol = symbol->_next) {
  141. if (const Name *identity = symbol->unqualifiedName()) {
  142. if (const OperatorNameId *op = identity->asOperatorNameId()) {
  143. if (op->kind() == operatorId)
  144. break;
  145. }
  146. }
  147. }
  148. return symbol;
  149. }
  150. void SymbolTable::rehash()
  151. {
  152. _hashSize <<= 1;
  153. if (! _hashSize)
  154. _hashSize = DefaultInitialSize;
  155. _hash = reinterpret_cast<Symbol **>(realloc(_hash, sizeof(Symbol *) * _hashSize));
  156. std::memset(_hash, 0, sizeof(Symbol *) * _hashSize);
  157. for (int index = 0; index < _symbolCount + 1; ++index) {
  158. Symbol *symbol = _symbols[index];
  159. const unsigned h = hashValue(symbol);
  160. symbol->_next = _hash[h];
  161. _hash[h] = symbol;
  162. }
  163. }
  164. unsigned SymbolTable::hashValue(Symbol *symbol) const
  165. {
  166. if (! symbol)
  167. return 0;
  168. return symbol->hashCode() % _hashSize;
  169. }
  170. bool SymbolTable::isEmpty() const
  171. { return _symbolCount == -1; }
  172. unsigned SymbolTable::symbolCount() const
  173. { return _symbolCount + 1; }
  174. Symbol *SymbolTable::symbolAt(unsigned index) const
  175. {
  176. if (! _symbols)
  177. return 0;
  178. return _symbols[index];
  179. }
  180. SymbolTable::iterator SymbolTable::firstSymbol() const
  181. { return _symbols; }
  182. SymbolTable::iterator SymbolTable::lastSymbol() const
  183. { return _symbols + _symbolCount + 1; }
  184. Scope::Scope(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
  185. : Symbol(translationUnit, sourceLocation, name),
  186. _members(0),
  187. _startOffset(0),
  188. _endOffset(0)
  189. { }
  190. Scope::Scope(Clone *clone, Subst *subst, Scope *original)
  191. : Symbol(clone, subst, original)
  192. , _members(0)
  193. , _startOffset(original->_startOffset)
  194. , _endOffset(original->_endOffset)
  195. {
  196. for (iterator it = original->firstMember(), end = original->lastMember(); it != end; ++it)
  197. addMember(clone->symbol(*it, subst));
  198. }
  199. Scope::~Scope()
  200. { delete _members; }
  201. /// Adds a Symbol to this Scope.
  202. void Scope::addMember(Symbol *symbol)
  203. {
  204. if (! _members)
  205. _members = new SymbolTable(this);
  206. _members->enterSymbol(symbol);
  207. }
  208. /// Returns true if this Scope is empty; otherwise returns false.
  209. bool Scope::isEmpty() const
  210. { return _members ? _members->isEmpty() : true; }
  211. /// Returns the number of symbols is in the scope.
  212. unsigned Scope::memberCount() const
  213. { return _members ? _members->symbolCount() : 0; }
  214. /// Returns the Symbol at the given position.
  215. Symbol *Scope::memberAt(unsigned index) const
  216. { return _members ? _members->symbolAt(index) : 0; }
  217. /// Returns the first Symbol in the scope.
  218. Scope::iterator Scope::firstMember() const
  219. { return _members ? _members->firstSymbol() : 0; }
  220. /// Returns the last Symbol in the scope.
  221. Scope::iterator Scope::lastMember() const
  222. { return _members ? _members->lastSymbol() : 0; }
  223. Symbol *Scope::find(const Identifier *id) const
  224. { return _members ? _members->lookat(id) : 0; }
  225. Symbol *Scope::find(OperatorNameId::Kind operatorId) const
  226. { return _members ? _members->lookat(operatorId) : 0; }
  227. /// Set the start offset of the scope
  228. unsigned Scope::startOffset() const
  229. { return _startOffset; }
  230. void Scope::setStartOffset(unsigned offset)
  231. { _startOffset = offset; }
  232. /// Set the end offset of the scope
  233. unsigned Scope::endOffset() const
  234. { return _endOffset; }
  235. void Scope::setEndOffset(unsigned offset)
  236. { _endOffset = offset; }