void GlobalStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) { BlockScopePtr scope = getScope(); 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::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp); const string &name = var->getName(); VariableTablePtr variables = scope->getVariables(); if (variables->needLocalCopy(name)) { cg_printf("%s%s = ref(g->%s);\n", Option::VariablePrefix, name.c_str(), variables->getGlobalVariableName(cg, ar, name).c_str()); } } else if (exp->is(Expression::KindOfDynamicVariable)) { DynamicVariablePtr var = dynamic_pointer_cast<DynamicVariable>(exp); ExpressionPtr exp = var->getSubExpression(); exp->outputCPPBegin(cg, ar); int id = cg.createNewLocalId(shared_from_this()); cg_printf("CStrRef dgv_%d((", id); exp->outputCPP(cg, ar); cg_printf("));\n"); cg_printf("variables->get(dgv_%d) = ref(g->get(dgv_%d));\n", id, id); exp->outputCPPEnd(cg, ar); } else { assert(false); } } if (m_exp->getCount() > 1) cg_indentEnd("}\n"); }
void GlobalStatement::outputCPP(CodeGenerator &cg, AnalysisResultPtr ar) { if (m_dynamicGlobal) { cg.printf("throw_fatal(\"dynamic global\");\n"); } else if (!ar->getScope()->inPseudoMain() || !isTopLevel()) { BlockScopePtr scope = ar->getScope(); 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::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp); const string &name = var->getName(); VariableTablePtr variables = scope->getVariables(); if (variables->needLocalCopy(name)) { cg.printf("%s%s = ref(g->%s);\n", Option::VariablePrefix, name.c_str(), variables->getGlobalVariableName(ar, name).c_str()); } } else { // type inference should have set m_dynamicGlobal to true. ASSERT(false); } } if (m_exp->getCount() > 1) cg.indentEnd("}\n"); } }
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 GlobalStatement::inferTypes(AnalysisResultPtr ar) { BlockScopePtr scope = ar->getScope(); scope->getVariables()->setAttribute(VariableTable::InsideGlobalStatement); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; if (exp->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp); VariableTablePtr variables = scope->getVariables(); const std::string &name = var->getName(); /* If we have already seen this variable in the current scope and it is not a global variable, record this variable as "redeclared" which will force Variant type. */ variables->checkRedeclared(name, KindOfGlobalStatement); /* If this is not a top-level global statement, the variable also needs to be Variant type. This should not be a common use case in php code. */ if (!isTopLevel()) { variables->addNestedGlobal(name); } var->setContext(Expression::Declaration); var->inferAndCheck(ar, NEW_TYPE(Any), true); if (variables->needLocalCopy(name)) { variables->forceVariant(ar, name); variables->setAttribute(VariableTable::NeedGlobalPointer); } ConstructPtr decl = ar->getVariables()->getDeclaration(var->getName()); if (decl) { ar->getDependencyGraph()->add(DependencyGraph::KindOfGlobalVariable, ar->getName(), var->getName(), var, var->getName(), decl); } } else { if (ar->isFirstPass()) { ar->getCodeError()->record(shared_from_this(), CodeError::UseDynamicGlobal, exp); } m_dynamicGlobal = true; } } FunctionScopePtr func = ar->getFunctionScope(); scope->getVariables()->clearAttribute(VariableTable::InsideGlobalStatement); }
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); }