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; }
57 auto priority()
const {
return hilti::operator_::Priority::Normal; }
59 std::vector<Operand> operands()
const {
60 return {{.type = type::Struct(type::Wildcard()), .doc =
"struct"},
61 {.type = type::Member(type::Wildcard()), .doc =
"<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 std::vector<Operand> operands()
const {
87 return {{.type = type::Struct(type::Wildcard()), .doc =
"struct"},
88 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
91 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
92 detail::checkName(i.op0(), i.op1(), p.node);
95 std::string doc()
const {
97 Retrieves the value of a struct's field. If the field does not have a value assigned, 98 it returns its ``&default`` expression if that has been defined; otherwise it 99 triggers an exception. 102 END_OPERATOR_CUSTOM_x 104 BEGIN_OPERATOR_CUSTOM_x(struct_, MemberConst, Member) 107 return type::DocOnly(
"<field type>");
109 return type::constant(detail::itemType(ops[0], ops[1]));
112 bool isLhs()
const {
return false; }
113 auto priority()
const {
return hilti::operator_::Priority::Normal; }
115 std::vector<Operand> operands()
const {
116 return {{.type = type::constant(type::Struct(type::Wildcard())), .doc =
"struct"},
117 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
120 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
121 detail::checkName(i.op0(), i.op1(), p.node);
124 std::string doc()
const {
126 Retrieves the value of a struct's field. If the field does not have a value assigned, 127 it returns its ``&default`` expression if that has been defined; otherwise it 128 triggers an exception. 131 END_OPERATOR_CUSTOM_x 133 BEGIN_OPERATOR_CUSTOM(struct_, TryMember) 136 return type::DocOnly(
"<field type>");
138 return detail::itemType(ops[0], ops[1]);
141 bool isLhs()
const {
return false; }
142 auto priority()
const {
return hilti::operator_::Priority::Normal; }
144 std::vector<Operand> operands()
const {
145 return {{.type = type::Struct(type::Wildcard()), .doc =
"struct"},
146 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
149 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
150 detail::checkName(i.op0(), i.op1(), p.node);
153 std::string doc()
const {
155 Retrieves the value of a struct's field. If the field does not have a value 156 assigned, it returns its ``&default`` expression if that has been defined; 157 otherwise it signals a special non-error exception to the host application 158 (which will normally still lead to aborting execution, similar to the standard 159 dereference operator, unless the host application specifically handles this 160 exception differently). 165 BEGIN_OPERATOR_CUSTOM(struct_, HasMember) 168 bool isLhs()
const {
return false; }
169 auto priority()
const {
return hilti::operator_::Priority::Normal; }
171 std::vector<Operand> operands()
const {
172 return {{.type = type::constant(type::Struct(type::Wildcard())), .doc =
"struct"},
173 {.type = type::Member(type::Wildcard()), .doc =
"<field>"}};
176 void validate(
const expression::ResolvedOperator& i, operator_::position_t p)
const {
177 detail::checkName(i.op0(), i.op1(), p.node);
180 std::string doc()
const {
181 return "Returns true if the struct's field has a value assigned (not counting any ``&default``).";
185 OPERATOR_DECLARE_ONLY(struct_, MemberCall)
191 using hilti::expression::ResolvedOperatorBase::ResolvedOperatorBase;
194 Operator(
const type::Struct& stype,
const declaration::Field& f) {
195 auto ftype = f.type().as<type::Function>();
196 auto op0 = operator_::Operand{.type = stype};
197 auto op1 = operator_::Operand{.type = type::Member(f.id())};
198 auto op2 = operator_::Operand{.type = type::OperandList::fromParameters(ftype.parameters())};
200 _operands = {op0, op1, op2};
201 _result = ftype.result().type();
204 static operator_::Kind kind() {
return operator_::Kind::MemberCall; }
205 std::vector<operator_::Operand> operands()
const {
return _operands; }
207 bool isLhs()
const {
return false; }
208 auto priority()
const {
return hilti::operator_::Priority::Normal; }
209 void validate(
const expression::ResolvedOperator& , operator_::position_t p)
const {}
210 std::string doc()
const {
return "<dynamic - no doc>"; }
211 std::string docNamespace()
const {
return "<dynamic - no ns>"; }
213 Expression instantiate(
const std::vector<Expression>& operands,
const Meta& meta)
const {
215 std::vector<Expression>{operands[0], expression::Member(_field.id(), _field.type(), _field.meta()),
218 auto ro = expression::ResolvedOperator(MemberCall(*
this, ops, meta));
224 declaration::Field _field;
225 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