{,List}AssignmentExpression: add support for RHS first evaluation order

Add a flag to {,List}AssignmentExpression that changes evaluation order
to RHS before LHS.

This will be used by YieldExpression.
Esse commit está contido em:
jan
2013-03-15 00:22:13 -07:00
commit de Sara Golemon
commit c2b38ad2b1
7 arquivos alterados com 77 adições e 40 exclusões
+1
Ver Arquivo
@@ -1841,6 +1841,7 @@ ExpressionPtr AliasManager::canonicalizeRecur(ExpressionPtr e) {
int n = e->getKidCount();
if (n < 2) delayVars = false;
if (e->is(Expression::KindOfAssignmentExpression)) delayVars = false;
m_inCall += inCall;
for (int j = delayVars ? 0 : 1; j < 2; j++) {
+56 -30
Ver Arquivo
@@ -2742,11 +2742,26 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
case Expression::KindOfAssignmentExpression: {
AssignmentExpressionPtr ae(
static_pointer_cast<AssignmentExpression>(node));
ExpressionPtr rhs = ae->getValue();
Id tempLocal = -1;
Offset start = InvalidAbsoluteOffset;
if (ae->isRhsFirst()) {
assert(!rhs->hasContext(Expression::RefValue));
tempLocal = emitVisitAndSetUnnamedL(e, rhs);
start = m_ue.bcPos();
}
visit(ae->getVariable());
emitClsIfSPropBase(e);
visit(ae->getValue());
if (ae->getValue()->hasContext(Expression::RefValue)) {
if (ae->isRhsFirst()) {
emitPushAndFreeUnnamedL(e, tempLocal, start);
} else {
visit(rhs);
}
if (rhs->hasContext(Expression::RefValue)) {
emitConvertToVar(e);
emitBind(e);
if (ae->hasAnyContext(Expression::AccessContext|
@@ -3259,9 +3274,19 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
ListAssignmentPtr la(static_pointer_cast<ListAssignment>(node));
ExpressionPtr rhs = la->getArray();
if (!rhs) {
// visitListAssignmentLHS should have handled this
assert(false);
// visitListAssignmentLHS should have handled this
assert(rhs);
bool nullRHS = la->getRHSKind() == ListAssignment::Null;
// Assign RHS to temp local, unless it's already a simple variable
bool simpleRHS = rhs->is(Expression::KindOfSimpleVariable)
&& !static_pointer_cast<SimpleVariable>(rhs)->getAlwaysStash();
Id tempLocal = -1;
Offset start = InvalidAbsoluteOffset;
if (!simpleRHS && la->isRhsFirst()) {
tempLocal = emitVisitAndSetUnnamedL(e, rhs);
start = m_ue.bcPos();
}
// We use "index chains" to deal with nested list assignment. We will
@@ -3271,19 +3296,10 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
IndexChain workingChain;
visitListAssignmentLHS(e, la, workingChain, indexChains);
bool nullRHS = la->getRHSKind() == ListAssignment::Null;
// Assign RHS to temp local, unless it's already a simple variable
bool simpleRHS = rhs->is(Expression::KindOfSimpleVariable)
&& !static_pointer_cast<SimpleVariable>(rhs)->getAlwaysStash();
Id tempLocal = -1;
Offset start = InvalidAbsoluteOffset;
if (!simpleRHS) {
tempLocal = m_curFunc->allocUnnamedLocal();
emitVirtualLocal(tempLocal);
visit(rhs);
emitConvertToCell(e);
emitSet(e);
emitPop(e);
if (!simpleRHS && !la->isRhsFirst()) {
assert(tempLocal == -1);
assert(start == InvalidAbsoluteOffset);
tempLocal = emitVisitAndSetUnnamedL(e, rhs);
start = m_ue.bcPos();
}
@@ -3319,20 +3335,9 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
if (simpleRHS) {
visit(rhs);
} else {
emitVirtualLocal(tempLocal);
emitCGet(e);
emitPushAndFreeUnnamedL(e, tempLocal, start);
}
// Null out and free unnamed local
if (!simpleRHS) {
assert(tempLocal >= 0);
assert(start != InvalidAbsoluteOffset);
newFaultRegion(start, m_ue.bcPos(),
new UnsetUnnamedLocalThunklet(tempLocal));
emitVirtualLocal(tempLocal);
emitUnset(e);
m_curFunc->freeUnnamedLocal(tempLocal);
}
return true;
}
@@ -4151,6 +4156,27 @@ void EmitterVisitor::emitVGet(Emitter& e) {
}
}
Id EmitterVisitor::emitVisitAndSetUnnamedL(Emitter& e, ExpressionPtr exp) {
Id tempLocal = m_curFunc->allocUnnamedLocal();
emitVirtualLocal(tempLocal);
visit(exp);
emitConvertToCell(e);
emitSet(e);
emitPop(e);
return tempLocal;
}
void EmitterVisitor::emitPushAndFreeUnnamedL(Emitter& e, Id tempLocal, Offset start) {
assert(tempLocal >= 0);
assert(start != InvalidAbsoluteOffset);
emitVirtualLocal(tempLocal);
emitCGet(e);
newFaultRegion(start, m_ue.bcPos(), new UnsetUnnamedLocalThunklet(tempLocal));
emitVirtualLocal(tempLocal);
emitUnset(e);
m_curFunc->freeUnnamedLocal(tempLocal);
}
EmitterVisitor::PassByRefKind EmitterVisitor::getPassByRefKind(ExpressionPtr exp) {
// The PassByRefKind of a list assignment expression is determined
// by the PassByRefKind of the RHS. This loop will repeatedly recurse
+2
Ver Arquivo
@@ -582,6 +582,8 @@ public:
template<class Expr> void emitVirtualClassBase(Emitter&, Expr* node);
void emitResolveClsBase(Emitter& e, int pos);
void emitClsIfSPropBase(Emitter& e);
Id emitVisitAndSetUnnamedL(Emitter& e, ExpressionPtr exp);
void emitPushAndFreeUnnamedL(Emitter& e, Id tempLocal, Offset start);
Label* getContinuationGotoLabel(StatementPtr s);
void emitContinuationSwitch(Emitter& e, SwitchStatementPtr s);
DataType analyzeSwitch(SwitchStatementPtr s, SwitchState& state);
@@ -42,9 +42,11 @@ using namespace HPHP;
AssignmentExpression::AssignmentExpression
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr variable, ExpressionPtr value, bool ref)
ExpressionPtr variable, ExpressionPtr value, bool ref,
bool rhsFirst /* = false */)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(AssignmentExpression)),
m_variable(variable), m_value(value), m_ref(ref) {
m_variable(variable), m_value(value), m_ref(ref), m_rhsFirst(rhsFirst) {
assert(!m_ref || !m_rhsFirst);
m_variable->setContext(Expression::DeepAssignmentLHS);
m_variable->setContext(Expression::AssignmentLHS);
m_variable->setContext(Expression::LValue);
@@ -135,7 +137,7 @@ void AssignmentExpression::analyzeProgram(AnalysisResultPtr ar) {
}
ConstructPtr AssignmentExpression::getNthKid(int n) const {
switch (n) {
switch (m_rhsFirst ? 1 - n : n) {
case 0:
return m_variable;
case 1:
@@ -152,7 +154,7 @@ int AssignmentExpression::getKidCount() const {
}
void AssignmentExpression::setNthKid(int n, ConstructPtr cp) {
switch (n) {
switch (m_rhsFirst ? 1 - n : n) {
case 0:
m_variable = boost::dynamic_pointer_cast<Expression>(cp);
break;
@@ -29,7 +29,7 @@ class AssignmentExpression : public Expression, public IParseHandler {
public:
AssignmentExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr variable, ExpressionPtr value,
bool ref);
bool ref, bool rhsFirst = false);
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
ExpressionPtr preOptimize(AnalysisResultConstPtr ar);
@@ -49,6 +49,7 @@ public:
ExpressionPtr getValue() { return m_value;}
void setVariable(ExpressionPtr v) { m_variable = v; }
void setValue(ExpressionPtr v) { m_value = v; }
bool isRhsFirst() { return m_rhsFirst; }
int getLocalEffects() const;
// $GLOBALS[<literal-string>] = <scalar>;
@@ -59,6 +60,7 @@ private:
ExpressionPtr m_variable;
ExpressionPtr m_value;
bool m_ref;
bool m_rhsFirst;
};
///////////////////////////////////////////////////////////////////////////////
+5 -4
Ver Arquivo
@@ -147,9 +147,10 @@ static bool AssignmentCouldSet(ExpressionListPtr vars, ExpressionPtr var) {
ListAssignment::ListAssignment
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionListPtr variables, ExpressionPtr array)
ExpressionListPtr variables, ExpressionPtr array, bool rhsFirst /* = false */)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ListAssignment)),
m_variables(variables), m_array(array), m_rhsKind(Regular) {
m_variables(variables), m_array(array), m_rhsKind(Regular),
m_rhsFirst(rhsFirst) {
setLValue();
if (m_array) {
@@ -217,7 +218,7 @@ void ListAssignment::analyzeProgram(AnalysisResultPtr ar) {
}
ConstructPtr ListAssignment::getNthKid(int n) const {
switch (n) {
switch (m_rhsFirst ? 1 - n : n) {
case 0:
return m_variables;
case 1:
@@ -234,7 +235,7 @@ int ListAssignment::getKidCount() const {
}
void ListAssignment::setNthKid(int n, ConstructPtr cp) {
switch (n) {
switch (m_rhsFirst ? 1 - n : n) {
case 0:
m_variables = boost::dynamic_pointer_cast<ExpressionList>(cp);
break;
+4 -1
Ver Arquivo
@@ -35,7 +35,8 @@ public:
Null
};
ListAssignment(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionListPtr variables, ExpressionPtr array);
ExpressionListPtr variables, ExpressionPtr array,
bool rhsFirst = false);
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
@@ -43,10 +44,12 @@ public:
ExpressionListPtr getVariables() const { return m_variables; }
ExpressionPtr getArray() const { return m_array; }
bool isRhsFirst() { return m_rhsFirst; }
private:
ExpressionListPtr m_variables;
ExpressionPtr m_array;
RHSKind m_rhsKind;
bool m_rhsFirst;
void setLValue();
};