PageRenderTime 37ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/compiler/analysis/constant_table.cpp

https://gitlab.com/Blueprint-Marketing/hhvm
C++ | 244 lines | 201 code | 23 blank | 20 comment | 57 complexity | f2cedbbb5ea4779f41921fc260bbcc16 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2014 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/constant_table.h"
  17. #include <vector>
  18. #include "hphp/compiler/analysis/analysis_result.h"
  19. #include "hphp/compiler/analysis/code_error.h"
  20. #include "hphp/compiler/analysis/type.h"
  21. #include "hphp/compiler/code_generator.h"
  22. #include "hphp/compiler/expression/expression.h"
  23. #include "hphp/compiler/expression/scalar_expression.h"
  24. #include "hphp/compiler/option.h"
  25. #include "hphp/util/hash.h"
  26. #include "hphp/compiler/analysis/class_scope.h"
  27. using namespace HPHP;
  28. ///////////////////////////////////////////////////////////////////////////////
  29. ConstantTable::ConstantTable(BlockScope &blockScope)
  30. : SymbolTable(blockScope, true),
  31. m_hasDynamic(false) {
  32. }
  33. ///////////////////////////////////////////////////////////////////////////////
  34. TypePtr ConstantTable::add(const std::string &name, TypePtr type,
  35. ExpressionPtr exp, AnalysisResultConstPtr ar,
  36. ConstructPtr construct) {
  37. if (name == "true" || name == "false") {
  38. return Type::Boolean;
  39. }
  40. Symbol *sym = genSymbol(name, true);
  41. if (!sym->declarationSet()) {
  42. assert(!sym->valueSet());
  43. setType(ar, sym, type, true);
  44. sym->setDeclaration(construct);
  45. sym->setValue(exp);
  46. return type;
  47. }
  48. assert(sym->declarationSet() && sym->valueSet());
  49. if (m_blockScope.isFirstPass()) {
  50. if (construct) {
  51. if (exp != sym->getValue()) {
  52. Compiler::Error(Compiler::DeclaredConstantTwice, construct,
  53. sym->getDeclaration());
  54. if (!sym->isDynamic()) {
  55. sym->setDynamic();
  56. m_hasDynamic = true;
  57. }
  58. type = Type::Variant;
  59. }
  60. } else if (exp) {
  61. sym->setValue(exp);
  62. }
  63. setType(ar, sym, type, true);
  64. }
  65. return type;
  66. }
  67. void ConstantTable::setDynamic(AnalysisResultConstPtr ar,
  68. const std::string &name, bool forceVariant) {
  69. Symbol *sym = genSymbol(name, true);
  70. if (!sym->isDynamic()) {
  71. Lock lock(BlockScope::s_constMutex);
  72. sym->setDynamic();
  73. if (sym->getDeclaration()) {
  74. sym->getDeclaration()->getScope()->
  75. addUpdates(BlockScope::UseKindConstRef);
  76. }
  77. m_hasDynamic = true;
  78. if (forceVariant) {
  79. setType(ar, sym, Type::Variant, true);
  80. }
  81. }
  82. }
  83. void ConstantTable::setValue(AnalysisResultConstPtr ar, const std::string &name,
  84. ExpressionPtr value) {
  85. Symbol *sym = getSymbol(name);
  86. assert(sym && sym->isPresent());
  87. sym->setValue(value);
  88. }
  89. bool ConstantTable::isRecursivelyDeclared(AnalysisResultConstPtr ar,
  90. const std::string &name) const {
  91. if (const Symbol *sym ATTRIBUTE_UNUSED = getSymbol(name)) {
  92. assert(sym->isPresent() && sym->valueSet());
  93. return true;
  94. }
  95. ClassScopePtr parent = findParent(ar, name);
  96. if (parent) {
  97. return parent->getConstants()->isRecursivelyDeclared(ar, name);
  98. }
  99. return false;
  100. }
  101. ConstructPtr ConstantTable::getValueRecur(AnalysisResultConstPtr ar,
  102. const std::string &name,
  103. ClassScopePtr &defClass) const {
  104. if (const Symbol *sym = getSymbol(name)) {
  105. assert(sym->isPresent() && sym->valueSet());
  106. if (sym->getValue()) return sym->getValue();
  107. }
  108. ClassScopePtr parent = findParent(ar, name);
  109. if (parent) {
  110. defClass = parent;
  111. return parent->getConstants()->getValueRecur(ar, name, defClass);
  112. }
  113. return ConstructPtr();
  114. }
  115. ConstructPtr ConstantTable::getDeclarationRecur(AnalysisResultConstPtr ar,
  116. const std::string &name,
  117. ClassScopePtr &defClass)
  118. const {
  119. if (const Symbol *sym = getSymbol(name)) {
  120. assert(sym->isPresent() && sym->valueSet());
  121. if (sym->getDeclaration()) return sym->getDeclaration();
  122. }
  123. ClassScopePtr parent = findParent(ar, name);
  124. if (parent) {
  125. defClass = parent;
  126. return parent->getConstants()->getDeclarationRecur(ar, name, defClass);
  127. }
  128. return ConstructPtr();
  129. }
  130. void ConstantTable::cleanupForError(AnalysisResultConstPtr ar) {
  131. AnalysisResult::Locker lock(ar);
  132. for (Symbol *sym: m_symbolVec) {
  133. if (!sym->isDynamic()) {
  134. sym->setDynamic();
  135. sym->setDeclaration(ConstructPtr());
  136. sym->setValue(ConstructPtr());
  137. }
  138. }
  139. }
  140. TypePtr ConstantTable::check(BlockScopeRawPtr context,
  141. const std::string &name, TypePtr type,
  142. bool coerce, AnalysisResultConstPtr ar,
  143. ConstructPtr construct,
  144. const std::vector<std::string> &bases,
  145. BlockScope *&defScope) {
  146. assert(!m_blockScope.is(BlockScope::FunctionScope));
  147. bool isClassScope = m_blockScope.is(BlockScope::ClassScope);
  148. TypePtr actualType;
  149. defScope = nullptr;
  150. if (name == "true" || name == "false") {
  151. actualType = Type::Boolean;
  152. } else {
  153. Symbol *sym = getSymbol(name);
  154. if (!sym) {
  155. if (ar->getPhase() >= AnalysisResult::AnalyzeAll) {
  156. if (isClassScope) {
  157. ClassScopeRawPtr parent = findBase(ar, name, bases);
  158. if (parent) {
  159. actualType = parent->getConstants()->check(
  160. context, name, type, coerce, ar, construct, bases, defScope);
  161. if (defScope) return actualType;
  162. }
  163. }
  164. if (!isClassScope || !((ClassScope*)&m_blockScope)->isTrait()) {
  165. if (strcasecmp("class", name.c_str())) {
  166. Compiler::Error(Compiler::UseUndeclaredConstant, construct);
  167. }
  168. }
  169. actualType = isClassScope || !Option::WholeProgram ?
  170. Type::Variant : Type::String;
  171. }
  172. } else {
  173. assert(sym->isPresent());
  174. assert(sym->getType());
  175. assert(sym->isConstant());
  176. defScope = &m_blockScope;
  177. if (isClassScope) {
  178. // if the current scope is a function scope, grab the lock.
  179. // otherwise if it's a class scope, then *try* to grab the lock.
  180. if (context->is(BlockScope::FunctionScope)) {
  181. GET_LOCK(BlockScopeRawPtr(&m_blockScope));
  182. return setType(ar, sym, type, coerce);
  183. } else {
  184. TRY_LOCK(BlockScopeRawPtr(&m_blockScope));
  185. return setType(ar, sym, type, coerce);
  186. }
  187. } else {
  188. Lock lock(m_blockScope.getMutex());
  189. return setType(ar, sym, type, coerce);
  190. }
  191. }
  192. }
  193. return actualType;
  194. }
  195. ClassScopePtr ConstantTable::findParent(AnalysisResultConstPtr ar,
  196. const std::string &name) const {
  197. for (ClassScopePtr parent = m_blockScope.getParentScope(ar);
  198. parent && !parent->isRedeclaring();
  199. parent = parent->getParentScope(ar)) {
  200. if (parent->hasConst(name)) {
  201. return parent;
  202. }
  203. }
  204. return ClassScopePtr();
  205. }
  206. ClassScopeRawPtr ConstantTable::findBase(
  207. AnalysisResultConstPtr ar, const std::string &name,
  208. const std::vector<std::string> &bases) const {
  209. for (int i = bases.size(); i--; ) {
  210. ClassScopeRawPtr p = ar->findClass(bases[i]);
  211. if (!p || p->isRedeclaring()) continue;
  212. if (p->hasConst(name)) return p;
  213. ConstantTablePtr constants = p->getConstants();
  214. p = constants->findBase(ar, name, p->getBases());
  215. if (p) return p;
  216. }
  217. return ClassScopeRawPtr();
  218. }
  219. ///////////////////////////////////////////////////////////////////////////////
  220. void ConstantTable::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
  221. }