9 #include <hilti/ast/ctors/bool.h> 10 #include <hilti/ast/ctors/coerced.h> 11 #include <hilti/ast/expressions/type.h> 12 #include <hilti/ast/operators/common.h> 13 #include <hilti/ast/types/address.h> 14 #include <hilti/ast/types/bool.h> 15 #include <hilti/ast/types/bytes.h> 16 #include <hilti/ast/types/error.h> 17 #include <hilti/ast/types/integer.h> 18 #include <hilti/ast/types/real.h> 19 #include <hilti/ast/types/reference.h> 20 #include <hilti/ast/types/result.h> 21 #include <hilti/ast/types/stream.h> 22 #include <hilti/ast/types/tuple.h> 23 #include <hilti/ast/types/type.h> 27 BEGIN_OPERATOR_CUSTOM(
generic, Pack)
30 return type::DocOnly(
"<packable>");
35 bool isLhs()
const {
return false; }
36 auto priority()
const {
return hilti::operator_::Priority::Normal; }
38 const std::vector<Operand>& operands()
const {
39 static std::vector<Operand> _operands = {Operand{{}, type::Tuple(type::Wildcard())}};
43 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
44 const auto args = i.op0().type().template as<type::Tuple>().elements();
47 p.node.addError(
"not enough arguments for pack operator");
51 const auto& input_type = args[0].type();
53 if ( input_type.isA<type::SignedInteger>() || input_type.isA<type::UnsignedInteger>() ) {
54 if ( args.size() == 2 ) {
55 auto arg1 = args[1].type().typeID();
56 if ( arg1 && arg1->local() == ID(
"ByteOrder") )
60 p.node.addError(
"invalid arguments for integer packing; want (<value>, <ByteOrder>)");
64 else if ( input_type.isA<type::Address>() ) {
65 if ( args.size() == 2 ) {
66 auto arg1 = args[1].type().typeID();
67 if ( arg1 && arg1->local() == ID(
"ByteOrder") )
71 p.node.addError(
"invalid arguments for address packing; want (<value>, <ByteOrder>)");
75 else if ( input_type.isA<type::Real>() ) {
76 if ( args.size() == 3 ) {
77 auto arg1 = args[1].type().typeID();
78 auto arg2 = args[2].type().typeID();
79 if ( arg1 && arg1->local() == ID(
"RealType") && arg2 && arg2->local() == ID(
"ByteOrder") )
83 p.node.addError(
"invalid arguments for real packing; want (<value>, <RealType>, <ByteOrder>)");
88 p.node.addError(
"type not packable");
91 std::string doc()
const {
return "Packs a value into a binary representation."; }
94 BEGIN_OPERATOR_CUSTOM(
generic, Unpack)
97 return type::DocOnly(
"<unpackable>");
99 const auto args = ops[1].type().template as<type::Tuple>().elements();
101 return type::Error();
103 auto t = type::Tuple({ops[0].type().as<type::Type_>().typeValue(), args[0].type()}, ops[0].meta());
105 auto throw_on_error = ops[2].as<expression::Ctor>().ctor().as<ctor::Bool>().value();
106 return throw_on_error ? Type(t) : Type(type::Result(t));
109 bool isLhs()
const {
return false; }
110 auto priority()
const {
return hilti::operator_::Priority::Normal; }
112 const std::vector<Operand>& operands()
const {
113 static std::vector<Operand> _operands = {Operand{{}, type::Type_(type::Wildcard())},
114 Operand{{}, type::Tuple(type::Wildcard())}, Operand({}, type::Bool())};
118 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
119 const auto& data_type = i.op0().type().as<type::Type_>().typeValue();
120 const auto args = i.op1().type().template as<type::Tuple>().elements();
122 if ( args.size() < 1 ) {
123 p.node.addError(
"not enough arguments for unpack operator");
127 const auto& input_type = args[0].type();
129 if ( ! (input_type.isA<type::Bytes>() || input_type.isA<type::stream::View>()) ) {
130 p.node.addError(
"unpack() can be used only with bytes or a stream view as input");
134 if ( data_type.isA<type::SignedInteger>() || data_type.isA<type::UnsignedInteger>() ) {
135 if ( args.size() == 2 ) {
136 auto arg1 = args[1].type().typeID();
137 if ( arg1 && arg1->local() == ID(
"ByteOrder") )
141 p.node.addError(
"invalid arguments for integer unpacking; want (<data>, <ByteOrder>)");
145 else if ( data_type.isA<type::Address>() ) {
146 if ( args.size() == 3 ) {
147 auto arg1 = args[1].type().typeID();
148 auto arg2 = args[2].type().typeID();
149 if ( arg1 && arg1->local() == ID(
"AddressFamily") && arg2 && arg2->local() == ID(
"ByteOrder") )
153 p.node.addError(
"invalid arguments for address unpacking; want (<data>, <AddressFamily>, <ByteOrder>)");
157 else if ( data_type.isA<type::Real>() ) {
158 if ( args.size() == 3 ) {
159 auto arg1 = args[1].type().typeID();
160 auto arg2 = args[2].type().typeID();
161 if ( arg1 && arg1->local() == ID(
"RealType") && arg2 && arg2->local() == ID(
"ByteOrder") )
165 p.node.addError(
"invalid arguments for real unpacking; want (<data>, <RealType>, <ByteOrder>)");
170 p.node.addError(
"type not unpackable");
173 std::string doc()
const {
return "Unpacks a value from a binary representation."; }
176 BEGIN_OPERATOR_CUSTOM(
generic, Begin)
179 return type::DocOnly(
"<iterator>");
181 return type::isIterable(ops[0].type()) ? ops[0].type().iteratorType(ops[0].isConstant()) : type::unknown;
184 bool isLhs()
const {
return false; }
185 auto priority()
const {
return hilti::operator_::Priority::Normal; }
187 const std::vector<Operand>& operands()
const {
188 static std::vector<Operand> _operands = {
189 Operand{{}, type::Any(),
false, {},
"<container>"},
194 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
195 if ( ! type::isIterable(i.operands()[0].type()) )
196 p.node.addError(
"not an iterable type");
199 std::string doc()
const {
return "Returns an iterator to the beginning of the container's content."; }
202 BEGIN_OPERATOR_CUSTOM(
generic, End)
205 return type::DocOnly(
"<iterator>");
207 return type::isIterable(ops[0].type()) ? ops[0].type().iteratorType(ops[0].isConstant()) : type::unknown;
210 bool isLhs()
const {
return false; }
211 auto priority()
const {
return hilti::operator_::Priority::Normal; }
213 const std::vector<Operand>& operands()
const {
214 static std::vector<Operand> _operands = {
215 {{}, type::Any(),
false, {},
"<container>"},
220 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
221 if ( ! type::isIterable(i.operands()[0].type()) )
222 p.node.addError(
"not an iterable type");
225 std::string doc()
const {
return "Returns an iterator to the end of the container's content."; }
228 BEGIN_OPERATOR_CUSTOM(
generic, New)
231 return type::DocOnly(
"strong_ref<T>");
233 auto t = ops[0].type();
235 if (
auto tv = ops[0].type().tryAs<type::Type_>() )
238 return type::StrongReference(t, t.meta());
241 bool isLhs()
const {
return false; }
242 auto priority()
const {
return hilti::operator_::Priority::Normal; }
244 const std::vector<Operand>& operands()
const {
245 static std::vector<Operand> _operands = {
247 {{}, type::Tuple(type::Wildcard())},
252 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
253 auto t = i.operands()[0].type();
255 if (
auto tv = i.operands()[0].type().tryAs<type::Type_>() )
258 if ( ! type::isAllocable(t) )
259 p.node.addError(
"not an allocable type");
262 std::string doc()
const {
264 Returns a reference to an instance of a type newly allocated on the heap. 265 If `x' is a type, a default instance of that type will be allocated. 266 If `x` is an expression, an instance of the expression's type will be allocated and initialized with the value of the expression. 276 OPERATOR_DECLARE_ONLY(generic, CastedCoercion)
282 using hilti::expression::ResolvedOperatorBase::ResolvedOperatorBase;
287 static operator_::Kind kind() {
return operator_::Kind::Cast; }
288 const std::vector<operator_::Operand>& operands()
const {
289 static std::vector<Operand> _operands = {};
295 bool isLhs()
const {
return false; }
296 auto priority()
const {
return hilti::operator_::Priority::Normal; }
298 std::string doc()
const {
return "<dynamic - no doc>"; }
299 std::string docNamespace()
const {
return "<dynamic - no ns>"; }
301 Expression instantiate(
const std::vector<Expression>& operands,
const Meta& meta)
const {
302 auto ro = expression::ResolvedOperator(
CastedCoercion(*
this, operands, meta));
304 return std::move(ro);
Definition: generic.h:280
Definition: visitor-types.h:28
Definition: operator-registry.h:15
Definition: operator.h:35
Definition: generic.h:284
Definition: resolved-operator.h:37