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(const 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 ( children()[0].isA<Declaration>() )
79  return NodeRef(children()[0]);
80  else
81  return {};
82  }
83 
84  auto id() const { return children()[1].tryAs<ID>(); }
85  auto parameters() const { return childrenOfType<type::function::Parameter>(); }
86  auto parameterRefs() const { return childRefsOfType<type::function::Parameter>(); }
87  auto items() const { return childrenOfType<unit::Item>(); }
88  auto itemRefs() const { return childRefsOfType<unit::Item>(); }
89  auto attributes() const { return children()[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 childrenOfType<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 
154  bool isFilter() const { return propertyItem("%filter").has_value(); }
155 
159  assert(_grammar);
160  return *_grammar;
161  }
162 
164  void addItems(std::vector<unit::Item> items) {
165  auto new_items = assignIndices(std::move(items));
166 
167  for ( auto i : new_items )
168  children().emplace_back(std::move(i));
169  }
170 
171  void setAttributes(const AttributeSet& attrs) { children()[2] = attrs; }
172  void setGrammar(std::shared_ptr<spicy::detail::codegen::Grammar> g) { _grammar = std::move(g); }
173  void setID(const ID& id) { children()[1] = id; }
174  void setPublic(bool p) { _public = p; }
175 
176  bool operator==(const Unit& other) const {
177  // We treat units as equal (only) if their type IDs match. That's
178  // checked upstream in the Type's comparison operator.
179  return false;
180  }
181 
182  // Type interface.
183  auto isEqual(const Type& other) const { return node::isEqual(this, other); }
184 
185  auto _isResolved(ResolvedState* rstate) const {
186  auto xs = items();
187  return std::all_of(xs.begin(), xs.end(), [](const auto& x) { return x.isResolved(); });
188  }
189 
190  // type::trait::Parameterized interface.
191  auto typeParameters() const { return children(); }
192  auto isWildcard() const { return _wildcard; }
193 
194  // Node interface.
195  auto properties() const { return node::Properties{{"public", _public}}; }
196 
203  static void setSelf(Node* n) {
204  assert(n->isA<type::Unit>());
205  Expression self = hilti::expression::Keyword(hilti::expression::keyword::Kind::Self,
206  hilti::type::pruneWalk(n->as<Type>()), n->meta());
207  Declaration d =
208  hilti::declaration::Expression("self", std::move(self), declaration::Linkage::Private, n->meta());
209  n->children()[0] = d;
210  }
211 
212 private:
213  bool _public = false;
214  bool _wildcard = false;
215  std::shared_ptr<spicy::detail::codegen::Grammar> _grammar;
216 };
217 
218 
219 } // namespace type
220 } // namespace spicy
Definition: type.h:13
auto items() const
Definition: unit.h:112
Definition: declaration.h:54
const spicy::detail::codegen::Grammar & grammar() const
Definition: unit.h:158
auto propertyItems(const std::string &name) const
Definition: unit.h:130
Definition: keyword.h:42
Definition: unit.h:57
Definition: type.h:38
static void setSelf(Node *n)
Definition: unit.h:203
Definition: meta.h:19
Definition: attribute.h:174
Definition: type.h:160
Definition: expression.h:16
Definition: optional-ref.h:22
Definition: node.h:41
auto isPublic() const
Definition: unit.h:145
Definition: type.h:206
void addItems(std::vector< unit::Item > items)
Definition: unit.h:164
bool isFilter() const
Definition: unit.h:154
hilti::optional_ref< const unit::item::Property > propertyItem(const std::string &name) const
Definition: unit.h:120
Definition: node.h:112
Definition: node-ref.h:45
Definition: type.h:33
Definition: type.h:277
Definition: grammar.h:21
Definition: id.h:18
hilti::optional_ref< const Type > contextType() const
Definition: unit.h:92