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; }
71 std::vector<Operand> operands()
const {
72 return {{.type = type::constant(type::Union(type::Wildcard())), .doc =
"union"},
73 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
76 void validate(
const expression::ResolvedOperator& i, position_t p)
const {
77 detail::checkName(i.op0(), i.op1(), p.node);
80 std::string doc()
const {
82 Retrieves the value of a union's field. If the union does not have the field set, 83 this triggers an exception. 88 BEGIN_OPERATOR_CUSTOM_x(union_, MemberNonConst, Member) 91 return type::DocOnly(
"<field type>");
93 return detail::itemType(ops[0], ops[1]);
96 bool isLhs()
const {
return true; }
98 std::vector<Operand> operands()
const {
99 return {{.type = type::Union(type::Wildcard()), .doc =
"union"},
100 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
103 void validate(
const expression::ResolvedOperator& i, position_t p)
const {
104 detail::checkName(i.op0(), i.op1(), p.node);
107 std::string doc()
const {
109 Retrieves the value of a union's field. If the union does not have the field set, 110 this triggers an exception unless the value is only being assigned to. 113 END_OPERATOR_CUSTOM_x 115 BEGIN_OPERATOR_CUSTOM(union_, HasMember) 118 bool isLhs()
const {
return false; }
120 std::vector<Operand> operands()
const {
121 return {{.type = type::Union(type::Wildcard()), .doc =
"union"},
122 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
125 void validate(
const expression::ResolvedOperator& i, position_t p)
const {
126 detail::checkName(i.op0(), i.op1(), p.node);
129 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