void StaticStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { BlockScopePtr scope = getScope(); if (scope->inPseudoMain()) { if (m_exp->getCount() > 1) cg_indentBegin("{\n"); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { exp->outputCPP(cg, ar); cg_printf(";\n"); } else { ASSERT(false); } } if (m_exp->getCount() > 1) cg_indentEnd("}\n"); return; } VariableTablePtr variables = scope->getVariables(); if (m_exp->getCount() > 1) cg_indentBegin("{\n"); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr variable = assignment_exp->getVariable(); SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); assert(var->hasContext(Expression::Declaration)); const std::string &name = var->getName(); if (variables->needLocalCopy(name)) { ASSERT(var->hasAssignableCPPVariable()); cg_printf("%s.assignRef(%s%s);\n", var->getAssignableCPPVariable(ar).c_str(), Option::StaticVariablePrefix, name.c_str()); } cg_indentBegin("if (!%s%s%s) {\n", Option::InitPrefix, Option::StaticVariablePrefix, name.c_str()); exp->outputCPP(cg, ar); cg_printf(";\n"); cg_printf("%s%s%s = true;\n", Option::InitPrefix, Option::StaticVariablePrefix, name.c_str()); cg_indentEnd("}\n"); } else { ASSERT(false); } } if (m_exp->getCount() > 1) cg_indentEnd("}\n"); }
void StaticStatement::inferTypes(AnalysisResultPtr ar) { BlockScopePtr scope = ar->getScope(); if (scope->inPseudoMain()) { // static just means to unset at global level for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr variable = assignment_exp->getVariable(); if (variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); var->setContext(Expression::Declaration); scope->getVariables()->forceVariant(ar, var->getName(), VariableTable::AnyStaticVars); } else { ASSERT(false); } } else { // Expression was optimized away; remove it m_exp->removeElement(i--); } } m_exp->inferTypes(ar, Type::Any, true); return; } scope->getVariables()->setAttribute(VariableTable::InsideStaticStatement); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; VariableTablePtr variables = scope->getVariables(); if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr variable = assignment_exp->getVariable(); if (variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); var->setContext(Expression::Declaration); const std::string &name = var->getName(); /* If we have already seen this variable in the current scope and it is not a static variable, record this variable as "redeclared" to force Variant type. */ if (ar->isFirstPass()) { variables->checkRedeclared(name, KindOfStaticStatement); } /* If this is not a top-level static statement, the variable also needs to be Variant type. This should not be a common use case in php code. */ if (!isTopLevel()) { variables->addNestedStatic(name); } if (variables->needLocalCopy(name)) { variables->forceVariant(ar, name, VariableTable::AnyStaticVars); } } else { ASSERT(false); } } else { // Expression was optimized away; remove it m_exp->removeElement(i--); continue; } exp->inferAndCheck(ar, Type::Any, false); } scope->getVariables()->clearAttribute(VariableTable::InsideStaticStatement); }