Use folly::dynamic::object and folly::dynamic::string exclusivly
[hiphop-php.git] / hphp / compiler / construct.h
blob2941ea1c6854405bd56962e0ae4527419d669092
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 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_CONSTRUCT_H_
18 #define incl_HPHP_CONSTRUCT_H_
20 #include "hphp/compiler/json.h"
21 #include "hphp/compiler/code_generator.h"
22 #include "hphp/compiler/analysis/code_error.h"
23 #include "hphp/compiler/analysis/block_scope.h"
25 namespace HPHP {
26 ///////////////////////////////////////////////////////////////////////////////
28 class Variant;
29 DECLARE_BOOST_TYPES(StatementList);
30 DECLARE_BOOST_TYPES(IParseHandler);
31 DECLARE_BOOST_TYPES(Location);
32 DECLARE_BOOST_TYPES(AnalysisResult);
33 DECLARE_BOOST_TYPES(BlockScope);
34 DECLARE_BOOST_TYPES(ClassScope);
35 DECLARE_BOOST_TYPES(FunctionScope);
36 DECLARE_BOOST_TYPES(FileScope);
38 class AstWalkerStateVec;
40 class IParseHandler {
41 /**
42 * To avoid iteration of parse tree, we move any work that can be done
43 * in parse phase into this function, so to speed up static analysis.
45 public:
46 virtual ~IParseHandler() {}
48 /**
49 * onParse is called by the parser when the construct has just been parsed
50 * to allow it to do any necessary work
52 virtual void onParse(AnalysisResultConstPtr ar, FileScopePtr scope) {
53 always_assert(0);
55 /**
56 * onParseRecur is called by a parent construct (ultimately a class or
57 * interface).
58 * This is done because at the time that onParse would be called for
59 * (eg) a method, the ClassScope doesnt exist. So we wait until onParse
60 * is called for the class, and it calls onParseRecur for its children.
62 virtual void onParseRecur(AnalysisResultConstPtr ar, ClassScopePtr scope) {
63 always_assert(0);
67 /**
68 * Base class of Expression and Statement.
70 class Construct : public std::enable_shared_from_this<Construct>,
71 public JSON::CodeError::ISerializable {
72 protected:
73 Construct(BlockScopePtr scope, LocationPtr loc);
74 public:
75 virtual ~Construct() {}
77 enum Effect {
78 NoEffect = 0,
79 IOEffect = 1, // could have an observable effect (not
80 // changing variable values)
81 AssignEffect = 2, // writes an object in a way understood by the
82 // alias manager
83 GlobalEffect = 4, // could affect global variables
84 LocalEffect = 8, // could affect variables from the local scope
85 ParamEffect = 0x10, // a function could affect its parameters
86 DeepParamEffect = 0x20, // a function could affect the array elements
87 // or object members referenced by its
88 // parameters
89 DynamicParamEffect = 0x40, // a function creates dynamic exps based
90 // on its parameters, which it could affect
91 CanThrow = 0x80, // can throw PHP exception
92 AccessorEffect = 0x100, // could contain a getter/setter
93 CreateEffect = 0x200, // could cause the creation of an array
94 // element or an object property
95 DiagnosticEffect = 0x400, // can cause a diagnostic to be issued
96 OtherEffect = 0x800, // something else
97 UnknownEffect = 0xfff // any of the above
100 LocationPtr getLocation() const { return m_loc;}
101 void setLocation(LocationPtr loc) { m_loc = loc;}
102 void setFileLevel() { m_flags.topLevel = m_flags.fileLevel = true;}
103 void setTopLevel() { m_flags.topLevel = true;}
104 void setVisited() { m_flags.visited = true;}
105 void clearVisited() { m_flags.visited = false;}
106 bool isFileLevel() const { return m_flags.fileLevel;}
107 bool isTopLevel() const { return m_flags.topLevel;}
108 bool isVisited() const { return m_flags.visited; }
110 void setAnticipated() { m_flags.anticipated = true; }
111 void clearAnticipated() { m_flags.anticipated = false; }
112 bool isAnticipated() const { return m_flags.anticipated; }
114 void setAvailable() { m_flags.available = true; }
115 void clearAvailable() { m_flags.available = false; }
116 bool isAvailable() const { return m_flags.available; }
118 void setNonNull() { m_flags.nonNull = true; }
119 void clearNonNull() { m_flags.nonNull = false; }
120 bool isNonNull() const { return m_flags.nonNull; }
122 void setLocalExprAltered() { m_flags.localExprNotAltered = false; }
123 void clearLocalExprAltered() { m_flags.localExprNotAltered = true; }
124 bool isLocalExprAltered() const { return !m_flags.localExprNotAltered; }
125 void setChainRoot() { m_flags.chainRoot = true; }
126 void clearChainRoot() { m_flags.chainRoot = false; }
127 bool isChainRoot() const { return m_flags.chainRoot; }
129 void setReferencedValid() { m_flags.referenced_valid = true; }
130 void clearReferencedValid() { m_flags.referenced_valid = false; }
131 bool isReferencedValid() const { return m_flags.referenced_valid; }
133 void setReferenced() { m_flags.referenced = true; }
134 void clearReferenced() { m_flags.referenced = false; }
135 bool isReferenced() const { return m_flags.referenced; }
137 void setNeededValid() { m_flags.needed_valid = true; }
138 void clearNeededValid() { m_flags.needed_valid = false; }
139 bool isNeededValid() const { return m_flags.needed_valid; }
141 void setNeeded() { m_flags.needed = true; }
142 void clearNeeded() { m_flags.needed = false; }
143 bool isNeeded() const { return m_flags.needed; }
145 void setNoRemove() { m_flags.noRemove = true; }
146 void clearNoRemove() { m_flags.noRemove = false; }
147 bool isNoRemove() const { return m_flags.noRemove; }
149 void setGuarded() { m_flags.guarded = true; }
150 void clearGuarded() { m_flags.guarded = false; }
151 bool isGuarded() const { return m_flags.guarded; }
153 void setRefCounted() { m_flags.refCounted = 3; }
154 void clearRefCounted() { m_flags.refCounted = 2; }
155 bool maybeRefCounted() const {
156 return !(m_flags.refCounted & 2) || (m_flags.refCounted & 1);
159 void setInited() { m_flags.inited = 3; }
160 void clearInited() { m_flags.inited = 2; }
161 bool maybeInited() const {
162 return !(m_flags.inited & 2) || (m_flags.inited & 1);
165 void setKilled() { m_flags.killed = true; }
166 void clearKilled() { m_flags.killed = false; }
167 bool isKilled() const { return m_flags.killed; }
169 BlockScopeRawPtr getScope() const { return m_blockScope; }
170 void setBlockScope(BlockScopeRawPtr scope) { m_blockScope = scope; }
171 FileScopeRawPtr getFileScope() const {
172 return m_blockScope->getContainingFile();
174 FunctionScopeRawPtr getFunctionScope() const {
175 return m_blockScope->getContainingFunction();
177 ClassScopeRawPtr getClassScope() const {
178 return m_blockScope->getContainingClass();
180 void resetScope(BlockScopeRawPtr scope, bool resetOrigScope=false);
181 void parseTimeFatal(Compiler::ErrorType error, const char *fmt, ...)
182 ATTRIBUTE_PRINTF(3,4);
183 void analysisTimeFatal(Compiler::ErrorType error, const char *fmt, ...)
184 ATTRIBUTE_PRINTF(3,4);
185 virtual int getLocalEffects() const { return UnknownEffect;}
186 int getChildrenEffects() const;
187 int getContainedEffects() const;
188 bool hasEffect() const { return getContainedEffects() != NoEffect;}
189 virtual bool kidUnused(int i) const { return false; }
191 template<typename T>
192 static std::shared_ptr<T> Clone(std::shared_ptr<T> constr) {
193 if (constr) {
194 return dynamic_pointer_cast<T>(constr->clone());
196 return std::shared_ptr<T>();
199 template<typename T>
200 std::shared_ptr<T> Clone(std::shared_ptr<T> constr,
201 BlockScopePtr scope) {
202 if (constr) {
203 constr = constr->clone();
204 constr->resetScope(scope);
206 return constr;
210 * Called when we analyze a program, which file it includes, which function
211 * and class it uses, etc.
213 virtual void analyzeProgram(AnalysisResultPtr ar) = 0;
216 * return the nth child construct
218 virtual ConstructPtr getNthKid(int n) const { return ConstructPtr(); }
221 * set the nth child construct
223 virtual void setNthKid(int n, ConstructPtr cp) {}
226 * get the kid count
228 virtual int getKidCount() const = 0;
230 // helpers for GDB
231 void dump(int spc, AnalysisResultPtr ar) {
232 AnalysisResultConstPtr arp(ar);
233 dump(spc, arp);
235 void dumpNode(int spc, AnalysisResultPtr ar) {
236 AnalysisResultConstPtr arp(ar);
237 dumpNode(spc, arp);
239 void dumpNode(int spc);
240 void dumpNode(int spc) const;
242 void dump(int spc, AnalysisResultConstPtr ar);
243 void dumpNode(int spc, AnalysisResultConstPtr ar);
245 static void dump(int spc, AnalysisResultConstPtr ar, bool functionOnly,
246 const AstWalkerStateVec &start,
247 ConstructPtr endBefore, ConstructPtr endAfter);
250 * Generates a serialized Code Model corresponding to this AST.
252 virtual void outputCodeModel(CodeGenerator &cg) = 0;
255 * Called when generating code.
257 virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) = 0;
260 * Implements JSON::CodeError::ISerializable.
262 virtual void serialize(JSON::CodeError::OutputStream &out) const;
265 * Get canonicalized PHP source code for this construct.
267 std::string getText(bool useCache, bool translate = false,
268 AnalysisResultPtr ar = AnalysisResultPtr());
270 std::string getText() { return getText(false); }
271 void recomputeEffects();
274 * Write where this construct was in PHP files.
276 void printSource(CodeGenerator &cg);
277 ExpressionPtr makeConstant(AnalysisResultConstPtr ar,
278 const std::string &value) const;
279 ExpressionPtr makeScalarExpression(AnalysisResultConstPtr ar,
280 const Variant &value) const;
281 private:
282 std::string m_text;
283 BlockScopeRawPtr m_blockScope;
284 union {
285 unsigned m_flagsVal;
286 struct {
287 unsigned fileLevel : 1; // is it at top level of a file
288 unsigned topLevel : 1; // is it at top level of a scope
289 unsigned visited : 1; // general purpose for walks
290 unsigned anticipated : 1;
291 unsigned available : 1;
292 unsigned localExprNotAltered : 1; // whether this node can be
293 // altered in this expression
294 unsigned nonNull : 1; // expression is not null
295 unsigned referenced : 1;
296 unsigned referenced_valid : 1; // is the above flag is valid
297 unsigned needed : 1;
298 unsigned needed_valid : 1; // is the above flag is valid
299 unsigned chainRoot : 1; // is this the begining of a
300 // CSE chain
301 unsigned noRemove : 1; // DCE should NOT remove this node
302 unsigned guarded : 1; // previously used
303 unsigned killed : 1;
304 unsigned refCounted : 2; // high bit indicates whether its valid
305 unsigned inited : 2; // high bit indicates whether its valid
306 } m_flags;
308 protected:
309 LocationPtr m_loc;
310 mutable int m_containedEffects;
311 mutable int m_effectsTag;
314 * Called by analyzeProgram() to add a reference to a user class or
315 * function.
317 void addUserFunction(AnalysisResultPtr ar, const std::string &name);
318 void addUserClass(AnalysisResultPtr ar, const std::string &name);
321 class LocalEffectsContainer {
322 public:
323 int getLocalEffects() const { return m_localEffects; }
324 virtual void effectsCallback() = 0;
325 protected:
326 explicit LocalEffectsContainer(Construct::Effect localEffect) :
327 m_localEffects(localEffect) {}
328 LocalEffectsContainer() :
329 m_localEffects(0) {}
330 void setLocalEffect (Construct::Effect effect);
331 void clearLocalEffect(Construct::Effect effect);
332 bool hasLocalEffect (Construct::Effect effect) const;
333 protected:
334 int m_localEffects;
337 #define DECL_AND_IMPL_LOCAL_EFFECTS_METHODS \
338 virtual int getLocalEffects() const { \
339 return LocalEffectsContainer::getLocalEffects(); \
341 virtual void effectsCallback() { recomputeEffects(); }
343 ///////////////////////////////////////////////////////////////////////////////
345 #endif // incl_HPHP_CONSTRUCT_H_