Spicy
common.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <string>
6 #include <vector>
7 
8 #include <hilti/ast/expression.h>
9 #include <hilti/ast/expressions/member.h>
10 #include <hilti/ast/expressions/resolved-operator.h>
11 #include <hilti/ast/expressions/unresolved-operator.h>
12 #include <hilti/ast/operator.h>
13 #include <hilti/ast/statements/expression.h>
14 #include <hilti/ast/types/doc-only.h>
15 #include <hilti/ast/types/operand-list.h>
16 
18 #define __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
19  namespace ns { \
20  \
21  class cls : public hilti::expression::ResolvedOperatorBase { \
22  public: \
23  using hilti::expression::ResolvedOperatorBase::ResolvedOperatorBase; \
24  \
25  \
26  struct Operator : public hilti::trait::isOperator { \
27  static ::hilti::operator_::Kind kind() { return ::hilti::operator_::Kind::op; } \
28  \
29  hilti::Expression instantiate(const std::vector<hilti::Expression>& operands, const Meta& meta) const; \
30  std::string docNamespace() const { return #ns; }
31 
33 #define __END_OPERATOR_CUSTOM \
34  } \
35  ; \
36  \
37 private: \
38  } \
39  ; \
40  }
41 
49 #define BEGIN_OPERATOR(ns, op) __BEGIN_OPERATOR_CUSTOM(ns, op, op)
50 
52 #define END_OPERATOR \
53  const std::vector<hilti::operator_::Operand>& operands() const { return signature().args; } \
54  \
55  std::string doc() const { return signature().doc; } \
56  \
57  hilti::Type result(const hilti::node::Range<hilti::Expression>& ops) const { \
58  return *hilti::operator_::type(signature().result, ops, ops); \
59  } \
60  \
61  bool isLhs() const { return signature().lhs; } \
62  hilti::operator_::Priority priority() const { return signature().priority; } \
63  \
64  void validate(const hilti::expression::ResolvedOperator& /* i */, hilti::operator_::position_t /* p */) const {} \
65  \
66  __END_OPERATOR_CUSTOM
67 
75 #define BEGIN_OPERATOR_CUSTOM(ns, op) __BEGIN_OPERATOR_CUSTOM(ns, op, op)
76 
81 #define END_OPERATOR_CUSTOM __END_OPERATOR_CUSTOM
82 
92 #define BEGIN_OPERATOR_CUSTOM_x(ns, cls, op) __BEGIN_OPERATOR_CUSTOM(ns, op, cls)
93 
98 #define END_OPERATOR_CUSTOM_x __END_OPERATOR_CUSTOM
99 
100 
104 #define STANDARD_OPERATOR_1(ns, op, result_, ty_op1, doc_) \
105  BEGIN_OPERATOR(ns, op) \
106  const auto& signature() const { \
107  static hilti::operator_::Signature _signature = {.result = result_, \
108  .args = \
109  { \
110  {"op", ty_op1}, \
111  }, \
112  .doc = doc_}; \
113  return _signature; \
114  } \
115  END_OPERATOR
116 
120 #define STANDARD_OPERATOR_1x(ns, cls, op, result_, ty_op1, doc_) \
121  __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
122  const auto& signature() const { \
123  static hilti::operator_::Signature _signature = {.result = result_, \
124  .args = \
125  { \
126  {"op", ty_op1}, \
127  }, \
128  .doc = doc_}; \
129  return _signature; \
130  } \
131  END_OPERATOR
132 
136 #define STANDARD_OPERATOR_2(ns, op, result_, ty_op1, ty_op2, doc_) \
137  BEGIN_OPERATOR(ns, op) \
138  const auto& signature() const { \
139  static hilti::operator_::Signature _signature = {.result = result_, \
140  .args = {{"op0", ty_op1}, {"op1", ty_op2}}, \
141  .doc = doc_}; \
142  return _signature; \
143  } \
144  END_OPERATOR
145 
149 #define STANDARD_OPERATOR_2x(ns, cls, op, result_, ty_op1, ty_op2, doc_) \
150  __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
151  const auto& signature() const { \
152  static hilti::operator_::Signature _signature = {.result = result_, \
153  .args = {{"op0", ty_op1}, {"op1", ty_op2}}, \
154  .doc = doc_}; \
155  return _signature; \
156  } \
157  END_OPERATOR
158 
162 #define STANDARD_OPERATOR_2x_low_prio(ns, cls, op, result_, ty_op1, ty_op2, doc_) \
163  __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
164  const auto& signature() const { \
165  static hilti::operator_::Signature _signature = {.priority = operator_::Priority::Low, \
166  .result = result_, \
167  .args = {{"op0", ty_op1}, {"op1", ty_op2}}, \
168  .doc = doc_}; \
169  return _signature; \
170  } \
171  END_OPERATOR
172 
176 #define STANDARD_OPERATOR_2x_lhs(ns, cls, op, result_, ty_op1, ty_op2, doc_) \
177  __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
178  const auto& signature() const { \
179  static hilti::operator_::Signature _signature = {.lhs = true, \
180  .result = result_, \
181  .args = {{"op0", ty_op1}, {"op1", ty_op2}}, \
182  .doc = doc_}; \
183  return _signature; \
184  } \
185  END_OPERATOR
186 
190 #define STANDARD_OPERATOR_3(ns, op, result_, ty_op1, ty_op2, ty_op3, doc_) \
191  BEGIN_OPERATOR(ns, op) \
192  const auto& signature() const { \
193  static hilti::operator_::Signature _signature = \
194  {.result = result_, .args = {{"op0", ty_op1}, {"op1", ty_op2}, {"op2", ty_op3}}, .doc = doc_}; \
195  return _signature; \
196  } \
197  END_OPERATOR
198 
206 #define BEGIN_METHOD(ns, method) __BEGIN_OPERATOR_CUSTOM(ns, MemberCall, method)
207 
215 #define BEGIN_METHOD_CUSTOM_RESULT(ns, method) __BEGIN_OPERATOR_CUSTOM(ns, MemberCall, method)
216 
218 #define __END_METHOD \
219  const std::vector<hilti::operator_::Operand>& operands() const { \
220  static std::vector<hilti::operator_::Operand> _operands = {{{}, signature().self}, \
221  {{}, hilti::type::Member(signature().id)}, \
222  {{}, hilti::type::OperandList(signature().args)}}; \
223  return _operands; \
224  } \
225  \
226  std::string doc() const { return signature().doc; }
227 
229 #define END_METHOD \
230  __END_METHOD \
231  \
232  hilti::Type result(const hilti::node::Range<hilti::Expression>& ops) const { \
233  return *hilti::operator_::type(signature().result, hilti::node::Range(ops), ops); \
234  } \
235  \
236  bool isLhs() const { return false; } \
237  hilti::operator_::Priority priority() const { return signature().priority; } \
238  \
239  void validate(const hilti::expression::ResolvedOperator& /* i */, hilti::operator_::position_t /* p */) const {} \
240  \
241  __END_OPERATOR_CUSTOM
242 
247 #define END_METHOD_CUSTOM_RESULT \
248  __END_METHOD \
249  __END_OPERATOR_CUSTOM
250 
257 #define BEGIN_CTOR(ns, cls) __BEGIN_OPERATOR_CUSTOM(ns, Call, cls)
258 
259 #define END_CTOR \
260  const std::vector<hilti::operator_::Operand>& operands() const { \
261  static std::vector<hilti::operator_::Operand> _operands = {{{}, hilti::type::Type_(ctorType())}, \
262  {{}, hilti::type::OperandList(signature().args)}}; \
263  return _operands; \
264  } \
265  \
266  std::string doc() const { return signature().doc; } \
267  \
268  hilti::Type result(const hilti::node::Range<hilti::Expression>& ops) const { \
269  if ( ops.size() ) \
270  return ops[0].type().as<hilti::type::Type_>().typeValue(); \
271  \
272  return ctorType(); \
273  } \
274  \
275  bool isLhs() const { return false; } \
276  hilti::operator_::Priority priority() const { return signature().priority; } \
277  \
278  void validate(const hilti::expression::ResolvedOperator& /* i */, hilti::operator_::position_t /* p */) const {} \
279  \
280  __END_OPERATOR_CUSTOM
281 
283 #define BEGIN_KEYWORD_CTOR(ns, cls, kw, result_, doc_) \
284  __BEGIN_OPERATOR_CUSTOM(ns, Call, cls) \
285  \
286  const auto& signature() const { \
287  static hilti::operator_::Signature _signature = {.result = result_, .args = parameters(), .doc = doc_}; \
288  return _signature; \
289  } \
290  \
291  const std::vector<hilti::operator_::Operand>& operands() const { \
292  static std::vector<hilti::operator_::Operand> _operands = {{{}, hilti::type::Member(kw)}, \
293  {{}, hilti::type::OperandList(signature().args)}}; \
294  return _operands; \
295  } \
296  \
297  std::string doc() const { return signature().doc; } \
298  \
299  hilti::Type result(const hilti::node::Range<hilti::Expression>& ops) const { \
300  return *hilti::operator_::type(signature().result, ops, ops); \
301  } \
302  \
303  bool isLhs() const { return signature().lhs; } \
304  hilti::operator_::Priority priority() const { return signature().priority; } \
305  \
306  void validate(const hilti::expression::ResolvedOperator& /* i */, hilti::operator_::position_t /* p */) const {}
307 
308 
309 #define END_KEYWORD_CTOR __END_OPERATOR_CUSTOM
310 
312 #define STANDARD_KEYWORD_CTOR(ns, cls, kw, result_, ty_op, doc_) \
313  BEGIN_KEYWORD_CTOR(ns, cls, kw, result_, doc_) \
314  \
315  std::vector<Operand> parameters() const { return {{"op", ty_op}}; } \
316  \
317  END_KEYWORD_CTOR
318 
323 #define OPERATOR_DECLARE_ONLY(ns, cls)