static void wrapValue(CodeGenerator &cg, AnalysisResultPtr ar, ExpressionPtr exp, bool ref, bool array, bool varnr) { bool close = false; if (ref) { cg_printf("ref("); close = true; } else if (array && !exp->hasCPPTemp() && !exp->isTemporary() && !exp->isScalar() && exp->getActualType() && !exp->getActualType()->isPrimitive() && exp->getActualType()->getKindOf() != Type::KindOfString) { cg_printf("wrap_variant("); close = true; } else if (varnr && exp->getCPPType()->isExactType()) { bool isScalar = exp->isScalar(); if (!isScalar || !Option::UseScalarVariant) { cg_printf("VarNR("); close = true; } else if (isScalar) { ASSERT(!cg.hasScalarVariant()); cg.setScalarVariant(); } } exp->outputCPP(cg, ar); cg.clearScalarVariant(); if (close) cg_printf(")"); }
void BinaryOpExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { if (isOpEqual() && outputCPPImplOpEqual(cg, ar)) return; bool wrapped = true; switch (m_op) { case T_CONCAT_EQUAL: if (const char *prefix = stringBufferPrefix(cg, ar, m_exp1)) { SimpleVariablePtr sv = static_pointer_cast<SimpleVariable>(m_exp1); ExpressionPtrVec ev; bool hasVoid = false; getConcatList(ev, m_exp2, hasVoid); cg_printf("%s", stringBufferName(Option::TempPrefix, prefix, sv->getName().c_str()).c_str()); outputStringBufExprs(ev, cg, ar); return; } cg_printf("concat_assign"); break; case '.': { ExpressionPtr self = static_pointer_cast<Expression>(shared_from_this()); ExpressionPtrVec ev; bool hasVoid = false; int num = getConcatList(ev, self, hasVoid); assert(!hasVoid); if ((num <= MAX_CONCAT_ARGS || (Option::GenConcat && cg.getOutput() != CodeGenerator::SystemCPP))) { assert(num >= 2); if (num == 2) { cg_printf("concat("); } else { if (num > MAX_CONCAT_ARGS) ar->m_concatLengths.insert(num); cg_printf("concat%d(", num); } for (size_t i = 0; i < ev.size(); i++) { ExpressionPtr exp = ev[i]; if (i) cg_printf(", "); outputStringExpr(cg, ar, exp, false); } cg_printf(")"); } else { cg_printf("StringBuffer()"); outputStringBufExprs(ev, cg, ar); cg_printf(".detach()"); } } return; case T_LOGICAL_XOR: cg_printf("logical_xor"); break; case '|': cg_printf("bitwise_or"); break; case '&': cg_printf("bitwise_and"); break; case '^': cg_printf("bitwise_xor"); break; case T_IS_IDENTICAL: cg_printf("same"); break; case T_IS_NOT_IDENTICAL: cg_printf("!same"); break; case T_IS_EQUAL: cg_printf("equal"); break; case T_IS_NOT_EQUAL: cg_printf("!equal"); break; case '<': cg_printf("less"); break; case T_IS_SMALLER_OR_EQUAL: cg_printf("not_more"); break; case '>': cg_printf("more"); break; case T_IS_GREATER_OR_EQUAL: cg_printf("not_less"); break; case '/': cg_printf("divide"); break; case '%': cg_printf("modulo"); break; case T_INSTANCEOF: cg_printf("instanceOf"); break; default: wrapped = !isUnused(); break; } if (wrapped) cg_printf("("); ExpressionPtr first = m_exp1; ExpressionPtr second = m_exp2; // we could implement these functions natively on String and Array classes switch (m_op) { case '+': case '-': case '*': case '/': { TypePtr actualType = first->getActualType(); if (actualType && (actualType->is(Type::KindOfString) || (m_op != '+' && actualType->is(Type::KindOfArray)))) { cg_printf("(Variant)("); first->outputCPP(cg, ar); cg_printf(")"); } else { bool flag = castIfNeeded(getActualType(), actualType, cg, ar, getScope()); first->outputCPP(cg, ar); if (flag) { cg_printf(")"); } } break; } case T_SL: case T_SR: cg_printf("toInt64("); first->outputCPP(cg, ar); cg_printf(")"); break; default: first->outputCPP(cg, ar); break; } switch (m_op) { case T_PLUS_EQUAL: cg_printf(" += "); break; case T_MINUS_EQUAL: cg_printf(" -= "); break; case T_MUL_EQUAL: cg_printf(" *= "); break; case T_DIV_EQUAL: cg_printf(" /= "); break; case T_MOD_EQUAL: cg_printf(" %%= "); break; case T_AND_EQUAL: cg_printf(" &= "); break; case T_OR_EQUAL: cg_printf(" |= "); break; case T_XOR_EQUAL: cg_printf(" ^= "); break; case T_SL_EQUAL: cg_printf(" <<= "); break; case T_SR_EQUAL: cg_printf(" >>= "); break; case T_BOOLEAN_OR: cg_printf(" || "); break; case T_BOOLEAN_AND: cg_printf(" && "); break; case T_LOGICAL_OR: cg_printf(" || "); break; case T_LOGICAL_AND: cg_printf(" && "); break; default: switch (m_op) { case '+': cg_printf(" + "); break; case '-': cg_printf(" - "); break; case '*': cg_printf(" * "); break; case T_SL: cg_printf(" << "); break; case T_SR: cg_printf(" >> "); break; default: cg_printf(", "); break; } break; } switch (m_op) { case '+': case '-': case '*': case '/': { TypePtr actualType = second->getActualType(); if (actualType && (actualType->is(Type::KindOfString) || (m_op != '+' && actualType->is(Type::KindOfArray)))) { cg_printf("(Variant)("); second->outputCPP(cg, ar); cg_printf(")"); } else { bool flag = castIfNeeded(getActualType(), actualType, cg, ar, getScope()); second->outputCPP(cg, ar); if (flag) { cg_printf(")"); } } break; } case T_INSTANCEOF: { if (second->isScalar()) { std::string s = second->getLiteralString(); std::string sLower = Util::toLower(s); if (sLower != "") { cg_printString(sLower, ar, shared_from_this()); } else { second->outputCPP(cg, ar); } } else { second->outputCPP(cg, ar); } break; } case T_PLUS_EQUAL: case T_MINUS_EQUAL: case T_MUL_EQUAL: { TypePtr t1 = first->getCPPType(); TypePtr t2 = second->getType(); if (t1 && !t1->is(Type::KindOfArray) && t2 && Type::IsCastNeeded(ar, t2, t1)) { t1->outputCPPCast(cg, ar, getScope()); cg_printf("("); second->outputCPP(cg, ar); cg_printf(")"); } else { second->outputCPP(cg, ar); } break; } case T_BOOLEAN_OR: case T_BOOLEAN_AND: case T_LOGICAL_AND: case T_LOGICAL_OR: if (isUnused()) { cg_printf("("); if (second->outputCPPUnneeded(cg, ar)) { cg_printf(","); } cg_printf("false)"); } else { second->outputCPP(cg, ar); } break; default: second->outputCPP(cg, ar); } if (wrapped) cg_printf(")"); }
void BinaryOpExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { if (isOpEqual() && outputCPPImplOpEqual(cg, ar)) return; bool wrapped = true; switch (m_op) { case T_CONCAT_EQUAL: if (const char *prefix = stringBufferPrefix(cg, ar, m_exp1)) { SimpleVariablePtr sv = static_pointer_cast<SimpleVariable>(m_exp1); ExpressionPtrVec ev; bool hasVoid = false; getConcatList(ev, m_exp2, hasVoid); cg_printf("%s", stringBufferName(Option::TempPrefix, prefix, sv->getName().c_str()).c_str()); outputStringBufExprs(ev, cg, ar); return; } cg_printf("concat_assign"); break; case '.': { ExpressionPtr self = static_pointer_cast<Expression>(shared_from_this()); ExpressionPtrVec ev; bool hasVoid = false; int num = getConcatList(ev, self, hasVoid); assert(!hasVoid); if (num <= MAX_CONCAT_ARGS) { assert(num >= 2); if (num == 2) { cg_printf("concat("); } else { if (num > MAX_CONCAT_ARGS) ar->m_concatLengths.insert(num); cg_printf("concat%d(", num); } for (size_t i = 0; i < ev.size(); i++) { ExpressionPtr exp = ev[i]; if (i) cg_printf(", "); outputStringExpr(cg, ar, exp, false); } cg_printf(")"); } else { cg_printf("StringBuffer()"); outputStringBufExprs(ev, cg, ar); cg_printf(".detach()"); } } return; case T_LOGICAL_XOR: cg_printf("logical_xor"); break; case '|': cg_printf("bitwise_or"); break; case '&': cg_printf("bitwise_and"); break; case '^': cg_printf("bitwise_xor"); break; case T_IS_IDENTICAL: cg_printf("same"); break; case T_IS_NOT_IDENTICAL: cg_printf("!same"); break; case T_IS_EQUAL: cg_printf("equal"); break; case T_IS_NOT_EQUAL: cg_printf("!equal"); break; case '<': cg_printf("less"); break; case T_IS_SMALLER_OR_EQUAL: cg_printf("not_more"); break; case '>': cg_printf("more"); break; case T_IS_GREATER_OR_EQUAL: cg_printf("not_less"); break; case '/': cg_printf("divide"); break; case '%': cg_printf("modulo"); break; case T_INSTANCEOF: cg_printf("instanceOf"); break; default: wrapped = !isUnused(); break; } if (wrapped) cg_printf("("); ExpressionPtr first = m_exp1; ExpressionPtr second = m_exp2; // we could implement these functions natively on String and Array classes switch (m_op) { case '+': case '-': case '*': case '/': if (!first->outputCPPArithArg(cg, ar, m_op == '+')) { TypePtr argType = first->hasCPPTemp() ? first->getType() : first->getActualType(); bool flag = castIfNeeded(getActualType(), argType, cg, ar, getScope()); first->outputCPP(cg, ar); if (flag) { cg_printf(")"); } } break; case T_SL: case T_SR: ASSERT(first->getType()->is(Type::KindOfInt64)); first->outputCPP(cg, ar); break; default: first->outputCPP(cg, ar); break; } switch (m_op) { case T_PLUS_EQUAL: cg_printf(" += "); break; case T_MINUS_EQUAL: cg_printf(" -= "); break; case T_MUL_EQUAL: cg_printf(" *= "); break; case T_DIV_EQUAL: cg_printf(" /= "); break; case T_MOD_EQUAL: cg_printf(" %%= "); break; case T_AND_EQUAL: cg_printf(" &= "); break; case T_OR_EQUAL: cg_printf(" |= "); break; case T_XOR_EQUAL: cg_printf(" ^= "); break; case T_SL_EQUAL: cg_printf(" <<= "); break; case T_SR_EQUAL: cg_printf(" >>= "); break; case T_BOOLEAN_OR: cg_printf(" || "); break; case T_BOOLEAN_AND: cg_printf(" && "); break; case T_LOGICAL_OR: cg_printf(" || "); break; case T_LOGICAL_AND: cg_printf(" && "); break; default: switch (m_op) { case '+': cg_printf(" + "); break; case '-': cg_printf(" - "); break; case '*': cg_printf(" * "); break; case T_SL: cg_printf(" << "); break; case T_SR: cg_printf(" >> "); break; default: cg_printf(", "); break; } break; } switch (m_op) { case '+': case '-': case '*': case '/': if (!second->outputCPPArithArg(cg, ar, m_op == '+')) { TypePtr argType = second->hasCPPTemp() ? second->getType() : second->getActualType(); bool flag = castIfNeeded(getActualType(), argType, cg, ar, getScope()); second->outputCPP(cg, ar); if (flag) { cg_printf(")"); } } break; case T_INSTANCEOF: { if (second->isScalar()) { ScalarExpressionPtr scalar = dynamic_pointer_cast<ScalarExpression>(second); bool notQuoted = scalar && !scalar->isQuoted(); std::string s = second->getLiteralString(); if (s == "static" && notQuoted) { cg_printf("FrameInjection::GetStaticClassName(fi.getThreadInfo())"); } else if (s != "") { if (s == "self" && notQuoted) { ClassScopeRawPtr cls = getOriginalClass(); if (cls) { s = cls->getOriginalName(); } } else if (s == "parent" && notQuoted) { ClassScopeRawPtr cls = getOriginalClass(); if (cls && !cls->getParent().empty()) { s = cls->getParent(); } } cg_printString(s, ar, shared_from_this()); } else { second->outputCPP(cg, ar); } } else { second->outputCPP(cg, ar); } break; } case T_PLUS_EQUAL: case T_MINUS_EQUAL: case T_MUL_EQUAL: { TypePtr t1 = first->getCPPType(); TypePtr t2 = second->getType(); if (t1 && !t1->is(Type::KindOfArray) && t2 && Type::IsCastNeeded(ar, t2, t1)) { t1->outputCPPCast(cg, ar, getScope()); cg_printf("("); second->outputCPP(cg, ar); cg_printf(")"); } else { second->outputCPP(cg, ar); } break; } case T_BOOLEAN_OR: case T_BOOLEAN_AND: case T_LOGICAL_AND: case T_LOGICAL_OR: if (isUnused()) { cg_printf("("); if (second->outputCPPUnneeded(cg, ar)) { cg_printf(","); } cg_printf("false)"); } else { second->outputCPP(cg, ar); } break; default: second->outputCPP(cg, ar); } if (wrapped) cg_printf(")"); }