예제 #1
0
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();
}
예제 #2
0
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);
}