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);
  }
}
Example #2
0
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;
  }
}
Example #3
0
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;
}
Example #5
0
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);
  }
}
Example #6
0
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();
    }
  }
}