Ejemplo n.º 1
0
void Parser::onYield(Token &out, Token *expr) {
  if (!RuntimeOption::EnableHipHopSyntax) {
    raise_error("Yield is not enabled: %s", getMessage().c_str());
    return;
  }
  if (!haveFunc()) {
    raise_error("Yield cannot only be used inside a function: %s",
                getMessage().c_str());
    return;
  }

  FunctionStatementPtr func = peekFunc();
  if (func->hasReturn()) {
    raise_error("Cannot mix 'return' and 'yield' in the same function: %s",
                getMessage().c_str());
    return;
  }
  int index = func->addYield();

  Token stmts;
  transform_yield(this, stmts, index, expr);

  out.reset();
  out->stmt() = stmts->getStmtList();
}
Ejemplo n.º 2
0
void ClassScope::informClosuresAboutScopeClone(
    ConstructPtr root,
    FunctionScopePtr outerScope,
    AnalysisResultPtr ar) {

  if (!root) {
    return;
  }

  for (int i = 0; i < root->getKidCount(); i++) {
    ConstructPtr cons = root->getNthKid(i);
    ClosureExpressionPtr closure =
      dynamic_pointer_cast<ClosureExpression>(cons);

    if (!closure) {
      informClosuresAboutScopeClone(cons, outerScope, ar);
      continue;
    }

    FunctionStatementPtr func = closure->getClosureFunction();
    HPHP::FunctionScopePtr funcScope = func->getFunctionScope();
    assert(funcScope->isClosure());
    funcScope->addClonedTraitOuterScope(outerScope);
    // Don't need to recurse
  }
}
Ejemplo n.º 3
0
void Parser::onFunction(Token &out, Token &ref, Token &name, Token &params,
                        Token &stmt) {
  out.reset();
  FunctionStatementPtr func = peekFunc();
  ASSERT(func);
  StatementListStatementPtr body = stmt->getStmtList();
  func->init(this, ref.num(), params->params(), body, m_hasCallToGetArgs);
  out->stmt() = func;
  popFunc();
}
Ejemplo n.º 4
0
void Parser::onReturn(Token &out, Token *expr, bool checkYield /* = true */) {
  out.reset();
  out->stmt() = NEW_STMT(Return, expr ?
                         (*expr)->exp() : ExpressionPtr());
  if (checkYield && haveFunc()) {
    FunctionStatementPtr func = peekFunc();
    if (func->hasYield()) {
      raise_error("Cannot mix 'return' and 'yield' in the same function: %s",
                  getMessage().c_str());
    }
    func->setHasReturn();
  }
}
Ejemplo n.º 5
0
void Parser::onFunction(Token *out, Token *ref, Token *name, Token *params,
                        Token *stmt) {
  if (!stmt->stmt) {
    stmt->stmt = NEW_STMT0(StatementList);
  }
  FunctionStatementPtr func = NEW_STMT_POP_LOC
    (FunctionStatement, ref->num, name->text(),
     dynamic_pointer_cast<ExpressionList>(params->exp),
     dynamic_pointer_cast<StatementList>(stmt->stmt),
     m_ar->getFileScope()->popAttribute(),
     popComment());
  out->stmt = func;
  func->onParse(m_ar);
}
Ejemplo n.º 6
0
void Parser::onParam(Token &out, Token *params, Token &type, Token &var,
                     bool ref, Token *defValue) {
  out.reset();
  if (params) {
    out = *params;
  }
  int idx = -1;
  if (haveFunc()) {
    FunctionStatementPtr func = peekFunc();
    idx = func->declareVariable(var.getText());
  }
  ParameterPtr p(new Parameter(this, type.getText(), var.getText(),
                               idx, ref, defValue ? (*defValue)->exp()
                               : ExpressionPtr(), out->params().size() + 1));
  out->params().push_back(p);
}
Ejemplo n.º 7
0
void Parser::onFunction(Token &out, Token &ret, Token &ref, Token &name,
                        Token &params, Token &stmt) {
  FunctionStatementPtr func = peekFunc();
  ASSERT(func);
  popFunc();
  func->setLoc(popFuncLocation().get());
  bool hasCallToGetArgs = m_hasCallToGetArgs.back();
  m_hasCallToGetArgs.pop_back();

  if (func->hasYield()) {
    string closureName = getClosureName();
    func->setName(closureName);

    Token new_params;
    prepare_generator(this, stmt, new_params, func->getYieldCount());
    StatementListStatementPtr body = stmt->getStmtList();
    func->init(this, ref.num(), new_params->params(), body, hasCallToGetArgs);

    out.reset();
    out->stmt() = func;
    create_generator(this, out, params, name, closureName, NULL, NULL);

  } else {
    StatementListStatementPtr body = stmt->getStmtList();
    func->init(this, ref.num(), params->params(), body, hasCallToGetArgs);
    out.reset();
    out->stmt() = func;
  }
}
Ejemplo n.º 8
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();
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
0
ClosureExpression::ClosureExpression(EXPRESSION_ARGS,
                                     FunctionStatementPtr func,
                                     const vector<ParameterPtr> &vars)
    : Expression(KindOfClosureExpression, EXPRESSION_PASS), m_func(func) {
  func->setClosure(this);

  // push the vars in reverse order, not retaining duplicates
  set<string> seenBefore;
  for (vector<ParameterPtr>::const_reverse_iterator it(vars.rbegin());
       it != vars.rend();
       it++) {
    ParameterPtr param(*it);
    if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) {
      seenBefore.insert(param->getName().c_str());
      m_vars.push_back(param);
    }
  }
  reverse(m_vars.begin(), m_vars.end());
}