2 +----------------------------------------------------------------------+
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 \
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 \
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, \
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)
47 ///////////////////////////////////////////////////////////////////////////////
49 DECLARE_BOOST_TYPES(Statement
);
50 DECLARE_BOOST_TYPES(Expression
);
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
{
83 #define DEC_EXPR_ENUM(x,t) KindOf##x
85 DECLARE_EXPRESSION_TYPES(DEC_EXPR_ENUM
)
87 static const char *Names
[];
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
144 Expression(EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS
);
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
);
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
);
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();
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 {
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() {
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 {
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
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
,
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
,
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
;
343 TypePtr
getGenType();
344 TypePtr
getCPPType();
346 bool isTypeAssertion() const {
347 return isNoRemove() && m_assertedType
;
350 static ExpressionPtr
MakeConstant(AnalysisResultConstPtr ar
,
353 const std::string
&value
);
354 static ExpressionPtr
MakeScalarExpression(AnalysisResultConstPtr ar
,
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();
378 static bool IsIdentifier(const std::string
&value
);
385 bool m_originalScopeSet
;
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
);
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_