void VariableTable::addStaticVariable(Symbol *sym, AnalysisResultPtr ar, bool member /* = false */) { if (isGlobalTable(ar) || sym->isStatic()) { return; // a static variable at global scope is the same as non-static } sym->setStatic(); m_hasStatic = true; FunctionScopeRawPtr funcScope = getFunctionScope(); if (funcScope && (funcScope->isClosure() || funcScope->isGeneratorFromClosure())) { // static variables for closures/closure generators are local to the // function scope m_staticLocalsVec.push_back(sym); } else { VariableTablePtr globalVariables = ar->getVariables(); StaticGlobalInfoPtr sgi(new StaticGlobalInfo()); sgi->sym = sym; sgi->variables = this; sgi->cls = getClassScope(); sgi->func = member ? FunctionScopeRawPtr() : getFunctionScope(); globalVariables->m_staticGlobalsVec.push_back(sgi); } }
void ClosureExpression::analyzeVars(AnalysisResultPtr ar) { m_values->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll) { getFunctionScope()->addUse(m_func->getFunctionScope(), BlockScope::UseKindClosure); m_func->getFunctionScope()->setClosureVars(m_vars); // closure function's variable table (not containing function's) VariableTablePtr variables = m_func->getFunctionScope()->getVariables(); VariableTablePtr containing = getFunctionScope()->getVariables(); for (int i = 0; i < m_vars->getCount(); i++) { auto param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); auto const& name = param->getName(); { Symbol *containingSym = containing->addDeclaredSymbol(name, param); containingSym->setPassClosureVar(); Symbol *sym = variables->addDeclaredSymbol(name, param); sym->setClosureVar(); sym->setDeclaration(ConstructPtr()); if (param->isRef()) { sym->setRefClosureVar(); } else { sym->clearRefClosureVar(); } } } return; } }
void ClosureExpression::analyzeVarsForClosureExpression( AnalysisResultConstRawPtr /*ar*/) { auto const containing = getFunctionScope(); for (auto const& var : *m_vars) { auto const param = dynamic_pointer_cast<ParameterExpression>(var); containing->addLocal(param->getName()); } }
TypePtr VariableTable::add(Symbol *sym, TypePtr type, bool implicit, AnalysisResultConstPtr ar, ConstructPtr construct, ModifierExpressionPtr modifiers) { if (getAttribute(InsideStaticStatement)) { addStaticVariable(sym, ar); if (ClassScope::NeedStaticArray(getClassScope(), getFunctionScope())) { forceVariant(ar, sym->getName(), AnyVars); } } else if (getAttribute(InsideGlobalStatement)) { sym->setGlobal(); m_hasGlobal = true; AnalysisResult::Locker lock(ar); if (!isGlobalTable(ar)) { lock->getVariables()->add(sym->getName(), type, implicit, ar, construct, modifiers); } assert(type->is(Type::KindOfSome) || type->is(Type::KindOfAny)); TypePtr varType = ar->getVariables()->getFinalType(sym->getName()); if (varType) { type = varType; } else { lock->getVariables()->setType(ar, sym->getName(), type, true); } } else if (!sym->isHidden() && isPseudoMainTable()) { // A variable used in a pseudomain // only need to do this once... should mark the sym. ar->lock()->getVariables()->add(sym->getName(), type, implicit, ar, construct, modifiers); } if (modifiers) { if (modifiers->isProtected()) { sym->setProtected(); } else if (modifiers->isPrivate()) { sym->setPrivate(); m_hasPrivate = true; if (!sym->isStatic() && !modifiers->isStatic()) { m_hasNonStaticPrivate = true; } } if (modifiers->isStatic()) { addStaticVariable(sym, ar); } } type = setType(ar, sym, type, true); sym->setDeclaration(construct); if (!implicit && m_blockScope.isFirstPass()) { if (!sym->getValue()) { sym->setValue(construct); } } return type; }
void ClosureExpression::analyzeProgram(AnalysisResultPtr ar) { m_func->analyzeProgram(ar); if (m_vars) analyzeVars(ar); FunctionScopeRawPtr container = getFunctionScope()->getContainingNonClosureFunction(); if (container && container->isStatic()) { m_func->getModifiers()->add(T_STATIC); } }
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(); } } }