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"); }
static void parse_string_arg(ExpressionPtr exp, std::string &var, std::string &lit) { if (exp->is(Expression::KindOfUnaryOpExpression)) { auto u = static_pointer_cast<UnaryOpExpression>(exp); if (u->getOp() == '(') { parse_string_arg(u->getExpression(), var, lit); return; } } else if (exp->is(Expression::KindOfBinaryOpExpression)) { auto b = static_pointer_cast<BinaryOpExpression>(exp); if (b->getOp() == '.') { std::string v, l; parse_string_arg(b->getExp2(), v, l); if (v.empty()) { parse_string_arg(b->getExp1(), var, lit); lit += l; return; } } } if (exp->isLiteralString()) { var = ""; lit = exp->getLiteralString(); return; } var = exp->getText(); lit = ""; return; }
int BinaryOpExpression::getConcatList(ExpressionPtrVec &ev, ExpressionPtr exp, bool &hasVoid) { if (!exp->hasCPPTemp()) { if (exp->is(Expression::KindOfUnaryOpExpression)) { UnaryOpExpressionPtr u = static_pointer_cast<UnaryOpExpression>(exp); if (u->getOp() == '(') { return getConcatList(ev, u->getExpression(), hasVoid); } } else if (exp->is(Expression::KindOfBinaryOpExpression)) { BinaryOpExpressionPtr b = static_pointer_cast<BinaryOpExpression>(exp); if (b->getOp() == '.') { return getConcatList(ev, b->getExp1(), hasVoid) + getConcatList(ev, b->getExp2(), hasVoid); } } else if (exp->is(Expression::KindOfEncapsListExpression)) { EncapsListExpressionPtr e = static_pointer_cast<EncapsListExpression>(exp); if (e->getType() != '`') { ExpressionListPtr el = e->getExpressions(); int num = 0; for (int i = 0, s = el->getCount(); i < s; i++) { ExpressionPtr exp = (*el)[i]; num += getConcatList(ev, exp, hasVoid); } return num; } } } ev.push_back(exp); bool isVoid = !exp->getActualType(); hasVoid |= isVoid; return isVoid ? 0 : 1; }
void GlobalStatement::inferTypes(AnalysisResultPtr ar) { 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); if (exp->is(Expression::KindOfDynamicVariable)) { exp->inferAndCheck(ar, Type::Any, true); } else { assert(false); } } } FunctionScopePtr func = getFunctionScope(); }
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); } } }
ExpressionPtr AssignmentExpression::preOptimize(AnalysisResultConstPtr ar) { if (m_variable->getContainedEffects() & ~(CreateEffect|AccessorEffect)) { return ExpressionPtr(); } ExpressionPtr val = m_value; while (val) { if (val->is(KindOfExpressionList)) { val = static_pointer_cast<ExpressionList>(val)->listValue(); continue; } if (val->is(KindOfAssignmentExpression)) { val = static_pointer_cast<AssignmentExpression>(val)->m_value; continue; } break; } if (val && val->isScalar()) { if (val != m_value) { ExpressionListPtr rep(new ExpressionList( getScope(), getRange(), ExpressionList::ListKindWrapped)); rep->addElement(m_value); m_value = val->clone(); rep->addElement(static_pointer_cast<Expression>(shared_from_this())); return replaceValue(rep); } } return ExpressionPtr(); }
bool ExpressionList::flattenLiteralStrings(vector<ExpressionPtr> &literals) const { for (unsigned i = 0; i < m_exps.size(); i++) { ExpressionPtr e = m_exps[i]; if (e->is(Expression::KindOfArrayPairExpression)) { ArrayPairExpressionPtr ap = dynamic_pointer_cast<ArrayPairExpression>(e); if (ap->getName()) return false; e = ap->getValue(); } if (e->is(Expression::KindOfUnaryOpExpression)) { UnaryOpExpressionPtr unary = dynamic_pointer_cast<UnaryOpExpression>(e); if (unary->getOp() == T_ARRAY) { ExpressionListPtr el = dynamic_pointer_cast<ExpressionList>(unary->getExpression()); if (!el->flattenLiteralStrings(literals)) { return false; } } } else if (e->isLiteralString()) { literals.push_back(e); } else { return false; } } return 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 ListAssignment::outputCPPAssignment(CodeGenerator &cg, AnalysisResultPtr ar, const string &arrTmp) { if (!m_variables) return; for (int i = m_variables->getCount() - 1; i >= 0; --i) { ExpressionPtr exp = (*m_variables)[i]; if (exp) { if (exp->is(Expression::KindOfListAssignment)) { ListAssignmentPtr sublist = dynamic_pointer_cast<ListAssignment>(exp); string subTmp = genCPPTemp(cg, ar); cg_printf("Variant %s((ref(%s[%d])));\n", subTmp.c_str(), arrTmp.c_str(), i); sublist->outputCPPAssignment(cg, ar, subTmp); } else { bool done = false; if (exp->is(Expression::KindOfArrayElementExpression)) { ArrayElementExpressionPtr arrExp = dynamic_pointer_cast<ArrayElementExpression>(exp); if (!arrExp->isSuperGlobal() && !arrExp->isDynamicGlobal()) { arrExp->getVariable()->outputCPP(cg, ar); if (arrExp->getOffset()) { cg_printf(".set("); arrExp->getOffset()->outputCPP(cg, ar); cg_printf(", "); } else { cg_printf(".append("); } cg_printf("%s[%d]);\n", arrTmp.c_str(), i); done = true; } } else if (exp->is(Expression::KindOfObjectPropertyExpression)) { ObjectPropertyExpressionPtr var( dynamic_pointer_cast<ObjectPropertyExpression>(exp)); if (!var->isValid()) { var->outputCPPObject(cg, ar); cg_printf("o_set("); var->outputCPPProperty(cg, ar); cg_printf(", %s[%d], %s);\n", arrTmp.c_str(), i, getClassScope() ? "s_class_name" : "empty_string"); done = true; } } if (!done) { exp->outputCPP(cg, ar); if (arrTmp == "null") { cg_printf(" = null;\n"); } else { cg_printf(" = %s[%d];\n", arrTmp.c_str(), i); } } } } } }
void ReturnStatement::analyzeProgram(AnalysisResultPtr ar) { if (m_exp) { FunctionScopePtr funcScope = getFunctionScope(); if (funcScope) { if (funcScope->isRefReturn()) { m_exp->setContext(Expression::RefValue); } } m_exp->analyzeProgram(ar); } if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { if (m_exp) { TypePtr retType = m_exp->getCPPType(); bool needsCheck = !retType->isPrimitive(); if (m_exp->is(Expression::KindOfSimpleFunctionCall) || m_exp->is(Expression::KindOfDynamicFunctionCall) || m_exp->is(Expression::KindOfObjectMethodExpression)) { // return a value from another function call needsCheck = false; } ExpressionPtr tmp = m_exp; while (tmp && (tmp->is(Expression::KindOfObjectPropertyExpression) || tmp->is(Expression::KindOfArrayElementExpression))) { if (ObjectPropertyExpressionPtr opExp = dynamic_pointer_cast<ObjectPropertyExpression>(tmp)) { tmp = opExp->getObject(); } else { ArrayElementExpressionPtr aeExp = dynamic_pointer_cast<ArrayElementExpression>(tmp); ASSERT(aeExp); tmp = aeExp->getVariable(); } } if (SimpleVariablePtr svExp = dynamic_pointer_cast<SimpleVariable>(tmp)) { if (svExp->isThis()) { // returning something from $this needsCheck = false; } else { Symbol *sym = svExp->getSymbol(); if (sym && sym->isParameter() && !sym->isLvalParam()) { // returning something from non-lval parameter needsCheck = false; } } } if (needsCheck) { FunctionScopePtr funcScope = getFunctionScope(); if (funcScope) funcScope->setNeedsCheckMem(); } } } }
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 DataFlowWalker::processAccessChain(ExpressionPtr e) { if (!e) return; if (!e->is(Expression::KindOfObjectPropertyExpression) && !e->is(Expression::KindOfArrayElementExpression)) { return; } for (int i = 0, n = e->getKidCount(); i < n; ++i) { ExpressionPtr kid(e->getNthExpr(i)); if (kid && kid->hasContext(Expression::AccessContext)) { processAccessChain(kid); process(kid, true); break; } } }
ExpressionPtr ClassConstantExpression::preOptimize(AnalysisResultConstPtr ar) { if (ar->getPhase() < AnalysisResult::FirstPreOptimize) { return ExpressionPtr(); } if (m_class) { updateClassName(); if (m_class) { return ExpressionPtr(); } } ClassScopePtr cls = resolveClass(); if (!cls || (cls->isVolatile() && !isPresent())) { if (cls && !m_depsSet) { cls->addUse(getScope(), BlockScope::UseKindConstRef); m_depsSet = true; } return ExpressionPtr(); } ConstantTablePtr constants = cls->getConstants(); ClassScopePtr defClass = cls; ConstructPtr decl = constants->getValueRecur(ar, m_varName, defClass); if (decl) { BlockScope::s_constMutex.lock(); ExpressionPtr value = dynamic_pointer_cast<Expression>(decl); BlockScope::s_constMutex.unlock(); if (!value->isScalar() && (value->is(KindOfClassConstantExpression) || value->is(KindOfConstantExpression))) { std::set<ExpressionPtr> seen; do { if (!seen.insert(value).second) return ExpressionPtr(); value = value->preOptimize(ar); if (!value) return ExpressionPtr(); } while (!value->isScalar() && (value->is(KindOfClassConstantExpression) || value->is(KindOfConstantExpression))); } ExpressionPtr rep = Clone(value, getScope()); rep->setComment(getText()); copyLocationTo(rep); return replaceValue(rep); } return ExpressionPtr(); }
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; } } }
int BinaryOpExpression::getConcatList(ExpressionPtrVec &ev, ExpressionPtr exp, bool &hasVoid) { if (!exp->hasCPPTemp()) { if (exp->is(Expression::KindOfUnaryOpExpression)) { UnaryOpExpressionPtr u = static_pointer_cast<UnaryOpExpression>(exp); if (u->getOp() == '(') { return getConcatList(ev, u->getExpression(), hasVoid); } } else if (exp->is(Expression::KindOfBinaryOpExpression)) { BinaryOpExpressionPtr b = static_pointer_cast<BinaryOpExpression>(exp); if (b->getOp() == '.') { if (b->getExp1()->is(Expression::KindOfSimpleVariable) && b->getExp1()->isLocalExprAltered() && !b->getExp1()->hasCPPTemp() && b->getExp2()->hasEffect() && !b->getExp2()->hasCPPTemp()) { /* In this case, the simple variable must be evaluated after b->getExp2(). But when we output a concat list we explicitly order the expressions from left to right. */ } else { return getConcatList(ev, b->getExp1(), hasVoid) + getConcatList(ev, b->getExp2(), hasVoid); } } } else if (exp->is(Expression::KindOfEncapsListExpression)) { EncapsListExpressionPtr e = static_pointer_cast<EncapsListExpression>(exp); if (e->getType() != '`') { ExpressionListPtr el = e->getExpressions(); int num = 0; for (int i = 0, s = el->getCount(); i < s; i++) { ExpressionPtr exp = (*el)[i]; num += getConcatList(ev, exp, hasVoid); } return num; } } } else if (!exp->getActualType()) { return 0; } ev.push_back(exp); bool isVoid = !exp->getActualType(); hasVoid |= isVoid; return isVoid ? 0 : 1; }
void ClassVariable::onParseRecur(AnalysisResultConstPtr ar, ClassScopePtr scope) { ModifierExpressionPtr modifiers = scope->setModifiers(m_modifiers); for (int i = 0; i < m_declaration->getCount(); i++) { VariableTablePtr variables = scope->getVariables(); ExpressionPtr exp = (*m_declaration)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr var = assignment->getVariable(); const std::string &name = dynamic_pointer_cast<SimpleVariable>(var)->getName(); if (variables->isPresent(name)) { Compiler::Error(Compiler::DeclaredVariableTwice, exp); m_declaration->removeElement(i--); } else { assignment->onParseRecur(ar, scope); } } else { const std::string &name = dynamic_pointer_cast<SimpleVariable>(exp)->getName(); if (variables->isPresent(name)) { Compiler::Error(Compiler::DeclaredVariableTwice, exp); m_declaration->removeElement(i--); } else { variables->add(name, Type::Variant, false, ar, exp, m_modifiers); } } } scope->setModifiers(modifiers); }
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 ClassVariable::onParse(AnalysisResultPtr ar) { ModifierExpressionPtr modifiers = ar->getScope()->setModifiers(m_modifiers); for (int i = 0; i < m_declaration->getCount(); i++) { VariableTablePtr variables = ar->getScope()->getVariables(); ExpressionPtr exp = (*m_declaration)[i]; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr var = assignment->getVariable(); const std::string &name = dynamic_pointer_cast<SimpleVariable>(var)->getName(); if (variables->isPresent(name)) { ar->getCodeError()->record(CodeError::DeclaredVariableTwice, exp); } IParseHandlerPtr ph = dynamic_pointer_cast<IParseHandler>(exp); ph->onParse(ar); } else { const std::string &name = dynamic_pointer_cast<SimpleVariable>(exp)->getName(); if (variables->isPresent(name)) { ar->getCodeError()->record(CodeError::DeclaredVariableTwice, exp); } variables->add(name, TypePtr(), false, ar, exp, m_modifiers); } } ar->getScope()->setModifiers(modifiers); }
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); } } }
ExpressionPtr Expression::unneededHelper() { ExpressionListPtr elist = ExpressionListPtr (new ExpressionList(getScope(), getRange(), ExpressionList::ListKindWrapped)); bool change = false; for (int i=0, n = getKidCount(); i < n; i++) { ExpressionPtr kid = getNthExpr(i); if (kid && kid->getContainedEffects()) { ExpressionPtr rep = kid->unneeded(); if (rep != kid) change = true; if (rep->is(Expression::KindOfExpressionList)) { for (int j=0, m = rep->getKidCount(); j < m; j++) { elist->addElement(rep->getNthExpr(j)); } } else { elist->addElement(rep); } } } if (change) { getScope()->addUpdates(BlockScope::UseKindCaller); } int n = elist->getCount(); assert(n); if (n == 1) { return elist->getNthExpr(0); } else { return elist; } }
ExpressionPtr Expression::replaceValue(ExpressionPtr rep, bool noWarn) { if (hasContext(Expression::RefValue) && isRefable(true) && !rep->isRefable(true)) { /* An assignment isRefable, but the rhs may not be. Need this to prevent "bad pass by reference" errors. */ auto el = std::make_shared<ExpressionList>( getScope(), getRange(), noWarn ? ExpressionList::ListKindWrappedNoWarn : ExpressionList::ListKindWrapped); el->addElement(rep); rep->clearContext(AssignmentRHS); rep = el; } if (rep->is(KindOfSimpleVariable) && !is(KindOfSimpleVariable)) { static_pointer_cast<SimpleVariable>(rep)->setAlwaysStash(); } rep->copyContext(m_context & ~(DeadStore|AccessContext)); if (rep->getScope() != getScope()) { rep->resetScope(getScope()); } return rep; }
void RefDict::visit(ExpressionPtr e) { if (!first_pass) { // only need to record expressions once return; } if (e->getScope()->inPseudoMain()) { // bail out for psuedomain return; } if (!e->is(Expression::KindOfSimpleVariable)) { // only need to record simple variables return; } SimpleVariablePtr ptr(static_pointer_cast<SimpleVariable>(e)); if (ptr->isSuperGlobal() || ptr->isThis()) { // don't both recording for super globals or this return; } // Good to go if (m_am.insertForDict(e)) { record(e); } }
void ClassVariable::inferTypes(AnalysisResultPtr ar) { assert(getScope().get() == getClassScope().get()); IMPLEMENT_INFER_AND_CHECK_ASSERT(getScope()); // assignments will ignore the passed in type, // but we need to ensure that Null is applied to // the simple variables. m_declaration->inferAndCheck(ar, Type::Null, false); if (m_modifiers->isStatic()) { ClassScopePtr scope = getClassScope(); for (int i = 0; i < m_declaration->getCount(); i++) { ExpressionPtr exp = (*m_declaration)[i]; SimpleVariablePtr var; if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr value = assignment->getValue(); if (value->containsDynamicConstant(ar)) { scope->getVariables()-> setAttribute(VariableTable::ContainsDynamicStatic); } } } } }
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 UserAttribute::outputCodeModel(CodeGenerator &cg) { cg.printObjectHeader("Attribute", m_exp != nullptr ? 3 : 2); cg.printPropertyHeader("attributeName"); cg.printValue(m_name); if (m_exp != nullptr && m_exp->is(Expression::KindOfUnaryOpExpression)) { UnaryOpExpressionPtr u(static_pointer_cast<UnaryOpExpression>(m_exp)); if (u->getOp() == T_ARRAY) { ExpressionPtr ex = u->getExpression(); if (ex != nullptr) { if (ex->is(Expression::KindOfExpressionList)) { ExpressionListPtr el(static_pointer_cast<ExpressionList>(ex)); cg.printPropertyHeader("expressions"); cg.printExpressionVector(el); } else { assert(false); } } else { ExpressionListPtr el; cg.printPropertyHeader("expressions"); cg.printExpressionVector(el); } } else { assert(false); } } cg.printPropertyHeader("sourceLocation"); cg.printLocation(this->getLocation()); cg.printObjectFooter(); }
ExpressionPtr Expression::replaceValue(ExpressionPtr rep) { if (hasContext(Expression::RefValue) && isRefable(true) && !rep->isRefable(true)) { /* An assignment isRefable, but the rhs may not be. Need this to prevent "bad pass by reference" errors. */ ExpressionListPtr el(new ExpressionList(getScope(), getRange(), ExpressionList::ListKindWrapped)); el->addElement(rep); rep->clearContext(AssignmentRHS); rep = el; } if (rep->is(KindOfSimpleVariable) && !is(KindOfSimpleVariable)) { static_pointer_cast<SimpleVariable>(rep)->setAlwaysStash(); } rep->copyContext(m_context & ~(DeadStore|AccessContext)); if (TypePtr t1 = getType()) { if (TypePtr t2 = rep->getType()) { if (!Type::SameType(t1, t2)) { rep->setExpectedType(t1); } } } if (rep->getScope() != getScope()) { rep->resetScope(getScope()); } return rep; }
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 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; } }
void SimpleFunctionCall::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) { outputLineMap(cg, ar); if (!m_className.empty()) { cg.printf("%s::%s(", m_className.c_str(), m_name.c_str()); } else { if (cg.getOutput() == CodeGenerator::InlinedPHP || cg.getOutput() == CodeGenerator::TrimmedPHP) { if (cg.getOutput() == CodeGenerator::TrimmedPHP && cg.usingStream(CodeGenerator::PrimaryStream) && Option::DynamicFunctionCalls.find(m_name) != Option::DynamicFunctionCalls.end()) { int funcNamePos = Option::DynamicFunctionCalls[m_name]; if (m_params && m_params->getCount() && m_params->getCount() >= funcNamePos + 1) { if (funcNamePos == -1) funcNamePos = m_params->getCount() - 1; ExpressionPtr funcName = (*m_params)[funcNamePos]; if (!funcName->is(Expression::KindOfScalarExpression)) { cg.printf("%s(", m_name.c_str()); for (int i = 0; i < m_params->getCount(); i++) { if (i > 0) cg.printf(", "); if (i == funcNamePos) { cg.printf("%sdynamic_load(", Option::IdPrefix.c_str()); funcName->outputPHP(cg, ar); cg.printf(")"); } else { ExpressionPtr param = (*m_params)[i]; if (param) param->outputPHP(cg, ar); } } cg.printf(")"); return; } } } /* simptodo: I dunno if (m_type == RenderTemplateFunction && !m_template.empty()) { cg.printf("%s_%s(", m_name.c_str(), Util::getIdentifier(m_template).c_str()); } else if (m_type == RenderTemplateIncludeFunction) { string templateName = ar->getProgram()->getCurrentTemplate(); cg.printf("%s_%s(", m_name.c_str(), Util::getIdentifier(templateName).c_str()); } else { */ cg.printf("%s(", m_name.c_str()); //} } else { cg.printf("%s(", m_name.c_str()); } } if (m_params) m_params->outputPHP(cg, ar); cg.printf(")"); }
static void setListKind(ExpressionPtr e) { if (e && e->is(Expression::KindOfExpressionList)) { ExpressionListPtr list = static_pointer_cast<ExpressionList>(e); list->setListKind(ExpressionList::ListKindComma); } }