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); } } }
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 } }
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()); } }
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); } } } }
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; }
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; }
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(); }
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(); }
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(); }
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); } } }
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"); }
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"); }
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); } } }