void Type::outputCPPDecl(CodeGenerator &cg, AnalysisResultConstPtr ar, BlockScopeRawPtr scope) { cg_printf(getCPPDecl(cg, ar, scope).c_str()); if (isSpecificObject() && cg.isFileOrClassHeader() && scope) { if (scope->getContainingClass()) { scope->getContainingClass()->addUsedClassHeader(m_name); } else if (scope->getContainingFile()) { scope->getContainingFile()->addUsedClassHeader(m_name); } } }
void ParameterExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { FunctionScopePtr func = getFunctionScope(); VariableTablePtr variables = func->getVariables(); Symbol *sym = variables->getSymbol(m_name); assert(sym && sym->isParameter()); bool inHeader = cg.isFileOrClassHeader(); cg.setFileOrClassHeader(true); CodeGenerator::Context context = cg.getContext(); bool typedWrapper = (context == CodeGenerator::CppTypedParamsWrapperImpl || context == CodeGenerator::CppTypedParamsWrapperDecl); TypePtr paramType = typedWrapper && func->getParamTypeSpec(sym->getParameterIndex()) ? Type::Variant : func->getParamType(sym->getParameterIndex()); bool wrapper = typedWrapper || context == CodeGenerator::CppFunctionWrapperImpl || context == CodeGenerator::CppFunctionWrapperDecl; bool isCVarRef = false; const char *prefix = ""; if (m_ref) { cg_printf("VRefParam"); if (!wrapper) { prefix = "r"; } } else if (wrapper || (!variables->isLvalParam(m_name) && !variables->getAttribute(VariableTable::ContainsDynamicVariable) && !variables->getAttribute(VariableTable::ContainsExtract))) { if (paramType->is(Type::KindOfVariant) || paramType->is(Type::KindOfSome)) { cg_printf("CVarRef"); isCVarRef = true; } else if (paramType->is(Type::KindOfArray)) cg_printf("CArrRef"); else if (paramType->is(Type::KindOfString)) cg_printf("CStrRef"); else paramType->outputCPPDecl(cg, ar, getScope()); } else { paramType->outputCPPDecl(cg, ar, getScope()); } cg_printf(" %s%s%s", prefix, Option::VariablePrefix, CodeGenerator::FormatLabel(m_name).c_str()); if (m_defaultValue && sym->getParameterIndex() >= func->getMinParamCount()) { bool comment = context == CodeGenerator::CppTypedParamsWrapperImpl || context == CodeGenerator::CppFunctionWrapperImpl || context == CodeGenerator::CppImplementation || (context == CodeGenerator::CppDeclaration && func->isInlined()); if (comment) { cg_printf(" // "); } cg_printf(" = "); ConstantExpressionPtr con = dynamic_pointer_cast<ConstantExpression>(m_defaultValue); bool done = false; if (con && con->isNull()) { done = true; if (isCVarRef) { cg_printf("null_variant"); } else if (paramType->is(Type::KindOfVariant) || paramType->is(Type::KindOfSome)) { cg_printf("null"); } else if (paramType->is(Type::KindOfObject)) { cg_printf("Object()"); } else if (paramType->is(Type::KindOfArray)) { cg_printf("Array()"); } else if (paramType->is(Type::KindOfString)) { cg_printf("String()"); } else { done = false; } } if (!done) { if (comment) { cg.setContext(CodeGenerator::CppParameterDefaultValueImpl); } else { cg.setContext(CodeGenerator::CppParameterDefaultValueDecl); } bool isScalar = m_defaultValue->isScalar(); if (isCVarRef && isScalar) { ASSERT(!cg.hasScalarVariant()); cg.setScalarVariant(); } m_defaultValue->outputCPP(cg, ar); if (isCVarRef && isScalar) cg.clearScalarVariant(); ASSERT(!cg.hasScalarVariant()); cg.setContext(context); } if (comment) { cg_printf("\n"); } } cg.setFileOrClassHeader(inHeader); }
void UnaryOpExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { if ((m_op == T_INC || m_op == T_DEC) && outputCPPImplOpEqual(cg, ar)) { return; } if (m_op == T_ARRAY && (getContext() & (RefValue|LValue)) == 0 && !cg.getInsideScalarArray()) { int id = -1; int hash = -1; int index = -1; string text; if (m_exp) { ExpressionListPtr pairs = dynamic_pointer_cast<ExpressionList>(m_exp); Variant v; if (pairs && pairs->isScalarArrayPairs() && pairs->getScalarValue(v)) { id = ar->registerScalarArray(cg.getInsideScalarArray(), getFileScope(), m_exp, hash, index, text); } } else { id = ar->registerScalarArray(cg.getInsideScalarArray(), getFileScope(), m_exp, hash, index, text); // empty array } if (id != -1) { if (Option::UseNamedScalarArray && cg.isFileOrClassHeader()) { if (getClassScope()) { getClassScope()->addUsedDefaultValueScalarArray(text); } else { getFileScope()->addUsedDefaultValueScalarArray(text); } } ar->outputCPPScalarArrayId(cg, id, hash, index); return; } } if ((m_op == T_ISSET || m_op == T_EMPTY || m_op == T_UNSET) && m_exp) { if (m_exp->is(Expression::KindOfExpressionList)) { ExpressionListPtr exps = dynamic_pointer_cast<ExpressionList>(m_exp); if (exps->getListKind() == ExpressionList::ListKindParam) { int count = exps->getCount(); if (count > 1) { cg_printf("("); } for (int i = 0; i < count; i++) { if (m_op == T_UNSET) { if (i > 0) cg_printf(", "); (*exps)[i]->outputCPPUnset(cg, ar); } else { if (i > 0) cg_printf(" && "); (*exps)[i]->outputCPPExistTest(cg, ar, m_op); } } if (exps->getCount() > 1) { cg_printf(")"); } return; } } if (m_op == T_UNSET) { m_exp->outputCPPUnset(cg, ar); } else { m_exp->outputCPPExistTest(cg, ar, m_op); } return; } if (m_front) { switch (m_op) { case T_CLONE: cg_printf("f_clone("); break; case T_INC: cg_printf("++"); break; case T_DEC: cg_printf("--"); break; case '+': cg_printf("+"); break; case '-': cg_printf("negate("); break; case '!': cg_printf("!("); break; case '~': cg_printf("~"); break; case T_INT_CAST: cg_printf("("); break; case T_DOUBLE_CAST: cg_printf("("); break; case T_STRING_CAST: cg_printf("("); break; case T_ARRAY_CAST: cg_printf("("); break; case T_OBJECT_CAST: cg_printf("("); break; case T_BOOL_CAST: cg_printf("("); break; case T_UNSET_CAST: if (m_exp->isScalar()) { cg_printf("(null)"); return; } if (m_exp->hasCPPTemp()) { cg_printf("(id("); } else { cg_printf("("); } break; case T_EXIT: cg_printf("f_exit("); break; case T_ARRAY: cg_printf("Array("); break; case T_PRINT: cg_printf("print("); break; case T_EVAL: if (Option::EnableEval > Option::NoEval) { bool instance; if (getClassScope()) { FunctionScopePtr fs = getFunctionScope(); instance = fs && !fs->isStatic(); } else { instance = false; } cg_printf("eval(%s, Object(%s), ", getScope()->inPseudoMain() ? "get_variable_table()" : "variables", instance ? "this" : ""); } else { cg_printf("f_eval("); } break; case '@': if (m_silencer >= 0) { cg_printf("(%s%d.enable(),%s%d.disable(", Option::SilencerPrefix, m_silencer, Option::SilencerPrefix, m_silencer); } break; case T_FILE: cg_printf("get_source_filename(\"%s\")", getLocation()->file); break; break; default: ASSERT(false); } } if (m_exp) { switch (m_op) { case '+': case '-': if (m_exp->getActualType() && (m_exp->getActualType()->is(Type::KindOfString) || m_exp->getActualType()->is(Type::KindOfArray))) { cg_printf("(Variant)("); m_exp->outputCPP(cg, ar); cg_printf(")"); } else { m_exp->outputCPP(cg, ar); } break; case '@': if (m_silencer < 0 && isUnused()) { m_exp->outputCPPUnneeded(cg, ar); } else if (!m_exp->hasCPPTemp() && !m_exp->getActualType()) { // Void needs to return something to silenceDec cg_printf("("); m_exp->outputCPP(cg, ar); cg_printf(",null)"); } else { m_exp->outputCPP(cg, ar); } break; default: m_exp->outputCPP(cg, ar); break; } } if (m_front) { switch (m_op) { case T_ARRAY: { ExpressionListPtr exps = dynamic_pointer_cast<ExpressionList>(m_exp); if (!exps) { cg_printf("ArrayData::Create()"); } cg_printf(")"); } break; case T_UNSET_CAST: if (m_exp->hasCPPTemp()) { cg_printf("),null"); } else { cg_printf(",null"); } case T_CLONE: case '!': case '-': case T_INT_CAST: case T_DOUBLE_CAST: case T_STRING_CAST: case T_ARRAY_CAST: case T_OBJECT_CAST: case T_BOOL_CAST: case T_EXIT: case T_PRINT: case T_EVAL: case T_INCLUDE: case T_INCLUDE_ONCE: case T_REQUIRE: case T_REQUIRE_ONCE: cg_printf(")"); break; case '@': if (m_silencer >= 0) { cg_printf("))"); } break; default: break; } } else { switch (m_op) { case T_INC: cg_printf("++"); break; case T_DEC: cg_printf("--"); break; default: ASSERT(false); } } }
void FunctionStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { CodeGenerator::Context context = cg.getContext(); FunctionScopeRawPtr funcScope = getFunctionScope(); string fname = funcScope->getId(); bool pseudoMain = funcScope->inPseudoMain(); string origFuncName = !pseudoMain ? funcScope->getOriginalName() : ("run_init::" + funcScope->getContainingFile()->getName()); if (outputFFI(cg, ar)) return; if (context == CodeGenerator::NoContext) { funcScope->outputCPPDef(cg); return; } if (context == CodeGenerator::CppDeclaration && !funcScope->isInlined()) return; if (context == CodeGenerator::CppPseudoMain && (!pseudoMain || getFileScope()->canUseDummyPseudoMain(ar))) { return; } if (context == CodeGenerator::CppImplementation && (funcScope->isInlined() || pseudoMain)) return; cg.setPHPLineNo(-1); if (pseudoMain && !Option::GenerateCPPMain) { if (context == CodeGenerator::CppPseudoMain) { if (cg.getOutput() != CodeGenerator::SystemCPP) { cg.setContext(CodeGenerator::NoContext); // no inner functions/classes funcScope->getVariables()->setAttribute(VariableTable::ForceGlobal); outputCPPStmt(cg, ar); funcScope->getVariables()->clearAttribute(VariableTable::ForceGlobal); cg.setContext(CodeGenerator::CppPseudoMain); return; } } else if (context == CodeGenerator::CppForwardDeclaration && cg.getOutput() != CodeGenerator::SystemCPP) { return; } } if (context == CodeGenerator::CppImplementation) { printSource(cg); } else if (context == CodeGenerator::CppForwardDeclaration && Option::GenerateCppLibCode) { cg_printf("\n"); printSource(cg); cg.printDocComment(funcScope->getDocComment()); } bool isWrapper = context == CodeGenerator::CppTypedParamsWrapperDecl || context == CodeGenerator::CppTypedParamsWrapperImpl; bool needsWrapper = isWrapper || (Option::HardTypeHints && funcScope->needsTypeCheckWrapper()); int startLineImplementation = -1; if (context == CodeGenerator::CppDeclaration || context == CodeGenerator::CppImplementation || context == CodeGenerator::CppPseudoMain) { startLineImplementation = cg.getLineNo(CodeGenerator::PrimaryStream); } if (funcScope->isInlined()) cg_printf("inline "); TypePtr type = funcScope->getReturnType(); if (type) { bool isHeader = cg.isFileOrClassHeader(); cg.setFileOrClassHeader(true); type->outputCPPDecl(cg, ar, getScope()); cg.setFileOrClassHeader(isHeader); } else { cg_printf("void"); } 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 (pseudoMain) { cg_printf(" %s%s(", Option::PseudoMainPrefix, funcScope->getContainingFile()->pseudoMainName().c_str()); } else { cg_printf(" %s%s(", needsWrapper && !isWrapper ? Option::TypedFunctionPrefix : Option::FunctionPrefix, fname.c_str()); } switch (context) { case CodeGenerator::CppForwardDeclaration: case CodeGenerator::CppTypedParamsWrapperDecl: funcScope->outputCPPParamsDecl(cg, ar, m_params, true); if (!isWrapper) { int opt = Option::GetOptimizationLevel(m_cppLength); if (opt < 3) cg_printf(") __attribute__((optimize(%d))", opt); } cg_printf(");\n"); if (!isWrapper) { if (funcScope->hasDirectInvoke()) { cg_printf("Variant %s%s(void *extra, CArrRef params);\n", Option::InvokePrefix, fname.c_str()); } if (needsWrapper) { cg.setContext(CodeGenerator::CppTypedParamsWrapperDecl); outputCPPImpl(cg, ar); cg.setContext(context); } } break; case CodeGenerator::CppDeclaration: case CodeGenerator::CppImplementation: case CodeGenerator::CppPseudoMain: case CodeGenerator::CppTypedParamsWrapperImpl: { funcScope->outputCPPParamsDecl(cg, ar, m_params, false); cg_indentBegin(") {\n"); if (!isWrapper) { const char *suffix = (cg.getOutput() == CodeGenerator::SystemCPP ? "_BUILTIN" : ""); if (pseudoMain) { cg_printf("PSEUDOMAIN_INJECTION%s(%s, %s%s);\n", suffix, origFuncName.c_str(), Option::PseudoMainPrefix, funcScope->getContainingFile()->pseudoMainName().c_str()); } else { if (m_stmt->hasBody()) { if (suffix[0] == '\0' && !funcScope->needsCheckMem()) { suffix = "_NOMEM"; } const string &name = funcScope->getInjectionId(); cg_printf("FUNCTION_INJECTION%s(%s);\n", suffix, name.c_str()); } outputCPPArgInjections(cg, ar, origFuncName.c_str(), ClassScopePtr(), funcScope); } funcScope->outputCPP(cg, ar); if (funcScope->needsRefTemp()) cg.genReferenceTemp(shared_from_this()); if (funcScope->needsObjTemp()) { cg_printf("ObjectData *obj_tmp UNUSED;\n"); } cg.setContext(CodeGenerator::NoContext); // no inner functions/classes outputCPPStmt(cg, ar); if (funcScope->needsRefTemp()) cg.clearRefereceTemp(); cg_indentEnd("}\n"); ASSERT(startLineImplementation >= 0); m_cppLength = cg.getLineNo(CodeGenerator::PrimaryStream) - startLineImplementation; if (needsWrapper) { cg.setContext(CodeGenerator::CppTypedParamsWrapperImpl); outputCPPImpl(cg, ar); } cg.setContext(context); } else { outputCPPTypeCheckWrapper(cg, ar); cg_indentEnd("}\n"); } cg.printImplSplitter(); } break; default: ASSERT(false); } }