9 #include <hilti/ast/expressions/member.h> 10 #include <hilti/ast/operators/common.h> 11 #include <hilti/ast/types/any.h> 12 #include <hilti/ast/types/union.h> 13 #include <hilti/ast/types/unknown.h> 18 namespace union_::detail {
21 static expression::Member memberExpression(
const Expression& op) {
22 if (
auto c = op.tryAs<expression::Coerced>() )
23 return c->expression().as<expression::Member>();
25 return op.as<expression::Member>();
29 static inline void checkName(
const Expression& op0,
const Expression& op1, Node& n) {
30 auto id = memberExpression(op1).id().local();
32 if (
auto f = op0.type().as<type::Union>().field(
id); ! f )
33 n.addError(
util::fmt(
"type does not have field '%s'",
id));
37 static inline Type itemType(
const Expression& op0,
const Expression& op1) {
38 if (
auto st = op0.type().tryAs<type::Union>() ) {
39 if (
auto f = st->field(memberExpression(op1).
id().local()) )
47 static inline Type methodResult(
const Expression& ,
const Expression& op1) {
48 if (
auto f = memberExpression(op1).type().
template tryAs<type::Function>() )
49 return f->result().type();
56 STANDARD_OPERATOR_2(union_, Equal, type::Bool(), type::constant(type::Union(type::Wildcard())),
57 operator_::sameTypeAs(0,
"union<*>"),
"Compares two unions element-wise.");
58 STANDARD_OPERATOR_2(union_, Unequal, type::Bool(), type::constant(type::Union(type::Wildcard())),
59 operator_::sameTypeAs(0,
"union<*>"),
"Compares two unions element-wise.");
61 BEGIN_OPERATOR_CUSTOM_x(union_, MemberConst, Member)
64 return type::DocOnly(
"<field type>");
66 return detail::itemType(ops[0], ops[1]);
69 bool isLhs()
const {
return false; }
70 auto priority()
const {
return hilti::operator_::Priority::Normal; }
72 std::vector<Operand> operands()
const {
73 return {{.type = type::constant(type::Union(type::Wildcard())), .doc =
"union"},
74 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
77 void validate(
const expression::ResolvedOperator& i, position_t p)
const {
78 detail::checkName(i.op0(), i.op1(), p.node);
81 std::string doc()
const {
83 Retrieves the value of a union's field. If the union does not have the field set, 84 this triggers an exception. 89 BEGIN_OPERATOR_CUSTOM_x(union_, MemberNonConst, Member) 92 return type::DocOnly(
"<field type>");
94 return detail::itemType(ops[0], ops[1]);
97 bool isLhs()
const {
return true; }
98 auto priority()
const {
return hilti::operator_::Priority::Normal; }
100 std::vector<Operand> operands()
const {
101 return {{.type = type::Union(type::Wildcard()), .doc =
"union"},
102 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
105 void validate(
const expression::ResolvedOperator& i, position_t p)
const {
106 detail::checkName(i.op0(), i.op1(), p.node);
109 std::string doc()
const {
111 Retrieves the value of a union's field. If the union does not have the field set, 112 this triggers an exception unless the value is only being assigned to. 115 END_OPERATOR_CUSTOM_x 117 BEGIN_OPERATOR_CUSTOM(union_, HasMember) 120 bool isLhs()
const {
return false; }
121 auto priority()
const {
return hilti::operator_::Priority::Normal; }
123 std::vector<Operand> operands()
const {
124 return {{.type = type::Union(type::Wildcard()), .doc =
"union"},
125 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
128 void validate(
const expression::ResolvedOperator& i, position_t p)
const {
129 detail::checkName(i.op0(), i.op1(), p.node);
132 std::string doc()
const {
return "Returns true if the union's field is set."; }
std::string fmt(const char *fmt, const Args &... args)
Definition: util.h:80