Exemplo n.º 1
0
void MethodStatement::onParse(AnalysisResultPtr ar, BlockScopePtr scope) {
  ClassScopePtr classScope = dynamic_pointer_cast<ClassScope>(scope);
  FunctionScopePtr fs = getFunctionScope();

  fs->setParamCounts(ar, -1, -1);
  classScope->addFunction(ar, fs);

  if (m_name == "__construct") {
    classScope->setAttribute(ClassScope::HasConstructor);
  } else if (m_name == "__destruct") {
    classScope->setAttribute(ClassScope::HasDestructor);
  }

  if (m_name == "__call") {
    classScope->setAttribute(ClassScope::HasUnknownMethodHandler);
  } else if (m_name == "__get") {
    classScope->setAttribute(ClassScope::HasUnknownPropGetter);
  } else if (m_name == "__set") {
    classScope->setAttribute(ClassScope::HasUnknownPropSetter);
  } else if (m_name == "__call") {
    classScope->setAttribute(ClassScope::HasUnknownMethodHandler);
  } else if (m_name == "__callstatic") {
    classScope->setAttribute(ClassScope::HasUnknownStaticMethodHandler);
  }

  m_className = classScope->getName();
  m_originalClassName = classScope->getOriginalName();
}
Exemplo n.º 2
0
FunctionScopePtr MethodStatement::onInitialParse(AnalysisResultConstPtr ar,
                                                 FileScopePtr fs) {
  int minParam, maxParam;
  ConstructPtr self = shared_from_this();
  minParam = maxParam = 0;
  bool hasRef = false;
  if (m_params) {
    std::set<string> names, allDeclNames;
    int i = 0;
    maxParam = m_params->getCount();
    for (i = maxParam; i--; ) {
      ParameterExpressionPtr param =
        dynamic_pointer_cast<ParameterExpression>((*m_params)[i]);
      if (param->isRef()) hasRef = true;
      if (!param->isOptional()) {
        if (!minParam) minParam = i + 1;
      } else if (minParam && !param->hasTypeHint()) {
        Compiler::Error(Compiler::RequiredAfterOptionalParam, param);
      }
      allDeclNames.insert(param->getName());
    }

    for (i = maxParam-1; i >= 0; i--) {
      ParameterExpressionPtr param =
        dynamic_pointer_cast<ParameterExpression>((*m_params)[i]);
      if (names.find(param->getName()) != names.end()) {
        Compiler::Error(Compiler::RedundantParameter, param);
        for (int j = 0; j < 1000; j++) {
          string name = param->getName() + lexical_cast<string>(j);
          if (names.find(name) == names.end() &&
              allDeclNames.find(name) == allDeclNames.end()) {
            param->rename(name);
            break;
          }
        }
      }
      names.insert(param->getName());
    }
  }

  if (hasRef || m_ref) {
    m_attribute |= FileScope::ContainsReference;
  }

  vector<UserAttributePtr> attrs;
  if (m_attrList) {
    for (int i = 0; i < m_attrList->getCount(); ++i) {
      UserAttributePtr a =
        dynamic_pointer_cast<UserAttribute>((*m_attrList)[i]);
      attrs.push_back(a);
    }
  }

  StatementPtr stmt = dynamic_pointer_cast<Statement>(shared_from_this());
  FunctionScopePtr funcScope
    (new FunctionScope(ar, m_method, m_name, stmt, m_ref, minParam, maxParam,
                       m_modifiers, m_attribute, m_docComment, fs, attrs));
  if (!m_stmt) {
    funcScope->setVirtual();
  }
  setBlockScope(funcScope);

  funcScope->setParamCounts(ar, -1, -1);
  return funcScope;
}
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
    auto location = this->getLocation();
    LabelScopePtr labelScope(new LabelScope());
    ReturnStatementPtr returnStatement(
        new ReturnStatement(BlockScopePtr(), labelScope, location, selectExpr)
    );

    // Wrap up the return statement in a list for the lambda body
    StatementListPtr stmt(
        new StatementList(BlockScopePtr(), labelScope, location)
    );
    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 array from the query provider
    // with an element for each server-side 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(), location, type, hhType,
                                paramName, byRefParam, modifier, defaultValue, attributeList)
    );
    ExpressionListPtr params(new ExpressionList(BlockScopePtr(), location));
    params->addElement(parameter);

    // Now create a function statement object
    ModifierExpressionPtr modifiers(
        new ModifierExpression(BlockScopePtr(), location)
    );
    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, location, 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));
    funcScope->setParamCounts(ar, 1, 1);
    FunctionScope::RecordFunctionInfo(name, funcScope);
    fileScope->addFunction(ar, funcScope);
    func->resetScope(funcScope, true);
    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(), location, ClosureType::Short,
                              func, captures)
    );
    closure->getClosureFunction()->setContainingClosure(closure);
    return closure;
}