TypePtr ConstantTable::add(const std::string &name, TypePtr type, ExpressionPtr exp, AnalysisResultConstPtr ar, ConstructPtr construct) { if (name == "true" || name == "false") { return Type::Boolean; } Symbol *sym = genSymbol(name, true); if (!sym->declarationSet()) { setType(ar, sym, type, true); sym->setDeclaration(construct); sym->setValue(exp); return type; } if (m_blockScope.isFirstPass()) { if (construct) { if (exp != sym->getValue()) { Compiler::Error(Compiler::DeclaredConstantTwice, construct, sym->getDeclaration()); if (!sym->isDynamic()) { sym->setDynamic(); m_hasDynamic = true; } type = Type::Variant; } } else if (exp) { sym->setValue(exp); } setType(ar, sym, type, true); } return type; }
void VariableTable::forceVariants(AnalysisResultConstPtr ar, int varClass, bool recur /* = true */) { int mask = varClass & ~m_forcedVariants; if (mask) { if (!m_hasPrivate) mask &= ~AnyPrivateVars; if (!m_hasStatic) mask &= ~AnyStaticVars; if (mask) { for (unsigned int i = 0; i < m_symbolVec.size(); i++) { Symbol *sym = m_symbolVec[i]; if (!sym->isHidden() && sym->declarationSet() && mask & GetVarClassMaskForSym(sym)) { setType(ar, sym, Type::Variant, true); sym->setIndirectAltered(); } } } m_forcedVariants |= varClass; if (recur) { ClassScopePtr parent = m_blockScope.getParentScope(ar); if (parent && !parent->isRedeclaring()) { parent->getVariables()->forceVariants(ar, varClass & ~AnyPrivateVars); } } } }
Symbol *VariableTable::findProperty(ClassScopePtr &cls, const string &name, AnalysisResultConstPtr ar) { Symbol *sym = getSymbol(name); if (sym) { assert(sym->declarationSet()); if (!sym->isOverride()) { return sym; } assert(!sym->isStatic()); sym = nullptr; } if (!sym) { if (ClassScopePtr parent = findParent(ar, name, sym)) { sym = parent->findProperty(parent, name, ar); if (sym) { cls = parent; return sym; } } } return sym; }
Symbol *SymbolTable::genSymbol(const std::string &name, bool konst, ConstructPtr construct) { Symbol *sym = genSymbol(name, konst); if (!sym->declarationSet() && construct) { m_symbolVec.push_back(sym); sym->setDeclaration(construct); } return sym; }
void ConstantTable::outputCPP(CodeGenerator &cg, AnalysisResultPtr ar) { bool decl = true; if (cg.getContext() == CodeGenerator::CppConstantsDecl) { decl = false; } bool printed = false; for (StringToSymbolMap::iterator iter = m_symbolMap.begin(), end = m_symbolMap.end(); iter != end; ++iter) { Symbol *sym = &iter->second; if (!sym->declarationSet() || sym->isDynamic()) continue; if (sym->isSystem() && cg.getOutput() != CodeGenerator::SystemCPP) continue; const string &name = sym->getName(); ConstructPtr value = sym->getValue(); printed = true; cg_printf(decl ? "extern const " : "const "); TypePtr type = sym->getFinalType(); bool isString = type->is(Type::KindOfString); if (isString) { cg_printf("StaticString"); } else { type->outputCPPDecl(cg, ar); } if (decl) { cg_printf(" %s%s", Option::ConstantPrefix, cg.formatLabel(name).c_str()); } else { cg_printf(" %s%s", Option::ConstantPrefix, cg.formatLabel(name).c_str()); cg_printf(isString ? "(" : " = "); if (value) { ExpressionPtr exp = dynamic_pointer_cast<Expression>(value); ASSERT(!exp->getExpectedType()); ScalarExpressionPtr scalarExp = dynamic_pointer_cast<ScalarExpression>(exp); if (isString && scalarExp) { cg_printf("LITSTR_INIT(%s)", scalarExp->getCPPLiteralString(cg).c_str()); } else { exp->outputCPP(cg, ar); } } else { cg_printf("\"%s\"", cg.escapeLabel(name).c_str()); } if (isString) { cg_printf(")"); } } cg_printf(";\n"); } if (printed) { cg_printf("\n"); } }
void ConstantTable::collectCPPGlobalSymbols(StringPairVec &symbols, CodeGenerator &cg, AnalysisResultPtr ar) { for (StringToSymbolMap::iterator iter = m_symbolMap.begin(), end = m_symbolMap.end(); iter != end; ++iter) { Symbol *sym = &iter->second; if (sym->declarationSet() && sym->isDynamic()) { string varname = Option::ConstantPrefix + cg.formatLabel(sym->getName()); symbols.push_back(pair<string, string>(varname, varname)); } } }
void ConstantTable::outputCPPDynamicImpl(CodeGenerator &cg, AnalysisResultPtr ar) { for (StringToSymbolMap::iterator iter = m_symbolMap.begin(), end = m_symbolMap.end(); iter != end; ++iter) { Symbol *sym = &iter->second; if (sym->declarationSet() && sym->isDynamic()) { cg_printf("%s%s = \"%s\";\n", Option::ConstantPrefix, cg.formatLabel(sym->getName()).c_str(), cg.escapeLabel(sym->getName()).c_str()); } } }
void Symbol::import(BlockScopeRawPtr scope, const Symbol &src_sym) { setName(src_sym.getName()); setSystem(); if (src_sym.declarationSet()) { ConstructPtr sc = src_sym.getDeclaration(); if (sc) sc->resetScope(scope); setDeclaration(sc); } if (src_sym.valueSet()) { ConstructPtr sc = src_sym.getValue(); if (sc) sc->resetScope(scope); setValue(sc); } if (src_sym.isDynamic()) { setDynamic(); } if (src_sym.isConstant()) { setConstant(); } }
void ConstantTable::outputCPPDynamicDecl(CodeGenerator &cg, AnalysisResultPtr ar) { const char *prefix = Option::ConstantPrefix; string classId; const char *fmt = "Variant %s%s%s;\n"; ClassScopePtr scope = ar->getClassScope(); if (scope) { prefix = Option::ClassConstantPrefix; classId = scope->getId(cg); fmt = "Variant %s%s_%s;\n"; } for (StringToSymbolMap::iterator iter = m_symbolMap.begin(), end = m_symbolMap.end(); iter != end; ++iter) { Symbol *sym = &iter->second; if (sym->declarationSet() && sym->isDynamic()) { cg_printf(fmt, prefix, classId.c_str(), cg.formatLabel(sym->getName()).c_str()); } } }
void MethodStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { FunctionScopeRawPtr funcScope = getFunctionScope(); ClassScopePtr scope = getClassScope(); if (outputFFI(cg, ar)) return; cg.setPHPLineNo(-1); CodeGenerator::Context context = cg.getContext(); if (context == CodeGenerator::CppImplementation) { printSource(cg); } bool isWrapper = context == CodeGenerator::CppTypedParamsWrapperDecl || context == CodeGenerator::CppTypedParamsWrapperImpl; bool needsWrapper = isWrapper || (Option::HardTypeHints && funcScope->needsTypeCheckWrapper()); const char *prefix = needsWrapper && !isWrapper ? Option::TypedMethodPrefix : Option::MethodPrefix; switch (context) { case CodeGenerator::CppDeclaration: case CodeGenerator::CppTypedParamsWrapperDecl: { if (!m_stmt && !funcScope->isPerfectVirtual()) { cg_printf("// "); } m_modifiers->outputCPP(cg, ar); if (!m_stmt || m_name == "__offsetget_lval" || funcScope->isPerfectVirtual()) { cg_printf("virtual "); } TypePtr type = funcScope->getReturnType(); if (type) { type->outputCPPDecl(cg, ar, getScope()); } else { cg_printf("void"); } if (m_name == "__offsetget_lval") { cg_printf(" &___offsetget_lval("); } else if (m_modifiers->isStatic() && m_stmt) { // Static method wrappers get generated as support methods cg_printf(" %s%s(CStrRef cls%s", needsWrapper && !isWrapper ? Option::TypedMethodImplPrefix : Option::MethodImplPrefix, cg.formatLabel(m_name).c_str(), funcScope->isVariableArgument() || (m_params && m_params->getCount()) ? ", " : ""); } else { cg_printf(" %s%s(", prefix, cg.formatLabel(m_name).c_str()); } funcScope->outputCPPParamsDecl(cg, ar, m_params, true); if (m_stmt) { cg_printf(");\n"); } else if (funcScope->isPerfectVirtual()) { cg_printf(") { return throw_fatal(\"pure virtual\");}\n"); } else { cg_printf(") = 0;\n"); } if (context != CodeGenerator::CppTypedParamsWrapperDecl) { if (funcScope->isConstructor(scope) && !funcScope->isAbstract() && !scope->isInterface()) { funcScope->outputCPPCreateDecl(cg, ar); } if (Option::HardTypeHints && funcScope->needsTypeCheckWrapper()) { cg.setContext(CodeGenerator::CppTypedParamsWrapperDecl); outputCPPImpl(cg, ar); cg.setContext(context); } } } break; case CodeGenerator::CppImplementation: case CodeGenerator::CppTypedParamsWrapperImpl: if (m_stmt) { TypePtr type = funcScope->getReturnType(); if (type) { type->outputCPPDecl(cg, ar, getScope()); } else { cg_printf("void"); } string origFuncName = getOriginalFullName(); if (Option::FunctionSections.find(origFuncName) != Option::FunctionSections.end()) { string funcSection = Option::FunctionSections[origFuncName]; if (!funcSection.empty()) { cg_printf(" __attribute__ ((section (\".text.%s\")))", funcSection.c_str()); } } if (m_name == "__offsetget_lval") { cg_printf(" &%s%s::___offsetget_lval(", Option::ClassPrefix, scope->getId(cg).c_str()); } else if (m_modifiers->isStatic()) { cg_printf(" %s%s::%s%s(CStrRef cls%s", Option::ClassPrefix, scope->getId(cg).c_str(), needsWrapper && !isWrapper ? Option::TypedMethodImplPrefix : Option::MethodImplPrefix, cg.formatLabel(m_name).c_str(), funcScope->isVariableArgument() || (m_params && m_params->getCount()) ? ", " : ""); } else { cg_printf(" %s%s::%s%s(", Option::ClassPrefix, scope->getId(cg).c_str(), prefix, cg.formatLabel(m_name).c_str()); } funcScope->outputCPPParamsDecl(cg, ar, m_params, false); cg_indentBegin(") {\n"); if (context != CodeGenerator::CppTypedParamsWrapperImpl) { if (m_stmt->hasBody()) { const char *sys = (cg.getOutput() == CodeGenerator::SystemCPP ? "_BUILTIN" : ""); if (m_modifiers->isStatic()) { cg_printf("STATIC_METHOD_INJECTION%s(%s, %s);\n", sys, scope->getOriginalName().c_str(), origFuncName.c_str()); } else if (cg.getOutput() != CodeGenerator::SystemCPP && !scope->isRedeclaring() && !scope->derivedByDynamic()) { cg_printf("INSTANCE_METHOD_INJECTION_ROOTLESS(%s, %s);\n", scope->getOriginalName().c_str(), origFuncName.c_str()); } else if (scope->getOriginalName() != "XhprofFrame") { cg_printf("INSTANCE_METHOD_INJECTION%s(%s, %s);\n", sys, scope->getOriginalName().c_str(), origFuncName.c_str()); } } outputCPPArgInjections(cg, ar, origFuncName.c_str(), scope, funcScope); if (m_name == "__offsetget_lval") { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[0]); cg_printf("Variant &v = %s->__lvalProxy;\n", cg.getGlobals(ar)); string lowered = Util::toLower(m_originalName); cg_printf("v = %s%s(%s%s);\n", prefix, lowered.c_str(), Option::VariablePrefix, param->getName().c_str()); cg_printf("return v;\n"); } else { if (funcScope->isConstructor(scope)) { cg_printf("bool oldInCtor = gasInCtor(true);\n"); } else if (m_name == "__destruct") { cg_printf("setInDtor();\n"); } funcScope->outputCPP(cg, ar); cg.setContext( CodeGenerator::NoContext); // no inner functions/classes if (!funcScope->isStatic() && funcScope->getVariables()-> getAttribute(VariableTable::ContainsDynamicVariable)) { Symbol *sym = funcScope->getVariables()->getSymbol("this"); if (sym && sym->declarationSet()) { cg_printf("%sthis = this;\n", Option::VariablePrefix); } } outputCPPStmt(cg, ar); } cg_indentEnd("}\n"); if (Option::HardTypeHints && funcScope->needsTypeCheckWrapper()) { cg.setContext(CodeGenerator::CppTypedParamsWrapperImpl); outputCPPImpl(cg, ar); } } else { outputCPPTypeCheckWrapper(cg, ar); cg_indentEnd("}\n"); } cg.setContext(context); cg.printImplSplitter(); } break; default: break; } }