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 std::vector<hilti::Expression>& ops) const { \
58  return *hilti::operator_::type(signature().result, ops, ops); \
59  } \
60  \
61  bool isLhs() const { return signature().lhs; } \
62  \
63  void validate(const hilti::expression::ResolvedOperator& /* i */, hilti::operator_::position_t /* p */) const {} \
64  \
65  __END_OPERATOR_CUSTOM
66 
74 #define BEGIN_OPERATOR_CUSTOM(ns, op) __BEGIN_OPERATOR_CUSTOM(ns, op, op)
75 
80 #define END_OPERATOR_CUSTOM __END_OPERATOR_CUSTOM
81 
91 #define BEGIN_OPERATOR_CUSTOM_x(ns, cls, op) __BEGIN_OPERATOR_CUSTOM(ns, op, cls)
92 
97 #define END_OPERATOR_CUSTOM_x __END_OPERATOR_CUSTOM
98 
99 
103 #define STANDARD_OPERATOR_1(ns, op, result_, ty_op1, doc_) \
104  BEGIN_OPERATOR(ns, op) \
105  auto signature() const { \
106  return hilti::operator_::Signature{.result = result_, \
107  .args = \
108  { \
109  {.id = "op", .type = ty_op1}, \
110  }, \
111  .doc = doc_}; \
112  } \
113  END_OPERATOR
114 
118 #define STANDARD_OPERATOR_1x(ns, cls, op, result_, ty_op1, doc_) \
119  __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
120  auto signature() const { \
121  return hilti::operator_::Signature{.result = result_, \
122  .args = \
123  { \
124  {.id = "op", .type = ty_op1}, \
125  }, \
126  .doc = doc_}; \
127  } \
128  END_OPERATOR
129 
133 #define STANDARD_OPERATOR_2(ns, op, result_, ty_op1, ty_op2, doc_) \
134  BEGIN_OPERATOR(ns, op) \
135  auto signature() const { \
136  return hilti::operator_::Signature{.result = result_, \
137  .args = {{.id = "op0", .type = ty_op1}, {.id = "op1", .type = ty_op2}}, \
138  .doc = doc_}; \
139  } \
140  END_OPERATOR
141 
145 #define STANDARD_OPERATOR_2x(ns, cls, op, result_, ty_op1, ty_op2, doc_) \
146  __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
147  auto signature() const { \
148  return hilti::operator_::Signature{.result = result_, \
149  .args = {{.id = "op0", .type = ty_op1}, {.id = "op1", .type = ty_op2}}, \
150  .doc = doc_}; \
151  } \
152  END_OPERATOR
153 
157 #define STANDARD_OPERATOR_2x_lhs(ns, cls, op, result_, ty_op1, ty_op2, doc_) \
158  __BEGIN_OPERATOR_CUSTOM(ns, op, cls) \
159  auto signature() const { \
160  return hilti::operator_::Signature{.lhs = true, \
161  .result = result_, \
162  .args = {{.id = "op0", .type = ty_op1}, {.id = "op1", .type = ty_op2}}, \
163  .doc = doc_}; \
164  } \
165  END_OPERATOR
166 
170 #define STANDARD_OPERATOR_3(ns, op, result_, ty_op1, ty_op2, ty_op3, doc_) \
171  BEGIN_OPERATOR(ns, op) \
172  auto signature() const { \
173  return hilti::operator_::Signature{.result = result_, \
174  .args = {{.id = "op0", .type = ty_op1}, \
175  {.id = "op1", .type = ty_op2}, \
176  {.id = "op2", .type = ty_op3}}, \
177  .doc = doc_}; \
178  } \
179  END_OPERATOR
180 
188 #define BEGIN_METHOD(ns, method) __BEGIN_OPERATOR_CUSTOM(ns, MemberCall, method)
189 
197 #define BEGIN_METHOD_CUSTOM_RESULT(ns, method) __BEGIN_OPERATOR_CUSTOM(ns, MemberCall, method)
198 
200 #define __END_METHOD \
201  std::vector<hilti::operator_::Operand> operands() const { \
202  return {{.type = signature().self}, \
203  {.type = hilti::type::Member(signature().id)}, \
204  {.type = hilti::type::OperandList(signature().args)}}; \
205  } \
206  \
207  std::string doc() const { return signature().doc; }
208 
210 #define END_METHOD \
211  __END_METHOD \
212  \
213  hilti::Type result(const std::vector<hilti::Expression>& ops) const { \
214  return *hilti::operator_::type(signature().result, ops, ops); \
215  } \
216  \
217  bool isLhs() const { return false; } \
218  \
219  void validate(const hilti::expression::ResolvedOperator& /* i */, hilti::operator_::position_t /* p */) const {} \
220  \
221  __END_OPERATOR_CUSTOM
222 
227 #define END_METHOD_CUSTOM_RESULT \
228  __END_METHOD \
229  __END_OPERATOR_CUSTOM
230 
237 #define BEGIN_CTOR(ns, cls) __BEGIN_OPERATOR_CUSTOM(ns, Call, cls)
238 
239 #define END_CTOR \
240  std::vector<hilti::operator_::Operand> operands() const { \
241  return {{.type = type::constant(hilti::type::Type_(ctorType()))}, \
242  {.type = hilti::type::OperandList(signature().args)}}; \
243  } \
244  \
245  std::string doc() const { return signature().doc; } \
246  \
247  hilti::Type result(const std::vector<hilti::Expression>& ops) const { \
248  if ( ops.size() ) \
249  return ops[0].type().as<hilti::type::Type_>().typeValue(); \
250  \
251  return ctorType(); \
252  } \
253  \
254  bool isLhs() const { return false; } \
255  \
256  void validate(const hilti::expression::ResolvedOperator& /* i */, hilti::operator_::position_t /* p */) const {} \
257  \
258  __END_OPERATOR_CUSTOM
259 
264 #define OPERATOR_DECLARE_ONLY(ns, cls)