void Parser::onYield(Token &out, Token *expr) { if (!RuntimeOption::EnableHipHopSyntax) { error("Yield is not enabled: %s", getMessage().c_str()); return; } if (!haveFunc()) { error("Yield cannot only be used inside a function: %s", getMessage().c_str()); return; } FunctionStatementPtr func = peekFunc(); if (func->hasReturn()) { error("Cannot mix 'return' and 'yield' in the same function: %s", getMessage().c_str()); return; } if (haveClass()) { if (strcasecmp(func->name().data(), peekClass()->name().data()) == 0) { error("'yield' is not allowed in potential constructors: %s", getMessage().c_str()); return; } if (func->name().substr(0, 2) == "__") { error("'yield' is not allowed in constructor, destructor, or " "magic methods: %s", getMessage().c_str()); return; } } int index = func->addYield(); Token stmts; transform_yield(this, stmts, index, expr); out.reset(); out->stmt() = stmts->getStmtList(); }
Variant EvalCreateFunction::InvokeImpl(VariableEnvironment &env, CArrRef params) { int size = params.size(); if (size != 2) throw InvalidFunctionCallException("create_function"); Variant var = params.rvalAt(0); Variant body = params.rvalAt(1); vector<StaticStatementPtr> statics; ostringstream fnStream; string id(RequestEvalState::unique()); fnStream << "<?php function lambda_" << id << "(" << var.toString().data() << ") {" << body.toString().data() << "}\n"; StatementPtr bodyAst = Parser::ParseString(fnStream.str().c_str(), statics); if (!bodyAst) return false; ostringstream nameStream; nameStream << "$lambda_" << id; FunctionStatementPtr f = bodyAst->cast<StatementListStatement>()->stmts()[0]; ASSERT(f); f->changeName(nameStream.str()); SmartPtr<CodeContainer> cc(new StringCodeContainer(bodyAst)); RequestEvalState::addCodeContainer(cc); f->eval(env); return String(f->name().c_str(), f->name().size(), AttachLiteral); }