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 ArrayElementExpression::setContext(Context context) { m_context |= context; switch (context) { case Expression::LValue: if (!hasContext(Expression::UnsetContext)) { m_variable->setContext(Expression::LValue); } if (m_variable->is(Expression::KindOfObjectPropertyExpression)) { m_variable->clearContext(Expression::NoLValueWrapper); } // special case for $GLOBALS[], see the if (m_global) check in // ArrayElementExpression::outputCPPImpl, we do not need lvalue wrapper if (m_variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_variable); if (var->getName() == "GLOBALS") { m_context |= Expression::NoLValueWrapper; } } break; case Expression::DeepAssignmentLHS: case Expression::DeepOprLValue: case Expression::ExistContext: case Expression::UnsetContext: case Expression::DeepReference: m_variable->setContext(context); break; case Expression::RefValue: case Expression::RefParameter: m_variable->setContext(DeepReference); break; default: break; } }
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 SwitchStatement::analyzeProgramImpl(AnalysisResultPtr ar) { m_exp->analyzeProgram(ar); if (m_cases) m_cases->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll && m_exp->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr exp = dynamic_pointer_cast<SimpleVariable>(m_exp); if (exp && exp->getSymbol() && exp->getSymbol()->isClassName()) { // Mark some classes as volitle since the name is used in switch for (int i = 0; i < m_cases->getCount(); i++) { CaseStatementPtr stmt = dynamic_pointer_cast<CaseStatement>((*m_cases)[i]); ASSERT(stmt); ExpressionPtr caseCond = stmt->getCondition(); if (caseCond && caseCond->isScalar()) { ScalarExpressionPtr name = dynamic_pointer_cast<ScalarExpression>(caseCond); if (name && name->isLiteralString()) { string className = name->getLiteralString(); ClassScopePtr cls = ar->findClass(Util::toLower(className)); if (cls && cls->isUserClass()) { cls->setVolatile(); } } } } // Also note this down as code error ConstructPtr self = shared_from_this(); Compiler::Error(Compiler::ConditionalClassLoading, self); } } }
ArrayElementExpression::ArrayElementExpression (EXPRESSION_CONSTRUCTOR_PARAMETERS, ExpressionPtr variable, ExpressionPtr offset) : Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES), m_variable(variable), m_offset(offset), m_global(false), m_dynamicGlobal(false), m_localEffects(AccessorEffect) { m_variable->setContext(Expression::AccessContext); if (m_variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_variable); if (var->getName() == "GLOBALS") { m_global = true; m_dynamicGlobal = true; if (m_offset && m_offset->is(Expression::KindOfScalarExpression)) { ScalarExpressionPtr offset = dynamic_pointer_cast<ScalarExpression>(m_offset); if (offset->isLiteralString()) { m_globalName = offset->getIdentifier(); if (!m_globalName.empty()) { m_dynamicGlobal = false; } } } } } }
void StaticStatement::analyzeProgram(AnalysisResultPtr ar) { m_exp->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll) { BlockScopePtr scope = getScope(); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; ExpressionPtr variable; ExpressionPtr value; // turn static $a; into static $a = null; if (exp->is(Expression::KindOfSimpleVariable)) { variable = dynamic_pointer_cast<SimpleVariable>(exp); exp = AssignmentExpressionPtr (new AssignmentExpression(exp->getScope(), exp->getLocation(), variable, CONSTANT("null"), false)); (*m_exp)[i] = exp; } always_assert(exp->is(Expression::KindOfAssignmentExpression)); AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); variable = assignment_exp->getVariable(); value = assignment_exp->getValue(); SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); // set the Declaration context here instead of all over this file - this phase // is the first to run var->setContext(Expression::Declaration); Symbol *sym = var->getSymbol(); sym->setStaticInitVal(value); } } }
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 } }
void ClassVariable::inferTypes(AnalysisResultPtr ar) { ASSERT(getScope().get() == getClassScope().get()); IMPLEMENT_INFER_AND_CHECK_ASSERT(getScope()); m_declaration->inferAndCheck(ar, Type::Variant, false); if (m_modifiers->isStatic()) { ClassScopePtr scope = getClassScope(); for (int i = 0; i < m_declaration->getCount(); i++) { ExpressionPtr exp = (*m_declaration)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); // If the class variable's type is Object, we have to // force it to be a Variant, because we don't include // the class header files in global_variables.h SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(assignment->getVariable()); if (var) { TypePtr type = scope->getVariables()->getFinalType(var->getName()); if (type->is(Type::KindOfObject)) { scope->getVariables()->forceVariant(ar, var->getName(), VariableTable::AnyVars); } } ExpressionPtr value = assignment->getValue(); if (value->containsDynamicConstant(ar)) { scope->getVariables()-> setAttribute(VariableTable::ContainsDynamicStatic); } } } } }
void GlobalStatement::inferTypes(AnalysisResultPtr ar) { IMPLEMENT_INFER_AND_CHECK_ASSERT(getScope()); BlockScopePtr scope = getScope(); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; VariableTablePtr variables = scope->getVariables(); variables->setAttribute(VariableTable::NeedGlobalPointer); if (exp->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp); 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->setAttribute(VariableTable::InsideGlobalStatement); variables->checkRedeclared(name, KindOfGlobalStatement); variables->addLocalGlobal(name); var->setContext(Expression::Declaration); var->inferAndCheck(ar, Type::Any, true); variables->forceVariant(ar, name, VariableTable::AnyVars); variables->clearAttribute(VariableTable::InsideGlobalStatement); } else { variables->forceVariants(ar, VariableTable::AnyVars); variables->setAttribute(VariableTable::ContainsLDynamicVariable); assert(exp->is(Expression::KindOfDynamicVariable)); exp->inferAndCheck(ar, Type::Any, true); } } }
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 ExpressionList::optimize(AnalysisResultConstPtr ar) { bool changed = false; size_t i = m_exps.size(); if (m_kind != ListKindParam) { size_t skip = m_kind == ListKindLeft ? 0 : i - 1; while (i--) { if (i != skip) { ExpressionPtr &e = m_exps[i]; if (!e || e->getContainedEffects() == NoEffect) { removeElement(i); changed = true; } else if (e->is(KindOfExpressionList)) { ExpressionListPtr el(static_pointer_cast<ExpressionList>(e)); removeElement(i); for (size_t j = el->getCount(); j--; ) { insertElement((*el)[j], i); } changed = true; } else if (e->getLocalEffects() == NoEffect) { e = e->unneeded(); // changed already handled by unneeded } } } if (m_exps.size() == 1) { m_kind = ListKindWrapped; } else if (m_kind == ListKindLeft && m_exps[0]->isScalar()) { ExpressionPtr e = m_exps[0]; removeElement(0); addElement(e); m_kind = ListKindWrapped; } } else { if (hasContext(UnsetContext) && ar->getPhase() >= AnalysisResult::PostOptimize) { while (i--) { ExpressionPtr &e = m_exps[i]; if (e->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(e); if (var->checkUnused()) { const std::string &name = var->getName(); VariableTablePtr variables = getScope()->getVariables(); if (!variables->isNeeded(name)) { removeElement(i); changed = true; } } } } } } if (changed) { getScope()->addUpdates(BlockScope::UseKindCaller); } }
static const char *stringBufferPrefix(AnalysisResultPtr ar, ExpressionPtr var) { if (var->is(Expression::KindOfSimpleVariable)) { if (LoopStatementPtr loop = ar->getLoopStatement()) { SimpleVariablePtr sv = static_pointer_cast<SimpleVariable>(var); if (loop->checkStringBuf(sv->getName())) { return ar->getScope()->getVariables()-> getVariablePrefix(ar, sv->getName()); } } } return 0; }
StatementPtr StaticStatement::preOptimize(AnalysisResultConstPtr ar) { BlockScopePtr scope = getScope(); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr variable = assignment_exp->getVariable(); ExpressionPtr value = assignment_exp->getValue(); SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); Symbol *sym = var->getSymbol(); sym->setStaticInitVal(value); } return StatementPtr(); }
ExpressionPtr AssignmentExpression::optimize(AnalysisResultConstPtr ar) { if (m_variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_variable); if (var->checkUnused() && !CheckNeeded(var, m_value)) { if (m_value->getContainedEffects() != getContainedEffects()) { recomputeEffects(); } return replaceValue(m_value); } } return ExpressionPtr(); }
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"); }
StatementPtr ClassVariable::preOptimize(AnalysisResultConstPtr ar) { ClassScopePtr scope = getClassScope(); for (int i = 0; i < m_declaration->getCount(); i++) { ExpressionPtr exp = (*m_declaration)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(assignment->getVariable()); ExpressionPtr value = assignment->getValue(); scope->getVariables()->setClassInitVal(var->getName(), value); } } return StatementPtr(); }
void StaticStatement::analyzeProgramImpl(AnalysisResultPtr ar) { m_exp->analyzeProgram(ar); BlockScopePtr scope = ar->getScope(); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; ExpressionPtr variable; ExpressionPtr value; if (ar->getPhase() == AnalysisResult::AnalyzeInclude) { // turn static $a; into static $a = null; if (exp->is(Expression::KindOfSimpleVariable)) { variable = dynamic_pointer_cast<SimpleVariable>(exp); exp = AssignmentExpressionPtr (new AssignmentExpression(exp->getLocation(), Expression::KindOfAssignmentExpression, variable, CONSTANT("null"), false)); (*m_exp)[i] = exp; } } if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); variable = assignment_exp->getVariable(); value = assignment_exp->getValue(); } else { ASSERT(false); } SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); if (ar->getPhase() == AnalysisResult::AnalyzeInclude) { if (scope->getVariables()->setStaticInitVal(var->getName(), value)) { ar->getCodeError()->record(CodeError::DeclaredStaticVariableTwice, exp); } } else if (ar->getPhase() == AnalysisResult::AnalyzeAll) { // update initial value const string &name = var->getName(); ExpressionPtr initValue = (dynamic_pointer_cast<Expression> (scope->getVariables()->getStaticInitVal(name)))->clone(); exp = AssignmentExpressionPtr (new AssignmentExpression(exp->getLocation(), Expression::KindOfAssignmentExpression, variable, initValue, false)); (*m_exp)[i] = exp; } } }
void ClassVariable::analyzeProgramImpl(AnalysisResultPtr ar) { m_declaration->analyzeProgram(ar); if (ar->getPhase() != AnalysisResult::AnalyzeInclude) return; ClassScopePtr scope = ar->getClassScope(); for (int i = 0; i < m_declaration->getCount(); i++) { ExpressionPtr exp = (*m_declaration)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(assignment->getVariable()); ExpressionPtr value = assignment->getValue(); scope->getVariables()->setClassInitVal(var->getName(), value); } } }
void ClassVariable::getCtorAndInitInfo( ExpressionPtr exp, bool &needsCppCtor, bool &needsInit, SimpleVariablePtr &var, TypePtr &type, Symbol *&sym, ExpressionPtr &value) { ClassScopePtr scope = getClassScope(); bool derivFromRedec = scope->derivesFromRedeclaring() && !m_modifiers->isPrivate(); AssignmentExpressionPtr assignment; bool isAssign = exp->is(Expression::KindOfAssignmentExpression); if (isAssign) { assignment = static_pointer_cast<AssignmentExpression>(exp); var = dynamic_pointer_cast<SimpleVariable>(assignment->getVariable()); ASSERT(var); value = assignment->getValue(); ASSERT(value); } else { var = dynamic_pointer_cast<SimpleVariable>(exp); ASSERT(var); } sym = scope->getVariables()->getSymbol(var->getName()); ASSERT(sym); type = scope->getVariables()->getFinalType(var->getName()); ASSERT(type); bool isValueNull = isAssign ? value->isLiteralNull() : false; bool typeIsInitable = type->is(Type::KindOfVariant) || type->getCPPInitializer(); if (!derivFromRedec && !sym->isOverride() && (isAssign ? (isValueNull || (value->is(Expression::KindOfScalarExpression) && type->isPrimitive())) : typeIsInitable)) { needsCppCtor = true; } else if (isAssign || typeIsInitable) { // if we aren't an assignment and the type is not a variant // w/ no CPP initializer, then we currently don't bother // to initialize it in init(). needsInit = true; } }
/** * If a simple variable refers to a name bound inside the query * then leave it alone. If not, rewrite it to be reference to * a query parameter. */ SimpleVariablePtr CaptureExtractor::rewriteSimpleVariable( SimpleVariablePtr sv) { assert(sv != nullptr); auto varName = sv->getName(); for (auto &boundVar : m_boundVars) { if (varName == boundVar) return sv; } return newQueryParamRef(sv); }
ExpressionPtr AssignmentExpression::postOptimize(AnalysisResultPtr ar) { ar->postOptimize(m_variable); ar->postOptimize(m_value); if (m_variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_variable); const std::string &name = var->getName(); VariableTablePtr variables = ar->getScope()->getVariables(); if (variables->checkUnused(name)) { variables->addUnused(name); if (m_value->getContainedEffects() != getContainedEffects()) { s_effectsTag++; } return m_value; } } return ExpressionPtr(); }
bool Expression::CheckNeeded(ExpressionPtr variable, ExpressionPtr value) { // if the value may involve object, consider the variable as "needed" // so that objects are not destructed prematurely. bool needed = true; if (value) needed = CheckNeededRHS(value); if (variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); const std::string &name = var->getName(); VariableTablePtr variables = var->getScope()->getVariables(); if (needed) { variables->addNeeded(name); } else { needed = variables->isNeeded(name); } } return needed; }
void ClassVariable::addTraitPropsToScope(AnalysisResultPtr ar, ClassScopePtr scope) { ModifierExpressionPtr modifiers = scope->setModifiers(m_modifiers); VariableTablePtr variables = scope->getVariables(); for (int i = 0; i < m_declaration->getCount(); i++) { ExpressionPtr exp = (*m_declaration)[i]; SimpleVariablePtr var; ExpressionPtr value; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); var = dynamic_pointer_cast<SimpleVariable>(assignment->getVariable()); value = assignment->getValue(); } else { var = dynamic_pointer_cast<SimpleVariable>(exp); value = makeConstant(ar, "null"); } const string &name = var->getName(); Symbol *sym; ClassScopePtr prevScope = variables->isPresent(name) ? scope : scope->getVariables()->findParent(ar, name, sym); if (prevScope && !isEquivRedecl(name, exp, m_modifiers, prevScope->getVariables()->getSymbol(name))) { Compiler::Error(Compiler::DeclaredVariableTwice, exp); m_declaration->removeElement(i--); } else { if (prevScope != scope) { // Property is new or override, so add it variables->add(name, Type::Variant, false, ar, exp, m_modifiers); variables->getSymbol(name)->setValue(exp); variables->setClassInitVal(name, value); variables->markOverride(ar, name); } else { m_declaration->removeElement(i--); } } } scope->setModifiers(modifiers); }
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()); } } } }
void ClassVariable::analyzeProgram(AnalysisResultPtr ar) { m_declaration->analyzeProgram(ar); AnalysisResult::Phase phase = ar->getPhase(); if (phase != AnalysisResult::AnalyzeAll) { return; } if (m_modifiers->isAbstract()) { Compiler::Error(Compiler::AbstractProperty, shared_from_this()); } ClassScopePtr scope = getClassScope(); for (int i = 0; i < m_declaration->getCount(); i++) { ExpressionPtr exp = (*m_declaration)[i]; bool error; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(assignment->getVariable()); ExpressionPtr value = assignment->getValue(); scope->getVariables()->setClassInitVal(var->getName(), value); error = scope->getVariables()->markOverride(ar, var->getName()); } else { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp); error = scope->getVariables()->markOverride(ar, var->getName()); scope->getVariables()->setClassInitVal(var->getName(), makeConstant(ar, "null")); } if (error) { Compiler::Error(Compiler::InvalidOverride, exp); } } }
void ClassVariable::analyzeProgramImpl(AnalysisResultPtr ar) { m_declaration->analyzeProgram(ar); AnalysisResult::Phase phase = ar->getPhase(); if (phase != AnalysisResult::AnalyzeAll) { return; } ClassScopePtr scope = getClassScope(); for (int i = 0; i < m_declaration->getCount(); i++) { ExpressionPtr exp = (*m_declaration)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(assignment->getVariable()); ExpressionPtr value = assignment->getValue(); scope->getVariables()->setClassInitVal(var->getName(), value); scope->getVariables()->markOverride(ar, var->getName()); } else { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp); scope->getVariables()->markOverride(ar, var->getName()); scope->getVariables()->setClassInitVal(var->getName(), makeConstant(ar, "null")); } } }
void ArrayElementExpression::setContext(Context context) { m_context |= context; if (context == Expression::LValue) { m_variable->setContext(Expression::LValue); if (m_variable->is(Expression::KindOfObjectPropertyExpression)) { m_variable->clearContext(Expression::NoLValueWrapper); } // special case for $GLOBALS[], see the if (m_global) check in // ArrayElementExpression::outputCPPImpl, we do not need lvalue wrapper if (m_variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_variable); if (var->getName() == "GLOBALS") { m_context |= Expression::NoLValueWrapper; } } } else if (context == Expression::DeepAssignmentLHS || context == Expression::ExistContext || context == Expression::UnsetContext) { m_variable->setContext(context); } }
bool ObjectPropertyExpression::directVariantProxy(AnalysisResultPtr ar) { TypePtr actualType = m_object->getActualType(); if (actualType && actualType->is(Type::KindOfVariant)) { if (m_object->is(KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_object); const std::string &name = var->getName(); FunctionScopePtr func = dynamic_pointer_cast<FunctionScope>(ar->getScope()); VariableTablePtr variables = func->getVariables(); if (!variables->isParameter(name) || variables->isLvalParam(name)) { return true; } if (variables->getAttribute(VariableTable::ContainsDynamicVariable) || variables->getAttribute(VariableTable::ContainsExtract)) { return true; } } else { return true; } } return false; }
ExpressionPtr AssignmentExpression::postOptimize(AnalysisResultPtr ar) { ar->postOptimize(m_variable); ar->postOptimize(m_value); if (m_variable->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_variable); const std::string &name = var->getName(); VariableTablePtr variables = ar->getScope()->getVariables(); if (!variables->isPseudoMainTable() && !variables->getAttribute(VariableTable::ContainsDynamicVariable) && !variables->isReferenced(name) && variables->isLocal(name)) { variables->addUnused(name); if (m_value->isScalar()) { m_value->setExpectedType(m_expectedType); return m_value; } else { return makeIdCall(ar); } } } return ExpressionPtr(); }
bool ExpressionList::optimize(AnalysisResultPtr ar) { bool changed = false; size_t i = m_exps.size(); if (m_kind != ListKindParam) { if (i--) { while (i--) { ExpressionPtr &e = m_exps[i]; if (!e || e->getContainedEffects() == NoEffect) { ar->incOptCounter(); removeElement(i); changed = true; } else if (e->getLocalEffects() == NoEffect) { e = e->unneeded(ar); changed = true; } } } return changed; } if (hasContext(UnsetContext) && ar->getPhase() >= AnalysisResult::PostOptimize) { while (i--) { ExpressionPtr &e = m_exps[i]; if (e->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(e); const std::string &name = var->getName(); VariableTablePtr variables = ar->getScope()->getVariables(); if (variables->checkUnused(name)) { removeElement(i); changed = true; } } } } return changed; }