Exemplo n.º 1
0
MethodStatementPtr
ClassScope::importTraitMethod(const TraitMethod&  traitMethod,
                              AnalysisResultPtr   ar,
                              string              methName,
                              const std::map<string, MethodStatementPtr>&
                              importedTraitMethods) {
  MethodStatementPtr meth = traitMethod.m_method;
  string origMethName = traitMethod.m_originalName;
  ModifierExpressionPtr modifiers = traitMethod.m_modifiers;

  MethodStatementPtr cloneMeth = dynamic_pointer_cast<MethodStatement>(
    dynamic_pointer_cast<ClassStatement>(m_stmt)->addClone(meth));
  cloneMeth->setName(methName);
  cloneMeth->setOriginalName(origMethName);
  // Note: keep previous modifiers if none specified when importing the trait
  if (modifiers && modifiers->getCount()) {
    cloneMeth->setModifiers(modifiers);
  }
  FunctionScopePtr funcScope = meth->getFunctionScope();

  // Trait method typehints, self and parent, need to be converted
  ClassScopePtr cScope = dynamic_pointer_cast<ClassScope>(shared_from_this());
  cloneMeth->fixupSelfAndParentTypehints( cScope );

  FunctionScopePtr cloneFuncScope
    (new HPHP::FunctionScope(funcScope, ar, methName, origMethName, cloneMeth,
                             cloneMeth->getModifiers(), cScope->isUserClass()));
  cloneMeth->resetScope(cloneFuncScope, true);
  cloneFuncScope->setOuterScope(shared_from_this());
  informClosuresAboutScopeClone(cloneMeth, cloneFuncScope, ar);

  cloneMeth->addTraitMethodToScope(ar,
               dynamic_pointer_cast<ClassScope>(shared_from_this()));

  // Preserve original filename (as this varies per-function and not per-unit
  // in the case of methods imported from flattened traits)
  cloneMeth->setOriginalFilename(meth->getFileScope()->getName());

  return cloneMeth;
}
Exemplo n.º 2
0
void makeFatalMeth(FileScope& file,
                   AnalysisResultConstPtr ar,
                   const std::string& msg,
                   int line,
                   Meth meth) {
  auto labelScope = std::make_shared<LabelScope>();
  auto r = Location::Range(line, 0, line, 0);
  BlockScopePtr scope;
  auto args = std::make_shared<ExpressionList>(scope, r);
  args->addElement(Expression::MakeScalarExpression(ar, scope, r, msg));
  auto e =
    std::make_shared<SimpleFunctionCall>(scope, r, "throw_fatal", false, args,
                                         ExpressionPtr());
  meth(e);
  auto exp = std::make_shared<ExpStatement>(scope, labelScope, r, e);
  auto stmts = std::make_shared<StatementList>(scope, labelScope, r);
  stmts->addElement(exp);

  FunctionScopePtr fs = file.setTree(ar, stmts);
  fs->setOuterScope(file.shared_from_this());
  fs->getStmt()->resetScope(fs);
  exp->copyLocationTo(fs->getStmt());
  file.setOuterScope(const_cast<AnalysisResult*>(ar.get())->shared_from_this());
}
Exemplo n.º 3
0
// Rewrite the outermost select clause so that it references properties of
// a result tuple constructed by the query provider. Then wrap this expression
// in a lambda so that the query provider can invoke it as a call back every
// time it produces a result tuple (row).
ClosureExpressionPtr QueryExpression::clientSideRewrite(
  AnalysisResultPtr ar, FileScopePtr fileScope) {
  // Rewrite the select expression into an expression that refers to
  // table columns (including computed columns) via properties of an
  // object produced by the query provider at runtime.
  ClientSideSelectRewriter cs;
  cs.rewriteQuery(static_pointer_cast<QueryExpression>(shared_from_this()));
  auto csSelect = cs.getClientSideSelectClause();
  // null if there is no select clause.
  if (csSelect == nullptr) return nullptr;
  ExpressionPtr selectExpr = csSelect->getExpression();

  // Now wrap up the rewritten expression into a lambda expression that
  // is passed to the query provider. When the query result is iterated,
  // the closure is called for each row in the query result in order to
  // produce the value specified by this select expression.

  // Create a return statement for the lambda body
  LabelScopePtr labelScope(new LabelScope());
  ReturnStatementPtr returnStatement(
    new ReturnStatement(BlockScopePtr(), labelScope, getRange(), selectExpr)
  );

  // Wrap up the return statement in a list for the lambda body
  StatementListPtr stmt(
    new StatementList(BlockScopePtr(), labelScope, getRange())
  );
  stmt->addElement(returnStatement);

  // Create a function statement for the lambda:

  // First create a formal parameter list, consisting of a single
  // parameter that will receive an object from the query provider
  // with a property for each table column that is referenced in the
  // expression of this select clause.
  TypeAnnotationPtr type;
  bool hhType = true;
  std::string paramName = "__query_result_row__";
  bool byRefParam = false;
  TokenID modifier = 0;
  ExpressionPtr defaultValue;
  ExpressionPtr attributeList;
  ParameterExpressionPtr parameter (
    new ParameterExpression(BlockScopePtr(), getRange(), type, hhType,
        paramName, byRefParam, modifier, defaultValue, attributeList)
  );
  ExpressionListPtr params(new ExpressionList(BlockScopePtr(), getRange()));
  params->addElement(parameter);

  // Now create a function statement object
  ModifierExpressionPtr modifiers(
    new ModifierExpression(BlockScopePtr(), getRange())
  );
  bool ref = false;
  static int counter = 0;
  std::string name = "__select__#" + std::to_string(counter++);
  TypeAnnotationPtr retTypeAnnotation;
  int attr = 0;
  std::string docComment;
  ExpressionListPtr attrList;
  FunctionStatementPtr func(
    new FunctionStatement(BlockScopePtr(), labelScope, getRange(), modifiers,
                          ref, name, params, retTypeAnnotation, stmt, attr,
                          docComment, attrList)
  );

  // The function statement needs a scope
  std::vector<UserAttributePtr> uattrs;
  FunctionScopePtr funcScope
    (new FunctionScope(ar, false, name, func, false, 1, 1,
                       nullptr, attr, docComment, fileScope, uattrs));
  fileScope->addFunction(ar, funcScope);
  func->resetScope(funcScope);
  funcScope->setOuterScope(fileScope);

  // Now construct a closure expression to create the closure value to
  // pass to the query provider.
  ExpressionListPtr captures;
  ClosureExpressionPtr closure(
    new ClosureExpression(BlockScopePtr(), getRange(), ClosureType::Short,
        func, captures)
  );
  closure->getClosureFunction()->setContainingClosure(closure);
  return closure;
}