PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/compiler/analysis/symbol_table.cpp

https://gitlab.com/iranjith4/hhvm
C++ | 318 lines | 245 code | 48 blank | 25 comment | 49 complexity | 4748775c3c87799c34b57a360ee51702 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2016 Facebook, Inc. (http://www.facebook.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. */
  16. #include "hphp/compiler/analysis/symbol_table.h"
  17. #include <map>
  18. #include "hphp/compiler/analysis/analysis_result.h"
  19. #include "hphp/compiler/analysis/class_scope.h"
  20. #include "hphp/compiler/analysis/file_scope.h"
  21. #include "hphp/compiler/analysis/function_scope.h"
  22. #include "hphp/compiler/expression/assignment_expression.h"
  23. #include "hphp/compiler/expression/constant_expression.h"
  24. #include "hphp/compiler/expression/expression_list.h"
  25. #include "hphp/compiler/expression/parameter_expression.h"
  26. #include "hphp/compiler/expression/simple_variable.h"
  27. #include "hphp/runtime/base/variable-serializer.h"
  28. #include "hphp/util/logger.h"
  29. #include "hphp/util/text-util.h"
  30. using namespace HPHP;
  31. ///////////////////////////////////////////////////////////////////////////////
  32. // Symbol
  33. void Symbol::import(BlockScopeRawPtr scope, const Symbol &src_sym) {
  34. setName(src_sym.getName());
  35. setSystem();
  36. if (src_sym.declarationSet()) {
  37. ConstructPtr sc = src_sym.getDeclaration();
  38. if (sc) sc->resetScope(scope);
  39. setDeclaration(sc);
  40. }
  41. if (src_sym.valueSet()) {
  42. ConstructPtr sc = src_sym.getValue();
  43. if (sc) sc->resetScope(scope);
  44. setValue(sc);
  45. }
  46. if (src_sym.isDynamic()) {
  47. setDynamic();
  48. }
  49. if (src_sym.isConstant()) {
  50. setConstant();
  51. }
  52. }
  53. bool Symbol::checkDefined() {
  54. if (isSystem()) return true;
  55. always_assert(m_flags.m_declaration_set);
  56. if (!m_declaration) return false;
  57. if (!m_declaration.unique()) return true;
  58. if (!m_flags.m_replaced) {
  59. Lock lock(BlockScope::s_constMutex);
  60. setDynamic();
  61. return false;
  62. }
  63. return true;
  64. }
  65. static inline
  66. std::string ExtractInitializer(AnalysisResultPtr ar, ExpressionPtr e) {
  67. switch (e->getKindOf()) {
  68. case Expression::KindOfParameterExpression:
  69. {
  70. auto p = static_pointer_cast<ParameterExpression>(e);
  71. if (!p->defaultValue()) return "";
  72. return p->defaultValue()->getText(ar);
  73. }
  74. default:
  75. // TODO(stephentu): this doesn't allow us to tell the difference between
  76. // something like:
  77. // class X { public $x; } versus
  78. // class X { public $x = null; }
  79. // we'll just end up treating both cases like the latter
  80. return e->getText(ar);
  81. }
  82. return "";
  83. }
  84. void Symbol::serializeParam(JSON::DocTarget::OutputStream &out) const {
  85. assert(isParameter());
  86. JSON::DocTarget::MapStream ms(out);
  87. ms.add("name", m_name);
  88. ms.add("initializer");
  89. if (m_value) {
  90. auto valueExp = dynamic_pointer_cast<Expression>(m_value);
  91. assert(valueExp);
  92. auto const init = ExtractInitializer(out.analysisResult(), valueExp);
  93. if (!init.empty()) out << init;
  94. else out << JSON::Null();
  95. } else {
  96. out << JSON::Null();
  97. }
  98. ms.done();
  99. }
  100. static inline std::string ExtractDocComment(ExpressionPtr e) {
  101. if (!e) return "";
  102. switch (e->getKindOf()) {
  103. case Expression::KindOfAssignmentExpression: {
  104. auto ae = static_pointer_cast<AssignmentExpression>(e);
  105. return ExtractDocComment(ae->getVariable());
  106. }
  107. case Expression::KindOfSimpleVariable: {
  108. auto sv = static_pointer_cast<SimpleVariable>(e);
  109. return sv->getDocComment();
  110. }
  111. case Expression::KindOfConstantExpression: {
  112. auto ce = static_pointer_cast<ConstantExpression>(e);
  113. return ce->getDocComment();
  114. }
  115. default: return "";
  116. }
  117. return "";
  118. }
  119. void Symbol::serializeClassVar(JSON::DocTarget::OutputStream &out) const {
  120. assert(!isParameter());
  121. JSON::DocTarget::MapStream ms(out);
  122. ms.add("name", m_name);
  123. ms.add("line", m_declaration ? m_declaration->line0() : 0);
  124. int mods = 0;
  125. if (isPublic()) mods |= AttrPublic;
  126. if (isProtected()) mods |= AttrProtected;
  127. if (isPrivate()) mods |= AttrPrivate;
  128. if (isStatic()) mods |= AttrStatic;
  129. ms.add("modifiers", mods);
  130. ms.add("initializer");
  131. if (m_initVal) {
  132. auto initExp = dynamic_pointer_cast<Expression>(m_initVal);
  133. assert(initExp);
  134. auto const init = ExtractInitializer(out.analysisResult(), initExp);
  135. if (!init.empty()) out << init;
  136. else out << JSON::Null();
  137. } else {
  138. out << JSON::Null();
  139. }
  140. auto const docs = ExtractDocComment(
  141. m_declaration ?
  142. dynamic_pointer_cast<Expression>(m_declaration) : ExpressionPtr());
  143. ms.add("docs", docs);
  144. ms.done();
  145. }
  146. ///////////////////////////////////////////////////////////////////////////////
  147. SymbolTable::SymbolTable(BlockScope &blockScope) :
  148. m_blockScope(blockScope) {
  149. }
  150. SymbolTable::~SymbolTable() {
  151. }
  152. void SymbolTable::import(SymbolTablePtr src) {
  153. assert(m_symbolMap.empty());
  154. for (unsigned int i = 0; i < src->m_symbolVec.size(); i++) {
  155. Symbol &src_sym = *src->m_symbolVec[i];
  156. Symbol &dst_sym = m_symbolMap[src_sym.getName()];
  157. m_symbolVec.push_back(&dst_sym);
  158. dst_sym.import(getBlockScope(), src_sym);
  159. }
  160. }
  161. FileScopeRawPtr SymbolTable::getFileScope() {
  162. return m_blockScope.getContainingFile();
  163. }
  164. FunctionScopeRawPtr SymbolTable::getFunctionScope() {
  165. return m_blockScope.getContainingFunction();
  166. }
  167. ClassScopeRawPtr SymbolTable::getClassScope() {
  168. return m_blockScope.getContainingClass();
  169. }
  170. bool SymbolTable::isPresent(const std::string &name) const {
  171. if (const Symbol *sym = getSymbol(name)) {
  172. return sym->isPresent();
  173. }
  174. return false;
  175. }
  176. bool SymbolTable::checkDefined(const std::string &name) {
  177. if (Symbol *sym = getSymbol(name)) {
  178. return sym->checkDefined();
  179. }
  180. return false;
  181. }
  182. bool SymbolTable::isSystem(const std::string &name) const {
  183. if (const Symbol *sym = getSymbol(name)) {
  184. return sym->isSystem();
  185. }
  186. return false;
  187. }
  188. ///////////////////////////////////////////////////////////////////////////////
  189. const Symbol *SymbolTable::getSymbolImpl(const std::string &name) const {
  190. std::map<std::string,Symbol>::const_iterator it = m_symbolMap.find(name);
  191. if (it != m_symbolMap.end()) {
  192. return &it->second;
  193. }
  194. return nullptr;
  195. }
  196. Symbol *SymbolTable::getSymbol(const std::string &name) {
  197. return const_cast<Symbol*>(getSymbolImpl(name));
  198. }
  199. const Symbol *SymbolTable::getSymbol(const std::string &name) const {
  200. return getSymbolImpl(name);
  201. }
  202. Symbol *SymbolTable::genSymbol(const std::string &name, bool konst) {
  203. std::map<std::string,Symbol>::iterator it = m_symbolMap.find(name);
  204. if (it != m_symbolMap.end()) {
  205. assert(konst == it->second.isConstant());
  206. return &it->second;
  207. }
  208. Symbol *sym = &m_symbolMap[name];
  209. sym->setName(name);
  210. if (konst) sym->setConstant();
  211. return sym;
  212. }
  213. Symbol *SymbolTable::genSymbol(const std::string &name, bool konst,
  214. ConstructPtr construct) {
  215. Symbol *sym = genSymbol(name, konst);
  216. if (!sym->declarationSet() && construct) {
  217. m_symbolVec.push_back(sym);
  218. sym->setDeclaration(construct);
  219. }
  220. return sym;
  221. }
  222. bool SymbolTable::isExplicitlyDeclared(const std::string &name) const {
  223. if (const Symbol *sym = getSymbol(name)) {
  224. return sym->valueSet();
  225. }
  226. return false;
  227. }
  228. ConstructPtr SymbolTable::getDeclaration(const std::string &name) const {
  229. if (const Symbol *sym = getSymbol(name)) {
  230. return sym->getDeclaration();
  231. }
  232. return ConstructPtr();
  233. }
  234. ConstructPtr SymbolTable::getValue(const std::string &name) const {
  235. if (const Symbol *sym = getSymbol(name)) {
  236. return sym->getValue();
  237. }
  238. return ConstructPtr();
  239. }
  240. static bool canonicalizeSymbolComp(const Symbol *s1, const Symbol *s2) {
  241. if (s1->isSystem() && !s2->isSystem()) return true;
  242. if (!s1->isSystem() && s2->isSystem()) return false;
  243. return s1->getName() < s2->getName();
  244. }
  245. void SymbolTable::canonicalizeSymbolOrder() {
  246. sort(m_symbolVec.begin(), m_symbolVec.end(), canonicalizeSymbolComp);
  247. }
  248. void SymbolTable::getSymbols(std::vector<Symbol*> &syms,
  249. bool filterHidden /* = false */) const {
  250. for (Symbol *sym: m_symbolVec) {
  251. if (!filterHidden || !sym->isHidden()) syms.push_back(sym);
  252. }
  253. }
  254. void SymbolTable::getSymbols(std::vector<std::string> &syms) const {
  255. for (Symbol *sym: m_symbolVec) {
  256. syms.push_back(sym->getName());
  257. }
  258. }
  259. ///////////////////////////////////////////////////////////////////////////////
  260. void SymbolTable::serialize(JSON::CodeError::OutputStream &out) const {
  261. std::vector<std::string> symbols;
  262. getSymbols(symbols);
  263. out << symbols;
  264. }
  265. std::string SymbolTable::getEscapedText(Variant v, int &len) {
  266. VariableSerializer vs(VariableSerializer::Type::Serialize);
  267. String str = vs.serialize(v, true);
  268. len = str.length();
  269. return escapeStringForCPP(str.data(), len);
  270. }