Spicy
function.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <algorithm>
6 #include <utility>
7 #include <vector>
8 
9 #include <hilti/ast/declarations/parameter.h>
10 #include <hilti/ast/expressions/void.h>
11 #include <hilti/ast/id.h>
12 #include <hilti/ast/type.h>
13 #include <hilti/ast/types/error.h>
14 #include <hilti/ast/types/operand-list.h>
15 #include <hilti/base/util.h>
16 
17 namespace hilti {
18 namespace type {
19 
20 namespace function {
21 
26 enum class Flavor {
27  Hook,
28  Method,
29  Standard
30 };
31 
32 namespace detail {
33 constexpr util::enum_::Value<Flavor> flavors[] = {
34  {Flavor::Hook, "hook"},
35  {Flavor::Method, "method"},
36  {Flavor::Standard, "standard"},
37 };
38 } // namespace detail
39 
40 constexpr auto to_string(Flavor f) { return util::enum_::to_string(f, detail::flavors); }
41 
42 namespace flavor {
43 constexpr auto from_string(const std::string_view& s) { return util::enum_::from_string<Flavor>(s, detail::flavors); }
44 } // namespace flavor
45 
47 class Result : public NodeBase {
48 public:
49  Result(Type type, Meta m = Meta()) : NodeBase(nodes(std::move(type)), std::move(m)) {}
50 
51  Result() : NodeBase(nodes(node::none), Meta()) {}
52 
53  const auto& type() const { return child<Type>(0); }
54 
55  void setType(const Type& x) { children()[0] = x; }
56 
57  bool operator==(const Result& other) const { return type() == other.type(); }
58 
60  auto properties() const { return node::Properties{}; }
61 };
62 
64 
65 namespace parameter {
66 using Kind = declaration::parameter::Kind;
67 } // namespace parameter
68 
69 } // namespace function
70 
72 public:
73  Function(Wildcard /*unused*/, Meta m = Meta())
74  : TypeBase(nodes(function::Result(type::Error(m))), std::move(m)), _wildcard(true) {}
75  Function(function::Result result, const std::vector<function::Parameter>& params,
76  function::Flavor flavor = function::Flavor::Standard, Meta m = Meta())
77  : TypeBase(nodes(std::move(result), util::transform(params, [](const auto& p) { return Declaration(p); })),
78  std::move(m)),
79  _flavor(flavor) {}
80 
81  const auto& result() const { return child<function::Result>(0); }
82  auto parameters() const { return children<function::Parameter>(1, -1); }
83  auto parameterRefs() const { return childRefsOfType<type::function::Parameter>(); }
84  auto flavor() const { return _flavor; }
85 
86  void setResultType(const Type& t) { children()[0].as<function::Result>().setType(t); }
87 
88  bool operator==(const Function& other) const {
89  return result() == other.result() && parameters() == other.parameters();
90  }
91 
93  auto isEqual(const Type& other) const { return node::isEqual(this, other); }
94 
96  auto _isResolved(ResolvedState* rstate) const {
97  if ( result().type().isA<type::Auto>() )
98  // We treat this as resolved because (1) it doesn't need to hold up
99  // other resolving, and (2) can lead to resolver dead-locks if we
100  // let it.
101  return true;
102 
103  if ( ! type::detail::isResolved(result().type(), rstate) )
104  return false;
105 
106  for ( auto p = children().begin() + 1; p != children().end(); p++ ) {
107  if ( ! p->as<function::Parameter>().isResolved(rstate) )
108  return false;
109  }
110 
111  return true;
112  }
113 
115  auto typeParameters() const { return children(); }
117  auto isWildcard() const { return _wildcard; }
118 
120  auto properties() const { return node::Properties{{"flavor", to_string(_flavor)}}; }
121 
122 private:
123  bool _wildcard = false;
124  function::Flavor _flavor = function::Flavor::Standard;
125 };
126 
131 inline bool areEquivalent(const Function& f1, const Function& f2) {
132  if ( ! (f1.result() == f2.result()) )
133  return false;
134 
135  auto p1 = f1.parameters();
136  auto p2 = f2.parameters();
137  return std::equal(std::begin(p1), std::end(p1), std::begin(p2), std::end(p2),
138  [](const auto& p1, const auto& p2) { return areEquivalent(p1, p2); });
139 }
140 
141 } // namespace type
142 
143 inline Node to_node(type::function::Result t) { return Node(std::move(t)); }
144 
145 } // namespace hilti
Definition: function.h:71
Definition: declaration.h:53
Definition: error.h:12
auto properties() const
Definition: function.h:60
Definition: function.h:47
auto properties() const
Definition: function.h:120
const Node none
Definition: node.cc:14
auto isWildcard() const
Definition: function.h:117
Definition: meta.h:19
Definition: type.h:158
Definition: parameter.h:46
auto _isResolved(ResolvedState *rstate) const
Definition: function.h:96
std::map< std::string, node::detail::PropertyValue > Properties
Definition: node.h:97
Definition: type.h:197
Definition: node.h:111
Definition: type.h:268
auto isEqual(const Type &other) const
Definition: function.h:93
auto typeParameters() const
Definition: function.h:115
Definition: node.h:359