Eliminate transform_yield_break()
The only places where ReturnStatement is constructed are: - onReturn(check_yield=true) -> not allowed in generator - onReturn(check_yield=false) -> coming from transform_yield_break, right after creating hphp_continuation_done() - MethodStatement, end of function call -> hphp_continuation_done() is created at end of generator in prepare_generator() Emitter is emitting ContExit in ReturnStatements used in generators. As can be seen from the analysis above, it's always preceded by emitting ContDone from hphp_continuation_done(). Let's emit ContDone inside the ReturnStatement directly and kill usage of hphp_continuation_done(). transform_yield_break() becomes a simple onReturn(check_yield=false), so let's inline it into onYield and create ReturnStatement directly. After this change, check_yield flag is always true and can be killed. ContExit was also used after emitting a generator method in case the end of method is still reachable. ContDone is added so that the generator is properly closed. I believe this is never actually used, as MethodStatement creates ReturnStatement at the end of method anyway.
Esse commit está contido em:
@@ -2181,7 +2181,8 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
ReturnStatementPtr r(static_pointer_cast<ReturnStatement>(node));
|
||||
bool retV = false;
|
||||
if (m_curFunc->isGenerator()) {
|
||||
// used by yield break
|
||||
assert(m_evalStack.size() == 0);
|
||||
e.ContDone();
|
||||
e.ContExit();
|
||||
return false;
|
||||
}
|
||||
@@ -3169,7 +3170,9 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
} else if (call->isCompilerCallToFunction("hphp_continuation_done")) {
|
||||
inputIsAnObject(0);
|
||||
e.ContDone();
|
||||
return false;
|
||||
e.ContExit();
|
||||
e.Null();
|
||||
return true;
|
||||
} else if ((call->isCallToFunction("class_exists") ||
|
||||
call->isCallToFunction("interface_exists") ||
|
||||
call->isCallToFunction("trait_exists")) && params &&
|
||||
@@ -5419,6 +5422,8 @@ void EmitterVisitor::emitPostponedMeths() {
|
||||
// return null
|
||||
if (currentPositionIsReachable()) {
|
||||
if (p.m_meth->getFunctionScope()->isGenerator()) {
|
||||
assert(m_evalStack.size() == 0);
|
||||
e.ContDone();
|
||||
e.ContExit();
|
||||
} else {
|
||||
e.Null();
|
||||
|
||||
+744
-770
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -116,7 +116,6 @@ extern void create_generator(Parser *_p, Token &out, Token ¶ms,
|
||||
const char *clsname, Token *modifiers,
|
||||
bool getArgs, Token &origGenFunc, bool isHhvm,
|
||||
Token *attr);
|
||||
extern void transform_yield_break(Parser *_p, Token &out);
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
@@ -790,9 +789,9 @@ void Parser::fixStaticVars() {
|
||||
m_staticVars.pop_back();
|
||||
}
|
||||
|
||||
void Parser::onFunction(Token &out, Token *modifiers, Token &ret, Token &ref,
|
||||
void Parser::onFunction(Token &out, Token *modifiers, Token &ret, Token &ref,
|
||||
Token &name, Token ¶ms, Token &stmt, Token *attr) {
|
||||
|
||||
|
||||
ModifierExpressionPtr exp = modifiers?
|
||||
dynamic_pointer_cast<ModifierExpression>(modifiers->exp)
|
||||
: NEW_EXP0(ModifierExpression);
|
||||
@@ -1341,9 +1340,9 @@ void Parser::onContinue(Token &out, Token *expr) {
|
||||
out->stmt = NEW_STMT(ContinueStatement, expr ? expr->exp : ExpressionPtr());
|
||||
}
|
||||
|
||||
void Parser::onReturn(Token &out, Token *expr, bool checkYield /* = true */) {
|
||||
void Parser::onReturn(Token &out, Token *expr) {
|
||||
out->stmt = NEW_STMT(ReturnStatement, expr ? expr->exp : ExpressionPtr());
|
||||
if (checkYield && !m_funcContexts.empty()) {
|
||||
if (!m_funcContexts.empty()) {
|
||||
if (!m_funcContexts.back().setIsNotGenerator()) {
|
||||
Compiler::Error(InvalidYield, out->stmt);
|
||||
PARSE_ERROR("Cannot mix 'return' and 'yield' in the same function");
|
||||
@@ -1420,7 +1419,7 @@ void Parser::onYieldBreak(Token &out) {
|
||||
return;
|
||||
}
|
||||
|
||||
transform_yield_break(this, out);
|
||||
out->stmt = NEW_STMT(ReturnStatement, ExpressionPtr());
|
||||
}
|
||||
|
||||
void Parser::onGlobal(Token &out, Token &expr) {
|
||||
@@ -1546,10 +1545,10 @@ void Parser::onClosureStart(Token &name) {
|
||||
onFunctionStart(name, true);
|
||||
}
|
||||
|
||||
void Parser::onClosure(Token &out, Token &ret, Token &ref, Token ¶ms,
|
||||
void Parser::onClosure(Token &out, Token &ret, Token &ref, Token ¶ms,
|
||||
Token &cparams, Token &stmts, bool is_static) {
|
||||
Token func, name, modifiers;
|
||||
|
||||
|
||||
ModifierExpressionPtr modifier_exp = NEW_EXP0(ModifierExpression);
|
||||
modifiers->exp = modifier_exp;
|
||||
if (is_static) {
|
||||
|
||||
@@ -169,7 +169,7 @@ public:
|
||||
void onClassConst(Token &out, Token &cls, Token &name, bool text);
|
||||
void fixStaticVars();
|
||||
void onFunctionStart(Token &name, bool doPushComment = true);
|
||||
void onFunction(Token &out, Token *modifier, Token &ret, Token &ref,
|
||||
void onFunction(Token &out, Token *modifier, Token &ret, Token &ref,
|
||||
Token &name, Token ¶ms, Token &stmt, Token *attr);
|
||||
void onParam(Token &out, Token *params, Token &type, Token &var,
|
||||
bool ref, Token *defValue, Token *attr);
|
||||
@@ -210,7 +210,7 @@ public:
|
||||
void onCase(Token &out, Token &cases, Token *cond, Token &stmt);
|
||||
void onBreak(Token &out, Token *expr);
|
||||
void onContinue(Token &out, Token *expr);
|
||||
void onReturn(Token &out, Token *expr, bool checkYield = true);
|
||||
void onReturn(Token &out, Token *expr);
|
||||
void onYield(Token &out, Token &expr);
|
||||
void onYieldBreak(Token &out);
|
||||
void onGlobal(Token &out, Token &expr);
|
||||
|
||||
@@ -242,14 +242,6 @@ DefineFunction(
|
||||
),
|
||||
));
|
||||
|
||||
DefineFunction(
|
||||
array(
|
||||
'name' => 'done',
|
||||
'return' => array(
|
||||
'type' => null,
|
||||
),
|
||||
));
|
||||
|
||||
DefineFunction(
|
||||
array(
|
||||
'name' => "getWaitHandle",
|
||||
|
||||
@@ -93,11 +93,6 @@ void c_Continuation::t_update(int64_t label, CVarRef value) {
|
||||
m_value.assignVal(value);
|
||||
}
|
||||
|
||||
void c_Continuation::t_done() {
|
||||
m_done = true;
|
||||
m_value.setNull();
|
||||
}
|
||||
|
||||
Object c_Continuation::t_getwaithandle() {
|
||||
return m_waitHandle.isNull() ? c_ContinuationWaitHandle::t_start(this) : m_waitHandle;
|
||||
}
|
||||
|
||||
@@ -283,42 +283,6 @@ TypedValue* tg_12Continuation_update(HPHP::VM::ActRec *ar) {
|
||||
return &ar->m_r;
|
||||
}
|
||||
|
||||
/*
|
||||
void HPHP::c_Continuation::t_done()
|
||||
_ZN4HPHP14c_Continuation6t_doneEv
|
||||
|
||||
this_ => rdi
|
||||
*/
|
||||
|
||||
void th_12Continuation_done(ObjectData* this_) asm("_ZN4HPHP14c_Continuation6t_doneEv");
|
||||
|
||||
TypedValue* tg_12Continuation_done(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_done((this_));
|
||||
frame_free_locals_inl(ar, 0);
|
||||
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
|
||||
return &ar->m_r;
|
||||
} else {
|
||||
throw_toomany_arguments_nr("Continuation::done", 0, 1);
|
||||
}
|
||||
} else {
|
||||
throw_instance_method_fatal("Continuation::done");
|
||||
}
|
||||
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::Object HPHP::c_Continuation::t_getwaithandle()
|
||||
_ZN4HPHP14c_Continuation15t_getwaithandleEv
|
||||
|
||||
@@ -48,7 +48,6 @@ class c_Continuation : public ExtObjectData {
|
||||
public: ~c_Continuation();
|
||||
public: void t___construct(int64_t func, CStrRef origFuncName, CVarRef obj = uninit_null(), CArrRef args = null_array);
|
||||
public: void t_update(int64_t label, CVarRef value);
|
||||
public: void t_done();
|
||||
public: Object t_getwaithandle();
|
||||
public: int64_t t_getlabel();
|
||||
public: int64_t t_num_args();
|
||||
|
||||
@@ -2401,7 +2401,6 @@ TypedValue* tg_13TupleIterator_rewind(VM::ActRec *ar);
|
||||
VM::Instance* new_Continuation_Instance(VM::Class*);
|
||||
TypedValue* tg_12Continuation___construct(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation_update(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation_done(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation_getWaitHandle(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation_getLabel(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation_num_args(VM::ActRec *ar);
|
||||
@@ -5464,11 +5463,10 @@ static const HhbcExtMethodInfo hhbc_ext_methods_TupleIterator[] = {
|
||||
{ "rewind", tg_13TupleIterator_rewind }
|
||||
};
|
||||
|
||||
static const long long hhbc_ext_method_count_Continuation = 17;
|
||||
static const long long hhbc_ext_method_count_Continuation = 16;
|
||||
static const HhbcExtMethodInfo hhbc_ext_methods_Continuation[] = {
|
||||
{ "__construct", tg_12Continuation___construct },
|
||||
{ "update", tg_12Continuation_update },
|
||||
{ "done", tg_12Continuation_done },
|
||||
{ "getWaitHandle", tg_12Continuation_getWaitHandle },
|
||||
{ "getLabel", tg_12Continuation_getLabel },
|
||||
{ "num_args", tg_12Continuation_num_args },
|
||||
|
||||
@@ -2071,7 +2071,7 @@ void VMExecutionContext::invokeFunc(TypedValue* retval,
|
||||
// If this is a method, either this_ or cls must be non-NULL
|
||||
assert(!f->preClass() || (this_ || cls));
|
||||
// If this is a static method, this_ must be NULL
|
||||
assert(!(f->attrs() & HPHP::VM::AttrStatic && !f->isClosureBody()) ||
|
||||
assert(!(f->attrs() & HPHP::VM::AttrStatic && !f->isClosureBody()) ||
|
||||
(!this_));
|
||||
// invName should only be non-NULL if we are calling __call or
|
||||
// __callStatic
|
||||
@@ -7076,7 +7076,8 @@ inline void OPTBLD_INLINE VMExecutionContext::iopContReceive(PC& pc) {
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopContDone(PC& pc) {
|
||||
NEXT();
|
||||
c_Continuation* cont = frame_continuation(m_fp);
|
||||
cont->t_done();
|
||||
cont->m_done = true;
|
||||
cont->m_value.setNull();
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopContNext(PC& pc) {
|
||||
|
||||
@@ -21953,11 +21953,6 @@ const char *g_class_map[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(const char *)0x10006040, "done", "", (const char*)0, (const char*)0,
|
||||
"/**\n * ( excerpt from http://php.net/manual/en/continuation.done.php )\n *\n *\n */",
|
||||
(const char *)-1, NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(const char *)0x10006040, "getWaitHandle", "", (const char*)0, (const char*)0,
|
||||
"/**\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 */",
|
||||
(const char *)0x40, NULL,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#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 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,
|
||||
"Continuation", "", "iterator","awaitable",NULL, "__construct", T(Void), S(0), "func", T(Int64), 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 * @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),"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
|
||||
|
||||
@@ -660,9 +660,7 @@ bool TestParserStmt::TestYieldStatement() {
|
||||
"function ($" CONTINUATION_OBJECT_NAME ") {\n"
|
||||
"switch (hphp_unpack_continuation($" CONTINUATION_OBJECT_NAME ")) {\n"
|
||||
"}\n"
|
||||
"hphp_continuation_done();\n"
|
||||
"return;\n"
|
||||
"hphp_continuation_done();\n"
|
||||
"}\n"
|
||||
"function foo() {\n"
|
||||
"return hphp_create_continuation"
|
||||
@@ -676,7 +674,6 @@ bool TestParserStmt::TestYieldStatement() {
|
||||
"goto " YIELD_LABEL_PREFIX "1;\n"
|
||||
"}\n"
|
||||
"yield 123;\n"
|
||||
"hphp_continuation_done();\n"
|
||||
"}\n"
|
||||
"function foo() {\n"
|
||||
"return hphp_create_continuation"
|
||||
@@ -699,7 +696,6 @@ bool TestParserStmt::TestYieldStatement() {
|
||||
"}\n"
|
||||
"yield 123;\n"
|
||||
"yield 456;\n"
|
||||
"hphp_continuation_done();\n"
|
||||
"}\n"
|
||||
"}\n");
|
||||
|
||||
|
||||
@@ -143,12 +143,6 @@ static void on_constant(Parser *_p, Token &out, Token *stmts,
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// continuation transformations
|
||||
|
||||
static void prepare_continuation_call(Parser* _p, Token& rhs, const char* cname) {
|
||||
Token fname; fname.setText(std::string("hphp_continuation_") + cname);
|
||||
Token empty;
|
||||
_p->onCall(rhs, false, fname, empty, NULL, true);
|
||||
}
|
||||
|
||||
void prepare_generator(Parser *_p, Token &stmt, Token ¶ms, int count) {
|
||||
// 1. add prologue and epilogue to original body and store it back to "stmt"
|
||||
{
|
||||
@@ -190,20 +184,14 @@ void prepare_generator(Parser *_p, Token &stmt, Token ¶ms, int count) {
|
||||
}
|
||||
_p->popLabelScope();
|
||||
}
|
||||
Token sdone;
|
||||
{
|
||||
Token mcall; prepare_continuation_call(_p, mcall, "done");
|
||||
_p->onExpStatement(sdone, mcall);
|
||||
}
|
||||
{
|
||||
Token stmts0; _p->onStatementListStart(stmts0);
|
||||
Token stmts1; _p->addStatement(stmts1, stmts0, scall);
|
||||
Token stmts2; _p->addStatement(stmts2, stmts1, sswitch);
|
||||
Token stmts3; _p->addStatement(stmts3, stmts2, stmt);
|
||||
Token stmts4; _p->addStatement(stmts4, stmts3, sdone);
|
||||
|
||||
stmt.reset();
|
||||
_p->finishStatement(stmt, stmts4); stmt = 1;
|
||||
_p->finishStatement(stmt, stmts3); stmt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,20 +276,6 @@ void create_generator(Parser *_p, Token &out, Token ¶ms,
|
||||
}
|
||||
}
|
||||
|
||||
void transform_yield_break(Parser *_p, Token &out) {
|
||||
// hphp_continuation_done()
|
||||
Token mcall; prepare_continuation_call(_p, mcall, "done");
|
||||
Token done; _p->onExpStatement(done, mcall);
|
||||
|
||||
// return
|
||||
Token ret; _p->onReturn(ret, NULL, false);
|
||||
|
||||
Token stmts0; _p->onStatementListStart(stmts0);
|
||||
Token stmts1; _p->addStatement(stmts1, stmts0, done);
|
||||
Token stmts2; _p->addStatement(stmts2, stmts1, ret);
|
||||
_p->finishStatement(out, stmts2); out = 1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void user_attribute_check(Parser *_p) {
|
||||
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -318,7 +318,7 @@ struct Parser : ParserBase {
|
||||
X(name);
|
||||
}
|
||||
|
||||
void onFunction(Token& out, Token* modifiers, Token& ret, Token& ref,
|
||||
void onFunction(Token& out, Token* modifiers, Token& ret, Token& ref,
|
||||
Token& name, Token& params, Token& stmt, Token* attr) {
|
||||
X(modifiers, ret, ref, name, params, stmt, attr);
|
||||
}
|
||||
@@ -437,8 +437,8 @@ struct Parser : ParserBase {
|
||||
X(expr);
|
||||
}
|
||||
|
||||
void onReturn(Token &out, Token *expr, bool checkYield = true) {
|
||||
X(expr, checkYield);
|
||||
void onReturn(Token &out, Token *expr) {
|
||||
X(expr);
|
||||
}
|
||||
|
||||
void onYield(Token &out, Token &expr) {
|
||||
@@ -484,7 +484,7 @@ struct Parser : ParserBase {
|
||||
|
||||
void onThrow(Token &out, Token &expr) { X(expr); }
|
||||
|
||||
void onClosure(Token &out, Token &ret, Token &ref, Token ¶ms,
|
||||
void onClosure(Token &out, Token &ret, Token &ref, Token ¶ms,
|
||||
Token &cparams, Token &stmts, bool is_static) {
|
||||
X(ret, ref, params, cparams, stmts, is_static);
|
||||
}
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário