Spicy
field.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <optional>
6 #include <utility>
7 #include <vector>
8 
9 #include <hilti/ast/declarations/expression.h>
10 #include <hilti/ast/expressions/keyword.h>
11 #include <hilti/ast/types/vector.h>
12 #include <hilti/base/uniquer.h>
13 #include <hilti/base/util.h>
14 
15 #include <spicy/ast/aliases.h>
16 #include <spicy/ast/engine.h>
17 #include <spicy/ast/types/unit-item.h>
18 
19 namespace spicy::type::unit::item {
20 
23 public:
24  Field(const std::optional<ID>& id, Type type, Engine e, const std::vector<Expression>& args,
25  std::optional<Expression> repeat, const std::vector<Expression>& sinks,
26  std::optional<AttributeSet> attrs = {}, std::optional<Expression> cond = {}, std::vector<Hook> hooks = {},
27  Meta m = Meta())
28  : NodeBase(nodes((id ? id : _uniquer.get("anon")), hilti::type::pruneWalk(std::move(type)), hilti::type::auto_,
29  hilti::node::none, hilti::type::auto_, node::none, repeat, std::move(attrs), std::move(cond),
30  args, sinks, hooks),
31  std::move(m)),
32  _is_forwarding(false),
33  _is_transient(! id.has_value()),
34  _engine(e),
35  _args_start(9),
36  _args_end(_args_start + static_cast<int>(args.size())),
37  _sinks_start(_args_end),
38  _sinks_end(_sinks_start + static_cast<int>(sinks.size())),
39  _hooks_start(_sinks_end),
40  _hooks_end(_hooks_start + static_cast<int>(hooks.size())) {}
41 
42  Field(const std::optional<ID>& id, Ctor ctor, Engine e, const std::vector<Expression>& args,
43  std::optional<Expression> repeat, const std::vector<Expression>& sinks,
44  std::optional<AttributeSet> attrs = {}, std::optional<Expression> cond = {}, std::vector<Hook> hooks = {},
45  Meta m = Meta())
46  : NodeBase(nodes((id ? id : _uniquer.get("anon")), hilti::node::none, hilti::type::auto_, hilti::node::none,
47  hilti::type::auto_, ctor, repeat, std::move(attrs), std::move(cond), args, sinks, hooks),
48  std::move(m)),
49  _is_forwarding(false),
50  _is_transient(! id.has_value()),
51  _engine(e),
52  _args_start(9),
53  _args_end(_args_start + static_cast<int>(args.size())),
54  _sinks_start(_args_end),
55  _sinks_end(_sinks_start + static_cast<int>(sinks.size())),
56  _hooks_start(_sinks_end),
57  _hooks_end(_hooks_start + static_cast<int>(hooks.size())) {}
58 
59  Field(const std::optional<ID>& id, Item item, Engine e, const std::vector<Expression>& args,
60  std::optional<Expression> repeat, const std::vector<Expression>& sinks,
61  std::optional<AttributeSet> attrs = {}, std::optional<Expression> cond = {}, std::vector<Hook> hooks = {},
62  const Meta& m = Meta())
63  : NodeBase(nodes((id ? id : _uniquer.get("anon")), hilti::node::none, hilti::type::auto_, hilti::node::none,
64  hilti::type::auto_, std::move(item), repeat, std::move(attrs), std::move(cond), args, sinks,
65  hooks),
66  m),
67  _is_forwarding(false),
68  _is_transient(! id.has_value()),
69  _engine(e),
70  _args_start(9),
71  _args_end(_args_start + static_cast<int>(args.size())),
72  _sinks_start(_args_end),
73  _sinks_end(_sinks_start + static_cast<int>(sinks.size())),
74  _hooks_start(_sinks_end),
75  _hooks_end(_hooks_start + static_cast<int>(hooks.size())) {}
76 
77  Field(const std::optional<ID>& id, NodeRef type, Engine e, const std::vector<Expression>& args,
78  std::optional<Expression> repeat, const std::vector<Expression>& sinks,
79  std::optional<AttributeSet> attrs = {}, std::optional<Expression> cond = {}, std::vector<Hook> hooks = {},
80  const Meta& m = Meta())
81  : NodeBase(nodes((id ? id : _uniquer.get("anon")), node::none, hilti::type::auto_, hilti::node::none,
82  hilti::type::auto_, node::none, repeat, std::move(attrs), std::move(cond), args, sinks, hooks),
83  std::move(m)),
84  _type(std::move(type)),
85  _is_forwarding(false),
86  _is_transient(! id.has_value()),
87  _engine(e),
88  _args_start(9),
89  _args_end(_args_start + static_cast<int>(args.size())),
90  _sinks_start(_args_end),
91  _sinks_end(_sinks_start + static_cast<int>(sinks.size())),
92  _hooks_start(_sinks_end),
93  _hooks_end(_hooks_start + static_cast<int>(hooks.size())) {
94  (*_type)->isA<hilti::declaration::Type>();
95  }
96 
97  Field() = delete;
98  Field(const Field& other) = default;
99  Field(Field&& other) = default;
100  ~Field() = default;
101 
102  const auto& id() const { return childs()[0].as<ID>(); }
103  auto index() const { return _index; }
104  auto ctor() const { return childs()[5].tryAs<Ctor>(); }
105  auto item() const { return childs()[5].tryAs<Item>(); }
106 
107  auto repeatCount() const { return childs()[6].tryAs<Expression>(); }
108  auto attributes() const { return childs()[7].tryAs<AttributeSet>(); }
109  auto condition() const { return childs()[8].tryAs<Expression>(); }
110  auto arguments() const { return childs<Expression>(_args_start, _args_end); }
111  auto sinks() const { return childs<Expression>(_sinks_start, _sinks_end); }
112  auto hooks() const { return childs<Hook>(_hooks_start, _hooks_end); }
113  Engine engine() const { return _engine; }
114 
115  bool isContainer() const { return repeatCount().has_value(); }
116  bool isForwarding() const { return _is_forwarding; }
117  bool isTransient() const { return _is_transient; }
118  bool emitHook() const { return ! isTransient() || hooks().size(); }
119 
120  const Type& originalType() const {
121  if ( _type )
122  return (*_type)->as<hilti::declaration::Type>().type();
123 
124  if ( auto t = childs()[1].tryAs<Type>() )
125  return *t;
126 
127  if ( auto c = ctor() )
128  return c->type();
129 
130  if ( auto i = item() )
131  return i->itemType();
132 
134  }
135 
136  const Type& parseType() const { return childs()[2].as<Type>(); }
137  NodeRef parseTypeRef() const { return NodeRef(childs()[2]); }
138  const Type& itemType() const { return childs()[4].as<Type>(); }
139 
140  const Type& ddType() const {
141  if ( auto x = childs()[3].tryAs<hilti::declaration::Expression>() )
142  return x->expression().type();
143  else
144  return hilti::type::auto_;
145  }
146 
147  NodeRef ddRef() const {
148  if ( childs()[3].isA<Declaration>() )
149  return NodeRef(childs()[3]);
150  else
151  return {};
152  }
153 
154  auto itemRef() { return NodeRef(childs()[5]); }
155 
156  // Get the `&convert` expression, if any.
157  std::optional<std::pair<const Expression, std::optional<const Type>>> convertExpression() const;
158 
159  void setForwarding(bool is_forwarding) { _is_forwarding = is_forwarding; }
160  void setDDType(Type t) { childs()[3] = hilti::expression::Keyword::createDollarDollarDeclaration(std::move(t)); }
161  void setIndex(uint64_t index) { _index = index; }
162  void setItemType(Type t) { childs()[4] = hilti::type::pruneWalk(std::move(t)); }
163  void setParseType(Type t) { childs()[2] = hilti::type::pruneWalk(std::move(t)); }
164 
165  bool operator==(const Field& other) const {
166  return _engine == other._engine && id() == other.id() && originalType() == other.originalType() &&
167  itemType() == other.itemType() && parseType() == other.parseType() &&
168  attributes() == other.attributes() && arguments() == other.arguments() && sinks() == other.sinks() &&
169  condition() == other.condition() && hooks() == other.hooks();
170  }
171 
172  Field& operator=(const Field& other) = default;
173  Field& operator=(Field&& other) = default;
174 
175  // Unit item interface
176  bool isResolved() const { return _type || item() || type::isResolved(itemType()); }
177  auto isEqual(const Item& other) const { return node::isEqual(this, other); }
178 
179  // Node interface.
180  auto properties() const {
181  return node::Properties{{"engine", to_string(_engine)},
182  {"transient", _is_transient},
183  {"forwarding", _is_forwarding}};
184  }
185 
186 private:
187  std::optional<NodeRef> _type;
188  std::optional<uint64_t> _index;
189  bool _is_forwarding;
190  bool _is_transient;
191  Engine _engine;
192  int _args_start;
193  int _args_end;
194  int _sinks_start;
195  int _sinks_end;
196  int _hooks_start;
197  int _hooks_end;
198 
199  static inline hilti::util::Uniquer<ID> _uniquer;
200 };
201 
202 } // namespace spicy::type::unit::item
NodeBase(Meta meta)
Definition: node.h:365
Definition: type.h:16
const Node none
Definition: node.cc:14
Definition: field.h:22
static Declaration createDollarDollarDeclaration(Type t)
Definition: keyword.h:64
Definition: meta.h:18
Definition: attribute.h:145
Definition: type.h:159
void cannot_be_reached() __attribute__((noreturn))
Definition: util.cc:32
Definition: uniquer.h:15
Definition: node-ref.h:44
Definition: unit-item.h:19
const auto & childs() const
Definition: node.h:470
Definition: hook.h:22
Definition: id.h:18
Definition: node.h:358