Yume
util.hpp
Go to the documentation of this file.
1#pragma once
2
4#include <array>
5#include <cstddef>
6#include <filesystem>
7#include <llvm/Support/Casting.h>
8#include <llvm/Support/FileSystem.h>
9#include <llvm/Support/raw_ostream.h>
10#include <memory>
11#include <numbers>
12#include <optional>
13#include <set>
14#include <span>
15#include <sstream>
16#include <string_view>
17#include <tuple>
18#include <type_traits>
19#include <utility>
20#include <variant>
21#include <vector>
22
23namespace yume {
24using namespace std::literals::string_literals;
25using namespace std::literals::string_view_literals;
26namespace fs = std::filesystem;
27using std::array;
28using std::optional;
29using std::span;
30using std::string;
31using std::string_view;
32using std::stringstream;
33using std::tuple;
34using std::unique_ptr;
35using std::variant;
36using std::vector;
37
38using llvm::cast;
39using llvm::dyn_cast;
40using llvm::errs;
41using llvm::isa;
42using std::move;
43
44template <typename... Ts>
45struct visitable_variant : public std::variant<Ts...> { // NOLINT(readability-identifier-naming): STL-like class
46private:
47 template <typename... Vs> struct Visitor : Vs... {
48 using Vs::operator()...;
49 };
50 template <typename... Vs> Visitor(Vs...) -> Visitor<Vs...>;
51
52public:
53 using std::variant<Ts...>::variant;
54
55 template <typename... Us> auto visit(Us... us) -> decltype(auto) { return std::visit(Visitor<Us...>{us...}, *this); }
56 template <typename... Us> [[nodiscard]] auto visit(Us... us) const -> decltype(auto) {
57 return std::visit(Visitor<Us...>{us...}, *this);
58 }
59};
60
61template <typename T>
62concept visitable = requires(T t) {
63 {
64 t.visit([](auto&&) {})
65 };
66 };
67
68#if __has_feature(nullability)
69template <typename T> using nullable = T _Nullable;
70template <typename T> using nonnull = T _Nonnull;
71#else
72template <typename T> using nullable = T;
73template <typename T> using nonnull = T;
74#endif
75
76#ifdef NDEBUG
77// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
78#define YUME_ASSERT(...) ((void)0);
79#else
80// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
81#define YUME_ASSERT(assertion, message) (static_cast<bool>(assertion) ? ((void)0) : yume_assert_failure(message))
82#endif
83
84[[noreturn]] inline void yume_assert_failure(const std::string_view log_msg = {},
85 const source_location location = source_location::current()) noexcept {
86 llvm::errs() << "*** assertion failed: " << at(location) << " " << log_msg << '\n';
87 std::abort();
88}
89
90/// Opens a writeable stream to a file with the given filename relative to the current working directory.
91auto inline open_file(nonnull<const char*> filename) -> unique_ptr<llvm::raw_pwrite_stream> {
92 std::error_code error_code;
93 auto dest =
94 std::make_unique<llvm::raw_fd_ostream>(filename, error_code, llvm::sys::fs::CreationDisposition::CD_CreateAlways);
95
96 if (error_code) {
97 llvm::errs() << "Could not open file: " << error_code.message() << "\n";
98 throw;
99 }
100
101 return dest;
102}
103
104template <size_t N> struct StringLiteral {
105 // NOLINTNEXTLINE(modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
106 constexpr StringLiteral(const char (&str)[N]) { std::copy_n(str, N, value); }
107
108 char value[N]{}; // NOLINT(modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
109 auto operator<=>(const StringLiteral&) const = default;
110};
111
112template <typename T> static void hash_combine(uint64_t& seed, const T& v) {
113 static constexpr auto PHI_FRAC = std::numbers::phi_v<long double> - 1;
114 static constexpr auto ALL_BITS = std::numeric_limits<std::size_t>::max();
115 static constexpr auto FLOATING_HASH_CONST = PHI_FRAC * ALL_BITS;
116 static constexpr auto HASH_CONST = static_cast<std::size_t>(FLOATING_HASH_CONST);
117 static constexpr auto TWIST_LEFT = 6;
118 static constexpr auto TWIST_RIGHT = 2;
119
120 std::hash<T> hasher;
121 seed ^= hasher(v) + HASH_CONST + (seed << TWIST_LEFT) + (seed >> TWIST_RIGHT);
122}
123
124} // namespace yume
Definition: ast.cpp:8
T nullable
Definition: util.hpp:72
auto at(const source_location location=source_location::current()) -> std::string
auto open_file(nonnull< const char * > filename) -> unique_ptr< llvm::raw_pwrite_stream >
Opens a writeable stream to a file with the given filename relative to the current working directory.
Definition: util.hpp:91
T nonnull
Definition: util.hpp:73
void yume_assert_failure(const std::string_view log_msg={}, const source_location location=source_location::current()) noexcept
Definition: util.hpp:84
static void hash_combine(uint64_t &seed, const T &v)
Definition: util.hpp:112
constexpr StringLiteral(const char(&str)[N])
Definition: util.hpp:106
auto operator<=>(const StringLiteral &) const =default
static constexpr auto current()
auto visit(Us... us) const -> decltype(auto)
Definition: util.hpp:56
auto visit(Us... us) -> decltype(auto)
Definition: util.hpp:55