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, ID id, UnqualifiedType* type, parameter::Kind kind, hilti::Expression* default_,
68  AttributeSet* attrs, Meta meta = {}) {
69  if ( ! attrs )
70  attrs = AttributeSet::create(ctx);
71 
72  return ctx->make<Parameter>(ctx, {_qtype(ctx, type, kind), default_, attrs}, std::move(id), kind, false,
73  std::move(meta));
74  }
75 
76  static auto create(ASTContext* ctx, ID id, UnqualifiedType* type, parameter::Kind kind, hilti::Expression* default_,
77  bool is_type_param, AttributeSet* attrs, Meta meta = {}) {
78  if ( ! attrs )
79  attrs = AttributeSet::create(ctx);
80 
81  return ctx->make<Parameter>(ctx, {_qtype(ctx, type, kind), default_, attrs}, std::move(id), kind, is_type_param,
82  std::move(meta));
83  }
84 
85 protected:
86  Parameter(ASTContext* ctx, Nodes children, ID id, parameter::Kind kind, bool is_type_param, Meta meta)
87  : Declaration(ctx, NodeTags, std::move(children), std::move(id), Linkage::Private, std::move(meta)),
88  _kind(kind),
89  _is_type_param(is_type_param) {}
90 
91  std::string _dump() const override { return isResolved() ? "(resolved)" : "(not resolved)"; }
92 
93  HILTI_NODE_1(declaration::Parameter, Declaration, final);
94 
95 private:
96  static QualifiedType* _qtype(ASTContext* ctx, UnqualifiedType* t, parameter::Kind kind) {
97  switch ( kind ) {
98  case parameter::Kind::Copy: return QualifiedType::create(ctx, t, Constness::Mutable, Side::LHS, t->meta());
99  case parameter::Kind::In: return QualifiedType::create(ctx, t, Constness::Const, Side::RHS, t->meta());
100  case parameter::Kind::InOut: return QualifiedType::create(ctx, t, Constness::Mutable, Side::LHS, t->meta());
101  default:
102  return QualifiedType::create(ctx, type::Unknown::create(ctx), Constness::Const, Side::RHS, t->meta());
103  }
104  }
105 
106  parameter::Kind _kind = parameter::Kind::Unknown;
107  bool _is_type_param = false;
108 };
109 
110 using Parameters = NodeVector<Parameter>;
111 
112 } // namespace hilti::declaration
113 
114 namespace hilti::declaration {
115 
117 inline bool areEquivalent(Parameter* p1, Parameter* p2) {
118  if ( p1->kind() != p2->kind() )
119  return false;
120 
121  if ( (p1->default_() && ! p2->default_()) || (p2->default_() && ! p1->default_()) )
122  return false;
123 
124  if ( p1->default_() && p2->default_() && p1->default_()->print() != p2->default_()->print() )
125  return false;
126 
127  auto auto1 = p1->type()->type()->isA<type::Auto>();
128  auto auto2 = p2->type()->type()->isA<type::Auto>();
129 
130  if ( auto1 || auto2 )
131  return true;
132 
133  return type::same(p1->type(), p2->type());
134 }
135 
137 inline bool areEquivalent(const node::Set<Parameter>& params1, const node::Set<Parameter>& params2) {
138  return std::ranges::equal(params1, params2, [](const auto& p1, const auto& p2) { return areEquivalent(p1, p2); });
139 }
140 
141 } // namespace hilti::declaration
Definition: ast-context.h:121
T * make(Args &&... args)
Definition: ast-context.h:366
Definition: attribute.h:200
Definition: declaration.h:48
node::Properties properties() const override
Definition: declaration.h:116
const auto & id() const
Definition: declaration.h:53
Definition: expression.h:15
Definition: id.h:15
Definition: meta.h:30
void setChild(ASTContext *ctx, size_t idx, Node *n)
Definition: node.h:602
const auto & children() const
Definition: node.h:364
const auto & meta() const
Definition: node.h:306
Definition: type.h:362
static auto create(ASTContext *ctx, UnqualifiedType *t, Constness const_, Meta m=Meta())
Definition: type.h:427
Definition: type.h:148
Definition: parameter.h:47
std::string _dump() const override
Definition: parameter.h:91
node::Properties properties() const final
Definition: parameter.h:62
std::string_view displayName() const final
Definition: parameter.h:60
Definition: node.h:1122