예제 #1
0
void ClassConstant::onParseRecur(AnalysisResultConstPtr ar,
                                 ClassScopePtr scope) {
  ConstantTablePtr constants = scope->getConstants();

  if (scope->isTrait()) {
    parseTimeFatal(Compiler::InvalidTraitStatement,
                   "Traits cannot have constants");
  }

  for (int i = 0; i < m_exp->getCount(); i++) {
    AssignmentExpressionPtr assignment =
      dynamic_pointer_cast<AssignmentExpression>((*m_exp)[i]);

    ExpressionPtr var = assignment->getVariable();
    const std::string &name =
      dynamic_pointer_cast<ConstantExpression>(var)->getName();
    if (constants->isPresent(name)) {
      assignment->parseTimeFatal(Compiler::DeclaredConstantTwice,
                                 "Cannot redeclare %s::%s",
                                 scope->getOriginalName().c_str(),
                                 name.c_str());
    } else {
      assignment->onParseRecur(ar, scope);
    }
  }
}
예제 #2
0
void AssignmentExpression::onParseRecur(AnalysisResultConstPtr ar,
                                        FileScopeRawPtr fs,
                                        ClassScopePtr scope) {
    auto isArray = false;
    if (m_value->is(Expression::KindOfUnaryOpExpression)) {
        auto uexp = dynamic_pointer_cast<UnaryOpExpression>(m_value);
        if (uexp->getOp() == T_ARRAY) {
            isArray = true;
        }
    }

    if (m_variable->is(Expression::KindOfConstantExpression)) {
        // ...as in ClassConstant statement
        // We are handling this one here, not in ClassConstant, purely because
        // we need "value" to store in constant table.
        if (isArray) {
            parseTimeFatal(fs,
                           Compiler::NoError,
                           "Arrays are not allowed in class constants");
        }
        auto exp = dynamic_pointer_cast<ConstantExpression>(m_variable);
        scope->getConstants()->add(exp->getName(), m_value, ar, m_variable);
    } else if (m_variable->is(Expression::KindOfSimpleVariable)) {
        auto var = dynamic_pointer_cast<SimpleVariable>(m_variable);
        scope->getVariables()->add(var->getName(), true, ar,
                                   shared_from_this(), scope->getModifiers());
        var->clearContext(Declaration); // to avoid wrong CodeError
    } else {
        assert(false); // parse phase shouldn't handle anything else
    }
}
void AssignmentExpression::onParseRecur(AnalysisResultConstPtr ar,
                                        ClassScopePtr scope) {
  // This is that much we can do during parse phase.
  TypePtr type;
  if (m_value->is(Expression::KindOfScalarExpression)) {
    type = static_pointer_cast<ScalarExpression>(m_value)->inferenceImpl(
      ar, Type::Some, false);
  } else if (m_value->is(Expression::KindOfUnaryOpExpression)) {
    UnaryOpExpressionPtr uexp =
      dynamic_pointer_cast<UnaryOpExpression>(m_value);
    if (uexp->getOp() == T_ARRAY) {
      type = Type::Array;
    }
  }
  if (!type) type = Type::Some;

  if (m_variable->is(Expression::KindOfConstantExpression)) {
    // ...as in ClassConstant statement
    // We are handling this one here, not in ClassConstant, purely because
    // we need "value" to store in constant table.
    ConstantExpressionPtr exp =
      dynamic_pointer_cast<ConstantExpression>(m_variable);
    scope->getConstants()->add(exp->getName(), type, m_value, ar, m_variable);
  } else if (m_variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_variable);
    scope->getVariables()->add(var->getName(), type, true, ar,
                               shared_from_this(), scope->getModifiers());
    var->clearContext(Declaration); // to avoid wrong CodeError
  } else {
    ASSERT(false); // parse phase shouldn't handle anything else
  }
}
예제 #4
0
bool ClassConstantExpression::containsDynamicConstant(AnalysisResultPtr ar)
  const {
  if (m_class) return true;
  ClassScopePtr cls = ar->findClass(m_origClassName);
  return !cls || cls->isVolatile() ||
    !cls->getConstants()->isRecursivelyDeclared(ar, m_varName);
}
void ClassConstantExpression::outputCPPImpl(CodeGenerator &cg,
                                            AnalysisResultPtr ar) {
  const char *globals = "g";
  if (cg.getContext() == CodeGenerator::CppParameterDefaultValueDecl ||
      cg.getContext() == CodeGenerator::CppParameterDefaultValueImpl) {
    globals = cg.getGlobals();
  }
  if (m_valid) {
    ClassScopePtr foundCls;
    string trueClassName;
    for (ClassScopePtr cls = ar->findClass(m_className);
         cls; cls = cls->getParentScope(ar)) {
      if (cls->getConstants()->isPresent(m_varName)) {
        foundCls = cls;
        trueClassName = cls->getName();
        break;
      }
    }
    ASSERT(!trueClassName.empty());
    ConstructPtr decl = foundCls->getConstants()->getValue(m_varName);
    if (decl) {
      decl->outputCPP(cg, ar);
      if (cg.getContext() == CodeGenerator::CppImplementation ||
          cg.getContext() == CodeGenerator::CppParameterDefaultValueImpl) {
        cg.printf("(%s::%s)", m_className.c_str(), m_varName.c_str());
      } else {
        cg.printf("/* %s::%s */", m_className.c_str(), m_varName.c_str());
      }
    } else {
      if (foundCls->getConstants()->isDynamic(m_varName)) {
        cg.printf("%s%s::lazy_initializer(%s)->", Option::ClassPrefix,
                  trueClassName.c_str(), globals);
      }
      cg.printf("%s%s_%s", Option::ClassConstantPrefix, trueClassName.c_str(),
                m_varName.c_str());
    }
  } else if (m_redeclared) {
    cg.printf("%s->%s%s->os_constant(\"%s\")", globals,
              Option::ClassStaticsObjectPrefix,
              m_className.c_str(), m_varName.c_str());
  } else {
    cg.printf("throw_fatal(\"unknown class constant %s::%s\")",
              m_className.c_str(), m_varName.c_str());
  }
}
예제 #6
0
void ClassConstant::onParseRecur(AnalysisResultConstPtr ar,
                                 ClassScopePtr scope) {
  ConstantTablePtr constants = scope->getConstants();

  if (scope->isTrait()) {
    parseTimeFatal(Compiler::InvalidTraitStatement,
                   "Traits cannot have constants");
  }

  if (isAbstract()) {
    for (int i = 0; i < m_exp->getCount(); i++) {
      ConstantExpressionPtr exp =
        dynamic_pointer_cast<ConstantExpression>((*m_exp)[i]);
      const std::string &name = exp->getName();
      if (constants->isPresent(name)) {
        exp->parseTimeFatal(Compiler::DeclaredConstantTwice,
                                   "Cannot redeclare %s::%s",
                                   scope->getOriginalName().c_str(),
                                   name.c_str());
      }

      // HACK: break attempts to write global constants here;
      // see ConstantExpression::preOptimize
      exp->setContext(Expression::LValue);

      // Unlike with assignment expression below, nothing needs to be added
      // to the scope's constant table
    }
  } else {
    for (int i = 0; i < m_exp->getCount(); i++) {
      AssignmentExpressionPtr assignment =
        dynamic_pointer_cast<AssignmentExpression>((*m_exp)[i]);

      ExpressionPtr var = assignment->getVariable();
      const std::string &name =
        dynamic_pointer_cast<ConstantExpression>(var)->getName();
      if (constants->isPresent(name)) {
        assignment->parseTimeFatal(Compiler::DeclaredConstantTwice,
                                   "Cannot redeclare %s::%s",
                                   scope->getOriginalName().c_str(),
                                   name.c_str());
      } else {
        if (isTypeconst()) {
          // We do not want type constants to be available at run time.
          // To ensure this we do not want them to be added to the constants
          // table. The constants table is used to inline values for expressions
          // See ClassConstantExpression::preOptimize.
          // AssignmentExpression::onParseRecur essentially adds constants to
          // the constant table so we skip it.
          continue;
        }
        assignment->onParseRecur(ar, scope);
      }
    }
  }
}
예제 #7
0
bool ConstantTable::isRecursivelyDeclared(AnalysisResultConstPtr ar,
                                          const std::string &name) {
  if (Symbol *sym = getSymbol(name)) {
    if (sym->valueSet()) return true;
  }
  ClassScopePtr parent = findParent(ar, name);
  if (parent) {
    return parent->getConstants()->isRecursivelyDeclared(ar, name);
  }
  return false;
}
예제 #8
0
ConstructPtr ConstantTable::getDeclarationRecur(AnalysisResultConstPtr ar,
                                                const std::string &name,
                                                ClassScopePtr &defClass) {
  if (Symbol *sym = getSymbol(name)) {
    if (sym->getDeclaration()) return sym->getDeclaration();
  }
  ClassScopePtr parent = findParent(ar, name);
  if (parent) {
    defClass = parent;
    return parent->getConstants()->getDeclarationRecur(ar, name, defClass);
  }
  return ConstructPtr();
}
TypePtr ClassConstantExpression::inferTypes(AnalysisResultPtr ar,
                                            TypePtr type, bool coerce) {
  m_valid = false;
  ConstructPtr self = shared_from_this();
  ClassScopePtr cls = ar->resolveClass(m_className);
  if (!cls || cls->isRedeclaring()) {
    if (cls) {
      m_redeclared = true;
      ar->getScope()->getVariables()->
        setAttribute(VariableTable::NeedGlobalPointer);
    }
    if (!cls && ar->isFirstPass()) {
      ar->getCodeError()->record(self, CodeError::UnknownClass, self);
    }
    return type;
  }
  if (cls->getConstants()->isDynamic(m_varName)) {
    ar->getScope()->getVariables()->
      setAttribute(VariableTable::NeedGlobalPointer);
  }
  if (cls->getConstants()->isExplicitlyDeclared(m_varName)) {
    string name = m_className + "::" + m_varName;
    ConstructPtr decl = cls->getConstants()->getDeclaration(m_varName);
    if (decl) { // No decl means an extension class.
      ar->getDependencyGraph()->add(DependencyGraph::KindOfConstant,
                                    ar->getName(),
                                    name, shared_from_this(), name, decl);
    }
    m_valid = true;
  }
  bool present;
  TypePtr t = cls->checkConst(m_varName, type, coerce, ar,
                              shared_from_this(), present);
  if (present) {
    m_valid = true;
  }

  return t;
}
예제 #10
0
ConstructPtr ConstantTable::getValueRecur(AnalysisResultConstPtr ar,
                                          const std::string &name,
                                          ClassScopePtr &defClass) const {
  if (const Symbol *sym = getSymbol(name)) {
    ASSERT(sym->isPresent() && sym->valueSet());
    if (sym->getValue()) return sym->getValue();
  }
  ClassScopePtr parent = findParent(ar, name);
  if (parent) {
    defClass = parent;
    return parent->getConstants()->getValueRecur(ar, name, defClass);
  }
  return ConstructPtr();
}
예제 #11
0
ExpressionPtr ClassConstantExpression::preOptimize(AnalysisResultConstPtr ar) {
  if (ar->getPhase() < AnalysisResult::FirstPreOptimize) {
    return ExpressionPtr();
  }
  if (m_class) {
    updateClassName();
    if (m_class) {
      return ExpressionPtr();
    }
  }

  ClassScopePtr cls = resolveClass();
  if (!cls || (cls->isVolatile() && !isPresent())) {
    if (cls && !m_depsSet) {
      cls->addUse(getScope(), BlockScope::UseKindConstRef);
      m_depsSet = true;
    }
    return ExpressionPtr();
  }

  ConstantTablePtr constants = cls->getConstants();
  ClassScopePtr defClass = cls;
  ConstructPtr decl = constants->getValueRecur(ar, m_varName, defClass);
  if (decl) {
    BlockScope::s_constMutex.lock();
    ExpressionPtr value = dynamic_pointer_cast<Expression>(decl);
    BlockScope::s_constMutex.unlock();

    if (!value->isScalar() &&
        (value->is(KindOfClassConstantExpression) ||
         value->is(KindOfConstantExpression))) {
      std::set<ExpressionPtr> seen;
      do {
        if (!seen.insert(value).second) return ExpressionPtr();
        value = value->preOptimize(ar);
        if (!value) return ExpressionPtr();
      } while (!value->isScalar() &&
               (value->is(KindOfClassConstantExpression) ||
                value->is(KindOfConstantExpression)));
    }

    ExpressionPtr rep = Clone(value, getScope());
    rep->setComment(getText());
    copyLocationTo(rep);
    return replaceValue(rep);
  }
  return ExpressionPtr();
}
예제 #12
0
void ClassConstant::onParseRecur(AnalysisResultConstPtr ar,
                                 ClassScopePtr scope) {
  ConstantTablePtr constants = scope->getConstants();

  for (int i = 0; i < m_exp->getCount(); i++) {
    AssignmentExpressionPtr assignment =
      dynamic_pointer_cast<AssignmentExpression>((*m_exp)[i]);

    ExpressionPtr var = assignment->getVariable();
    const std::string &name =
      dynamic_pointer_cast<ConstantExpression>(var)->getName();
    if (constants->isPresent(name)) {
      Compiler::Error(Compiler::DeclaredConstantTwice, assignment);
      m_exp->removeElement(i--);
    } else {
      assignment->onParseRecur(ar, scope);
    }
  }
}
ExpressionPtr ClassConstantExpression::preOptimize(AnalysisResultPtr ar) {
  if (ar->getPhase() < AnalysisResult::FirstPreOptimize) {
    return ExpressionPtr();
  }
  if (m_redeclared) return ExpressionPtr();
  ClassScopePtr cls = ar->resolveClass(m_className);
  if (!cls || cls->isRedeclaring()) return ExpressionPtr();
  ConstantTablePtr constants = cls->getConstants();
  if (constants->isExplicitlyDeclared(m_varName)) {
    ConstructPtr decl = constants->getValue(m_varName);
    if (decl) {
      ExpressionPtr value = dynamic_pointer_cast<Expression>(decl);
      if (!m_visited) {
        m_visited = true;
        ar->pushScope(cls);
        ExpressionPtr optExp = value->preOptimize(ar);
        ar->popScope();
        m_visited = false;
        if (optExp) value = optExp;
      }
      if (value->isScalar()) {
        // inline the value
        if (value->is(Expression::KindOfScalarExpression)) {
          ScalarExpressionPtr exp =
            dynamic_pointer_cast<ScalarExpression>(Clone(value));
          exp->setComment(getText());
          return exp;
        } else if (value->is(Expression::KindOfConstantExpression)) {
          // inline the value
          ConstantExpressionPtr exp =
            dynamic_pointer_cast<ConstantExpression>(Clone(value));
          exp->setComment(getText());
          return exp;
        }
      }
    }
  }
  return ExpressionPtr();
}
예제 #14
0
void ClassConstant::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  if (cg.getContext() != CodeGenerator::CppClassConstantsDecl &&
      cg.getContext() != CodeGenerator::CppClassConstantsImpl) {
    return;
  }

  ClassScopePtr scope = getClassScope();
  for (int i = 0; i < m_exp->getCount(); i++) {
    AssignmentExpressionPtr exp =
      dynamic_pointer_cast<AssignmentExpression>((*m_exp)[i]);
    ConstantExpressionPtr var =
      dynamic_pointer_cast<ConstantExpression>(exp->getVariable());
    TypePtr type = scope->getConstants()->getFinalType(var->getName());
    ExpressionPtr value = exp->getValue();
    if (scope->getConstants()->isDynamic(var->getName())) {
        continue;
    }
    switch (cg.getContext()) {
    case CodeGenerator::CppClassConstantsDecl:
      cg_printf("extern const ");
      if (type->is(Type::KindOfString)) {
        cg_printf("StaticString");
      } else {
        type->outputCPPDecl(cg, ar, getScope());
      }
      cg_printf(" %s%s%s%s;\n",
                Option::ClassConstantPrefix, scope->getId().c_str(),
                Option::IdPrefix.c_str(), var->getName().c_str());
      break;
    case CodeGenerator::CppClassConstantsImpl: {
      bool isString = type->is(Type::KindOfString);
      bool isVariant = Type::IsMappedToVariant(type);
      ScalarExpressionPtr scalarExp =
        dynamic_pointer_cast<ScalarExpression>(value);
      bool stringForVariant = false;
      if (isVariant && scalarExp &&
          scalarExp->getActualType() &&
          scalarExp->getActualType()->is(Type::KindOfString)) {
        cg_printf("static const StaticString %s%s%s%s%sv(LITSTR_INIT(%s));\n",
                  Option::ClassConstantPrefix, scope->getId().c_str(),
                  Option::IdPrefix.c_str(), var->getName().c_str(),
                  Option::IdPrefix.c_str(),
                  scalarExp->getCPPLiteralString().c_str());
        stringForVariant = true;
      }
      cg_printf("const ");
      if (isString) {
        cg_printf("StaticString");
      } else {
        type->outputCPPDecl(cg, ar, getScope());
      }
      value->outputCPPBegin(cg, ar);
      cg_printf(" %s%s%s%s",
                Option::ClassConstantPrefix, scope->getId().c_str(),
                Option::IdPrefix.c_str(), var->getName().c_str());
      cg_printf(isString ? "(" : " = ");
      if (stringForVariant) {
        cg_printf("%s%s%s%s%sv",
                  Option::ClassConstantPrefix, scope->getId().c_str(),
                  Option::IdPrefix.c_str(), var->getName().c_str(),
                  Option::IdPrefix.c_str());
      } else if (isString && scalarExp) {
        cg_printf("LITSTR_INIT(%s)",
                  scalarExp->getCPPLiteralString().c_str());
      } else {
        value->outputCPP(cg, ar);
      }
      cg_printf(isString ? ");\n" : ";\n");
      value->outputCPPEnd(cg, ar);
      break;
    }
    default:
      assert(false);
    }
  }
}
예제 #15
0
void ClassStatement::outputCPPClassDecl(CodeGenerator &cg,
                                        AnalysisResultPtr ar,
                                        const char *clsName,
                                        const char *originalName,
                                        const char *parent) {
  ClassScopePtr classScope = m_classScope.lock();
  VariableTablePtr variables = classScope->getVariables();
  ConstantTablePtr constants = classScope->getConstants();
  if (variables->hasAllJumpTables() && constants->hasJumpTable() &&
      classScope->hasAllJumpTables()) {
    cg_printf("DECLARE_CLASS(%s, %s, %s)\n", clsName, originalName, parent);
    return;
  }

  // Now we start to break down DECLARE_CLASS into lines of code that could
  // be generated differently...

  cg_printf("DECLARE_CLASS_COMMON(%s, %s)\n", clsName, originalName);
  cg_printf("DECLARE_INVOKE_EX(%s, %s, %s)\n",
            clsName, originalName, parent);

  cg.printSection("DECLARE_STATIC_PROP_OPS");
  cg_printf("public:\n");
  if (classScope->needStaticInitializer()) {
    cg_printf("static void os_static_initializer();\n");
  }
  if (variables->hasJumpTable(VariableTable::JumpTableClassStaticGetInit)) {
    cg_printf("static Variant os_getInit(const char *s, int64 hash);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_GETINIT_%s 1\n", clsName);
  }
  if (variables->hasJumpTable(VariableTable::JumpTableClassStaticGet)) {
    cg_printf("static Variant os_get(const char *s, int64 hash);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_GET_%s 1\n", clsName);
  }
  if (variables->hasJumpTable(VariableTable::JumpTableClassStaticLval)) {
    cg_printf("static Variant &os_lval(const char *s, int64 hash);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_LVAL_%s 1\n", clsName);
  }
  if (constants->hasJumpTable()) {
    cg_printf("static Variant os_constant(const char *s);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_CONSTANT_%s 1\n", clsName);
  }

  cg.printSection("DECLARE_INSTANCE_PROP_OPS");
  cg_printf("public:\n");
  cg_printf("virtual bool o_exists(CStrRef s, int64 hash,\n");
  cg_printf("                      const char *context = NULL) const;\n");
  cg_printf("bool o_existsPrivate(CStrRef s, int64 hash) const;\n");
  cg_printf("virtual void o_get(Array &props) const;\n");
  cg_printf("virtual Variant o_get(CStrRef s, int64 hash, "
            "bool error = true,\n");
  cg_printf("                      const char *context = NULL);\n");
  cg_printf("Variant o_getPrivate(CStrRef s, int64 hash, "
            "bool error = true);\n");
  cg_printf("virtual Variant o_set(CStrRef s, int64 hash, CVarRef v,\n");
  cg_printf("                      bool forInit = false,\n");
  cg_printf("                      const char *context = NULL);\n");
  cg_printf("Variant o_setPrivate(CStrRef s, int64 hash, CVarRef v, "
            "bool forInit);\n");
  cg_printf("virtual Variant &o_lval(CStrRef s, int64 hash,\n");
  cg_printf("                        const char *context = NULL);\n");
  cg_printf("Variant &o_lvalPrivate(CStrRef s, int64 hash);\n");

  cg.printSection("DECLARE_INSTANCE_PUBLIC_PROP_OPS");
  cg_printf("public:\n");
  if (variables->hasJumpTable(VariableTable::JumpTableClassExistsPublic)) {
    cg_printf("virtual bool o_existsPublic(CStrRef s, int64 hash) const;\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_exists_PUBLIC_%s 1\n", clsName);
  }
  if (variables->hasJumpTable(VariableTable::JumpTableClassGetPublic)) {
    cg_printf("virtual Variant o_getPublic(CStrRef s, int64 hash,\n");
    cg_printf("                            bool error = true);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_get_PUBLIC_%s 1\n", clsName);
  }
  if (variables->hasJumpTable(VariableTable::JumpTableClassSetPublic)) {
    cg_printf("virtual Variant o_setPublic(CStrRef s, int64 hash,\n");
    cg_printf("                            CVarRef v, bool forInit);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_set_PUBLIC_%s 1\n", clsName);
  }
  if (variables->hasJumpTable(VariableTable::JumpTableClassLvalPublic)) {
    cg_printf("virtual Variant &o_lvalPublic(CStrRef s, int64 hash);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_lval_PUBLIC_%s 1\n", clsName);
  }

  cg.printSection("DECLARE_COMMON_INVOKE");
  if (classScope->hasJumpTable(ClassScope::JumpTableStaticInvoke)) {
    cg_printf("static Variant os_invoke(const char *c, const char *s,\n");
    cg_printf("                         CArrRef ps, int64 h, "
              "bool f = true);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_INVOKE_%s 1\n", clsName);
  }
  if (classScope->hasJumpTable(ClassScope::JumpTableInvoke)) {
    cg_printf("virtual Variant o_invoke(const char *s, CArrRef ps, "
              "int64 h,\n");
    cg_printf("                         bool f = true);\n");
    cg_printf("virtual Variant o_invoke_few_args(const char *s, int64 h,\n");
    cg_printf("                                  int count,\n");
    cg_printf("                                  "
              "INVOKE_FEW_ARGS_DECL_ARGS);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_INVOKE_%s 1\n", clsName);
  }

  cg_printf("\n");
  cg_printf("public:\n");
}
예제 #16
0
void ClassStatement::outputCPPClassDecl(CodeGenerator &cg,
                                        AnalysisResultPtr ar,
                                        const char *clsName,
                                        const char *originalName,
                                        const char *parent) {
  ClassScopePtr classScope = m_classScope.lock();
  VariableTablePtr variables = classScope->getVariables();
  ConstantTablePtr constants = classScope->getConstants();
  if (variables->hasAllJumpTables() && constants->hasJumpTable() &&
      classScope->hasAllJumpTables()) {
    cg_printf("DECLARE_CLASS(%s, %s, %s)\n", clsName, originalName, parent);
    return;
  }

  // Now we start to break down DECLARE_CLASS into lines of code that could
  // be generated differently...

  cg_printf("DECLARE_CLASS_COMMON(%s, %s)\n", clsName, originalName);
  cg_printf("DECLARE_INVOKE_EX(%s, %s, %s)\n",
            clsName, originalName, parent);

  cg.printSection("DECLARE_STATIC_PROP_OPS");
  cg_printf("public:\n");
  if (classScope->needStaticInitializer()) {
    cg_printf("static void os_static_initializer();\n");
  }
  if (variables->hasJumpTable(VariableTable::JumpTableClassStaticGetInit)) {
    cg_printf("static Variant os_getInit(CStrRef s);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_GETINIT_%s 1\n", clsName);
  }
  if (variables->hasJumpTable(VariableTable::JumpTableClassStaticGet)) {
    cg_printf("static Variant os_get(CStrRef s);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_GET_%s 1\n", clsName);
  }
  if (variables->hasJumpTable(VariableTable::JumpTableClassStaticLval)) {
    cg_printf("static Variant &os_lval(CStrRef s);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_LVAL_%s 1\n", clsName);
  }
  if (constants->hasJumpTable()) {
    cg_printf("static Variant os_constant(const char *s);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_CONSTANT_%s 1\n", clsName);
  }

  cg.printSection("DECLARE_INSTANCE_PROP_OPS");
  cg_printf("public:\n");

  if (variables->hasJumpTable(VariableTable::JumpTableClassGetArray)) {
    cg_printf("virtual void o_getArray(Array &props) const;\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_GETARRAY_%s 1\n", clsName);
  }
  if (variables->hasJumpTable(VariableTable::JumpTableClassSetArray)) {
    cg_printf("virtual void o_setArray(CArrRef props);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_SETARRAY_%s 1\n", clsName);
  }

  if (variables->hasJumpTable(VariableTable::JumpTableClassRealProp)) {
    cg_printf("virtual Variant *o_realProp(CStrRef s, int flags,\n");
    cg_printf("                            CStrRef context = null_string) "
              "const;\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_realProp_%s 1\n", clsName);
  }
  if (variables->hasNonStaticPrivate()) {
    cg_printf("Variant *o_realPropPrivate(CStrRef s, int flags) const;\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_realProp_PRIVATE_%s 1\n", clsName);
  }

  cg.printSection("DECLARE_INSTANCE_PUBLIC_PROP_OPS");
  cg_printf("public:\n");
  if (variables->hasJumpTable(VariableTable::JumpTableClassRealPropPublic)) {
    cg_printf("virtual Variant *o_realPropPublic(CStrRef s, "
              "int flags) const;\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_realProp_PUBLIC_%s 1\n", clsName);
  }

  cg.printSection("DECLARE_COMMON_INVOKE");
  if (classScope->hasJumpTable(ClassScope::JumpTableStaticInvoke)) {
    cg_printf("static Variant os_invoke(const char *c, "
              "MethodIndex methodIndex,\n");
    cg_printf("                         const char *s, CArrRef ps, int64 h, "
              "bool f = true);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_STATIC_INVOKE_%s 1\n", clsName);
  }
  if (classScope->hasJumpTable(ClassScope::JumpTableInvoke)) {
    cg_printf("virtual Variant o_invoke(MethodIndex methodIndex, "
              "const char *s, CArrRef ps,\n");
    cg_printf("                         int64 h, bool f = true);\n");
    cg_printf("virtual Variant o_invoke_few_args(MethodIndex methodIndex, "
              "const char *s,\n");
    cg_printf("                                  int64 h, int count,\n");
    cg_printf("                                  "
              "INVOKE_FEW_ARGS_DECL_ARGS);\n");
  } else {
    cg_printf("#define OMIT_JUMP_TABLE_CLASS_INVOKE_%s 1\n", clsName);
  }

  cg_printf("\n");
  cg_printf("public:\n");
}
예제 #17
0
void ClassConstant::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  bool lazyInit = cg.getContext() == CodeGenerator::CppLazyStaticInitializer;
  if (cg.getContext() != CodeGenerator::CppClassConstantsDecl &&
      cg.getContext() != CodeGenerator::CppClassConstantsImpl &&
      !lazyInit) {
    return;
  }

  ClassScopePtr scope = getClassScope();
  for (int i = 0; i < m_exp->getCount(); i++) {
    AssignmentExpressionPtr exp =
      dynamic_pointer_cast<AssignmentExpression>((*m_exp)[i]);
    ConstantExpressionPtr var =
      dynamic_pointer_cast<ConstantExpression>(exp->getVariable());
    TypePtr type = scope->getConstants()->getFinalType(var->getName());
    ExpressionPtr value = exp->getValue();
    if (!scope->getConstants()->isDynamic(var->getName()) == lazyInit) {
        continue;
    }
    switch (cg.getContext()) {
    case CodeGenerator::CppClassConstantsDecl:
      cg_printf("extern const ");
      if (type->is(Type::KindOfString)) {
        cg_printf("StaticString");
      } else {
        type->outputCPPDecl(cg, ar, getScope());
      }
      cg_printf(" %s%s_%s;\n", Option::ClassConstantPrefix,
                scope->getId(cg).c_str(),
                var->getName().c_str());
      break;
    case CodeGenerator::CppClassConstantsImpl: {
      cg_printf("const ");
      bool isString = type->is(Type::KindOfString);
      if (isString) {
        cg_printf("StaticString");
      } else {
        type->outputCPPDecl(cg, ar, getScope());
      }
      value->outputCPPBegin(cg, ar);
      cg_printf(" %s%s_%s", Option::ClassConstantPrefix,
                scope->getId(cg).c_str(),
                var->getName().c_str());
      cg_printf(isString ? "(" : " = ");
      ScalarExpressionPtr scalarExp =
        dynamic_pointer_cast<ScalarExpression>(value);
      if (isString && scalarExp) {
        cg_printf("LITSTR_INIT(%s)",
                  scalarExp->getCPPLiteralString(cg).c_str());
      } else {
        value->outputCPP(cg, ar);
      }
      cg_printf(isString ? ");\n" : ";\n");
      value->outputCPPEnd(cg, ar);
      break;
    }
    case CodeGenerator::CppLazyStaticInitializer:
      value->outputCPPBegin(cg, ar);
      cg_printf("g->%s%s_%s = ", Option::ClassConstantPrefix,
                scope->getId(cg).c_str(),
                var->getName().c_str());
      value->outputCPP(cg, ar);
      cg_printf(";\n");
      value->outputCPPEnd(cg, ar);
      break;
    default:
      ASSERT(false);
    }
  }
}