Spicy
unit.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <algorithm>
6 #include <memory>
7 #include <optional>
8 #include <set>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include <hilti/ast/declarations/expression.h>
14 #include <hilti/ast/expressions/grouping.h>
15 #include <hilti/ast/expressions/keyword.h>
16 #include <hilti/ast/expressions/type.h>
17 #include <hilti/ast/types/reference.h>
18 
19 #include <spicy/ast/types/unit-item.h>
20 #include <spicy/ast/types/unit-items/field.h>
21 #include <spicy/ast/types/unit-items/property.h>
22 #include <spicy/ast/types/unit-items/switch.h>
23 #include <spicy/ast/types/unit-items/unresolved-field.h>
24 #include <spicy/compiler/detail/codegen/grammar.h>
25 
26 namespace spicy {
27 
28 namespace detail::codegen {
29 class Grammar;
30 } // namespace detail::codegen
31 
32 namespace type {
33 
34 namespace detail {
43 struct AssignIndices {
50  std::vector<unit::Item> assignIndices(std::vector<unit::Item> items);
51 
52  uint64_t _next_index = 0;
53 };
54 } // namespace detail
55 
58  public hilti::TypeBase,
63 public:
64  Unit(std::vector<type::function::Parameter> params, std::vector<unit::Item> i,
65  const std::optional<AttributeSet>& /* attrs */ = {}, Meta m = Meta())
66  : TypeBase(hilti::nodes(node::none, node::none, node::none,
67  hilti::util::transform(params,
68  [](auto p) {
69  p.setIsTypeParameter();
70  return Declaration(p);
71  }),
72  assignIndices(std::move(i))),
73  std::move(m)) {}
74 
75  Unit(Wildcard /*unused*/, Meta m = Meta()) : TypeBase(std::move(m)), _wildcard(true) {}
76 
77  NodeRef selfRef() const {
78  if ( childs()[0].isA<Declaration>() )
79  return NodeRef(childs()[0]);
80  else
81  return {};
82  }
83 
84  auto id() const { return childs()[1].tryAs<ID>(); }
85  auto parameters() const { return childsOfType<type::function::Parameter>(); }
86  auto parameterRefs() const { return childRefsOfType<type::function::Parameter>(); }
87  auto items() const { return childsOfType<unit::Item>(); }
88  auto itemRefs() const { return childRefsOfType<unit::Item>(); }
89  auto attributes() const { return childs()[2].tryAs<AttributeSet>(); }
90 
93  if ( auto context = propertyItem("%context") )
94  return context->expression()->as<hilti::expression::Type_>().typeValue();
95  else
96  return {};
97  }
98 
103  hilti::optional_ref<const type::unit::Item> itemByName(const ID& id) const;
104 
106  NodeRef itemRefByName(const ID& id) const;
107 
111  template<typename T>
112  auto items() const {
113  return childsOfType<T>();
114  }
115 
121  for ( const auto& i : items<unit::item::Property>() ) {
122  if ( i.id() == name )
123  return i;
124  }
125 
126  return {};
127  }
128 
130  auto propertyItems(const std::string& name) const {
132 
133  for ( const auto& i : items<unit::item::Property>() ) {
134  if ( i.id() == name )
135  props.insert(i);
136  }
137 
138  return props;
139  }
140 
145  auto isPublic() const { return _public; };
146 
156  bool usesRandomAccess() const { return propertyItem("%random-access").has_value(); }
157 
165  bool supportsSinks() const { return isPublic(); }
166 
174  bool supportsFilters() const { return isPublic(); }
175 
183  bool isFilter() const { return propertyItem("%filter").has_value(); }
184 
188  assert(_grammar);
189  return *_grammar;
190  }
191 
193  void addItems(std::vector<unit::Item> items) {
194  auto new_items = assignIndices(items);
195 
196  for ( auto i : new_items )
197  childs().emplace_back(std::move(i));
198  }
199 
200  void setAttributes(AttributeSet attrs) { childs()[2] = std::move(attrs); }
201  void setGrammar(std::shared_ptr<spicy::detail::codegen::Grammar> g) { _grammar = std::move(g); }
202  void setID(ID id) { childs()[1] = std::move(id); }
203  void setPublic(bool p) { _public = p; }
204 
205  bool operator==(const Unit& other) const {
206  // We treat units as equal (only) if their type IDs match. That's
207  // checked upstream in the Type's comparision operator.
208  return false;
209  }
210 
211  // Type interface.
212  auto isEqual(const Type& other) const { return node::isEqual(this, other); }
213 
214  auto _isResolved(ResolvedState* rstate) const {
215  for ( const auto& i : items() ) {
216  if ( ! i.isResolved() )
217  return false;
218  }
219 
220  return true;
221  }
222 
223  // type::trait::Parameterized interface.
224  auto typeParameters() const { return childs(); }
225  auto isWildcard() const { return _wildcard; }
226 
227  // Node interface.
228  auto properties() const { return node::Properties{{"public", _public}}; }
229 
236  static void setSelf(Node* n) {
237  assert(n->isA<type::Unit>());
238  Expression self = hilti::expression::Keyword(hilti::expression::keyword::Kind::Self,
239  StrongReference(hilti::type::pruneWalk(n->as<Type>())), n->meta());
240  Declaration d =
241  hilti::declaration::Expression("self", std::move(self), declaration::Linkage::Private, n->meta());
242  n->childs()[0] = std::move(d);
243  }
244 
245 private:
246  bool _public = false;
247  bool _wildcard = false;
248  std::shared_ptr<spicy::detail::codegen::Grammar> _grammar;
249 };
250 
251 
252 } // namespace type
253 } // namespace spicy
Definition: type.h:14
bool supportsSinks() const
Definition: unit.h:165
bool supportsFilters() const
Definition: unit.h:174
auto items() const
Definition: unit.h:112
Definition: declaration.h:53
const spicy::detail::codegen::Grammar & grammar() const
Definition: unit.h:187
auto propertyItems(const std::string &name) const
Definition: unit.h:130
Definition: keyword.h:39
Definition: unit.h:57
Definition: reference.h:16
Definition: type.h:37
static void setSelf(Node *n)
Definition: unit.h:236
Definition: meta.h:18
Definition: attribute.h:145
Definition: type.h:159
Definition: expression.h:17
Definition: optional-ref.h:22
Definition: node.h:42
auto isPublic() const
Definition: unit.h:145
bool usesRandomAccess() const
Definition: unit.h:156
Definition: type.h:198
void addItems(std::vector< unit::Item > items)
Definition: unit.h:193
bool isFilter() const
Definition: unit.h:183
hilti::optional_ref< const unit::item::Property > propertyItem(const std::string &name) const
Definition: unit.h:120
Definition: node.h:113
Definition: node-ref.h:44
Definition: type.h:33
Definition: type.h:269
Definition: grammar.h:21
Definition: id.h:18
hilti::optional_ref< const Type > contextType() const
Definition: unit.h:92