9 #include <hilti/ast/ctors/tuple.h> 10 #include <hilti/ast/operators/common.h> 11 #include <hilti/ast/types/tuple.h> 16 STANDARD_OPERATOR_2(tuple, Equal, type::Bool(), type::constant(type::Tuple(type::Wildcard())),
17 operator_::sameTypeAs(0,
"tuple<*>"),
"Compares two tuples element-wise.");
18 STANDARD_OPERATOR_2(tuple, Unequal, type::Bool(), type::constant(type::Tuple(type::Wildcard())),
19 operator_::sameTypeAs(0,
"tuple<*>"),
"Compares two tuples element-wise.");
21 BEGIN_OPERATOR_CUSTOM(tuple, Index)
24 return type::DocOnly(
"<type of element>");
29 auto ctor = ops[1].tryAs<expression::Ctor>();
33 auto i = ctor->ctor().tryAs<ctor::UnsignedInteger>();
37 const auto& elements = ops[0].type().as<type::Tuple>().elements();
39 if ( static_cast<uint64_t>(elements.size()) <= i->value() )
42 return elements[i->value()].type();
45 bool isLhs()
const {
return true; }
46 auto priority()
const {
return hilti::operator_::Priority::Normal; }
48 std::vector<Operand> operands()
const {
49 return {{.type = type::Tuple(type::Wildcard())}, {.type = 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() < 0 ||
56 c->value() >=
static_cast<uint64_t
>(i.op0().type().as<type::Tuple>().elements().size()) )
57 p.node.addError(
"tuple index out of range");
62 p.node.addError(
"tuple index must be an integer constant");
65 std::string doc()
const {
66 return "Extracts the tuple element at the given index. The index must be a constant unsigned integer.";
70 BEGIN_OPERATOR_CUSTOM(tuple, Member)
73 return type::DocOnly(
"<type of element>");
75 auto id = ops[1].as<expression::Member>().
id();
76 auto elem = ops[0].type().as<type::Tuple>().elementByID(
id);
80 return elem->second->type();
83 bool isLhs()
const {
return true; }
84 auto priority()
const {
return hilti::operator_::Priority::Normal; }
86 std::vector<Operand> operands()
const {
87 return {{.type = type::Tuple(type::Wildcard())}, {.type = type::Member(type::Wildcard()), .doc =
"<id>"}};
90 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
91 auto id = i.operands()[1].as<expression::Member>().
id();
92 auto elem = i.operands()[0].type().as<type::Tuple>().elementByID(
id);
95 p.node.addError(
"unknown tuple element");
98 std::string doc()
const {
return "Extracts the tuple element corresponding to the given ID."; }
101 BEGIN_OPERATOR_CUSTOM(tuple, CustomAssign)
104 return type::DocOnly(
"<tuple>");
106 return ops[0].type();
109 bool isLhs()
const {
return false; }
110 auto priority()
const {
return hilti::operator_::Priority::Normal; }
112 std::vector<Operand> operands()
const {
115 .type = type::Member(type::Wildcard()),
116 .doc =
"(x, ..., y)",
118 {.type = type::Tuple(type::Wildcard()), .doc =
"<tuple>"}};
122 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
123 auto lhs = i.operands()[0].as<expression::Ctor>().ctor().as<ctor::Tuple>();
124 auto lhs_type = lhs.type().as<type::Tuple>();
125 auto rhs_type = i.operands()[1].type().tryAs<type::Tuple>();
127 p.node.addError(
"rhs is not a tuple");
131 if ( lhs_type.elements().size() != rhs_type->elements().size() ) {
132 p.node.addError(
"cannot assign tuples of different length");
136 for (
auto i = 0u; i < lhs_type.elements().size(); i++ ) {
137 const auto& lhs_elem = lhs.value()[i];
138 const auto& lhs_elem_type = lhs_type.elements()[i].type();
139 const auto& rhs_elem_type = rhs_type->elements()[i].type();
141 if ( ! lhs_elem.isLhs() )
142 p.node.addError(
util::fmt(
"cannot assign to expression: %s", to_node(lhs_elem)));
144 if ( ! type::sameExceptForConstness(lhs_elem_type, rhs_elem_type) )
145 p.node.addError(
util::fmt(
"type mismatch for element %d in assignment, expected type %s but got %s", i,
146 lhs_elem_type, rhs_elem_type));
150 std::string doc()
const {
return "Assigns element-wise to the left-hand-side tuple"; }
151 END_OPERATOR_CUSTOM_x
std::string fmt(const char *fmt, const Args &... args)
Definition: util.h:80