<commit_before>#include <monsoon/expressions/operators.h>
#include <monsoon/metric_value.h>
#include <monsoon/interpolate.h>
#include <type_traits>
#include <string_view>
#include <ostream>
#include <utility>
#include <algorithm>
#include <functional>
#include <map>
#include <set>
#include <deque>
#include <iterator>
#include "../overload.h"

namespace monsoon {
namespace expressions {


template<typename Fn>
class monsoon_expr_local_ unop_t final
: public expression
{
 public:
  unop_t(Fn&&, std::string_view, expression_ptr&&);
  ~unop_t() noexcept override;

  auto operator()(const metric_source&,
      const time_range&, time_point::duration) const
      -> std::variant<scalar_objpipe, vector_objpipe> override;

  bool is_scalar() const noexcept override;
  bool is_vector() const noexcept override;

 private:
  void do_ostream(std::ostream&) const override;

  static auto apply_scalar_(scalar_emit_type&, const Fn&) -> scalar_emit_type&;
  static auto apply_vector_(vector_emit_type&, const Fn&) -> vector_emit_type&;

  expression_ptr nested_;
  Fn fn_;
  std::string_view sign_;
};


template<typename Fn>
class monsoon_expr_local_ binop_t final
: public expression
{
 private:
  class application;

 public:
  binop_t(Fn&&, std::string_view, expression_ptr&&, expression_ptr&&);
  ~binop_t() noexcept override;

  auto operator()(const metric_source&,
      const time_range&, time_point::duration) const
      -> std::variant<scalar_objpipe, vector_objpipe> override;

  bool is_scalar() const noexcept override;
  bool is_vector() const noexcept override;

 private:
  void do_ostream(std::ostream&) const override;

  expression_ptr x_, y_;
  Fn fn_;
  std::string_view sign_;
};


class monsoon_expr_local_ scalar_accumulator {
 private:
  using speculative_map = std::map<time_point, metric_value>;
  using factual_list = std::deque<std::pair<time_point, metric_value>>;

 public:
  auto operator[](time_point tp) const
      -> std::optional<std::tuple<metric_value, bool>>;
  auto factual_until() const noexcept -> std::optional<time_point>;
  void advance_factual(time_point) noexcept;
  void add(expression::scalar_emit_type&& v);

 private:
  void add_speculative_(time_point tp, metric_value&& v);
  void add_factual_(time_point tp, metric_value&& v);

  speculative_map speculative_;
  factual_list factual_;
};


class monsoon_expr_local_ vector_accumulator {
 private:
  struct speculative_cmp {
    using is_transparent = std::true_type;

    bool operator()(
        std::tuple<time_point, const tags&> x,
        std::tuple<time_point, const tags&> y) const noexcept {
      return x < y;
    }

    bool operator()(
        std::tuple<time_point, const tags&> x,
        const time_point& y) const noexcept {
      return std::get<0>(x) < y;
    }

    bool operator()(
        const time_point& x,
        std::tuple<time_point, const tags&> y) const noexcept {
      return x < std::get<0>(y);
    }
  };

  using speculative_map = std::map<
      std::tuple<time_point, tags>,
      metric_value,
      speculative_cmp>;

  struct speculative_index_cmp {
   private:
    using internal_type = std::tuple<const tags&, time_point>;

   public:
    using is_transparent = std::true_type;

    template<typename X, typename Y>
    bool operator()(const X& x, const Y& y) const noexcept {
      return intern_(x) < intern_(y);
    }

   private:
    static auto intern_(const speculative_map::const_iterator i) noexcept
    -> internal_type {
      return intern_(i->first);
    }

    static auto intern_(const internal_type& i) noexcept
    -> const internal_type& {
      return i;
    }

    static auto intern_(std::tuple<time_point, const tags&> i)
    -> internal_type {
      return std::tie(std::get<1>(i), std::get<0>(i));
    }
  };

  using speculative_index = std::set<
      speculative_map::const_iterator,
      speculative_index_cmp>;
  using factual_list =
      std::deque<std::pair<time_point, expression::factual_vector>>;

 public:
  struct tp_proxy {
   public:
    tp_proxy(const vector_accumulator& self, time_point tp) noexcept
    : self_(self),
      tp_(tp)
    {}

    auto operator[](const tags& tag_set) const
        -> std::optional<std::tuple<metric_value, bool>> {
      return self_.interpolate_(tp_, tag_set);
    }

    bool has_value() const noexcept {
      return self_.factual_until() >= tp_;
    }

    auto value() const
        -> std::variant<
            expression::factual_vector,
            const expression::factual_vector*> {
      return self_.interpolate_(tp_);
    }

   private:
    const vector_accumulator& self_;
    time_point tp_;
  };

  auto operator[](time_point tp) const -> tp_proxy {
    return tp_proxy(*this, tp);
  }

  auto factual_until() const noexcept -> std::optional<time_point>;
  void advance_factual(time_point) noexcept;
  void add(expression::vector_emit_type&& v);

 private:
  void add_speculative_(time_point tp, expression::speculative_vector&& v);
  void add_factual_(time_point tp, expression::factual_vector&& v);
  auto interpolate_(time_point tp, const tags& tag_set) const
      -> std::optional<std::tuple<metric_value, bool>>;
  auto interpolate_(time_point tp) const
      -> std::variant<
          expression::factual_vector,
          const expression::factual_vector*>;

  speculative_map speculative_;
  factual_list factual_;
  speculative_index speculative_index_;
};


template<typename Fn>
unop_t<Fn>::unop_t(Fn&& fn, std::string_view sign, expression_ptr&& nested)
: fn_(std::move(fn)),
  sign_(std::move(sign)),
  nested_(std::move(nested))
{
  if (nested_ == nullptr) throw std::invalid_argument("null expression_ptr");
}

template<typename Fn>
unop_t<Fn>::~unop_t() noexcept {}

template<typename Fn>
auto unop_t<Fn>::operator()(
    const metric_source& src,
    const time_range& tr, time_point::duration slack) const
-> std::variant<scalar_objpipe, vector_objpipe> {
  using namespace std::placeholders;

  return std::visit(
      overload(
          [this](scalar_objpipe&& s)
          -> std::variant<scalar_objpipe, vector_objpipe> {
            return std::move(s)
                .transform_copy(std::bind(&unop_t::apply_scalar_, _1, fn_));
          },
          [this](vector_objpipe&& s)
          -> std::variant<scalar_objpipe, vector_objpipe> {
            return std::move(s)
                .transform_copy(std::bind(&unop_t::apply_vector_, _1, fn_));
          }),
      std::invoke(*nested_, src, tr, std::move(slack)));
}

template<typename Fn>
bool unop_t<Fn>::is_scalar() const noexcept {
  return nested_->is_scalar();
}

template<typename Fn>
bool unop_t<Fn>::is_vector() const noexcept {
  return nested_->is_scalar();
}

template<typename Fn>
void unop_t<Fn>::do_ostream(std::ostream& out) const {
  out << sign_ << *nested_;
}

template<typename Fn>
auto unop_t<Fn>::apply_scalar_(scalar_emit_type& emt, const Fn& fn)
-> scalar_emit_type& {
  std::visit(
      [&fn](metric_value& v) {
        v = std::invoke(fn, std::move(v));
      },
      emt.data);
  return emt;
}

template<typename Fn>
auto unop_t<Fn>::apply_vector_(vector_emit_type& emt, const Fn& fn)
-> vector_emit_type& {
  std::visit(
      overload(
          [&fn](speculative_vector& v) {
            std::get<1>(v) = std::invoke(fn, std::move(std::get<1>(v)));
          },
          [&fn](factual_vector& map) {
            for (auto& elem : map)
              elem.second = std::invoke(fn, std::move(elem.second));
          }),
      emt.data);
  return emt;
}


template<typename Fn>
binop_t<Fn>::binop_t(Fn&& fn, std::string_view sign,
    expression_ptr&& x, expression_ptr&& y)
: fn_(std::move(fn)),
  sign_(std::move(sign)),
  x_(std::move(x)),
  y_(std::move(y))
{
  if (x_ == nullptr) throw std::invalid_argument("null expression_ptr x");
  if (y_ == nullptr) throw std::invalid_argument("null expression_ptr y");
}

template<typename Fn>
binop_t<Fn>::~binop_t() noexcept {}

template<typename Fn>
bool binop_t<Fn>::is_scalar() const noexcept {
  return x_->is_scalar() && y_->is_scalar();
}

template<typename Fn>
bool binop_t<Fn>::is_vector() const noexcept {
  return x_->is_vector() || y_->is_vector();
}<commit_msg>Fix member initialization order.<commit_after>#include <monsoon/expressions/operators.h>
#include <monsoon/metric_value.h>
#include <monsoon/interpolate.h>
#include <type_traits>
#include <string_view>
#include <ostream>
#include <utility>
#include <algorithm>
#include <functional>
#include <map>
#include <set>
#include <deque>
#include <iterator>
#include "../overload.h"

namespace monsoon {
namespace expressions {


template<typename Fn>
class monsoon_expr_local_ unop_t final
: public expression
{
 public:
  unop_t(Fn&&, std::string_view, expression_ptr&&);
  ~unop_t() noexcept override;

  auto operator()(const metric_source&,
      const time_range&, time_point::duration) const
      -> std::variant<scalar_objpipe, vector_objpipe> override;

  bool is_scalar() const noexcept override;
  bool is_vector() const noexcept override;

 private:
  void do_ostream(std::ostream&) const override;

  static auto apply_scalar_(scalar_emit_type&, const Fn&) -> scalar_emit_type&;
  static auto apply_vector_(vector_emit_type&, const Fn&) -> vector_emit_type&;

  Fn fn_;
  expression_ptr nested_;
  std::string_view sign_;
};


template<typename Fn>
class monsoon_expr_local_ binop_t final
: public expression
{
 private:
  class application;

 public:
  binop_t(Fn&&, std::string_view, expression_ptr&&, expression_ptr&&);
  ~binop_t() noexcept override;

  auto operator()(const metric_source&,
      const time_range&, time_point::duration) const
      -> std::variant<scalar_objpipe, vector_objpipe> override;

  bool is_scalar() const noexcept override;
  bool is_vector() const noexcept override;

 private:
  void do_ostream(std::ostream&) const override;

  Fn fn_;
  expression_ptr x_, y_;
  std::string_view sign_;
};


class monsoon_expr_local_ scalar_accumulator {
 private:
  using speculative_map = std::map<time_point, metric_value>;
  using factual_list = std::deque<std::pair<time_point, metric_value>>;

 public:
  auto operator[](time_point tp) const
      -> std::optional<std::tuple<metric_value, bool>>;
  auto factual_until() const noexcept -> std::optional<time_point>;
  void advance_factual(time_point) noexcept;
  void add(expression::scalar_emit_type&& v);

 private:
  void add_speculative_(time_point tp, metric_value&& v);
  void add_factual_(time_point tp, metric_value&& v);

  speculative_map speculative_;
  factual_list factual_;
};


class monsoon_expr_local_ vector_accumulator {
 private:
  struct speculative_cmp {
    using is_transparent = std::true_type;

    bool operator()(
        std::tuple<time_point, const tags&> x,
        std::tuple<time_point, const tags&> y) const noexcept {
      return x < y;
    }

    bool operator()(
        std::tuple<time_point, const tags&> x,
        const time_point& y) const noexcept {
      return std::get<0>(x) < y;
    }

    bool operator()(
        const time_point& x,
        std::tuple<time_point, const tags&> y) const noexcept {
      return x < std::get<0>(y);
    }
  };

  using speculative_map = std::map<
      std::tuple<time_point, tags>,
      metric_value,
      speculative_cmp>;

  struct speculative_index_cmp {
   private:
    using internal_type = std::tuple<const tags&, time_point>;

   public:
    using is_transparent = std::true_type;

    template<typename X, typename Y>
    bool operator()(const X& x, const Y& y) const noexcept {
      return intern_(x) < intern_(y);
    }

   private:
    static auto intern_(const speculative_map::const_iterator i) noexcept
    -> internal_type {
      return intern_(i->first);
    }

    static auto intern_(const internal_type& i) noexcept
    -> const internal_type& {
      return i;
    }

    static auto intern_(std::tuple<time_point, const tags&> i)
    -> internal_type {
      return std::tie(std::get<1>(i), std::get<0>(i));
    }
  };

  using speculative_index = std::set<
      speculative_map::const_iterator,
      speculative_index_cmp>;
  using factual_list =
      std::deque<std::pair<time_point, expression::factual_vector>>;

 public:
  struct tp_proxy {
   public:
    tp_proxy(const vector_accumulator& self, time_point tp) noexcept
    : self_(self),
      tp_(tp)
    {}

    auto operator[](const tags& tag_set) const
        -> std::optional<std::tuple<metric_value, bool>> {
      return self_.interpolate_(tp_, tag_set);
    }

    bool has_value() const noexcept {
      return self_.factual_until() >= tp_;
    }

    auto value() const
        -> std::variant<
            expression::factual_vector,
            const expression::factual_vector*> {
      return self_.interpolate_(tp_);
    }

   private:
    const vector_accumulator& self_;
    time_point tp_;
  };

  auto operator[](time_point tp) const -> tp_proxy {
    return tp_proxy(*this, tp);
  }

  auto factual_until() const noexcept -> std::optional<time_point>;
  void advance_factual(time_point) noexcept;
  void add(expression::vector_emit_type&& v);

 private:
  void add_speculative_(time_point tp, expression::speculative_vector&& v);
  void add_factual_(time_point tp, expression::factual_vector&& v);
  auto interpolate_(time_point tp, const tags& tag_set) const
      -> std::optional<std::tuple<metric_value, bool>>;
  auto interpolate_(time_point tp) const
      -> std::variant<
          expression::factual_vector,
          const expression::factual_vector*>;

  speculative_map speculative_;
  factual_list factual_;
  speculative_index speculative_index_;
};


template<typename Fn>
unop_t<Fn>::unop_t(Fn&& fn, std::string_view sign, expression_ptr&& nested)
: fn_(std::move(fn)),
  nested_(std::move(nested)),
  sign_(std::move(sign))
{
  if (nested_ == nullptr) throw std::invalid_argument("null expression_ptr");
}

template<typename Fn>
unop_t<Fn>::~unop_t() noexcept {}

template<typename Fn>
auto unop_t<Fn>::operator()(
    const metric_source& src,
    const time_range& tr, time_point::duration slack) const
-> std::variant<scalar_objpipe, vector_objpipe> {
  using namespace std::placeholders;

  return std::visit(
      overload(
          [this](scalar_objpipe&& s)
          -> std::variant<scalar_objpipe, vector_objpipe> {
            return std::move(s)
                .transform_copy(std::bind(&unop_t::apply_scalar_, _1, fn_));
          },
          [this](vector_objpipe&& s)
          -> std::variant<scalar_objpipe, vector_objpipe> {
            return std::move(s)
                .transform_copy(std::bind(&unop_t::apply_vector_, _1, fn_));
          }),
      std::invoke(*nested_, src, tr, std::move(slack)));
}

template<typename Fn>
bool unop_t<Fn>::is_scalar() const noexcept {
  return nested_->is_scalar();
}

template<typename Fn>
bool unop_t<Fn>::is_vector() const noexcept {
  return nested_->is_scalar();
}

template<typename Fn>
void unop_t<Fn>::do_ostream(std::ostream& out) const {
  out << sign_ << *nested_;
}

template<typename Fn>
auto unop_t<Fn>::apply_scalar_(scalar_emit_type& emt, const Fn& fn)
-> scalar_emit_type& {
  std::visit(
      [&fn](metric_value& v) {
        v = std::invoke(fn, std::move(v));
      },
      emt.data);
  return emt;
}

template<typename Fn>
auto unop_t<Fn>::apply_vector_(vector_emit_type& emt, const Fn& fn)
-> vector_emit_type& {
  std::visit(
      overload(
          [&fn](speculative_vector& v) {
            std::get<1>(v) = std::invoke(fn, std::move(std::get<1>(v)));
          },
          [&fn](factual_vector& map) {
            for (auto& elem : map)
              elem.second = std::invoke(fn, std::move(elem.second));
          }),
      emt.data);
  return emt;
}


template<typename Fn>
binop_t<Fn>::binop_t(Fn&& fn, std::string_view sign,
    expression_ptr&& x, expression_ptr&& y)
: fn_(std::move(fn)),
  x_(std::move(x)),
  y_(std::move(y)),
  sign_(std::move(sign))
{
  if (x_ == nullptr) throw std::invalid_argument("null expression_ptr x");
  if (y_ == nullptr) throw std::invalid_argument("null expression_ptr y");
}

template<typename Fn>
binop_t<Fn>::~binop_t() noexcept {}

template<typename Fn>
bool binop_t<Fn>::is_scalar() const noexcept {
  return x_->is_scalar() && y_->is_scalar();
}

template<typename Fn>
bool binop_t<Fn>::is_vector() const noexcept {
  return x_->is_vector() || y_->is_vector();
}
{'fraction_non_alphanumeric': 0.13454367626383032, 'fraction_numerical': 0.0009780548933308881, 'mean_word_length': 4.0261136712749614, 'pattern_counts': {'":': 0, '<': 169, '<?xml version=': 0, '>': 209, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7638679', 'n_tokens_mistral': 5528, 'n_tokens_neox': 5420, 'n_words': 1191}