void ClassVariable::analyzeProgram(AnalysisResultConstRawPtr ar) { auto phase = ar->getPhase(); if (phase != AnalysisResult::AnalyzeAll) { return; } auto scope = getClassScope(); for (int i = 0; i < m_declaration->getCount(); i++) { auto exp = (*m_declaration)[i]; bool error; if (exp->is(Expression::KindOfAssignmentExpression)) { auto assignment = dynamic_pointer_cast<AssignmentExpression>(exp); auto var = dynamic_pointer_cast<SimpleVariable>(assignment->getVariable()); auto value = assignment->getValue(); scope->getVariables()->setClassInitVal(var->getName(), value); error = scope->getVariables()->markOverride(ar, var->getName()); } else { auto 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 SwitchStatement::analyzeProgram(AnalysisResultConstRawPtr ar) { if (ar->getPhase() == AnalysisResult::AnalyzeAll && m_exp->is(Expression::KindOfSimpleVariable)) { auto exp = dynamic_pointer_cast<SimpleVariable>(m_exp); if (exp && exp->getSymbol() && exp->getSymbol()->isClassName()) { // Mark some classes as volatile since the name is used in switch for (int i = 0; i < m_cases->getCount(); i++) { auto stmt = dynamic_pointer_cast<CaseStatement>((*m_cases)[i]); assert(stmt); ExpressionPtr caseCond = stmt->getCondition(); if (caseCond && caseCond->isScalar()) { auto name = dynamic_pointer_cast<ScalarExpression>(caseCond); if (name && name->isLiteralString()) { string className = name->getLiteralString(); ClassScopePtr cls = ar->findClass(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); } } }
void NewObjectExpression::analyzeProgram(AnalysisResultConstRawPtr ar) { FunctionCall::analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll) { resolveClass(); if (m_params) { m_params->markParams(); } } }
void DynamicFunctionCall::analyzeProgram(AnalysisResultConstRawPtr ar) { FunctionCall::analyzeProgram(ar); if (ar->getPhase() >= AnalysisResult::AnalyzeAll) { if (hasStaticClass()) { resolveClass(); } if (m_params) { m_params->markParams(); } } }
void InterfaceStatement::analyzeProgram(AnalysisResultConstRawPtr ar) { if (ar->getPhase() != AnalysisResult::AnalyzeAll) return; std::vector<std::string> bases; if (m_base) m_base->getStrings(bases); for (unsigned int i = 0; i < bases.size(); i++) { ClassScopePtr cls = ar->findClass(bases[i]); if (cls) { if (!cls->isInterface()) { Compiler::Error( Compiler::InvalidDerivation, shared_from_this(), cls->getOriginalName() + " must be an interface"); } } } }
void ClosureExpression::analyzeProgram(AnalysisResultConstRawPtr ar) { always_assert(getFileScope() == FileScope::getCurrent()); auto const sameScope = m_func->getFileScope() == FileScope::getCurrent(); if (sameScope) { // Closures in flattened traits could come from another file. // Only let the owner analyze them ar->analyzeProgram(m_func); if (m_captureState == CaptureState::Unknown) { assert(m_type == ClosureType::Short); FileScope::getCurrent()->addLambda(ClosureExpressionRawPtr{this}); } } else { if (m_captureState == CaptureState::Unknown) { assert(m_type == ClosureType::Short); ar->lock()->addClonedLambda(ClosureExpressionRawPtr{this}); } } if (m_vars && ar->getPhase() == AnalysisResult::AnalyzeAll) { if (sameScope) analyzeVarsForClosure(ar); analyzeVarsForClosureExpression(ar); } if (!sameScope || m_func->getModifiers()->isStatic()) return; auto const funcScope = getFunctionScope(); auto const container = funcScope->getContainingNonClosureFunction(); if (container && container->isStatic()) { m_func->getModifiers()->add(T_STATIC); } else { auto const closureFuncScope = m_func->getFunctionScope(); if (m_type != ClosureType::Short || closureFuncScope->containsThis()) { funcScope->setContainsThis(); } } }