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)
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) 77 return type::DocOnly(
"<field type>");
79 return type::nonConstant(detail::itemType(ops[0], ops[1]),
true);
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) 105 return type::DocOnly(
"<field type>");
107 return type::constant(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) 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) 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 declaration::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 = type::OperandList::fromParameters(ftype.parameters())};
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; }
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 declaration::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:40