Identify direct children of yield expressions
[hiphop-php.git] / hphp / compiler / expression / expression.h
blobe11f94c3caa81f86c1c0da76a691f13a10b9ac26
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 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_EXPRESSION_H_
18 #define incl_HPHP_EXPRESSION_H_
20 #include "hphp/compiler/construct.h"
21 #include "hphp/compiler/analysis/type.h"
22 #include "hphp/compiler/analysis/analysis_result.h"
24 #define EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS \
25 BlockScopePtr scope, LocationPtr loc, Expression::KindOf kindOf
26 #define EXPRESSION_CONSTRUCTOR_BASE_PARAMETER_VALUES \
27 scope, loc, kindOf
28 #define EXPRESSION_CONSTRUCTOR_PARAMETERS \
29 BlockScopePtr scope, LocationPtr loc
30 #define EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(kindOf) \
31 scope, loc, Expression::KindOf##kindOf
32 #define EXPRESSION_CONSTRUCTOR_DERIVED_PARAMETER_VALUES \
33 scope, loc
34 #define DECLARE_BASE_EXPRESSION_VIRTUAL_FUNCTIONS \
35 virtual void analyzeProgram(AnalysisResultPtr ar); \
36 virtual ExpressionPtr clone(); \
37 virtual TypePtr inferTypes(AnalysisResultPtr ar, TypePtr type, \
38 bool coerce); \
39 virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
40 #define DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS \
41 DECLARE_BASE_EXPRESSION_VIRTUAL_FUNCTIONS; \
42 virtual ConstructPtr getNthKid(int n) const; \
43 virtual int getKidCount() const; \
44 virtual void setNthKid(int n, ConstructPtr cp)
46 namespace HPHP {
47 ///////////////////////////////////////////////////////////////////////////////
49 DECLARE_BOOST_TYPES(Statement);
50 DECLARE_BOOST_TYPES(Expression);
51 class Variant;
53 #define DECLARE_EXPRESSION_TYPES(x) \
54 x(ExpressionList, None), \
55 x(AssignmentExpression, Store), \
56 x(SimpleVariable, Load), \
57 x(DynamicVariable, Load), \
58 x(StaticMemberExpression, Load), \
59 x(ArrayElementExpression, Load), \
60 x(DynamicFunctionCall, Call), \
61 x(SimpleFunctionCall, Call), \
62 x(ScalarExpression, None), \
63 x(ObjectPropertyExpression, Load), \
64 x(ObjectMethodExpression, Call), \
65 x(ListAssignment, Store), \
66 x(NewObjectExpression, Call), \
67 x(UnaryOpExpression, Update), \
68 x(IncludeExpression, Call), \
69 x(BinaryOpExpression, Update), \
70 x(QOpExpression, None), \
71 x(ArrayPairExpression, None), \
72 x(ClassConstantExpression, Const), \
73 x(ParameterExpression, None), \
74 x(ModifierExpression, None), \
75 x(ConstantExpression, Const), \
76 x(EncapsListExpression, None), \
77 x(ClosureExpression, None), \
78 x(YieldExpression, None), \
79 x(UserAttribute, None)
81 class Expression : public Construct {
82 public:
83 #define DEC_EXPR_ENUM(x,t) KindOf##x
84 enum KindOf {
85 DECLARE_EXPRESSION_TYPES(DEC_EXPR_ENUM)
87 static const char *Names[];
88 enum ExprClass {
89 None,
90 Load = 1,
91 Store = 2,
92 Update = 3,
93 Const = 4,
94 Call = 8
97 enum Context {
98 NoContext = 0,
99 RValue = 0,
100 LValue = 1, // assignment exp; foreach stmt
101 Declaration = LValue | 2, // global or static stmt, or delayed var
102 NoLValueWrapper = 4, // ok to not have lval() wrapper
103 RefValue = 8, // &exp
104 NoRefWrapper = 0x10, // ok to not have ref() wrapper
105 ObjectContext = 0x20, // $obj->
106 InParameterExpression = 0x40,// for default value expression
107 ExistContext = 0x80, // isset(...) or empty(...) recursively
108 UnsetContext = 0x100, // Within unset(...), arr el recursively
109 AssignmentLHS = 0x200, // LHS in assignment
110 DeepAssignmentLHS = 0x400, // LHS in assignment, deep
111 InvokeArgument = 0x800, // Invoke arguments
112 RefParameter = 0x1000, // eg f(&$x)
113 OprLValue = 0x2000, // Lhs of op=, or operand of ++,--
114 DeepOprLValue = 0x4000, // LHS of op=, or operand of ++,--, deep
115 DeadStore = 0x8000, // This is an assignment, op=, or ++/--
116 // which can be killed
117 CondExpr = 0x10000, // Used by alias manager to track expressions
118 // which are conditionally executed
119 AssignmentRHS = 0x20000, // RHS in assignment
120 DeepReference = 0x40000, // Value is not available for copy propagation
121 // because it is referenced in some way
122 // eg $b in &$b['foo']
123 AccessContext = 0x80000, // ArrayElementExpression::m_variable or
124 // ObjectPropertyExpression::m_object
125 RefAssignmentLHS = 0x100000, // LHS of a reference assignment
126 ReturnContext = 0x200000, // Return expression
129 enum Order {
130 FixOrder = 1,
131 StashVars = 2,
132 StashKidVars = 4,
133 StashByRef = 8,
134 StashAll = 16,
135 ForceTemp = 32,
138 enum Error {
139 NoError = 0,
140 BadPassByRef = 1,
143 protected:
144 Expression(EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS);
146 public:
149 * Set this expression's context.
151 virtual void setContext(Context context) { m_context |= context;}
152 virtual void clearContext(Context context) { m_context &= ~context;}
153 void copyContext(ExpressionPtr from) { copyContext(from->m_context); }
154 void copyContext(int contexts);
155 ExpressionPtr replaceValue(ExpressionPtr rep);
156 void clearContext();
157 int getContext() const { return m_context;}
158 bool hasContext(Context context) const {
159 return (m_context & context) == context;
161 bool hasAnyContext(int context) const {
162 if ((context & Declaration) == Declaration) {
163 // special case Declaration because it is 2 bit fields
164 if (hasContext(Declaration)) return true;
165 // clear Declaration since we already checked for it
166 context &= ~Declaration;
168 return m_context & context;
170 bool hasAllContext(int context) const {
171 return (m_context & context) == context;
173 bool hasSubExpr(ExpressionPtr sub) const;
174 virtual void setComment(const std::string &) {}
175 virtual std::string getComment() { return ""; }
177 * Set this expression's error flags.
179 virtual void setError(Error error) { m_error |= error;}
180 virtual void clearError(Error error) { m_error &= ~error;}
181 int getError() const { return m_error;}
182 bool hasError(Error error) const { return m_error & error; }
184 ExprClass getExprClass() const;
185 virtual ExpressionPtr getStoreVariable() const { return ExpressionPtr(); }
186 void setArgNum(int n);
189 * Implementing Construct.
191 void collectCPPTemps(ExpressionPtrVec &collection);
192 void disableCSE();
193 bool hasChainRoots();
194 std::string genCPPTemp(CodeGenerator &cg, AnalysisResultPtr ar);
195 BlockScopeRawPtr getOriginalScope();
196 void setOriginalScope(BlockScopeRawPtr scope);
197 ClassScopeRawPtr getOriginalClass();
198 FunctionScopeRawPtr getOriginalFunction();
201 * For generic walks
203 virtual int getKidCount() const { return 0; }
204 ExpressionPtr getNthExpr(int n) const { return
205 boost::static_pointer_cast<Expression>(getNthKid(n)); }
208 * For cse & canonicalization
210 virtual unsigned getCanonHash() const;
211 virtual bool canonCompare(ExpressionPtr e) const;
212 bool equals(ExpressionPtr other);
213 void setCanonID(unsigned id) { m_canon_id = id; }
214 unsigned getCanonID() const { return m_canon_id; }
215 void setCanonPtr(ExpressionPtr e) { m_canonPtr = e; }
216 ExpressionPtr getCanonPtr() const {
217 return m_context & (LValue|RefValue|UnsetContext|DeepReference) ?
218 ExpressionPtr() : m_canonPtr;
220 ExpressionPtr getCanonLVal() const {
221 return m_canonPtr;
223 ExpressionPtr getNextCanonCsePtr() const;
224 ExpressionPtr getCanonCsePtr() const;
225 ExpressionPtr getCanonTypeInfPtr() const;
228 * Type checking without RTTI.
230 bool is(KindOf kindOf) const { return m_kindOf == kindOf;}
231 KindOf getKindOf() const { return m_kindOf;}
232 virtual bool isTemporary() const { return false; }
233 virtual bool isScalar() const { return false; }
234 bool isArray() const;
235 virtual bool isRefable(bool checkError = false) const { return false; }
236 virtual bool getScalarValue(Variant &value) { return false; }
237 FileScopeRawPtr getUsedScalarScope(CodeGenerator& cg);
238 bool getEffectiveScalar(Variant &value);
239 virtual ExpressionPtr clone() {
240 assert(false);
241 return ExpressionPtr();
243 virtual bool isThis() const { return false;}
244 virtual bool isLiteralString() const { return false;}
245 virtual bool isLiteralNull() const { return false;}
246 bool isUnquotedScalar() const;
247 virtual std::string getLiteralString() const { return "";}
248 virtual bool containsDynamicConstant(AnalysisResultPtr ar) const {
249 return false;
251 void deepCopy(ExpressionPtr exp);
252 virtual ExpressionPtr unneeded();
253 virtual ExpressionPtr unneededHelper();
256 * This is to avoid dynamic casting to ExpressionList in Parser.
258 virtual void addElement(ExpressionPtr exp);
259 virtual void insertElement(ExpressionPtr exp, int index = 0);
261 virtual void analyzeProgram(AnalysisResultPtr ar);
264 * Called before type inference.
266 virtual ExpressionPtr preOptimize(AnalysisResultConstPtr ar) {
267 return ExpressionPtr();
271 * Called after type inference.
273 virtual ExpressionPtr postOptimize(AnalysisResultConstPtr ar) {
274 return ExpressionPtr();
278 * Find other types that have been inferred for this expression,
279 * and combine them with inType to form a new, tighter type.
281 TypePtr propagateTypes(AnalysisResultConstPtr ar, TypePtr inType);
284 * Called when types need to be inferred inside this expression.
286 * When coerce is true, it means this expression will have to be able to
287 * hold that type of data. When it's false, it means as long as this
288 * expression can be converted to the type, we are fine.
290 * This is the key function to understand in order to understand type
291 * inference. Basically, "type" parameter is "expected" type, under
292 * either l-value context, when coerce == true, or r-value context, when
293 * coerce == false. But it's not always l-value context that "coerce" can
294 * be set to true, since for example, there are cases like foreach ($a ...)
295 * that we know $a needs to be an Array for sure. Some l-value context
296 * cannot set "coerce" to true, for example $a++, which doesn't actually
297 * change $a's type to anything new.
299 * Return type is ALWAYS an r-value type that this expression is evaluated
300 * to. It's always up to this expression's parent to determine whether this
301 * returned type is used as a "coerce"-d one or not onto another
302 * expression.
304 * @param type This expression is evaluated as this type.
305 * @coerce Whether to force this expression to be that type.
306 * @return What type this expression is evaluated to.
308 virtual TypePtr inferTypes(AnalysisResultPtr ar, TypePtr type,
309 bool coerce) = 0;
312 * Call inferTypes() and check to make sure return type is convertible
313 * to specified type. If not, raise a CodeError.
315 virtual TypePtr inferAndCheck(AnalysisResultPtr ar, TypePtr type,
316 bool coerce);
319 * Check to make sure return type is convertible to specified type.
320 * If not, raise a CodeError.
322 TypePtr checkTypesImpl(AnalysisResultConstPtr ar, TypePtr expectedType,
323 TypePtr actualType, bool coerce);
325 TypePtr getActualType() { return m_actualType; }
326 TypePtr getExpectedType() { return m_expectedType; }
327 TypePtr getImplementedType() { return m_implementedType; }
328 TypePtr getAssertedType() { return m_assertedType; }
330 void setActualType(TypePtr actualType) {
331 m_actualType = actualType;
333 void setExpectedType(TypePtr expectedType) {
334 m_expectedType = expectedType;
336 void setImplementedType(TypePtr implementedType) {
337 m_implementedType = implementedType;
339 void setAssertedType(TypePtr assertedType) {
340 m_assertedType = assertedType;
342 TypePtr getType();
343 TypePtr getGenType();
344 TypePtr getCPPType();
346 bool isTypeAssertion() const {
347 return isNoRemove() && m_assertedType;
350 static ExpressionPtr MakeConstant(AnalysisResultConstPtr ar,
351 BlockScopePtr scope,
352 LocationPtr loc,
353 const std::string &value);
354 static ExpressionPtr MakeScalarExpression(AnalysisResultConstPtr ar,
355 BlockScopePtr scope,
356 LocationPtr loc,
357 const Variant &value);
358 static void CheckPassByReference(AnalysisResultPtr ar,
359 ExpressionPtr param);
361 static bool CheckNeededRHS(ExpressionPtr value);
362 static bool CheckNeeded(ExpressionPtr variable, ExpressionPtr value);
363 static bool CheckVarNR(ExpressionPtr value, TypePtr expectedType = TypePtr());
365 static bool GetCseTempInfo(
366 AnalysisResultPtr ar, ExpressionPtr p, TypePtr &t);
368 bool isUnused() const { return m_unused; }
369 void setUnused(bool u) { m_unused = u; }
370 ExpressionPtr fetchReplacement();
371 void setReplacement(ExpressionPtr rep) { m_replacement = rep; }
374 * Correctly compute the local expression altered bit
376 void computeLocalExprAltered();
377 protected:
378 static bool IsIdentifier(const std::string &value);
380 int m_context;
381 int m_argNum;
383 private:
384 KindOf m_kindOf;
385 bool m_originalScopeSet;
386 bool m_unused;
387 unsigned m_canon_id;
388 mutable int m_error;
390 protected:
391 TypePtr m_actualType;
392 TypePtr m_expectedType; // null if the same as m_actualType
393 TypePtr m_implementedType; // null if the same as m_actualType
394 TypePtr m_assertedType;
396 TypePtr inferAssignmentTypes(AnalysisResultPtr ar, TypePtr type,
397 bool coerce, ExpressionPtr variable,
398 ExpressionPtr value = ExpressionPtr());
399 void setTypes(AnalysisResultConstPtr ar, TypePtr actualType,
400 TypePtr expectedType);
401 void setDynamicByIdentifier(AnalysisResultPtr ar,
402 const std::string &value);
403 void resetTypes();
404 private:
405 static ExprClass Classes[];
408 * Returns true if a type cast is needed, and sets src/dst type
410 bool getTypeCastPtrs(
411 AnalysisResultPtr ar, TypePtr &srcType, TypePtr &dstType);
413 BlockScopeRawPtr m_originalScope;
414 ExpressionPtr m_canonPtr;
415 ExpressionPtr m_replacement;
418 ///////////////////////////////////////////////////////////////////////////////
421 #endif // incl_HPHP_EXPRESSION_H_