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> 17 namespace union_::detail {
20 static expression::Member memberExpression(
const Expression& op) {
21 if (
auto c = op.tryAs<expression::Coerced>() )
22 return c->expression().as<expression::Member>();
24 return op.as<expression::Member>();
28 static inline void checkName(
const Expression& op0,
const Expression& op1, Node& n) {
29 auto id = memberExpression(op1).id().local();
31 if (
auto f = op0.type().as<type::Union>().field(
id); ! f )
32 n.addError(util::fmt(
"type does not have field '%s'",
id));
36 static inline Type itemType(
const Expression& op0,
const Expression& op1) {
37 if (
auto st = op0.type().tryAs<type::Union>() ) {
38 if (
auto f = st->field(memberExpression(op1).
id().local()) )
46 static inline Type methodResult(
const Expression& ,
const Expression& op1) {
47 if (
auto f = memberExpression(op1).type().
template tryAs<type::Function>() )
48 return f->result().type();
55 STANDARD_OPERATOR_2(union_, Equal, type::Bool(), type::constant(type::Union(type::Wildcard())),
56 operator_::sameTypeAs(0,
"union<*>"),
"Compares two unions element-wise.");
57 STANDARD_OPERATOR_2(union_, Unequal, type::Bool(), type::constant(type::Union(type::Wildcard())),
58 operator_::sameTypeAs(0,
"union<*>"),
"Compares two unions element-wise.");
60 BEGIN_OPERATOR_CUSTOM_x(union_, MemberConst, Member)
63 return type::DocOnly(
"<field type>");
65 return detail::itemType(ops[0], ops[1]);
68 bool isLhs()
const {
return false; }
69 auto priority()
const {
return hilti::operator_::Priority::Normal; }
71 const std::vector<Operand>& operands()
const {
72 static std::vector<Operand> _operands =
73 {{{}, type::constant(type::Union(type::Wildcard())),
false, {},
"union"},
74 {{}, type::Member(type::Wildcard()),
false, {},
"<field>"}};
78 void validate(
const expression::ResolvedOperator& i, position_t p)
const {
79 detail::checkName(i.op0(), i.op1(), p.node);
82 std::string doc()
const {
84 Retrieves the value of a union's field. If the union does not have the field set, 85 this triggers an exception. 90 BEGIN_OPERATOR_CUSTOM_x(union_, MemberNonConst, Member) 93 return type::DocOnly(
"<field type>");
95 return detail::itemType(ops[0], ops[1]);
98 bool isLhs()
const {
return true; }
99 auto priority()
const {
return hilti::operator_::Priority::Normal; }
101 const std::vector<Operand>& operands()
const {
102 static std::vector<Operand> _operands = {{{}, type::Union(type::Wildcard()),
false, {},
"union"},
103 {{}, type::Member(type::Wildcard()),
false, {},
"<field>"}};
107 void validate(
const expression::ResolvedOperator& i, position_t p)
const {
108 detail::checkName(i.op0(), i.op1(), p.node);
111 std::string doc()
const {
113 Retrieves the value of a union's field. If the union does not have the field set, 114 this triggers an exception unless the value is only being assigned to. 117 END_OPERATOR_CUSTOM_x 119 BEGIN_OPERATOR_CUSTOM(union_, HasMember) 122 bool isLhs()
const {
return false; }
123 auto priority()
const {
return hilti::operator_::Priority::Normal; }
125 const std::vector<Operand>& operands()
const {
126 static std::vector<Operand> _operands = {{{}, type::Union(type::Wildcard()),
false, {},
"union"},
127 {{}, type::Member(type::Wildcard()),
false, {},
"<field>"}};
131 void validate(
const expression::ResolvedOperator& i, position_t p)
const {
132 detail::checkName(i.op0(), i.op1(), p.node);
135 std::string doc()
const {
return "Returns true if the union's field is set."; }
Definition: operator-registry.h:15