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