예제 #1
0
void ClassStatement::onParse(AnalysisResultPtr ar) {
  ClassScope::KindOf kindOf = ClassScope::KindOfObjectClass;
  switch (m_type) {
  case T_CLASS:     kindOf = ClassScope::KindOfObjectClass;   break;
  case T_ABSTRACT:  kindOf = ClassScope::KindOfAbstractClass; break;
  case T_FINAL:     kindOf = ClassScope::KindOfFinalClass;    break;
  default:
    ASSERT(false);
  }

  vector<string> bases;
  if (!m_parent.empty()) {
    bases.push_back(m_parent);
    ar->addNonFinal(m_parent);
  }
  if (m_base) m_base->getStrings(bases);
  StatementPtr stmt = dynamic_pointer_cast<Statement>(shared_from_this());
  ClassScopePtr classScope(new ClassScope(kindOf, m_originalName, m_parent,
                                          bases, m_docComment,
                                          stmt, ar->getFileScope()));
  m_classScope = classScope;
  if (!ar->getFileScope()->addClass(ar, classScope)) {
    m_ignored = true;
    return;
  }
  ar->recordClassSource(m_name, ar->getFileScope()->getName());

  if (m_stmt) {
    ar->pushScope(classScope);
    bool seenConstruct = false;
    for (int i = 0; i < m_stmt->getCount(); i++) {
      MethodStatementPtr meth =
        dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]);
      if (meth && meth->getName() == "__construct") {
        seenConstruct = true;
        break;
      }
    }
    for (int i = 0; i < m_stmt->getCount(); i++) {
      if (!seenConstruct) {
        MethodStatementPtr meth =
          dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]);
        if (meth && classScope && meth->getName() == classScope->getName()
         && !meth->getModifiers()->isStatic()) {
          // class-name constructor
          classScope->setAttribute(ClassScope::classNameConstructor);
        }
      }
      IParseHandlerPtr ph = dynamic_pointer_cast<IParseHandler>((*m_stmt)[i]);
      ph->onParse(ar);
    }
    ar->popScope();
  }
}
예제 #2
0
void InterfaceStatement::checkArgumentsToPromote(
    ExpressionListPtr promotedParams, int type) {
  if (!m_stmt) {
    return;
  }
  for (int i = 0; i < m_stmt->getCount(); i++) {
    MethodStatementPtr meth =
      dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]);
    if (meth && meth->getName() == "__construct") {
      ExpressionListPtr params = meth->getParams();
      if (params) {
        for (int i = 0; i < params->getCount(); i++) {
          ParameterExpressionPtr param =
            dynamic_pointer_cast<ParameterExpression>((*params)[i]);
          if (param->getModifier() != 0) {
            if (type == T_TRAIT || type == T_INTERFACE) {
              param->parseTimeFatal(Compiler::InvalidAttribute,
                                    "Constructor parameter promotion "
                                    "not allowed on traits or interfaces");
            }
            if (promotedParams) {
              promotedParams->addElement(param);
            }
          }
        }
      }
      return; // nothing else to look at
    }
  }
}
예제 #3
0
void StatementList::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  FunctionScopePtr func = getFunctionScope();

  for (unsigned int i = 0; i < m_stmts.size(); i++) {
    StatementPtr stmt = m_stmts[i];
    stmt->outputCPP(cg, ar);
    if (stmt->is(Statement::KindOfMethodStatement)) {
      MethodStatementPtr methodStmt =
        dynamic_pointer_cast<MethodStatement>(stmt);
      std::string methodName = methodStmt->getName();
      if (methodName == "offsetget") {
        ClassScopePtr cls = getClassScope();
        std::string arrayAccess("arrayaccess");
        if (cls->derivesFrom(ar, arrayAccess, false, false)) {
          FunctionScopePtr funcScope = methodStmt->getFunctionScope();
          std::string name = funcScope->getName();
          funcScope->setName("__offsetget_lval");
          methodStmt->setName("__offsetget_lval");
          methodStmt->outputCPP(cg, ar);
          funcScope->setName(name);
          methodStmt->setName("offsetget");
        }
      }
    }
  }
}
예제 #4
0
void StatementList::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  FunctionScopePtr func = getFunctionScope();
  bool inPseudoMain = func && func->inPseudoMain();
  std::vector<bool> isDeclaration;

  if (inPseudoMain) {
    // We need these declarations to go first, because PHP allows top level
    // function and class declarations to appear after usage.
    for (unsigned int i = 0; i < m_stmts.size(); i++) {
      StatementPtr stmt = m_stmts[i];
      bool isDecl = false;
      if (stmt->is(Statement::KindOfFunctionStatement)) {
        isDecl = true;
      } else if (stmt->is(Statement::KindOfClassStatement) ||
                 stmt->is(Statement::KindOfInterfaceStatement)) {
        ClassScopePtr cls =
          (dynamic_pointer_cast<InterfaceStatement>(stmt))->getClassScope();
        isDecl = cls->isBaseClass() || !cls->isVolatile();
      }
      if (isDecl) stmt->outputCPP(cg,ar);
      isDeclaration.push_back(isDecl);
    }
  }

  for (unsigned int i = 0; i < m_stmts.size(); i++) {
    StatementPtr stmt = m_stmts[i];
    if (stmt->is(Statement::KindOfClassStatement)) {
      if (!inPseudoMain || !isDeclaration[i]) stmt->outputCPP(cg, ar);
    } else if (!(stmt->is(Statement::KindOfFunctionStatement) ||
                 stmt->is(Statement::KindOfInterfaceStatement)) ||
               (!inPseudoMain || !isDeclaration[i])) {
      stmt->outputCPP(cg, ar);
      if (stmt->is(Statement::KindOfMethodStatement)) {
        MethodStatementPtr methodStmt =
          dynamic_pointer_cast<MethodStatement>(stmt);
        std::string methodName = methodStmt->getName();
        if (methodName == "offsetget") {
          ClassScopePtr cls = getClassScope();
          std::string arrayAccess("arrayaccess");
          if (cls->derivesFrom(ar, arrayAccess, false, false)) {
            FunctionScopePtr funcScope = methodStmt->getFunctionScope();
            std::string name = funcScope->getName();
            funcScope->setName("__offsetget_lval");
            methodStmt->setName("__offsetget_lval");
            methodStmt->outputCPP(cg, ar);
            funcScope->setName(name);
            methodStmt->setName("offsetget");
          }
        }
      }
    }
  }
}
예제 #5
0
void ClassScope::findTraitMethodsToImport(AnalysisResultPtr ar,
                                          ClassScopePtr trait) {
  assert(Option::WholeProgram);
  ClassStatementPtr tStmt =
    dynamic_pointer_cast<ClassStatement>(trait->getStmt());
  StatementListPtr tStmts = tStmt->getStmts();
  if (!tStmts) return;

  for (int s = 0; s < tStmts->getCount(); s++) {
    MethodStatementPtr meth =
      dynamic_pointer_cast<MethodStatement>((*tStmts)[s]);
    if (meth) {
      TraitMethod traitMethod(trait, meth, ModifierExpressionPtr(),
                              MethodStatementPtr());
      addImportTraitMethod(traitMethod, meth->getName());
    }
  }
}
예제 #6
0
MethodStatementPtr
ClassScope::findTraitMethod(AnalysisResultPtr ar,
                            ClassScopePtr trait,
                            const string &methodName,
                            std::set<ClassScopePtr> &visitedTraits) {
  if (visitedTraits.find(trait) != visitedTraits.end()) {
    return MethodStatementPtr();
  }
  visitedTraits.insert(trait);

  ClassStatementPtr tStmt =
    dynamic_pointer_cast<ClassStatement>(trait->getStmt());
  StatementListPtr tStmts = tStmt->getStmts();

  // Look in the current trait
  for (int s = 0; s < tStmts->getCount(); s++) {
    MethodStatementPtr meth =
      dynamic_pointer_cast<MethodStatement>((*tStmts)[s]);
    if (meth) {    // Handle methods
      if (meth->getName() == methodName) {
        return meth;
      }
    }
  }

  // Look into children traits
  for (int s = 0; s < tStmts->getCount(); s++) {
    UseTraitStatementPtr useTraitStmt =
      dynamic_pointer_cast<UseTraitStatement>((*tStmts)[s]);
    if (useTraitStmt) {
      vector<string> usedTraits;
      useTraitStmt->getUsedTraitNames(usedTraits);
      for (unsigned i = 0; i < usedTraits.size(); i++) {
        MethodStatementPtr foundMethod =
          findTraitMethod(ar, ar->findClass(usedTraits[i]), methodName,
                          visitedTraits);
        if (foundMethod) return foundMethod;
      }
    }
  }
  return MethodStatementPtr(); // not found
}
예제 #7
0
void ClassStatement::onParse(AnalysisResultConstPtr ar, FileScopePtr fs) {
  ClassScope::KindOf kindOf = ClassScope::KindOfObjectClass;
  switch (m_type) {
  case T_CLASS:     kindOf = ClassScope::KindOfObjectClass;   break;
  case T_ABSTRACT:  kindOf = ClassScope::KindOfAbstractClass; break;
  case T_FINAL:     kindOf = ClassScope::KindOfFinalClass;    break;
  default:
    ASSERT(false);
  }

  vector<string> bases;
  if (!m_parent.empty()) {
    bases.push_back(m_parent);
  }
  if (m_base) m_base->getStrings(bases);
  StatementPtr stmt = dynamic_pointer_cast<Statement>(shared_from_this());
  ClassScopePtr classScope(new ClassScope(kindOf, m_originalName, m_parent,
                                          bases, m_docComment,
                                          stmt));
  setBlockScope(classScope);
  if (!fs->addClass(ar, classScope)) {
    m_ignored = true;
    return;
  }

  if (m_stmt) {
    bool seenConstruct = false;

    // flatten continuation StatementList into MethodStatements
    for (int i = 0; i < m_stmt->getCount(); i++) {
      StatementListPtr stmts =
        dynamic_pointer_cast<StatementList>((*m_stmt)[i]);
      if (stmts) {
        m_stmt->removeElement(i);
        for (int j = 0; j < stmts->getCount(); j++) {
          m_stmt->insertElement((*stmts)[j], i + j);
        }
      }
    }

    for (int i = 0; i < m_stmt->getCount(); i++) {
      MethodStatementPtr meth =
        dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]);
      if (meth && meth->getName() == "__construct") {
        seenConstruct = true;
        break;
      }
    }
    for (int i = 0; i < m_stmt->getCount(); i++) {
      if (!seenConstruct) {
        MethodStatementPtr meth =
          dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]);
        if (meth && classScope && meth->getName() == classScope->getName()
         && !meth->getModifiers()->isStatic()) {
          // class-name constructor
          classScope->setAttribute(ClassScope::ClassNameConstructor);
        }
      }
      IParseHandlerPtr ph = dynamic_pointer_cast<IParseHandler>((*m_stmt)[i]);
      ph->onParseRecur(ar, classScope);
    }
  }
}
예제 #8
0
void ClassStatement::onParse(AnalysisResultConstPtr ar, FileScopePtr fs) {
  ClassScope::KindOf kindOf = ClassScope::KindOfObjectClass;
  switch (m_type) {
  case T_CLASS:     kindOf = ClassScope::KindOfObjectClass;   break;
  case T_ABSTRACT:  kindOf = ClassScope::KindOfAbstractClass; break;
  case T_FINAL:     kindOf = ClassScope::KindOfFinalClass;    break;
  case T_TRAIT:     kindOf = ClassScope::KindOfTrait;         break;
  default:
    assert(false);
  }

  vector<string> bases;
  if (!m_originalParent.empty()) {
    bases.push_back(m_originalParent);
  }
  if (m_base) m_base->getOriginalStrings(bases);

  for (auto &b : bases) {
    ar->parseOnDemandByClass(Util::toLower(b));
  }

  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());
  ClassScopePtr classScope(new ClassScope(kindOf, m_originalName,
                                          m_originalParent,
                                          bases, m_docComment,
                                          stmt, attrs));
  setBlockScope(classScope);
  if (!fs->addClass(ar, classScope)) {
    m_ignored = true;
    return;
  }

  if (Option::PersistenceHook) {
    classScope->setPersistent(Option::PersistenceHook(classScope, fs));
  }

  if (m_stmt) {
    MethodStatementPtr constructor;

    // flatten continuation StatementList into MethodStatements
    for (int i = 0; i < m_stmt->getCount(); i++) {
      StatementListPtr stmts =
        dynamic_pointer_cast<StatementList>((*m_stmt)[i]);
      if (stmts) {
        m_stmt->removeElement(i);
        for (int j = 0; j < stmts->getCount(); j++) {
          m_stmt->insertElement((*stmts)[j], i + j);
        }
      }
    }

    for (int i = 0; i < m_stmt->getCount(); i++) {
      MethodStatementPtr meth =
        dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]);
      if (meth && meth->getName() == "__construct") {
        constructor = meth;
        break;
      }
    }
    for (int i = 0; i < m_stmt->getCount(); i++) {
      if (!constructor) {
        MethodStatementPtr meth =
          dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]);
        if (meth && meth->getName() == classScope->getName()
            && !classScope->isTrait()) {
          // class-name constructor
          constructor = meth;
          classScope->setAttribute(ClassScope::ClassNameConstructor);
        }
      }
      IParseHandlerPtr ph = dynamic_pointer_cast<IParseHandler>((*m_stmt)[i]);
      ph->onParseRecur(ar, classScope);
    }
    if (constructor && constructor->getModifiers()->isStatic()) {
      constructor->parseTimeFatal(Compiler::InvalidAttribute,
                                  "Constructor %s::%s() cannot be static",
                                  classScope->getOriginalName().c_str(),
                                  constructor->getOriginalName().c_str());
    }
  }
}