My Project
expressions.h
1 #ifndef EXPRESSIONS_H
2 #define EXPRESSIONS_H
3 
4 #include "tstrings.h"
5 
6 #include <gsl/span>
7 #include <kblib/poly_obj.h>
8 
9 #if 0
10 struct eval_context {
11  argslist args;
12 };
13 
14 struct Expr {
15  std::vector<kblib::poly_obj<Expr, 64>> children;
16 
17  virtual arg_t operator()(const bytecode_machine& bm,
18  eval_context c) const final {
19  return eval(bm, c);
20  }
21 
22  virtual arg_t eval(const bytecode_machine& bm, eval_context c) const;
23 
24  Expr() noexcept = default;
25  Expr(const Expr& e) = default;
26  Expr(Expr&&) noexcept = default;
27  Expr& operator=(const Expr&) = default;
28  Expr& operator=(Expr&&) = default;
29  virtual ~Expr() = default;
30 };
31 
32 using ExprList = decltype(Expr::children);
33 using Expr_t = ExprList::value_type;
34 
35 static_assert(std::is_copy_constructible_v<Expr>);
36 
37 struct literal_expr : Expr {
38  std::string text;
39  literal_expr(std::string s) : text(std::move(s)) {}
40 
41  arg_t eval(const bytecode_machine&, eval_context) const override {
42  return text;
43  }
44 };
45 
46 struct arg_expr : Expr {
47  int arg;
48  arg_expr(int a) noexcept : arg(a) {}
49 
50  arg_t eval(const bytecode_machine&, eval_context c) const override {
51  return c.args.at(kblib::to_unsigned(arg));
52  }
53 };
54 
55 struct sarg_expr : Expr {
56  std::string arg;
57  sarg_expr(std::string a) noexcept : arg(std::move(a)) {}
58 
59  arg_t eval(const bytecode_machine& bm, eval_context c) const override {
60  return c.args.at(kblib::to_unsigned(bm.special_argument(arg)));
61  }
62 };
63 
64 namespace helpers {
65 
66 // move is_transformer here later
67 
68 template <typename T>
69 using _l_h = std::is_convertible<decltype(std::declval<T>()(
70  std::declval<ExprList>(),
71  std::declval<const bytecode_machine&>(),
72  std::declval<eval_context>())),
73  arg_t>;
74 
75 template <typename T, typename = std::void_t<>>
76 struct is_lazy_transformer :
77  // can't find is_invocable
78  // std::is_invocable<arg_t, T, argslist>
79  public std::false_type {};
80 
81 template <typename T>
82 struct is_lazy_transformer<T, std::void_t<_l_h<T>>> : public _l_h<T> {};
83 
84 template <typename T>
85 constexpr bool is_lazy_transformer_v = is_lazy_transformer<T>::value;
86 
87 }; // namespace helpers
88 
89 template <typename Callable,
90  typename std::enable_if_t<helpers::is_transformer_v<Callable>, int> =
91  0>
92 class eager_transformer final : public Expr {
93  public:
94  eager_transformer(Callable _c) : c(std::move(_c)) {}
95  [[nodiscard]] arg_t eval(const bytecode_machine& bm,
96  eval_context context) const override {
97  return c(kblib::build<argslist>(
98  children.begin(), children.end(),
99  [&](const Expr_t& a) -> decltype(auto) { return a(bm, context); }));
100  }
101 
102  private:
103  Callable c;
104 };
105 
106 template <typename Callable,
107  typename std::enable_if_t<helpers::is_lazy_transformer_v<Callable>,
108  int> = 0>
109 class lazy_transformer final : public Expr {
110  public:
111  lazy_transformer(Callable _c) : c(std::move(_c)) {}
112  [[nodiscard]] arg_t eval(const bytecode_machine& bm,
113  eval_context context) const override {
114  return c(children, bm, context);
115  }
116 
117  private:
118  Callable c;
119 };
120 
121 template <typename Callable, typename... Ts>
122 [[nodiscard]] auto make_eager_expr(Callable&& c, Ts&&... ts)
123  -> eager_transformer<std::decay_t<Callable>> {
124  return {std::forward<Callable>(c), {std::forward<Ts>(ts)...}};
125 }
126 
127 template <typename Callable, typename... Ts>
128 [[nodiscard]] auto make_lazy_expr(Callable&& c, Ts&&... ts)
129  -> lazy_transformer<std::decay_t<Callable>> {
130  return {std::forward<Callable>(c), {std::forward<Ts>(ts)...}};
131 }
132 
133 using index_type = gsl::span<bytecode_op>::index_type;
134 
135 auto do_lookup(std::string_view) -> Expr_t (*)();
136 #if 0
137 Expr_t parse_expr(gsl::span<bytecode_op> in, index_type& consumed) {
138  assert(!in.empty());
139  ++consumed;
140  literal_expr l{std::get<std::string>(in[0].data)};
141  switch (in[0].type) {
142  case op::text:
143  return Expr_t::make_aggregate<literal_expr>(
144  std::get<std::string>(in[0].data));
145  case op::argument:
146  return Expr_t::make_aggregate<arg_expr>(std::get<int>(in[0].data));
147  case op::ellipsis:
148  return Expr_t::make_aggregate<sarg_expr>("...");
149  case op::special_argument:
150  return Expr_t::make_aggregate<sarg_expr>(
151  std::get<std::string>(in[0].data));
152  case op::push_func:;
153  {
154  Expr_t e = do_lookup(std::get<std::string>(in[0].data))();
155  // Expr_t e = make_eager_expr(std::get<transformer*>(in[0].data));
156  index_type skip = 1;
157 
158  while (skip != in.extent) {
159  auto& code = in[skip];
160  if (code.type == op::call_func) {
161  ++skip;
162  break;
163  } else {
164  e->children.push_back(parse_expr(in.subspan(skip), skip));
165  }
166  }
167 
168  consumed += skip;
169  return e;
170  }
171  case op::null:
172  case op::call_func:
173  std::abort();
174  }
175 }
176 
177 Expr_t parse_tokens(gsl::span<bytecode_op> in) {
178 
179  Expr_t e(std::in_place);
180 
181  index_type begin = 0;
182 
183  while (begin != in.extent) {
184  e->children.push_back(parse_expr(in.subspan(begin), begin));
185  }
186  return e;
187 }
188 #endif
189 #endif
190 
191 #endif // EXPRESSIONS_H
Definition: tstrings.h:113
Definition: tstrings.h:196