Introduce YieldExpression

Unhack the parser and introduce YieldExpression that emits the
equivalent set of opcodes that were emitted by bunch of
expressions/statements generated by parser before.

YieldExpression expects evaluation stack to contain just the value
being yielded, so {,List}AssignmentExpression need to evaluate RHS
first. The previous code had the same behavior.

This will let us consolidate continuation-related opcodes and make
them less tied with continuation objects.
Esse commit está contido em:
jan
2013-03-12 12:03:00 -07:00
commit de Sara Golemon
commit 7b7343b56a
33 arquivos alterados com 41820 adições e 42231 exclusões
+1
Ver Arquivo
@@ -1551,6 +1551,7 @@ ExpressionPtr AliasManager::canonicalizeNode(
cur = next;
}
if (!m_inCall &&
!last->is(Expression::KindOfYieldExpression) &&
ae->isUnused() && m_accessList.isLast(ae) &&
!e->hasAnyContext(Expression::AccessContext |
Expression::ObjectContext |
+42 -24
Ver Arquivo
@@ -60,6 +60,7 @@
#include <compiler/expression/simple_function_call.h>
#include <compiler/expression/static_member_expression.h>
#include <compiler/expression/unary_op_expression.h>
#include <compiler/expression/yield_expression.h>
#include <compiler/statement/break_statement.h>
#include <compiler/statement/case_statement.h>
@@ -2180,6 +2181,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
ReturnStatementPtr r(static_pointer_cast<ReturnStatement>(node));
bool retV = false;
if (m_curFunc->isGenerator()) {
// used by yield break
e.ContExit();
return false;
}
@@ -3152,18 +3154,6 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
inputIsAnObject(0);
e.UnpackCont();
return true;
} else if (call->isCompilerCallToFunction("hphp_pack_continuation")) {
assert(params && params->getCount() == 3);
ExpressionPtr label = (*params)[1];
Variant lVar;
UNUSED bool isScalar = label->getScalarValue(lVar);
assert(isScalar && lVar.isInteger());
visit((*params)[2]);
emitConvertToCell(e);
inputIsAnObject(1);
e.PackCont(lVar.asInt64Val());
return false;
} else if (call->isCompilerCallToFunction("hphp_create_continuation")) {
assert(params && (params->getCount() == 3 ||
params->getCount() == 4));
@@ -3176,15 +3166,6 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
bool callGetArgs = params->getCount() == 4;
e.CreateCont(callGetArgs, nameStr);
return true;
} else if (call->isCompilerCallToFunction("hphp_continuation_raised")) {
inputIsAnObject(0);
e.ContRaised();
return false;
} else if (
call->isCompilerCallToFunction("hphp_continuation_receive")) {
inputIsAnObject(0);
e.ContReceive();
return true;
} else if (call->isCompilerCallToFunction("hphp_continuation_done")) {
inputIsAnObject(0);
e.ContDone();
@@ -3836,6 +3817,39 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
return true;
}
case Expression::KindOfYieldExpression: {
YieldExpressionPtr y(static_pointer_cast<YieldExpression>(node));
assert(m_evalStack.size() == 0);
// evaluate expression passed to yield
visit(y->getExpression());
emitConvertToCell(e);
// pack continuation and set the return label
assert(m_evalStack.size() == 1);
m_metaInfo.addKnownDataType(
KindOfObject, false, m_ue.bcPos(), false, 1);
e.PackCont(y->getLabel());
// transfer control
assert(m_evalStack.size() == 0);
e.ContExit();
// emit return label
StringData* nName = StringData::GetStaticString(
YIELD_LABEL_PREFIX + boost::lexical_cast<std::string>(y->getLabel()));
Label& lab = m_gotoLabels[nName];
lab.set(e);
// check for exception and retrieve result
assert(m_evalStack.size() == 0);
m_metaInfo.addKnownDataType(
KindOfObject, false, m_ue.bcPos(), false, 0);
e.ContReceive();
assert(m_evalStack.size() == 1);
return true;
}
}
}
@@ -4157,11 +4171,15 @@ 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);
// HACK: emitVirtualLocal would pollute m_evalStack before visiting exp,
// YieldExpression won't be happy
Id tempLocal = m_curFunc->allocUnnamedLocal();
e.getUnitEmitter().emitOp(OpSetL);
e.getUnitEmitter().emitIVA(tempLocal);
emitPop(e);
return tempLocal;
}
+1
Ver Arquivo
@@ -75,6 +75,7 @@ class Variant;
x(ConstantExpression, Const), \
x(EncapsListExpression, None), \
x(ClosureExpression, None), \
x(YieldExpression, None), \
x(UserAttribute, None)
class Expression : public Construct {
@@ -75,6 +75,7 @@ static ListAssignment::RHSKind GetRHSKind(ExpressionPtr rhs) {
case Expression::KindOfAssignmentExpression:
case Expression::KindOfExpressionList:
case Expression::KindOfIncludeExpression:
case Expression::KindOfYieldExpression:
return ListAssignment::Regular;
case Expression::KindOfListAssignment:
@@ -0,0 +1,91 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include <compiler/expression/yield_expression.h>
#include <compiler/analysis/function_scope.h>
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
YieldExpression::YieldExpression
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr exp, int label)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(YieldExpression)),
m_exp(exp), m_label(label) {
}
ExpressionPtr YieldExpression::clone() {
YieldExpressionPtr exp(new YieldExpression(*this));
Expression::deepCopy(exp);
exp->m_exp = Clone(m_exp);
exp->m_label = m_label;
return exp;
}
///////////////////////////////////////////////////////////////////////////////
// parser functions
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
void YieldExpression::analyzeProgram(AnalysisResultPtr ar) {
assert(getFunctionScope() && getFunctionScope()->isGenerator());
m_exp->analyzeProgram(ar);
}
ConstructPtr YieldExpression::getNthKid(int n) const {
switch (n) {
case 0:
return m_exp;
default:
assert(false);
break;
}
return ConstructPtr();
}
int YieldExpression::getKidCount() const {
return 1;
}
void YieldExpression::setNthKid(int n, ConstructPtr cp) {
switch (n) {
case 0:
m_exp = boost::dynamic_pointer_cast<Expression>(cp);
break;
default:
assert(false);
break;
}
}
TypePtr YieldExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
bool coerce) {
m_exp->inferAndCheck(ar, Type::Some, false);
return Type::Variant;
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void YieldExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
cg_printf("yield ");
m_exp->outputPHP(cg, ar);
}
+45
Ver Arquivo
@@ -0,0 +1,45 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef __YIELD_EXPRESSION_H__
#define __YIELD_EXPRESSION_H__
#include <compiler/expression/expression.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(YieldExpression);
class YieldExpression : public Expression {
public:
YieldExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr exp, int label);
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
ExpressionPtr getExpression() { return m_exp; }
int getLabel() { return m_label; }
private:
ExpressionPtr m_exp;
int m_label;
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // __YIELD_EXPRESSION_H__
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+10 -9
Ver Arquivo
@@ -42,6 +42,7 @@
#include <compiler/expression/constant_expression.h>
#include <compiler/expression/encaps_list_expression.h>
#include <compiler/expression/closure_expression.h>
#include <compiler/expression/yield_expression.h>
#include <compiler/expression/user_attribute.h>
#include <compiler/statement/function_statement.h>
@@ -115,8 +116,6 @@ extern void create_generator(Parser *_p, Token &out, Token &params,
const char *clsname, Token *modifiers,
bool getArgs, Token &origGenFunc, bool isHhvm,
Token *attr);
extern void transform_yield(Parser *_p, Token &stmts, int index,
Token *expr, bool assign);
extern void transform_yield_break(Parser *_p, Token &out);
namespace HPHP {
@@ -563,7 +562,8 @@ void Parser::onExprListElem(Token &out, Token *exprs, Token &expr) {
out->exp = expList;
}
void Parser::onListAssignment(Token &out, Token &vars, Token *expr) {
void Parser::onListAssignment(Token &out, Token &vars, Token *expr,
bool rhsFirst /* = false */) {
ExpressionListPtr el(dynamic_pointer_cast<ExpressionList>(vars->exp));
for (int i = 0; i < el->getCount(); i++) {
if (dynamic_pointer_cast<FunctionCall>((*el)[i])) {
@@ -572,7 +572,7 @@ void Parser::onListAssignment(Token &out, Token &vars, Token *expr) {
}
out->exp = NEW_EXP(ListAssignment,
dynamic_pointer_cast<ExpressionList>(vars->exp),
expr ? expr->exp : ExpressionPtr());
expr ? expr->exp : ExpressionPtr(), rhsFirst);
}
void Parser::onAListVar(Token &out, Token *list, Token *var) {
@@ -601,12 +601,13 @@ void Parser::checkAssignThis(Token &var) {
}
}
void Parser::onAssign(Token &out, Token &var, Token &expr, bool ref) {
void Parser::onAssign(Token &out, Token &var, Token &expr, bool ref,
bool rhsFirst /* = false */) {
if (dynamic_pointer_cast<FunctionCall>(var->exp)) {
PARSE_ERROR("Can't use return value in write context");
}
checkAssignThis(var);
out->exp = NEW_EXP(AssignmentExpression, var->exp, expr->exp, ref);
out->exp = NEW_EXP(AssignmentExpression, var->exp, expr->exp, ref, rhsFirst);
}
void Parser::onAssignNew(Token &out, Token &var, Token &name, Token &args) {
@@ -1404,14 +1405,14 @@ bool Parser::setIsGenerator() {
return true;
}
void Parser::onYield(Token &out, Token *expr, bool assign) {
void Parser::onYield(Token &out, Token &expr) {
if (!setIsGenerator()) {
return;
}
FunctionContext &funcContext = m_funcContexts.back();
int index = ++funcContext.numYields;
transform_yield(this, out, index, expr, assign);
int label = ++funcContext.numYields;
out->exp = NEW_EXP(YieldExpression, expr->exp, label);
}
void Parser::onYieldBreak(Token &out) {
+5 -3
Ver Arquivo
@@ -149,10 +149,12 @@ public:
void onObjectProperty(Token &out, Token &base, Token &prop);
void onObjectMethodCall(Token &out, Token &base, Token &prop, Token &params);
void onListAssignment(Token &out, Token &vars, Token *expr);
void onListAssignment(Token &out, Token &vars, Token *expr,
bool rhsFirst = false);
void onAListVar(Token &out, Token *list, Token *var);
void onAListSub(Token &out, Token *list, Token &sublist);
void onAssign(Token &out, Token &var, Token &expr, bool ref);
void onAssign(Token &out, Token &var, Token &expr, bool ref,
bool rhsFirst = false);
void onAssignNew(Token &out, Token &var, Token &name, Token &args);
void onNewObject(Token &out, Token &name, Token &args);
void onUnaryOpExp(Token &out, Token &operand, int op, bool front);
@@ -209,7 +211,7 @@ public:
void onBreak(Token &out, Token *expr);
void onContinue(Token &out, Token *expr);
void onReturn(Token &out, Token *expr, bool checkYield = true);
void onYield(Token &out, Token *expr, bool assign);
void onYield(Token &out, Token &expr);
void onYieldBreak(Token &out);
void onGlobal(Token &out, Token &expr);
void onGlobalVar(Token &out, Token *exprs, Token &expr);
-6
Ver Arquivo
@@ -3643,12 +3643,6 @@ PackCont <label id> [C] -> []
continuation as the result of the current iteration and the continuation's
label is set to <label id>.
ContRaised [] -> []
Check for continuation exception. If the continuation in local 0 has a
pending exception, this instruction will throw that exception. Otherwise, it
does nothing.
ContReceive [] -> [C]
Receive continuation value. If the continuation in local 0 has a pending
-39
Ver Arquivo
@@ -77,29 +77,6 @@ DefineFunction(
'taint_observer' => false,
));
DefineFunction(
array(
'name' => 'hphp_pack_continuation',
'return' => array(
'type' => null,
),
'args' => array(
array(
'name' => 'continuation',
'type' => Object,
),
array(
'name' => 'label',
'type' => Int64,
),
array(
'name' => 'value',
'type' => Variant,
),
),
'taint_observer' => false,
));
DefineFunction(
array(
'name' => 'hphp_unpack_continuation',
@@ -389,22 +366,6 @@ DefineFunction(
),
));
DefineFunction(
array(
'name' => 'raised',
'return' => array(
'type' => null,
),
));
DefineFunction(
array(
'name' => 'receive',
'return' => array(
'type' => Variant,
),
));
DefineFunction(
array(
'name' => 'getOrigFuncName',
-13
Ver Arquivo
@@ -40,11 +40,6 @@ p_Continuation f_hphp_create_continuation(CStrRef clsname,
return NULL;
}
void f_hphp_pack_continuation(CObjRef continuation,
int64_t label, CVarRef value) {
throw_fatal("Invalid call hphp_pack_continuation");
}
void f_hphp_unpack_continuation(CObjRef continuation) {
throw_fatal("Invalid call hphp_unpack_continuation");
}
@@ -168,14 +163,6 @@ void c_Continuation::t_raised() {
}
}
Variant c_Continuation::t_receive() {
if (m_should_throw) {
m_should_throw = false;
throw_exception(m_received);
}
return m_received;
}
String c_Continuation::t_getorigfuncname() {
String called_class;
if (actRec()->hasThis()) {
@@ -95,63 +95,6 @@ TypedValue* fg_hphp_create_continuation(HPHP::VM::ActRec *ar) {
/*
void HPHP::f_hphp_pack_continuation(HPHP::Object const&, long, HPHP::Variant const&)
_ZN4HPHP24f_hphp_pack_continuationERKNS_6ObjectElRKNS_7VariantE
continuation => rdi
label => rsi
value => rdx
*/
void fh_hphp_pack_continuation(Value* continuation, long label, TypedValue* value) asm("_ZN4HPHP24f_hphp_pack_continuationERKNS_6ObjectElRKNS_7VariantE");
TypedValue * fg1_hphp_pack_continuation(TypedValue* rv, HPHP::VM::ActRec* ar, int64_t count) __attribute__((noinline,cold));
TypedValue * fg1_hphp_pack_continuation(TypedValue* rv, HPHP::VM::ActRec* ar, int64_t count) {
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
rv->m_data.num = 0LL;
rv->m_type = KindOfNull;
if ((args-1)->m_type != KindOfInt64) {
tvCastToInt64InPlace(args-1);
}
if ((args-0)->m_type != KindOfObject) {
tvCastToObjectInPlace(args-0);
}
fh_hphp_pack_continuation((Value*)(args-0), (long)(args[-1].m_data.num), (args-2));
return rv;
}
TypedValue* fg_hphp_pack_continuation(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
if (count == 3LL) {
if ((args-1)->m_type == KindOfInt64 && (args-0)->m_type == KindOfObject) {
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
fh_hphp_pack_continuation((Value*)(args-0), (long)(args[-1].m_data.num), (args-2));
frame_free_locals_no_this_inl(ar, 3);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
fg1_hphp_pack_continuation(&rv, ar, count);
frame_free_locals_no_this_inl(ar, 3);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
}
} else {
throw_wrong_arguments_nr("hphp_pack_continuation", count, 3, 3, 1);
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_no_this_inl(ar, 3);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
void HPHP::f_hphp_unpack_continuation(HPHP::Object const&)
_ZN4HPHP26f_hphp_unpack_continuationERKNS_6ObjectE
@@ -833,79 +776,6 @@ TypedValue* tg_12Continuation_raise(HPHP::VM::ActRec *ar) {
return &ar->m_r;
}
/*
void HPHP::c_Continuation::t_raised()
_ZN4HPHP14c_Continuation8t_raisedEv
this_ => rdi
*/
void th_12Continuation_raised(ObjectData* this_) asm("_ZN4HPHP14c_Continuation8t_raisedEv");
TypedValue* tg_12Continuation_raised(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
th_12Continuation_raised((this_));
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("Continuation::raised", 0, 1);
}
} else {
throw_instance_method_fatal("Continuation::raised");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
HPHP::Variant HPHP::c_Continuation::t_receive()
_ZN4HPHP14c_Continuation9t_receiveEv
(return value) => rax
_rv => rdi
this_ => rsi
*/
TypedValue* th_12Continuation_receive(TypedValue* _rv, ObjectData* this_) asm("_ZN4HPHP14c_Continuation9t_receiveEv");
TypedValue* tg_12Continuation_receive(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
th_12Continuation_receive((&(rv)), (this_));
if (rv.m_type == KindOfUninit) rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("Continuation::receive", 0, 1);
}
} else {
throw_instance_method_fatal("Continuation::receive");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
HPHP::String HPHP::c_Continuation::t_getorigfuncname()
_ZN4HPHP14c_Continuation17t_getorigfuncnameEv
-11
Ver Arquivo
@@ -30,17 +30,6 @@ args => r8
Value* fh_hphp_create_continuation(Value* _rv, Value* clsname, Value* funcname, Value* origFuncName, Value* args) asm("_ZN4HPHP26f_hphp_create_continuationERKNS_6StringES2_S2_RKNS_5ArrayE");
/*
void HPHP::f_hphp_pack_continuation(HPHP::Object const&, long, HPHP::Variant const&)
_ZN4HPHP24f_hphp_pack_continuationERKNS_6ObjectElRKNS_7VariantE
continuation => rdi
label => rsi
value => rdx
*/
void fh_hphp_pack_continuation(Value* continuation, long label, TypedValue* value) asm("_ZN4HPHP24f_hphp_pack_continuationERKNS_6ObjectElRKNS_7VariantE");
/*
void HPHP::f_hphp_unpack_continuation(HPHP::Object const&)
_ZN4HPHP26f_hphp_unpack_continuationERKNS_6ObjectE
-2
Ver Arquivo
@@ -28,7 +28,6 @@ namespace HPHP {
FORWARD_DECLARE_CLASS_BUILTIN(Continuation);
FORWARD_DECLARE_CLASS_BUILTIN(ContinuationWaitHandle);
p_Continuation f_hphp_create_continuation(CStrRef clsname, CStrRef funcname, CStrRef origFuncName, CArrRef args = null_array);
void f_hphp_pack_continuation(CObjRef continuation, int64_t label, CVarRef value);
void f_hphp_unpack_continuation(CObjRef continuation);
///////////////////////////////////////////////////////////////////////////////
@@ -63,7 +62,6 @@ class c_Continuation : public ExtObjectData {
public: void t_send(CVarRef v);
public: void t_raise(CVarRef v);
public: void t_raised();
public: Variant t_receive();
public: String t_getorigfuncname();
public: Variant t___clone();
+2 -8
Ver Arquivo
@@ -191,7 +191,6 @@ TypedValue* fg_get_object_vars(VM::ActRec *ar);
TypedValue* fg_call_user_method_array(VM::ActRec *ar);
TypedValue* fg_call_user_method(VM::ActRec *ar);
TypedValue* fg_hphp_create_continuation(VM::ActRec *ar);
TypedValue* fg_hphp_pack_continuation(VM::ActRec *ar);
TypedValue* fg_hphp_unpack_continuation(VM::ActRec *ar);
TypedValue* fg_ctype_alnum(VM::ActRec *ar);
TypedValue* fg_ctype_alpha(VM::ActRec *ar);
@@ -2415,8 +2414,6 @@ TypedValue* tg_12Continuation_rewind(VM::ActRec *ar);
TypedValue* tg_12Continuation_valid(VM::ActRec *ar);
TypedValue* tg_12Continuation_send(VM::ActRec *ar);
TypedValue* tg_12Continuation_raise(VM::ActRec *ar);
TypedValue* tg_12Continuation_raised(VM::ActRec *ar);
TypedValue* tg_12Continuation_receive(VM::ActRec *ar);
TypedValue* tg_12Continuation_getOrigFuncName(VM::ActRec *ar);
TypedValue* tg_12Continuation___clone(VM::ActRec *ar);
VM::Instance* new_DummyContinuation_Instance(VM::Class*);
@@ -3024,7 +3021,7 @@ TypedValue* tg_9XMLWriter_endDTD(VM::ActRec *ar);
TypedValue* tg_9XMLWriter_flush(VM::ActRec *ar);
TypedValue* tg_9XMLWriter_outputMemory(VM::ActRec *ar);
const long long hhbc_ext_funcs_count = 2209;
const long long hhbc_ext_funcs_count = 2208;
const HhbcExtFuncInfo hhbc_ext_funcs[] = {
{ "apache_note", fg_apache_note, (void *)&fh_apache_note },
{ "apache_request_headers", fg_apache_request_headers, (void *)&fh_apache_request_headers },
@@ -3194,7 +3191,6 @@ const HhbcExtFuncInfo hhbc_ext_funcs[] = {
{ "call_user_method_array", fg_call_user_method_array, (void *)&fh_call_user_method_array },
{ "call_user_method", fg_call_user_method, (void *)&fh_call_user_method },
{ "hphp_create_continuation", fg_hphp_create_continuation, (void *)&fh_hphp_create_continuation },
{ "hphp_pack_continuation", fg_hphp_pack_continuation, (void *)&fh_hphp_pack_continuation },
{ "hphp_unpack_continuation", fg_hphp_unpack_continuation, (void *)&fh_hphp_unpack_continuation },
{ "ctype_alnum", fg_ctype_alnum, (void *)&fh_ctype_alnum },
{ "ctype_alpha", fg_ctype_alpha, (void *)&fh_ctype_alpha },
@@ -5468,7 +5464,7 @@ static const HhbcExtMethodInfo hhbc_ext_methods_TupleIterator[] = {
{ "rewind", tg_13TupleIterator_rewind }
};
static const long long hhbc_ext_method_count_Continuation = 19;
static const long long hhbc_ext_method_count_Continuation = 17;
static const HhbcExtMethodInfo hhbc_ext_methods_Continuation[] = {
{ "__construct", tg_12Continuation___construct },
{ "update", tg_12Continuation_update },
@@ -5485,8 +5481,6 @@ static const HhbcExtMethodInfo hhbc_ext_methods_Continuation[] = {
{ "valid", tg_12Continuation_valid },
{ "send", tg_12Continuation_send },
{ "raise", tg_12Continuation_raise },
{ "raised", tg_12Continuation_raised },
{ "receive", tg_12Continuation_receive },
{ "getOrigFuncName", tg_12Continuation_getOrigFuncName },
{ "__clone", tg_12Continuation___clone }
};
+2 -10
Ver Arquivo
@@ -7066,19 +7066,11 @@ inline void OPTBLD_INLINE VMExecutionContext::iopPackCont(PC& pc) {
}
inline void OPTBLD_INLINE VMExecutionContext::iopContReceive(PC& pc) {
NEXT();
c_Continuation* cont = frame_continuation(m_fp);
Variant val = cont->t_receive();
TypedValue* tv = m_stack.allocTV();
tvWriteUninit(tv);
tvAsVariant(tv) = val;
}
inline void OPTBLD_INLINE VMExecutionContext::iopContRaised(PC& pc) {
NEXT();
c_Continuation* cont = frame_continuation(m_fp);
cont->t_raised();
TypedValue* tv = m_stack.allocTV();
tvDup(cont->m_received.asTypedValue(), tv);
}
inline void OPTBLD_INLINE VMExecutionContext::iopContDone(PC& pc) {
-1
Ver Arquivo
@@ -556,7 +556,6 @@ enum SetOpOp {
O(ContExit, NA, NOV, NOV, CF) \
O(UnpackCont, NA, NOV, ONE(CV), NF) \
O(PackCont, ONE(IVA), ONE(CV), NOV, NF) \
O(ContRaised, NA, NOV, NOV, NF) \
O(ContReceive, NA, NOV, ONE(CV), NF) \
O(ContDone, NA, NOV, NOV, NF) \
O(ContNext, NA, NOV, NOV, NF) \
@@ -752,11 +752,6 @@ void HhbcTranslator::emitContReceive() {
push(value);
}
void HhbcTranslator::emitContRaised() {
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
m_tb->genContRaiseCheck(cont, getExitSlowTrace());
}
void HhbcTranslator::emitContDone() {
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
m_tb->genStRaw(cont, RawMemSlot::ContDone, m_tb->genDefConst(true));
@@ -346,7 +346,6 @@ struct HhbcTranslator {
void emitUnpackCont();
void emitPackCont(int64_t labelId);
void emitContReceive();
void emitContRaised();
void emitContDone();
void emitContNext();
void emitContSendImpl(bool raise);
@@ -633,11 +633,6 @@ void TranslatorX64::irTranslateContReceive(const Tracelet& t,
HHIR_EMIT(ContReceive);
}
void TranslatorX64::irTranslateContRaised(const Tracelet& t,
const NormalizedInstruction& i) {
HHIR_EMIT(ContRaised);
}
void TranslatorX64::irTranslateContDone(const Tracelet& t,
const NormalizedInstruction& i) {
HHIR_EMIT(ContDone);
@@ -7499,11 +7499,6 @@ void TranslatorX64::translateContReceive(const Tracelet& t,
emitCopyToStack(a, i, r(rScratch), -1 * (int)sizeof(Cell));
}
void TranslatorX64::translateContRaised(const Tracelet& t,
const NormalizedInstruction& i) {
emitContRaiseCheck(a, i);
}
void TranslatorX64::translateContEnter(const Tracelet& t,
const NormalizedInstruction& i) {
// We're about to execute the generator body, which uses regs
@@ -12383,7 +12378,6 @@ bool TranslatorX64::dumpTCData() {
SUPPORTED_OP(PackCont) \
SUPPORTED_OP(ContDone) \
SUPPORTED_OP(ContReceive) \
SUPPORTED_OP(ContRaised) \
SUPPORTED_OP(ContNext) \
SUPPORTED_OP(ContSend) \
SUPPORTED_OP(ContRaise) \
@@ -593,7 +593,6 @@ MINSTRS
CASE(UnpackCont) \
CASE(PackCont) \
CASE(ContReceive) \
CASE(ContRaised) \
CASE(ContDone) \
CASE(ContNext) \
CASE(ContSend) \
-2
Ver Arquivo
@@ -1201,7 +1201,6 @@ static const struct {
{ OpContExit, {None, None, OutNone, 0 }},
{ OpUnpackCont, {Local, Stack1, OutInt64, 1 }},
{ OpPackCont, {Local|Stack1, None, OutNone, -1 }},
{ OpContRaised, {Local, None, OutNone, 0 }},
{ OpContReceive, {Local, Stack1, OutUnknown, 1 }},
{ OpContDone, {Local, None, OutNone, 0 }},
{ OpContNext, {None, None, OutNone, 0 }},
@@ -1960,7 +1959,6 @@ void Translator::getInputs(Tracelet& t,
case OpUnpackCont:
case OpPackCont:
case OpContReceive:
case OpContRaised:
case OpContDone:
case OpContSend:
case OpContRaise:
-18
Ver Arquivo
@@ -7146,14 +7146,6 @@ const char *g_class_map[] = {
NULL,
NULL,
NULL,
(const char *)0x10006040, "hphp_pack_continuation", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from\n * http://php.net/manual/en/function.hphp-pack-continuation.php )\n *\n *\n * @continuation\n * object\n * @label int\n * @value mixed\n */",
(const char *)-1, (const char *)0x2000, "continuation", "", (const char *)0x40, "", "", NULL,
(const char *)0x2000, "label", "", (const char *)0xa, "", "", NULL,
(const char *)0x2000, "value", "", (const char *)0xffffffff, "", "", NULL,
NULL,
NULL,
NULL,
(const char *)0x10006040, "hphp_unpack_continuation", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from\n * http://php.net/manual/en/function.hphp-unpack-continuation.php )\n *\n *\n * @continuation\n * object\n */",
(const char *)-1, (const char *)0x2000, "continuation", "", (const char *)0x40, "", "", NULL,
@@ -22029,16 +22021,6 @@ const char *g_class_map[] = {
NULL,
NULL,
NULL,
(const char *)0x10006040, "raised", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/continuation.raised.php )\n *\n *\n */",
(const char *)-1, NULL,
NULL,
NULL,
(const char *)0x10006040, "receive", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/continuation.receive.php )\n *\n *\n * @return mixed\n */",
(const char *)0xffffffff, NULL,
NULL,
NULL,
(const char *)0x10006040, "getOrigFuncName", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/continuation.getorigfuncname.php\n * )\n *\n *\n * @return string\n */",
(const char *)0x14, NULL,
+1 -2
Ver Arquivo
@@ -2,13 +2,12 @@
#if EXT_TYPE == 0
"hphp_create_continuation", S(999), "Continuation", S(0), "clsname", T(String), NULL, S(0), NULL, S(0), "funcname", T(String), NULL, S(0), NULL, S(0), "origFuncName", T(String), NULL, S(0), NULL, S(0), "args", T(Array), "N;", S(2), "null", S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.hphp-create-continuation.php )\n *\n *\n * @clsname string\n * @funcname string\n * @origFuncName\n * string\n * @args map\n *\n * @return Continuation\n *\n */",
"hphp_pack_continuation", T(Void), S(0), "continuation", T(Object), NULL, S(0), NULL, S(0), "label", T(Int64), NULL, S(0), NULL, S(0), "value", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.hphp-pack-continuation.php )\n *\n *\n * @continuation\n * object\n * @label int\n * @value mixed\n */",
"hphp_unpack_continuation", T(Void), S(0), "continuation", T(Object), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.hphp-unpack-continuation.php )\n *\n *\n * @continuation\n * object\n */",
#elif EXT_TYPE == 1
#elif EXT_TYPE == 2
"Continuation", "", "iterator","awaitable",NULL, "__construct", T(Void), S(0), "func", T(Int64), NULL, S(0), NULL, S(0), "extra", T(Int64), NULL, S(0), NULL, S(0), "isMethod", T(Boolean), NULL, S(0), NULL, S(0), "origFuncName", T(String), NULL, S(0), NULL, S(0), "obj", T(Variant), "N;", S(2), "null", S(0), "args", T(Array), "N;", S(2), "null", S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.construct.php )\n *\n *\n * @func int\n * @extra int\n * @isMethod bool\n * @origFuncName\n * string\n * @obj mixed\n * @args map\n */", S(16384),"update", T(Void), S(0), "label", T(Int64), NULL, S(0), NULL, S(0), "value", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.update.php )\n *\n *\n * @label int\n * @value mixed\n */", S(16384),"done", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.done.php )\n *\n *\n */", S(16384),"getWaitHandle", T(Object), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getwaithandle.php )\n *\n * Start this continuation to the current scheduler context and return the\n * wait handle.\n *\n * @return object\n */", S(16384),"getLabel", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getlabel.php )\n *\n *\n * @return int\n */", S(16384),"num_args", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.num-args.php )\n *\n *\n * @return int\n */", S(16384),"get_args", T(Array), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.get-args.php )\n *\n *\n * @return vector\n */", S(16384),"get_arg", T(Variant), S(0), "id", T(Int64), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.get-arg.php )\n *\n *\n * @id int\n *\n * @return mixed\n */", S(16384),"current", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.current.php )\n *\n *\n * @return mixed\n */", S(16384),"key", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.key.php )\n *\n *\n * @return int\n */", S(16384),"next", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.next.php )\n *\n *\n */", S(16384),"rewind", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.rewind.php )\n *\n *\n */", S(16384),"valid", T(Boolean), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.valid.php )\n *\n *\n * @return bool\n */", S(16384),"send", T(Void), S(0), "v", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.send.php )\n *\n *\n * @v mixed\n */", S(16384),"raise", T(Void), S(0), "v", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.raise.php )\n *\n *\n * @v mixed\n */", S(16384),"raised", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.raised.php )\n *\n *\n */", S(16384),"receive", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.receive.php )\n *\n *\n * @return mixed\n */", S(16384),"getOrigFuncName", T(String), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getorigfuncname.php\n * )\n *\n *\n * @return string\n */", S(16384),"__clone", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.clone.php )\n *\n *\n * @return mixed\n */", S(16384),NULL,NULL,NULL,
"Continuation", "", "iterator","awaitable",NULL, "__construct", T(Void), S(0), "func", T(Int64), NULL, S(0), NULL, S(0), "extra", T(Int64), NULL, S(0), NULL, S(0), "isMethod", T(Boolean), NULL, S(0), NULL, S(0), "origFuncName", T(String), NULL, S(0), NULL, S(0), "obj", T(Variant), "N;", S(2), "null", S(0), "args", T(Array), "N;", S(2), "null", S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.construct.php )\n *\n *\n * @func int\n * @extra int\n * @isMethod bool\n * @origFuncName\n * string\n * @obj mixed\n * @args map\n */", S(16384),"update", T(Void), S(0), "label", T(Int64), NULL, S(0), NULL, S(0), "value", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.update.php )\n *\n *\n * @label int\n * @value mixed\n */", S(16384),"done", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.done.php )\n *\n *\n */", S(16384),"getWaitHandle", T(Object), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getwaithandle.php )\n *\n * Start asynchronous execution of this Continuation and return the wait\n * handle\n *\n * @return object\n */", S(16384),"getLabel", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getlabel.php )\n *\n *\n * @return int\n */", S(16384),"num_args", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.num-args.php )\n *\n *\n * @return int\n */", S(16384),"get_args", T(Array), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.get-args.php )\n *\n *\n * @return vector\n */", S(16384),"get_arg", T(Variant), S(0), "id", T(Int64), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.get-arg.php )\n *\n *\n * @id int\n *\n * @return mixed\n */", S(16384),"current", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.current.php )\n *\n *\n * @return mixed\n */", S(16384),"key", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.key.php )\n *\n *\n * @return int\n */", S(16384),"next", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.next.php )\n *\n *\n */", S(16384),"rewind", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.rewind.php )\n *\n *\n */", S(16384),"valid", T(Boolean), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.valid.php )\n *\n *\n * @return bool\n */", S(16384),"send", T(Void), S(0), "v", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.send.php )\n *\n *\n * @v mixed\n */", S(16384),"raise", T(Void), S(0), "v", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.raise.php )\n *\n *\n * @v mixed\n */", S(16384),"getOrigFuncName", T(String), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getorigfuncname.php\n * )\n *\n *\n * @return string\n */", S(16384),"__clone", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.clone.php )\n *\n *\n * @return mixed\n */", S(16384),NULL,NULL,NULL,
S(16416), "/**\n * ( excerpt from http://php.net/manual/en/class.continuation.php )\n *\n *\n */", "DummyContinuation", "", "iterator",NULL, "__construct", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.construct.php\n * )\n *\n *\n */", S(16384),"current", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.current.php )\n *\n *\n * @return mixed\n */", S(16384),"key", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.key.php )\n *\n *\n * @return int\n */", S(16384),"next", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.next.php )\n *\n *\n */", S(16384),"rewind", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.rewind.php )\n *\n *\n */", S(16384),"valid", T(Boolean), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.valid.php )\n *\n *\n * @return bool\n */", S(16384),NULL,NULL,NULL,
S(16384), "/**\n * ( excerpt from http://php.net/manual/en/class.dummycontinuation.php )\n *\n * Represents an invalid continuation which will fatal when used.\n *\n */",
#endif
+3 -12
Ver Arquivo
@@ -675,10 +675,7 @@ bool TestParserStmt::TestYieldStatement() {
"case 1:\n"
"goto " YIELD_LABEL_PREFIX "1;\n"
"}\n"
"hphp_pack_continuation($" CONTINUATION_OBJECT_NAME ", 1, 123);\n"
"return;\n"
YIELD_LABEL_PREFIX "1:\n"
"hphp_continuation_raised();\n"
"yield 123;\n"
"hphp_continuation_done();\n"
"}\n"
"function foo() {\n"
@@ -700,14 +697,8 @@ bool TestParserStmt::TestYieldStatement() {
"case 1:\n"
"goto " YIELD_LABEL_PREFIX "1;\n"
"}\n"
"hphp_pack_continuation($" CONTINUATION_OBJECT_NAME ", 1, 123);\n"
"return;\n"
YIELD_LABEL_PREFIX "1:\n"
"hphp_continuation_raised();\n"
"hphp_pack_continuation($" CONTINUATION_OBJECT_NAME ", 2, 456);\n"
"return;\n"
YIELD_LABEL_PREFIX "2:\n"
"hphp_continuation_raised();\n"
"yield 123;\n"
"yield 456;\n"
"hphp_continuation_done();\n"
"}\n"
"}\n");
+16 -75
Ver Arquivo
@@ -149,33 +149,6 @@ static void prepare_continuation_call(Parser* _p, Token& rhs, const char* cname)
_p->onCall(rhs, false, fname, empty, NULL, true);
}
static void on_yield_assign(Parser *_p, Token &out, Token &var, Token *expr) {
Token yield; _p->onYield(yield, expr, true);
Token rhs; prepare_continuation_call(_p, rhs, "receive");
Token assign; _p->onAssign(assign, var, rhs, 0);
Token stmt; _p->onExpStatement(stmt, assign);
Token stmts0; _p->onStatementListStart(stmts0);
Token stmts1; _p->addStatement(stmts1, stmts0, yield);
Token stmts2; _p->addStatement(stmts2, stmts1, stmt);
_p->finishStatement(out, stmts2); out = 1;
}
static void on_yield_list_assign(Parser *_p, Token &out, Token &var,
Token *expr) {
Token yield; _p->onYield(yield, expr, true);
Token rhs; prepare_continuation_call(_p, rhs, "receive");
Token assign; _p->onListAssignment(assign, var, &rhs);
Token stmt; _p->onExpStatement(stmt, assign);
Token stmts0; _p->onStatementListStart(stmts0);
Token stmts1; _p->addStatement(stmts1, stmts0, yield);
Token stmts2; _p->addStatement(stmts2, stmts1, stmt);
_p->finishStatement(out, stmts2); out = 1;
}
void prepare_generator(Parser *_p, Token &stmt, Token &params, int count) {
// 1. add prologue and epilogue to original body and store it back to "stmt"
{
@@ -315,50 +288,6 @@ void create_generator(Parser *_p, Token &out, Token &params,
}
}
void transform_yield(Parser *_p, Token &stmts, int index,
Token *expr, bool assign) {
// hphp_pack_continuation(v___cont__, label, value)
Token update;
{
Token name; name.setText(CONTINUATION_OBJECT_NAME);
Token var; _p->onSynthesizedVariable(var, name);
Token param0; _p->onCallParam(param0, NULL, var, false);
Token snum; snum.setText(boost::lexical_cast<std::string>(index));
Token num; _p->onScalar(num, T_LNUMBER, snum);
Token param1; _p->onCallParam(param1, &param0, num, false);
Token param2; _p->onCallParam(param2, &param1, *expr, false);
Token cname; cname.setText("hphp_pack_continuation");
Token call; _p->onCall(call, false, cname, param2, NULL, true);
_p->onExpStatement(update, call);
}
// return
Token ret; _p->onReturn(ret, NULL, false);
// __yield__N:
Token lname; lname.setText(YIELD_LABEL_PREFIX +
boost::lexical_cast<std::string>(index));
Token label; _p->onLabel(label, lname);
_p->addLabel(lname.text(), _p->getLocation(), &label);
Token stmts0; _p->onStatementListStart(stmts0);
Token stmts1; _p->addStatement(stmts1, stmts0, update);
Token stmts2; _p->addStatement(stmts2, stmts1, ret);
Token stmts3; _p->addStatement(stmts3, stmts2, label);
if (assign) {
_p->finishStatement(stmts, stmts3); stmts = 1;
} else {
Token fcall; prepare_continuation_call(_p, fcall, "raised");
Token fstmt; _p->onExpStatement(fstmt, fcall);
Token stmts4; _p->addStatement(stmts4, stmts3, fstmt);
_p->finishStatement(stmts, stmts4); stmts = 1;
}
}
void transform_yield_break(Parser *_p, Token &out) {
// hphp_continuation_done()
Token mcall; prepare_continuation_call(_p, mcall, "done");
@@ -1061,10 +990,6 @@ statement:
| T_RETURN ';' { _p->onReturn($$, NULL);}
| T_RETURN expr ';' { _p->onReturn($$, &$2);}
| T_YIELD T_BREAK ';' { _p->onYieldBreak($$);}
| T_YIELD expr ';' { _p->onYield($$, &$2, false);}
| variable '=' T_YIELD expr ';' { on_yield_assign(_p, $$, $1, &$4);}
| T_LIST '(' assignment_list ')'
'=' T_YIELD expr ';' { on_yield_list_assign(_p, $$, $3, &$7);}
| T_GLOBAL global_var_list ';' { _p->onGlobal($$, $2);}
| T_STATIC static_var_list ';' { _p->onStatic($$, $2);}
| T_ECHO expr_list ';' { _p->onEcho($$, $2, 0);}
@@ -1095,6 +1020,9 @@ statement:
_p->getLocation(),
&$$); }
| expr ';' { _p->onExpStatement($$, $1);}
| yield_expr ';' { _p->onExpStatement($$, $1);}
| yield_assign_expr ';' { _p->onExpStatement($$, $1);}
| yield_list_assign_expr ';' { _p->onExpStatement($$, $1);}
| ident ':' { _p->onLabel($$, $1);
_p->addLabel($1.text(),
_p->getLocation(),
@@ -1639,6 +1567,19 @@ for_expr:
| { $$.reset();}
;
yield_expr:
T_YIELD expr { _p->onYield($$, $2);}
;
yield_assign_expr:
variable '=' yield_expr { _p->onAssign($$, $1, $3, 0, true);}
;
yield_list_assign_expr:
T_LIST '(' assignment_list ')'
'=' yield_expr { _p->onListAssignment($$, $3, &$6, true);}
;
expr:
expr_no_variable { $$ = $1;}
| variable { $$ = $1;}
+4 -4
Ver Arquivo
@@ -247,6 +247,10 @@ void ParserBase::popLabelInfo() {
for (unsigned int i = 0; i < info.gotos.size(); i++) {
const GotoInfo &gotoInfo = info.gotos[i];
if (gotoInfo.label.find(YIELD_LABEL_PREFIX) == 0) {
labels.erase(gotoInfo.label);
continue;
}
LabelMap::const_iterator iter = info.labels.find(gotoInfo.label);
if (iter == info.labels.end()) {
invalidateGoto(gotoInfo.stmt, UndefLabel);
@@ -255,10 +259,6 @@ void ParserBase::popLabelInfo() {
continue;
}
const LabelStmtInfo &labelInfo = iter->second;
if (gotoInfo.label.find(YIELD_LABEL_PREFIX) == 0) {
labels.erase(gotoInfo.label);
continue;
}
int labelScopeId = labelInfo.scopeId;
bool found = false;
for (int j = gotoInfo.scopes.size() - 1; j >= 0; j--) {
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+8 -6
Ver Arquivo
@@ -246,8 +246,9 @@ struct Parser : ParserBase {
X(base, prop, params);
}
void onListAssignment(Token &out, Token &vars, Token *expr) {
X(vars, expr);
void onListAssignment(Token &out, Token &vars, Token *expr,
bool rhsFirst = false) {
X(vars, expr, rhsFirst);
}
void onAListVar(Token &out, Token *list, Token *var) {
@@ -258,8 +259,9 @@ struct Parser : ParserBase {
X(list, sublist);
}
void onAssign(Token& out, Token& var, Token& expr, bool ref) {
X(var, expr, ref);
void onAssign(Token& out, Token& var, Token& expr, bool ref,
bool rhsFirst = false) {
X(var, expr, ref, rhsFirst);
}
void onAssignNew(Token &out, Token &var, Token &name, Token &args) {
@@ -439,8 +441,8 @@ struct Parser : ParserBase {
X(expr, checkYield);
}
void onYield(Token &out, Token *expr, bool assign) {
X(expr, assign);
void onYield(Token &out, Token &expr) {
X(expr);
}
void onYieldBreak(Token &out) { X(); }