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> 17 namespace struct_::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& node,
bool check_optional =
false) {
29 auto id = memberExpression(op1).id().local();
30 auto f = op0.type().as<type::Struct>().field(
id);
33 node.addError(
util::fmt(
"type does not have field '%s'",
id));
37 if ( check_optional && ! f->isOptional() )
38 node.addError(
util::fmt(
"field '%s' is not &optional",
id));
42 static inline Type itemType(
const Expression& op0,
const Expression& op1) {
43 if (
auto st = op0.type().tryAs<type::Struct>() ) {
44 if (
auto f = st->field(memberExpression(op1).
id().local()) )
53 BEGIN_OPERATOR_CUSTOM(struct_, Unset)
54 Type result(
const std::vector<Expression>& ops)
const {
return type::Void(); }
56 bool isLhs()
const {
return true; }
58 std::vector<Operand> operands()
const {
59 return {{.type = type::Struct(type::Wildcard()), .doc =
"struct"},
60 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
63 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
64 detail::checkName(i.op0(), i.op1(), p.node,
true);
67 std::string doc()
const {
69 Clears an optional field. 74 BEGIN_OPERATOR_CUSTOM_x(struct_, MemberNonConst, Member) 75 Type result(const std::vector<Expression>& ops)
const {
77 return type::DocOnly(
"<field type>");
79 return detail::itemType(ops[0], ops[1]);
82 bool isLhs()
const {
return true; }
84 std::vector<Operand> operands()
const {
85 return {{.type = type::Struct(type::Wildcard()), .doc =
"struct"},
86 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
89 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
90 detail::checkName(i.op0(), i.op1(), p.node);
93 std::string doc()
const {
95 Retrieves the value of a struct's field. If the field does not have a value assigned, 96 it returns its ``&default`` expression if that has been defined; otherwise it 97 triggers an exception. 100 END_OPERATOR_CUSTOM_x 102 BEGIN_OPERATOR_CUSTOM_x(struct_, MemberConst, Member) 103 Type result(const std::vector<Expression>& ops)
const {
105 return type::DocOnly(
"<field type>");
107 return detail::itemType(ops[0], ops[1]);
110 bool isLhs()
const {
return false; }
112 std::vector<Operand> operands()
const {
113 return {{.type = type::constant(type::Struct(type::Wildcard())), .doc =
"struct"},
114 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
117 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
118 detail::checkName(i.op0(), i.op1(), p.node);
121 std::string doc()
const {
123 Retrieves the value of a struct's field. If the field does not have a value assigned, 124 it returns its ``&default`` expression if that has been defined; otherwise it 125 triggers an exception. 128 END_OPERATOR_CUSTOM_x 130 BEGIN_OPERATOR_CUSTOM(struct_, TryMember) 131 Type result(const std::vector<Expression>& ops)
const {
133 return type::DocOnly(
"<field type>");
135 return detail::itemType(ops[0], ops[1]);
138 bool isLhs()
const {
return false; }
140 std::vector<Operand> operands()
const {
141 return {{.type = type::Struct(type::Wildcard()), .doc =
"struct"},
142 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
145 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
146 detail::checkName(i.op0(), i.op1(), p.node);
149 std::string doc()
const {
151 Retrieves the value of a struct's field. If the field does not have a value 152 assigned, it returns its ``&default`` expression if that has been defined; 153 otherwise it signals a special non-error exception to the host application 154 (which will normally still lead to aborting execution, similar to the standard 155 dereference operator, unless the host application specifically handles this 156 exception differently). 161 BEGIN_OPERATOR_CUSTOM(struct_, HasMember) 162 Type result(const std::vector<Expression>& )
const {
return type::Bool(); }
164 bool isLhs()
const {
return false; }
166 std::vector<Operand> operands()
const {
167 return {{.type = type::constant(type::Struct(type::Wildcard())), .doc =
"struct"},
168 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
171 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
172 detail::checkName(i.op0(), i.op1(), p.node);
175 std::string doc()
const {
176 return "Returns true if the struct's field has a value assigned (not counting any ``&default``).";
180 OPERATOR_DECLARE_ONLY(struct_, MemberCall)
186 using hilti::expression::ResolvedOperatorBase::ResolvedOperatorBase;
189 Operator(
const type::Struct& stype,
const type::struct_::Field& f) {
190 auto ftype = f.type().as<type::Function>();
191 auto op0 = operator_::Operand{.type = stype};
192 auto op1 = operator_::Operand{.type = type::Member(f.id())};
193 auto op2 = operator_::Operand{.type = ftype.operands()};
195 _operands = {op0, op1, op2};
196 _result = ftype.result().type();
199 static operator_::Kind kind() {
return operator_::Kind::MemberCall; }
200 std::vector<operator_::Operand> operands()
const {
return _operands; }
201 Type result(
const std::vector<Expression>& )
const {
return _result; }
202 bool isLhs()
const {
return false; }
203 void validate(
const expression::ResolvedOperator& , operator_::position_t p)
const {}
204 std::string doc()
const {
return "<dynamic - no doc>"; }
205 std::string docNamespace()
const {
return "<dynamic - no ns>"; }
207 Expression instantiate(
const std::vector<Expression>& operands,
const Meta& meta)
const {
209 std::vector<Expression>{operands[0], expression::Member(_field.id(), _field.type(), _field.meta()),
212 auto ro = expression::ResolvedOperator(MemberCall(*
this, ops, meta));
218 type::struct_::Field _field;
219 std::vector<operator_::Operand> _operands;
Definition: operator.h:38
std::string fmt(const char *fmt, const Args &... args)
Definition: util.h:80
Definition: resolved-operator.h:55