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  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  auto signature() const { \
107  return hilti::operator_::Signature{.result = result_, \
108  .args = \
109  { \
110  {.id = "op", .type = ty_op1}, \
111  }, \
112  .doc = doc_}; \
113  } \
114  END_OPERATOR
115 
119 #define STANDARD_OPERATOR_1x(ns, cls, op, result_, ty_op1, doc_) \
120  __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
121  auto signature() const { \
122  return hilti::operator_::Signature{.result = result_, \
123  .args = \
124  { \
125  {.id = "op", .type = ty_op1}, \
126  }, \
127  .doc = doc_}; \
128  } \
129  END_OPERATOR
130 
134 #define STANDARD_OPERATOR_2(ns, op, result_, ty_op1, ty_op2, doc_) \
135  BEGIN_OPERATOR(ns, op) \
136  auto signature() const { \
137  return hilti::operator_::Signature{.result = result_, \
138  .args = {{.id = "op0", .type = ty_op1}, {.id = "op1", .type = ty_op2}}, \
139  .doc = doc_}; \
140  } \
141  END_OPERATOR
142 
146 #define STANDARD_OPERATOR_2x(ns, cls, op, result_, ty_op1, ty_op2, doc_) \
147  __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
148  auto signature() const { \
149  return hilti::operator_::Signature{.result = result_, \
150  .args = {{.id = "op0", .type = ty_op1}, {.id = "op1", .type = ty_op2}}, \
151  .doc = doc_}; \
152  } \
153  END_OPERATOR
154 
158 #define STANDARD_OPERATOR_2x_low_prio(ns, cls, op, result_, ty_op1, ty_op2, doc_) \
159  __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
160  auto signature() const { \
161  return hilti::operator_::Signature{.priority = operator_::Priority::Low, \
162  .result = result_, \
163  .args = {{.id = "op0", .type = ty_op1}, {.id = "op1", .type = ty_op2}}, \
164  .doc = doc_}; \
165  } \
166  END_OPERATOR
167 
171 #define STANDARD_OPERATOR_2x_lhs(ns, cls, op, result_, ty_op1, ty_op2, doc_) \
172  __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
173  auto signature() const { \
174  return hilti::operator_::Signature{.lhs = true, \
175  .result = result_, \
176  .args = {{.id = "op0", .type = ty_op1}, {.id = "op1", .type = ty_op2}}, \
177  .doc = doc_}; \
178  } \
179  END_OPERATOR
180 
184 #define STANDARD_OPERATOR_3(ns, op, result_, ty_op1, ty_op2, ty_op3, doc_) \
185  BEGIN_OPERATOR(ns, op) \
186  auto signature() const { \
187  return hilti::operator_::Signature{.result = result_, \
188  .args = {{.id = "op0", .type = ty_op1}, \
189  {.id = "op1", .type = ty_op2}, \
190  {.id = "op2", .type = ty_op3}}, \
191  .doc = doc_}; \
192  } \
193  END_OPERATOR
194 
202 #define BEGIN_METHOD(ns, method) __BEGIN_OPERATOR_CUSTOM(ns, MemberCall, method)
203 
211 #define BEGIN_METHOD_CUSTOM_RESULT(ns, method) __BEGIN_OPERATOR_CUSTOM(ns, MemberCall, method)
212 
214 #define __END_METHOD \
215  std::vector<hilti::operator_::Operand> operands() const { \
216  return {{.type = signature().self}, \
217  {.type = hilti::type::Member(signature().id)}, \
218  {.type = hilti::type::OperandList(signature().args)}}; \
219  } \
220  \
221  std::string doc() const { return signature().doc; }
222 
224 #define END_METHOD \
225  __END_METHOD \
226  \
227  hilti::Type result(const hilti::node::Range<hilti::Expression>& ops) const { \
228  return *hilti::operator_::type(signature().result, hilti::node::Range(ops), ops); \
229  } \
230  \
231  bool isLhs() const { return false; } \
232  hilti::operator_::Priority priority() const { return signature().priority; } \
233  \
234  void validate(const hilti::expression::ResolvedOperator& /* i */, hilti::operator_::position_t /* p */) const {} \
235  \
236  __END_OPERATOR_CUSTOM
237 
242 #define END_METHOD_CUSTOM_RESULT \
243  __END_METHOD \
244  __END_OPERATOR_CUSTOM
245 
252 #define BEGIN_CTOR(ns, cls) __BEGIN_OPERATOR_CUSTOM(ns, Call, cls)
253 
254 #define END_CTOR \
255  std::vector<hilti::operator_::Operand> operands() const { \
256  return {{.type = hilti::type::Type_(ctorType())}, {.type = hilti::type::OperandList(signature().args)}}; \
257  } \
258  \
259  std::string doc() const { return signature().doc; } \
260  \
261  hilti::Type result(const hilti::node::Range<hilti::Expression>& ops) const { \
262  if ( ops.size() ) \
263  return ops[0].type().as<hilti::type::Type_>().typeValue(); \
264  \
265  return ctorType(); \
266  } \
267  \
268  bool isLhs() const { return false; } \
269  hilti::operator_::Priority priority() const { return signature().priority; } \
270  \
271  void validate(const hilti::expression::ResolvedOperator& /* i */, hilti::operator_::position_t /* p */) const {} \
272  \
273  __END_OPERATOR_CUSTOM
274 
279 #define OPERATOR_DECLARE_ONLY(ns, cls)