Spicy
parameter.h
1 // Copyright (c) 2020-now by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <algorithm>
6 #include <string>
7 #include <string_view>
8 #include <utility>
9 
10 #include <hilti/ast/attribute.h>
11 #include <hilti/ast/declaration.h>
12 #include <hilti/ast/expression.h>
13 #include <hilti/ast/type.h>
14 #include <hilti/ast/types/auto.h>
15 #include <hilti/ast/types/unknown.h>
16 
17 namespace hilti::parameter {
18 
20 enum class Kind {
21  Unknown,
22  Copy,
23  In,
24  InOut
25 };
26 
27 namespace detail {
28 constexpr util::enum_::Value<Kind> Kinds[] = {
29  {.value = Kind::Unknown, .name = "unknown"},
30  {.value = Kind::Copy, .name = "copy"},
31  {.value = Kind::In, .name = "in"},
32  {.value = Kind::InOut, .name = "inout"},
33 };
34 } // namespace detail
35 
36 constexpr auto to_string(Kind k) { return util::enum_::to_string(k, detail::Kinds); }
37 
38 namespace kind {
39 constexpr auto from_string(std::string_view s) { return util::enum_::from_string<Kind>(s, detail::Kinds); }
40 } // namespace kind
41 
42 } // namespace hilti::parameter
43 
44 namespace hilti::declaration {
45 
47 class Parameter : public Declaration {
48 public:
49  auto attributes() const { return child<AttributeSet>(2); }
50  auto default_() const { return child<hilti::Expression>(1); }
51  auto kind() const { return _kind; }
52  auto type() const { return child<hilti::QualifiedType>(0); }
53  auto isTypeParameter() const { return _is_type_param; }
54  auto isResolved(node::CycleDetector* cd = nullptr) const { return type()->isResolved(cd); }
55 
56  void setDefault(ASTContext* ctx, hilti::Expression* e) { setChild(ctx, 1, e); }
57  void setIsTypeParameter() { _is_type_param = true; }
58  void setType(ASTContext* ctx, QualifiedType* t) { setChild(ctx, 0, t); }
59 
60  std::string_view displayName() const final { return "parameter"; }
61 
62  node::Properties properties() const final {
63  auto p = node::Properties{{"kind", to_string(_kind)}, {"is_type_param", _is_type_param}};
64  return Declaration::properties() + std::move(p);
65  }
66 
67  static auto create(ASTContext* ctx,
68  ID id,
69  UnqualifiedType* type,
70  parameter::Kind kind,
71  hilti::Expression* default_,
72  AttributeSet* attrs,
73  Meta meta = {}) {
74  if ( ! attrs )
75  attrs = AttributeSet::create(ctx);
76 
77  return ctx->make<Parameter>(ctx,
78  {_qtype(ctx, type, kind), default_, attrs},
79  std::move(id),
80  kind,
81  false,
82  std::move(meta));
83  }
84 
85  static auto create(ASTContext* ctx,
86  ID id,
87  UnqualifiedType* type,
88  parameter::Kind kind,
89  hilti::Expression* default_,
90  bool is_type_param,
91  AttributeSet* attrs,
92  Meta meta = {}) {
93  if ( ! attrs )
94  attrs = AttributeSet::create(ctx);
95 
96  return ctx->make<Parameter>(ctx,
97  {_qtype(ctx, type, kind), default_, attrs},
98  std::move(id),
99  kind,
100  is_type_param,
101  std::move(meta));
102  }
103 
104 protected:
105  Parameter(ASTContext* ctx, Nodes children, ID id, parameter::Kind kind, bool is_type_param, Meta meta)
106  : Declaration(ctx, NodeTags, std::move(children), std::move(id), Linkage::Private, std::move(meta)),
107  _kind(kind),
108  _is_type_param(is_type_param) {}
109 
110  std::string _dump() const override { return isResolved() ? "(resolved)" : "(not resolved)"; }
111 
112  HILTI_NODE_1(declaration::Parameter, Declaration, final);
113 
114 private:
115  static QualifiedType* _qtype(ASTContext* ctx, UnqualifiedType* t, parameter::Kind kind) {
116  switch ( kind ) {
117  case parameter::Kind::Copy: return QualifiedType::create(ctx, t, Constness::Mutable, Side::LHS, t->meta());
118  case parameter::Kind::In: return QualifiedType::create(ctx, t, Constness::Const, Side::RHS, t->meta());
119  case parameter::Kind::InOut: return QualifiedType::create(ctx, t, Constness::Mutable, Side::LHS, t->meta());
120  default:
121  return QualifiedType::create(ctx, type::Unknown::create(ctx), Constness::Const, Side::RHS, t->meta());
122  }
123  }
124 
125  parameter::Kind _kind = parameter::Kind::Unknown;
126  bool _is_type_param = false;
127 };
128 
129 using Parameters = NodeVector<Parameter>;
130 
131 } // namespace hilti::declaration
132 
133 namespace hilti::declaration {
134 
136 inline bool areEquivalent(Parameter* p1, Parameter* p2) {
137  if ( p1->kind() != p2->kind() )
138  return false;
139 
140  if ( (p1->default_() && ! p2->default_()) || (p2->default_() && ! p1->default_()) )
141  return false;
142 
143  if ( p1->default_() && p2->default_() && p1->default_()->print() != p2->default_()->print() )
144  return false;
145 
146  auto auto1 = p1->type()->type()->isA<type::Auto>();
147  auto auto2 = p2->type()->type()->isA<type::Auto>();
148 
149  if ( auto1 || auto2 )
150  return true;
151 
152  return type::same(p1->type(), p2->type());
153 }
154 
156 inline bool areEquivalent(const node::Set<Parameter>& params1, const node::Set<Parameter>& params2) {
157  return std::ranges::equal(params1, params2, [](const auto& p1, const auto& p2) { return areEquivalent(p1, p2); });
158 }
159 
160 } // namespace hilti::declaration
Definition: ast-context.h:128
T * make(Args &&... args)
Definition: ast-context.h:382
Definition: attribute.h:200
Definition: declaration.h:53
node::Properties properties() const override
Definition: declaration.h:126
const auto & id() const
Definition: declaration.h:58
Definition: expression.h:15
Definition: id.h:15
Definition: meta.h:30
void setChild(ASTContext *ctx, size_t idx, Node *n)
Definition: node.h:631
const auto & children() const
Definition: node.h:382
const auto & meta() const
Definition: node.h:324
Definition: type.h:365
static auto create(ASTContext *ctx, UnqualifiedType *t, Constness const_, Meta m=Meta())
Definition: type.h:436
Definition: type.h:147
Definition: parameter.h:47
std::string _dump() const override
Definition: parameter.h:110
node::Properties properties() const final
Definition: parameter.h:62
std::string_view displayName() const final
Definition: parameter.h:60
Definition: node.h:1191