TypePtr ParameterExpression::getTypeSpec(AnalysisResultPtr ar, bool forInference) { const Type::TypePtrMap &types = Type::GetTypeHintTypes(m_hhType); Type::TypePtrMap::const_iterator iter; TypePtr ret; if (m_type.empty()) { ret = Type::Some; } else if ((iter = types.find(m_type)) != types.end()) { ret = iter->second; } else { ret = getTypeSpecForClass(ar, forInference); } ConstantExpressionPtr p; if (ret->isPrimitive() && m_defaultValue && (p = dynamic_pointer_cast<ConstantExpression>(m_defaultValue)) && p->isNull()) { // if we have a primitive type on the LHS w/ a default // of null, then don't bother to infer it's type, since we will // not specialize for this case ret = Type::Some; } // we still want the above to run, so to record errors and infer defaults if (m_ref && forInference) { ret = Type::Variant; } return ret; }
void AssignmentExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { bool ref = (m_ref && m_value->isRefable()); bool setNull = false; if (SpecialAssignment(cg, ar, m_variable, m_value, NULL, ref)) { return; } if (m_variable->is(Expression::KindOfSimpleVariable) && m_value->is(Expression::KindOfConstantExpression)) { ConstantExpressionPtr exp = dynamic_pointer_cast<ConstantExpression>(m_value); if (exp->isNull()) setNull = true; } bool wrapped = true; if (setNull) { cg_printf("setNull("); m_variable->outputCPP(cg, ar); } else { if ((wrapped = !isUnused())) { cg_printf("("); } m_variable->outputCPP(cg, ar); cg_printf(" = "); wrapValue(cg, ar, m_value, ref, false); } if (wrapped) { cg_printf(")"); } }
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 } }
TypePtr AssignmentExpression:: inferTypesImpl(AnalysisResultPtr ar, TypePtr type, bool coerce, ExpressionPtr variable, ExpressionPtr value /* = ExpressionPtr() */) { TypePtr ret = type; if (value) { if (coerce) { ret = value->inferAndCheck(ar, type, coerce); } else { ret = value->inferAndCheck(ar, NEW_TYPE(Some), coerce); } } BlockScopePtr scope = ar->getScope(); if (variable->is(Expression::KindOfConstantExpression)) { // ...as in ClassConstant statement ConstantExpressionPtr exp = dynamic_pointer_cast<ConstantExpression>(variable); bool p; scope->getConstants()->check(exp->getName(), ret, true, ar, variable, p); } else if (variable->is(Expression::KindOfDynamicVariable)) { // simptodo: not too sure about this ar->getFileScope()->setAttribute(FileScope::ContainsLDynamicVariable); } else if (variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); if (var->getName() == "this" && ar->getClassScope()) { if (ar->isFirstPass()) { ar->getCodeError()->record(variable, CodeError::ReassignThis, variable); } } if (ar->getPhase() == AnalysisResult::LastInference && value) { if (!value->getExpectedType()) { value->setExpectedType(variable->getActualType()); } } } // if the value may involve object, consider the variable as "referenced" // so that objects are not destructed prematurely. bool referenced = true; if (value && value->isScalar()) referenced = false; if (ret && ret->isNoObjectInvolved()) referenced = false; if (referenced && variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); const std::string &name = var->getName(); VariableTablePtr variables = ar->getScope()->getVariables(); variables->addReferenced(name); } TypePtr vt = variable->inferAndCheck(ar, ret, true); if (!coerce && type->is(Type::KindOfAny)) { ret = vt; } return ret; }
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 Option::Load(bool &option, ExpressionPtr value) { ConstantExpressionPtr v = dynamic_pointer_cast<ConstantExpression>(value); if (!v || !v->isBoolean()) { Logger::Error("Line %d: invalid boolean: %s", value->getLocation()->line1, value->getText().c_str()); return false; } option = v->getBooleanValue(); return true; }
ExpressionPtr Parser::getDynamicVariable(ExpressionPtr exp, bool encap) { NamePtr n; if (encap) { ConstantExpressionPtr var = exp->cast<ConstantExpression>(); if (var) { n = Name::fromString(this, var->getName()); } } else { n = Name::fromExp(this, exp); } return NEW_EXP(Variable, n); }
ExpressionPtr Parser::getDynamicVariable(ExpressionPtr exp, bool encap) { if (encap) { ConstantExpressionPtr var = exp->unsafe_cast<ConstantExpression>(); NamePtr n; if (var) { n = Name::fromString(this, var->getName()); } return NEW_EXP(Variable, n); } return createDynamicVariable(exp); }
void ParameterExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { FunctionScopePtr func = dynamic_pointer_cast<FunctionScope>(ar->getScope()); VariableTablePtr variables = func->getVariables(); TypePtr paramType = func->getParamType(cg.getItemIndex()); bool isCVarRef = false; if (cg.getContext() == CodeGenerator::CppStaticMethodWrapper || (!variables->isLvalParam(m_name) && !variables->getAttribute(VariableTable::ContainsDynamicVariable) && !variables->getAttribute(VariableTable::ContainsExtract) && !m_ref)) { 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); } else { paramType->outputCPPDecl(cg, ar); } cg_printf(" %s%s", Option::VariablePrefix, m_name.c_str()); if (m_defaultValue) { CodeGenerator::Context context = cg.getContext(); bool comment = context == CodeGenerator::CppImplementation || (context == CodeGenerator::CppDeclaration && func->isInlined()); if (comment) { cg_printf(" // "); } cg_printf(" = "); ConstantExpressionPtr con = dynamic_pointer_cast<ConstantExpression>(m_defaultValue); if (isCVarRef && con && con->isNull()) { cg_printf("null_variant"); } else { if (comment) { cg.setContext(CodeGenerator::CppParameterDefaultValueImpl); } else { cg.setContext(CodeGenerator::CppParameterDefaultValueDecl); } m_defaultValue->outputCPP(cg, ar); cg.setContext(context); } if (comment) { cg_printf("\n"); } } }
ExpressionPtr Parser::getDynamicVariable(ExpressionPtr exp, bool encap) { if (encap) { ConstantExpressionPtr var = dynamic_pointer_cast<ConstantExpression>(exp); if (var) { return NEW_EXP(SimpleVariable, var->getName()); } } else { ScalarExpressionPtr var = dynamic_pointer_cast<ScalarExpression>(exp); if (var) { return NEW_EXP(SimpleVariable, var->getString()); } } return createDynamicVariable(exp); }
StatementPtr IfStatement::postOptimize(AnalysisResultConstPtr ar) { // we cannot optimize away the code inside if statement, because // there may be a goto that goes into if statement. if (hasReachableLabel()) { return StatementPtr(); } bool changed = false; for (int i = 0; i < m_stmts->getCount(); i++) { IfBranchStatementPtr branch = dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[i]); ExpressionPtr condition = branch->getCondition(); if (!branch->getStmt() || !branch->getStmt()->hasImpl()) { if (!condition || (i == m_stmts->getCount() - 1 && !condition->hasEffect())) { // remove else branch without C++ implementation. m_stmts->removeElement(i); changed = true; } else if (condition->is(Expression::KindOfConstantExpression)) { ConstantExpressionPtr exp = dynamic_pointer_cast<ConstantExpression>(condition); // Remove if (false) branch without C++ implementation. // if (true) branch without C++ implementation is kept unless // it is the last branch. In general we cannot let a if (true) // branch short-circuit the rest branches which if removed may // cause g++ to complain unreferenced variables. if (exp->isBoolean()) { if (!exp->getBooleanValue() || (exp->getBooleanValue() && i == m_stmts->getCount() - 1)) { m_stmts->removeElement(i); changed = true; i--; } } } } } if (m_stmts->getCount() == 0) { return NULL_STATEMENT(); } else { return changed ? static_pointer_cast<Statement>(shared_from_this()) : StatementPtr(); } }
void AssignmentExpression::analyzeProgram(AnalysisResultPtr ar) { m_variable->analyzeProgram(ar); m_value->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll) { if (m_ref && m_variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_variable); const std::string &name = var->getName(); VariableTablePtr variables = ar->getScope()->getVariables(); variables->addUsed(name); } if (m_variable->is(Expression::KindOfConstantExpression)) { ConstantExpressionPtr exp = dynamic_pointer_cast<ConstantExpression>(m_variable); if (!m_value->isScalar()) { ar->getScope()->getConstants()->setDynamic(ar, exp->getName()); } } } }
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(); }
ExpressionPtr BinaryOpExpression::simplifyLogical(AnalysisResultPtr ar) { if (m_exp1->is(Expression::KindOfConstantExpression)) { ConstantExpressionPtr con = dynamic_pointer_cast<ConstantExpression>(m_exp1); if (con->isBoolean()) { if (con->getBooleanValue()) { if (ar->getPhase() >= AnalysisResult::PostOptimize) { // true && v (true AND v) => v ASSERT(m_exp2->getType()->is(Type::KindOfBoolean)); if (m_op == T_BOOLEAN_AND || m_op == T_LOGICAL_AND) return m_exp2; } // true || v (true OR v) => true if (m_op == T_BOOLEAN_OR || m_op == T_LOGICAL_OR) { return CONSTANT("true"); } } else { if (ar->getPhase() >= AnalysisResult::PostOptimize) { ASSERT(m_exp2->getType()->is(Type::KindOfBoolean)); // false || v (false OR v) => v if (m_op == T_BOOLEAN_OR || m_op == T_LOGICAL_OR) return m_exp2; } // false && v (false AND v) => false if (m_op == T_BOOLEAN_AND || m_op == T_LOGICAL_AND) { return CONSTANT("false"); } } } } if (m_exp2->is(Expression::KindOfConstantExpression)) { ConstantExpressionPtr con = dynamic_pointer_cast<ConstantExpression>(m_exp2); if (con->isBoolean()) { if (con->getBooleanValue()) { if (ar->getPhase() >= AnalysisResult::PostOptimize) { ASSERT(m_exp1->getType()->is(Type::KindOfBoolean)); // v && true (v AND true) => v if (m_op == T_BOOLEAN_AND || m_op == T_LOGICAL_AND) return m_exp1; } // v || true (v OR true) => true when v does not have effect if (m_op == T_BOOLEAN_OR || m_op == T_LOGICAL_OR) { if (!m_exp1->hasEffect()) return CONSTANT("true"); } } else { if (ar->getPhase() >= AnalysisResult::PostOptimize) { ASSERT(m_exp1->getType()->is(Type::KindOfBoolean)); // v || false (v OR false) => v if (m_op == T_BOOLEAN_OR || m_op == T_LOGICAL_OR) return m_exp1; } // v && false (v AND false) => false when v does not have effect if (m_op == T_BOOLEAN_AND || m_op == T_LOGICAL_AND) { if (!m_exp1->hasEffect()) return CONSTANT("false"); } } } } return ExpressionPtr(); }
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 AssignmentExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { BlockScopePtr scope = ar->getScope(); bool ref = (m_ref && m_value->isRefable()); bool setNull = false; bool arrayLike = false; if (m_variable->is(Expression::KindOfArrayElementExpression)) { ArrayElementExpressionPtr exp = dynamic_pointer_cast<ArrayElementExpression>(m_variable); if (!exp->isSuperGlobal() && !exp->isDynamicGlobal()) { exp->getVariable()->outputCPP(cg, ar); if (exp->getOffset()) { cg_printf(".set("); exp->getOffset()->outputCPP(cg, ar); cg_printf(", ("); } else { cg_printf(".append(("); } wrapValue(cg, ar, m_value, ref, true); cg_printf(")"); ExpressionPtr off = exp->getOffset(); if (off) { ScalarExpressionPtr sc = dynamic_pointer_cast<ScalarExpression>(off); if (sc) { if (sc->isLiteralString()) { String s(sc->getLiteralString()); int64 n; if (!s.get()->isStrictlyInteger(n)) { cg_printf(", true"); // skip toKey() at run time } } } } cg_printf(")"); return; } } else if (m_variable->is(Expression::KindOfObjectPropertyExpression)) { ObjectPropertyExpressionPtr var( dynamic_pointer_cast<ObjectPropertyExpression>(m_variable)); if (!var->isValid()) { var->outputCPPObject(cg, ar); cg_printf("o_set("); var->outputCPPProperty(cg, ar); cg_printf(", %s", ref ? "ref(" : ""); m_value->outputCPP(cg, ar); cg_printf("%s, %s)", ref ? ")" : "", ar->getClassScope() ? "s_class_name" : "empty_string"); return; } } else if (m_variable->is(Expression::KindOfSimpleVariable) && m_value->is(Expression::KindOfConstantExpression)) { ConstantExpressionPtr exp = dynamic_pointer_cast<ConstantExpression>(m_value); if (exp->isNull()) setNull = true; } bool wrapped = true; if (setNull) { cg_printf("setNull("); m_variable->outputCPP(cg, ar); } else { if ((wrapped = !isUnused())) { cg_printf("("); } m_variable->outputCPP(cg, ar); cg_printf(" = "); wrapValue(cg, ar, m_value, ref, arrayLike); } if (wrapped) { cg_printf(")"); } }
void AssignmentExpression::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { BlockScopePtr scope = ar->getScope(); bool ref = (m_ref && !m_value->is(Expression::KindOfNewObjectExpression)); bool setElement = false; // turning $a['elem'] = $b into $a.set('elem', $b); bool type_cast = false; bool setNull = false; TypePtr m_actualType; if (m_variable->is(Expression::KindOfArrayElementExpression)) { ArrayElementExpressionPtr exp = dynamic_pointer_cast<ArrayElementExpression>(m_variable); m_actualType = m_variable->getActualType(); if (m_actualType && m_actualType->getKindOf() == Type::KindOfVariant && !ref) { //type_cast = true; } if (!exp->isSuperGlobal() && !exp->isDynamicGlobal()) { exp->getVariable()->outputCPP(cg, ar); if (exp->getOffset()) { cg.printf(".set("); exp->getOffset()->outputCPP(cg, ar); cg.printf(", ("); } else { cg.printf(".append(("); } if (type_cast) { m_actualType->outputCPPCast(cg, ar); cg.printf("("); } if (ref && m_value->isRefable()) cg.printf("ref("); m_value->outputCPP(cg, ar); if (ref && m_value->isRefable()) cg.printf(")"); if (type_cast) cg.printf(")"); cg.printf(")"); ExpressionPtr off = exp->getOffset(); if (off) { ScalarExpressionPtr sc = dynamic_pointer_cast<ScalarExpression>(off); if (sc) { int64 hash = sc->getHash(); if (hash >= 0) { cg.printf(", 0x%016llXLL", hash); } else { cg.printf(", -1"); } if (sc->isLiteralString()) { String s(sc->getLiteralString()); int64 n; if (!s.get()->isStrictlyInteger(n)) { cg.printf(", true"); // skip toKey() at run time } } } } cg.printf(")"); setElement = true; } } if (m_variable->is(Expression::KindOfSimpleVariable) && m_value->is(Expression::KindOfConstantExpression)) { ConstantExpressionPtr exp = dynamic_pointer_cast<ConstantExpression>(m_value); if (exp->isNull()) setNull = true; } if (!setElement) { if (setNull) { cg.printf("setNull("); m_variable->outputCPP(cg, ar); } else { cg.printf("("); m_variable->outputCPP(cg, ar); cg.printf(" = "); if (type_cast) { m_actualType->outputCPPCast(cg, ar); cg.printf("("); } if (ref && m_value->isRefable()) cg.printf("ref("); m_value->outputCPP(cg, ar); if (ref && m_value->isRefable()) cg.printf(")"); if (type_cast) cg.printf(")"); } cg.printf(")"); } }
StatementPtr IfStatement::preOptimize(AnalysisResultPtr ar) { if (ar->getPhase() < AnalysisResult::FirstPreOptimize) { return StatementPtr(); } bool changed = false; int i; int j; for (i = 0; i < m_stmts->getCount(); i++) { IfBranchStatementPtr branch = dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[i]); ExpressionPtr condition = branch->getCondition(); if (!condition) { StatementPtr stmt = branch->getStmt(); if (stmt && stmt->is(KindOfIfStatement)) { StatementListPtr sub_stmts = dynamic_pointer_cast<IfStatement>(stmt)->m_stmts; m_stmts->removeElement(i); changed = true; for (j = 0; j < sub_stmts->getCount(); j++) { m_stmts->insertElement((*sub_stmts)[j], i++); } } break; } else if (condition->is(Expression::KindOfConstantExpression)) { ConstantExpressionPtr exp = dynamic_pointer_cast<ConstantExpression>(condition); if (exp->isBoolean()) { if (exp->getBooleanValue()) { // if (true) branch for (j = i + 1; j < m_stmts->getCount(); j++) { if ((*m_stmts)[j]->hasDecl()) break; } // no declarations after if (true) if (j == m_stmts->getCount()) break; } else { // if (false) branch if (!branch->hasDecl()) { m_stmts->removeElement(i); changed = true; i--; } } } } } if (i == m_stmts->getCount()) return StatementPtr(); // either else branch or if (true) branch without further declarations i++; while (i < m_stmts->getCount()) { m_stmts->removeElement(i); changed = true; } // if there is only one branch left, return stmt. if (m_stmts->getCount() == 1) { return dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[0])->getStmt(); } else if (m_stmts->getCount() == 0) { return NULL_STATEMENT(); } else { return changed ? static_pointer_cast<Statement>(shared_from_this()) : StatementPtr(); } }
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 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); } } }