Exemple #1
0
void ClosureExpression::initializeFromUseList(ExpressionListPtr vars) {
  m_vars = ExpressionListPtr(
    new ExpressionList(vars->getScope(), vars->getRange()));

  // Because PHP is insane you can have a use variable with the same
  // name as a param name.
  // In that case, params win (which is different than zend but much easier)
  auto seenBefore = collectParamNames();

  for (int i = vars->getCount() - 1; i >= 0; i--) {
    auto param = dynamic_pointer_cast<ParameterExpression>((*vars)[i]);
    assert(param);
    if (param->getName() == "this") {
      // "this" is automatically included.
      // Once we get rid of all the callsites, make this an error
      continue;
    }
    if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) {
      seenBefore.insert(param->getName().c_str());
      m_vars->insertElement(param);
    }
  }

  initializeValuesFromVars();
}
void ClosureExpression::setCaptureList(
    AnalysisResultConstRawPtr ar,
    const std::set<std::string>& captureNames) {
  assert(m_captureState == CaptureState::Unknown);
  m_captureState = CaptureState::Known;

  bool usedThis = false;
  SCOPE_EXIT {
    /*
     * TODO: closures in a non-class scope should be neither static
     * nor non-static, but right now we don't really have this idea.
     *
     * This would allow not having to check for a $this or late bound
     * class in the closure object or on the ActRec when returning
     * from those closures.
     *
     * (We could also mark closures that don't use late static binding
     * with this flag to avoid checks on closures in member functions
     * when they use neither $this nor static::)
     */
    if (!usedThis && !m_func->getModifiers()->isStatic()) {
      m_func->getModifiers()->add(T_STATIC);
    }
  };

  if (captureNames.empty()) return;

  m_vars = ExpressionListPtr(
    new ExpressionList(getScope(), getRange()));

  for (auto const& name : captureNames) {
    if (name == "this") {
      usedThis = true;
      continue;
    }

    auto expr = std::make_shared<ParameterExpression>(
      BlockScopePtr(getScope()),
      getRange(),
      TypeAnnotationPtr(),
      true /* hhType */,
      name,
      ParamMode::In,
      0 /* token modifier thing */,
      ExpressionPtr(),
      ExpressionPtr()
    );
    m_vars->insertElement(expr);
  }

  initializeValuesFromVars();
  analyzeVarsForClosure(ar);
  analyzeVarsForClosureExpression(ar);
}