Spicy
generic.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <string>
6 #include <utility>
7 #include <vector>
8 
9 #include <hilti/ast/expressions/type.h>
10 #include <hilti/ast/operators/common.h>
11 #include <hilti/ast/types/bytes.h>
12 #include <hilti/ast/types/reference.h>
13 #include <hilti/ast/types/result.h>
14 #include <hilti/ast/types/stream.h>
15 #include <hilti/ast/types/tuple.h>
16 #include <hilti/ast/types/type.h>
17 
18 namespace hilti::operator_ {
19 
20 BEGIN_OPERATOR_CUSTOM(generic, Unpack)
21  Type result(const hilti::node::Range<Expression>& ops) const {
22  if ( ops.empty() )
23  return type::DocOnly("<unpackable>");
24 
25  const auto& elements = ops[1].type().as<type::Tuple>().elements();
26  const auto& data_type = elements[0].type();
27  return type::Result(type::Tuple({ops[0].type().as<type::Type_>().typeValue(), data_type}, ops[0].meta()));
28  }
29 
30  bool isLhs() const { return false; }
31  auto priority() const { return hilti::operator_::Priority::Normal; }
32 
33  const std::vector<Operand>& operands() const {
34  static std::vector<Operand> _operands = {Operand{{}, type::Type_(type::Wildcard())},
35  Operand{{}, type::Tuple(type::Wildcard())}};
36  return _operands;
37  }
38 
39  void validate(const expression::ResolvedOperator& i, operator_::position_t p) const {
40  const auto& elements = i.op1().type().template as<type::Tuple>().elements();
41  const auto& data_type = elements[0].type();
42 
43  if ( ! (data_type.isA<type::Bytes>() || data_type.isA<type::stream::View>()) )
44  p.node.addError("unpack() can be used only with bytes or a stream view as input");
45  }
46 
47  std::string doc() const { return "Unpacks a value from a binary representation."; }
48 END_OPERATOR_CUSTOM
49 
50 BEGIN_OPERATOR_CUSTOM(generic, Begin)
51  Type result(const hilti::node::Range<Expression>& ops) const {
52  if ( ops.empty() )
53  return type::DocOnly("<iterator>");
54 
55  return type::isIterable(ops[0].type()) ? ops[0].type().iteratorType(ops[0].isConstant()) : type::unknown;
56  }
57 
58  bool isLhs() const { return false; }
59  auto priority() const { return hilti::operator_::Priority::Normal; }
60 
61  const std::vector<Operand>& operands() const {
62  static std::vector<Operand> _operands = {
63  Operand{{}, type::Any(), false, {}, "<container>"},
64  };
65  return _operands;
66  }
67 
68  void validate(const expression::ResolvedOperator& i, operator_::position_t p) const {
69  if ( ! type::isIterable(i.operands()[0].type()) )
70  p.node.addError("not an iterable type");
71  }
72 
73  std::string doc() const { return "Returns an iterator to the beginning of the container's content."; }
74 END_OPERATOR_CUSTOM
75 
76 BEGIN_OPERATOR_CUSTOM(generic, End)
77  Type result(const hilti::node::Range<Expression>& ops) const {
78  if ( ops.empty() )
79  return type::DocOnly("<iterator>");
80 
81  return type::isIterable(ops[0].type()) ? ops[0].type().iteratorType(ops[0].isConstant()) : type::unknown;
82  }
83 
84  bool isLhs() const { return false; }
85  auto priority() const { return hilti::operator_::Priority::Normal; }
86 
87  const std::vector<Operand>& operands() const {
88  static std::vector<Operand> _operands = {
89  {{}, type::Any(), false, {}, "<container>"},
90  };
91  return _operands;
92  }
93 
94  void validate(const expression::ResolvedOperator& i, operator_::position_t p) const {
95  if ( ! type::isIterable(i.operands()[0].type()) )
96  p.node.addError("not an iterable type");
97  }
98 
99  std::string doc() const { return "Returns an iterator to the end of the container's content."; }
100 END_OPERATOR_CUSTOM
101 
102 BEGIN_OPERATOR_CUSTOM(generic, New)
103  Type result(const hilti::node::Range<Expression>& ops) const {
104  if ( ops.empty() )
105  return type::DocOnly("strong_ref<T>");
106 
107  auto t = ops[0].type();
108 
109  if ( auto tv = ops[0].type().tryAs<type::Type_>() )
110  t = tv->typeValue();
111 
112  return type::StrongReference(t, t.meta());
113  }
114 
115  bool isLhs() const { return false; }
116  auto priority() const { return hilti::operator_::Priority::Normal; }
117 
118  const std::vector<Operand>& operands() const {
119  static std::vector<Operand> _operands = {
120  {"t", type::Any()},
121  {{}, type::Tuple(type::Wildcard())},
122  };
123  return _operands;
124  }
125 
126  void validate(const expression::ResolvedOperator& i, operator_::position_t p) const {
127  auto t = i.operands()[0].type();
128 
129  if ( auto tv = i.operands()[0].type().tryAs<type::Type_>() )
130  t = tv->typeValue();
131 
132  if ( ! type::isAllocable(t) )
133  p.node.addError("not an allocable type");
134  }
135 
136  std::string doc() const {
137  return R"(
138 Returns a reference to an instance of a type newly allocated on the heap.
139 If `x' is a type, a default instance of that type will be allocated.
140 If `x` is an expression, an instance of the expression's type will be allocated and initialized with the value of the expression.
141 )";
142  }
143 END_OPERATOR_CUSTOM
144 
150 OPERATOR_DECLARE_ONLY(generic, CastedCoercion)
151 
152 namespace generic {
153 
155 public:
156  using hilti::expression::ResolvedOperatorBase::ResolvedOperatorBase;
157 
159  Operator() = default;
160 
161  static operator_::Kind kind() { return operator_::Kind::Cast; }
162  const std::vector<operator_::Operand>& operands() const {
163  static std::vector<Operand> _operands = {}; // Won't participate in overload resolution
164  return _operands;
165  }
166  Type result(const hilti::node::Range<Expression>& ops) const {
167  return ops[1].as<expression::Type_>().typeValue();
168  }
169  bool isLhs() const { return false; }
170  auto priority() const { return hilti::operator_::Priority::Normal; }
171  void validate(const expression::ResolvedOperator& /* i */, operator_::position_t /* p */) const {}
172  std::string doc() const { return "<dynamic - no doc>"; }
173  std::string docNamespace() const { return "<dynamic - no ns>"; }
174 
175  Expression instantiate(const std::vector<Expression>& operands, const Meta& meta) const {
176  auto ro = expression::ResolvedOperator(CastedCoercion(*this, operands, meta));
177  ro.setMeta(meta);
178  return std::move(ro);
179  }
180  };
181 };
182 } // namespace generic
183 
184 } // namespace hilti::operator_
Definition: type.h:13
Definition: node.h:37
Definition: visitor-types.h:28
Definition: operator-registry.h:15
Definition: operator.h:35
Definition: meta.h:19
Definition: type.h:158
Definition: resolved-operator.h:37