9 #include <hilti/ast/ctors/tuple.h> 10 #include <hilti/ast/operators/common.h> 11 #include <hilti/ast/types/tuple.h> 15 STANDARD_OPERATOR_2(tuple, Equal, type::Bool(), type::constant(type::Tuple(type::Wildcard())),
16 operator_::sameTypeAs(0,
"tuple<*>"),
"Compares two tuples element-wise.");
17 STANDARD_OPERATOR_2(tuple, Unequal, type::Bool(), type::constant(type::Tuple(type::Wildcard())),
18 operator_::sameTypeAs(0,
"tuple<*>"),
"Compares two tuples element-wise.");
20 BEGIN_OPERATOR_CUSTOM(tuple, Index)
23 return type::DocOnly(
"<type of element>");
28 auto ctor = ops[1].tryAs<expression::Ctor>();
32 auto i = ctor->ctor().tryAs<ctor::UnsignedInteger>();
36 const auto& elements = ops[0].type().as<type::Tuple>().elements();
38 if ( static_cast<uint64_t>(elements.size()) <= i->value() )
41 return elements[i->value()].type();
44 bool isLhs()
const {
return true; }
45 auto priority()
const {
return hilti::operator_::Priority::Normal; }
47 const std::vector<Operand>& operands()
const {
48 static std::vector<Operand> _operands = {{{}, type::Tuple(type::Wildcard())}, {{}, type::UnsignedInteger(64)}};
52 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
53 if (
auto ec = i.op1().tryAs<expression::Ctor>() )
54 if (
auto c = ec->ctor().tryAs<ctor::UnsignedInteger>() ) {
55 if ( c->value() >=
static_cast<uint64_t
>(i.op0().type().as<type::Tuple>().elements().size()) )
56 p.node.addError(
"tuple index out of range");
61 p.node.addError(
"tuple index must be an integer constant");
64 std::string doc()
const {
65 return "Extracts the tuple element at the given index. The index must be a constant unsigned integer.";
69 BEGIN_OPERATOR_CUSTOM(tuple, Member)
72 return type::DocOnly(
"<type of element>");
74 auto id = ops[1].as<expression::Member>().
id();
75 auto tt = ops[0].type().tryAs<type::Tuple>();
79 auto elem = tt->elementByID(
id);
83 return elem->second->type();
86 bool isLhs()
const {
return true; }
87 auto priority()
const {
return hilti::operator_::Priority::Normal; }
89 const std::vector<Operand>& operands()
const {
90 static std::vector<Operand> _operands = {{{}, type::Tuple(type::Wildcard())},
91 {{}, type::Member(type::Wildcard()),
false, {},
"<id>"}};
95 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
96 auto id = i.operands()[1].as<expression::Member>().
id();
98 auto tt = i.operands()[0].type().tryAs<type::Tuple>();
100 p.node.addError(
"unknown tuple element");
104 auto elem = tt->elementByID(
id);
107 p.node.addError(
"unknown tuple element");
110 std::string doc()
const {
return "Extracts the tuple element corresponding to the given ID."; }
111 END_OPERATOR_CUSTOM_x
113 BEGIN_OPERATOR_CUSTOM(tuple, CustomAssign)
116 return type::DocOnly(
"<tuple>");
118 return ops[0].type();
121 bool isLhs()
const {
return false; }
122 auto priority()
const {
return hilti::operator_::Priority::Normal; }
124 const std::vector<Operand>& operands()
const {
126 static std::vector<Operand> _operands = {{
128 type::Member(type::Wildcard()),
133 {{}, type::Tuple(type::Wildcard()),
false, {},
"<tuple>"}};
137 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
138 auto lhs = i.operands()[0].as<expression::Ctor>().ctor().as<ctor::Tuple>();
139 auto lhs_type = lhs.type().as<type::Tuple>();
140 auto rhs_type = i.operands()[1].type().tryAs<type::Tuple>();
142 p.node.addError(
"rhs is not a tuple");
146 if ( lhs_type.elements().size() != rhs_type->elements().size() ) {
147 p.node.addError(
"cannot assign tuples of different length");
151 for (
auto j = 0U; j < lhs_type.elements().size(); j++ ) {
152 const auto& lhs_elem = lhs.value()[j];
153 const auto& lhs_elem_type = lhs_type.elements()[j].type();
154 const auto& rhs_elem_type = rhs_type->elements()[j].type();
156 if ( ! lhs_elem.isLhs() )
157 p.node.addError(util::fmt(
"cannot assign to expression: %s", to_node(lhs_elem)));
159 if ( ! type::sameExceptForConstness(lhs_elem_type, rhs_elem_type) )
160 p.node.addError(util::fmt(
"type mismatch for element %d in assignment, expected type %s but got %s", j,
161 lhs_elem_type, rhs_elem_type));
165 std::string doc()
const {
return "Assigns element-wise to the left-hand-side tuple"; }
166 END_OPERATOR_CUSTOM_x
Definition: operator-registry.h:15