8 #include <hilti/ast/expressions/member.h> 9 #include <hilti/ast/operators/common.h> 10 #include <hilti/ast/types/any.h> 11 #include <hilti/ast/types/struct.h> 12 #include <hilti/ast/types/unknown.h> 16 namespace struct_::detail {
19 static expression::Member memberExpression(
const Expression& op) {
20 if (
auto c = op.tryAs<expression::Coerced>() )
21 return c->expression().as<expression::Member>();
23 return op.as<expression::Member>();
27 static inline void checkName(
const Expression& op0,
const Expression& op1, Node& node,
bool check_optional =
false) {
28 auto id = memberExpression(op1).id().local();
29 auto f = op0.type().as<type::Struct>().field(
id);
32 node.addError(util::fmt(
"type does not have field '%s'",
id));
36 if ( check_optional && ! f->isOptional() )
37 node.addError(util::fmt(
"field '%s' is not &optional",
id));
41 static inline Type itemType(
const Expression& op0,
const Expression& op1) {
42 if (
auto st = op0.type().tryAs<type::Struct>() ) {
43 if (
auto f = st->field(memberExpression(op1).
id().local()) )
52 BEGIN_OPERATOR_CUSTOM(struct_, Unset)
55 bool isLhs()
const {
return true; }
56 auto priority()
const {
return hilti::operator_::Priority::Normal; }
58 const std::vector<Operand>& operands()
const {
59 static std::vector<Operand> _operands = {{{}, type::Struct(type::Wildcard()),
false, {},
"struct"},
60 {{}, type::Member(type::Wildcard()),
false, {},
"<field>"}};
64 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
65 detail::checkName(i.op0(), i.op1(), p.node,
true);
68 std::string doc()
const {
70 Clears an optional field. 75 BEGIN_OPERATOR_CUSTOM_x(struct_, MemberNonConst, Member) 78 return type::DocOnly(
"<field type>");
80 return type::nonConstant(detail::itemType(ops[0], ops[1]),
true);
83 bool isLhs()
const {
return true; }
84 auto priority()
const {
return hilti::operator_::Priority::Normal; }
86 const std::vector<Operand>& operands()
const {
87 static std::vector<Operand> _operands = {{{}, type::Struct(type::Wildcard()),
false, {},
"struct"},
88 {{}, type::Member(type::Wildcard()),
false, {},
"<field>"}};
92 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
93 detail::checkName(i.op0(), i.op1(), p.node);
96 std::string doc()
const {
98 Retrieves the value of a struct's field. If the field does not have a value assigned, 99 it returns its ``&default`` expression if that has been defined; otherwise it 100 triggers an exception. 103 END_OPERATOR_CUSTOM_x 105 BEGIN_OPERATOR_CUSTOM_x(struct_, MemberConst, Member) 108 return type::DocOnly(
"<field type>");
110 return type::constant(detail::itemType(ops[0], ops[1]));
113 bool isLhs()
const {
return false; }
114 auto priority()
const {
return hilti::operator_::Priority::Normal; }
116 const std::vector<Operand>& operands()
const {
117 static std::vector<Operand> _operands =
118 {{{}, type::constant(type::Struct(type::Wildcard())),
false, {},
"struct"},
119 {{}, type::Member(type::Wildcard()),
false, {},
"<field>"}};
123 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
124 detail::checkName(i.op0(), i.op1(), p.node);
127 std::string doc()
const {
129 Retrieves the value of a struct's field. If the field does not have a value assigned, 130 it returns its ``&default`` expression if that has been defined; otherwise it 131 triggers an exception. 134 END_OPERATOR_CUSTOM_x 136 BEGIN_OPERATOR_CUSTOM(struct_, TryMember) 139 return type::DocOnly(
"<field type>");
141 return detail::itemType(ops[0], ops[1]);
144 bool isLhs()
const {
return false; }
145 auto priority()
const {
return hilti::operator_::Priority::Normal; }
147 const std::vector<Operand>& operands()
const {
148 static std::vector<Operand> _operands = {{{}, type::Struct(type::Wildcard()),
false, {},
"struct"},
149 {{}, type::Member(type::Wildcard()),
false, {},
"<field>"}};
153 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
154 detail::checkName(i.op0(), i.op1(), p.node);
157 std::string doc()
const {
159 Retrieves the value of a struct's field. If the field does not have a value 160 assigned, it returns its ``&default`` expression if that has been defined; 161 otherwise it signals a special non-error exception to the host application 162 (which will normally still lead to aborting execution, similar to the standard 163 dereference operator, unless the host application specifically handles this 164 exception differently). 169 BEGIN_OPERATOR_CUSTOM(struct_, HasMember) 172 bool isLhs()
const {
return false; }
173 auto priority()
const {
return hilti::operator_::Priority::Normal; }
175 const std::vector<Operand>& operands()
const {
176 static std::vector<Operand> _operands =
177 {{{}, type::constant(type::Struct(type::Wildcard())),
false, {},
"struct"},
178 {{}, type::Member(type::Wildcard()),
false, {},
"<field>"}};
182 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
183 detail::checkName(i.op0(), i.op1(), p.node);
186 std::string doc()
const {
187 return "Returns true if the struct's field has a value assigned (not counting any ``&default``).";
191 OPERATOR_DECLARE_ONLY(struct_, MemberCall)
197 using hilti::expression::ResolvedOperatorBase::ResolvedOperatorBase;
200 Operator(
const type::Struct& stype,
const declaration::Field& f) {
201 auto ftype = f.type().as<type::Function>();
202 auto op0 = operator_::Operand{{}, stype};
203 auto op1 = operator_::Operand{{}, type::Member(f.id())};
204 auto op2 = operator_::Operand{{}, type::OperandList::fromParameters(ftype.parameters())};
206 _operands = {op0, op1, op2};
207 _result = ftype.result().type();
210 static operator_::Kind kind() {
return operator_::Kind::MemberCall; }
211 const std::vector<operator_::Operand>& operands()
const {
return _operands; }
213 bool isLhs()
const {
return false; }
214 auto priority()
const {
return hilti::operator_::Priority::Normal; }
215 void validate(
const expression::ResolvedOperator& , operator_::position_t p)
const {}
216 std::string doc()
const {
return "<dynamic - no doc>"; }
217 std::string docNamespace()
const {
return "<dynamic - no ns>"; }
219 Expression instantiate(
const std::vector<Expression>& operands,
const Meta& meta)
const {
221 std::vector<Expression>{operands[0], expression::Member(_field.id(), _field.type(), _field.meta()),
224 auto ro = expression::ResolvedOperator(MemberCall(*
this, ops, meta));
230 declaration::Field _field;
231 std::vector<operator_::Operand> _operands;
Definition: operator-registry.h:15
Definition: operator.h:35
Definition: resolved-operator.h:37