Spicy
bitfield.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <string>
6 #include <vector>
7 
8 #include <hilti/ast/expressions/coerced.h>
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/integer.h>
13 #include <hilti/ast/types/unknown.h>
14 
15 #include <spicy/ast/types/bitfield.h>
16 
17 namespace spicy {
18 namespace operator_ {
19 
20 namespace bitfield::detail {
21 
22 // Returns an operand as a member expression.
23 static hilti::expression::Member memberExpression(const Expression& op) {
24  if ( auto c = op.tryAs<hilti::expression::Coerced>() )
25  return c->expression().as<hilti::expression::Member>();
26 
27  return op.as<hilti::expression::Member>();
28 }
29 
30 // Checks if an operand refers to a valid field inside a bitfield.
31 static inline void checkName(const Expression& op0, const Expression& op1, Node& n) {
32  auto id = memberExpression(op1).id().local();
33 
34  if ( const auto& f = op0.type().as<type::Bitfield>().bits(id); ! f )
35  n.addError(hilti::util::fmt("bitfield type does not have attribute '%s'", id));
36 }
37 
38 static inline Type itemType(const Expression& op0, const Expression& op1) {
39  if ( auto st = op0.type().tryAs<type::Bitfield>() ) {
40  if ( const auto& f = st->bits(memberExpression(op1).id().local()) )
41  return f->itemType();
42  }
43 
44  return type::unknown;
45 }
46 
47 } // namespace bitfield::detail
48 
49 BEGIN_OPERATOR_CUSTOM(bitfield, Member)
50  Type result(const hilti::node::Range<Expression>& ops) const {
51  if ( ops.empty() )
52  return type::DocOnly("<field type>");
53 
54  return detail::itemType(ops[0], ops[1]);
55  }
56 
57  bool isLhs() const { return false; }
58 
59  std::vector<hilti::operator_::Operand> operands() const {
60  return {{.type = type::constant(type::Bitfield(type::Wildcard())), .doc = "bitfield"},
61  {.type = type::Member(type::Wildcard()), .doc = "<attribute>"}};
62  }
63 
64  void validate(const hilti::expression::ResolvedOperator& i, hilti::operator_::position_t p) const {
65  detail::checkName(i.op0(), i.op1(), p.node);
66  }
67 
68  std::string doc() const {
69  return R"(
70 Retrieves the value of a bitfield's attribute. This is the value of the
71 corresponding bits inside the underlying integer value, shifted to the very
72 right.
73 )";
74  }
75 END_OPERATOR_CUSTOM_x
76 
77 } // namespace operator_
78 } // namespace spicy
Definition: member.h:19
Definition: coerced.h:13
Definition: node.h:39
Definition: visitor-types.h:28
E node
Definition: visitor-types.h:33
std::string fmt(const char *fmt, const Args &... args)
Definition: util.h:80