My C++ sensible prelude.
1/* ========================================================================
2 *
3 * Filename: prelude.hpp
4 * Description: C++ sensible prelude - Declarations
5 * Author: Diego A. Estrada Rivera
6 * Version: 0.0.4
7 *
8 * ======================================================================== */
9#pragma once
10
11/* === Numeric Types === */
12#include <cstdint>
13#include <limits.h>
14using Size = std::size_t;
15
16/* Floating Point */
17// brain floating point
18// see https://en.wikipedia.org/wiki/Bfloat16_floating-point_format
19typedef __bf16 BF16;
20typedef _Float16 F16;
21typedef float F32;
22static_assert(sizeof(F32) * CHAR_BIT == 32); //
23typedef double F64;
24static_assert(sizeof(F64) * CHAR_BIT == 64);
25#if __float80_max < __float128_max
26 typedef __float80 F80; // sometimes is the same as F128
27#endif
28typedef __float128 F128;
29
30// decimal floating points
31// see decimal32/64/128 in https://en.wikipedia.org/wiki/IEEE_754
32//typedef float __attribute__((mode(SD))) D32;
33//typedef float __attribute__((mode(DD))) D64;
34//typedef float __attribute__((mode(TD))) D128;
35
36/* Integer */
37typedef uint8_t U8;
38typedef uint16_t U16;
39typedef uint32_t U32;
40typedef uint64_t U64;
41typedef __uint128_t U128;
42
43typedef int8_t I8;
44typedef int16_t I16;
45typedef int32_t I32;
46typedef int64_t I64;
47typedef __int128_t I128;
48
49// generic Integer type
50typedef int_fast32_t Int;
51
52/* === Other Types === */
53typedef bool Bool;
54typedef char Char;
55typedef const char * CString;
56
57#include <vector>
58template <typename T> using Vector = std::vector<T>;
59
60#include <string>
61using String = std::string;
62using namespace std::string_literals;
63
64// Unit type
65enum class Unit { unit };
66
67// Void type
68enum class Void {};
69
70// Pointer types
71template <typename T> using Ref = T&;
72
73template <typename T> using Handle = T*;
74
75/* === Keywords === */
76template <class T>
77concept Auto = true;
78#define let auto const
79#define var auto
80
81#define fn [[nodiscard, gnu::const]] auto
82#define proc [[nodiscard]] auto
83
84/* This is included as a static member variable of <tuple>.
85 * However, there is no way to bring the std::ignore namespace static variable
86 * into the current scope. This is a way to do that.
87 * https://en.cppreference.com/w/cpp/utility/tuple/ignore
88 */
89namespace detail {
90struct ignore_t {
91 template <typename T>
92 constexpr // required since C++14
93 void
94 operator = (T&&) const noexcept {}
95};
96} // namespace detail
97inline constinit const detail::ignore_t ignore; // changed to constinit
98
99// manage tuples better
100#define fst std::get<0>
101#define snd std::get<1>
102#define thr std::get<2>
103
104/* === Miscellaneous Functions */
105#include <concepts>
106#include <type_traits>
107#include <unordered_map>
108
109// key_hash comes from this stack overflow: https://stackoverflow.com/questions/20834838/using-tuple-in-unordered-map
110// this is necessary so we can index the hashmap using tuples
111template <class... Types> struct n_tuple_key_hash {
112 fn operator()(std::tuple<Types...> const& args) const noexcept -> size_t
113 {
114 return std::apply([](var... t) { return (t ^ ...); }, args);
115 }
116};
117
118template <class... Types> fn memoize(let&& op) noexcept
119{
120 static var mp =
121 std::unordered_map<std::tuple<Types...>,
122 std::invoke_result_t<decltype(op), Types...>,
123 n_tuple_key_hash<Types...>>();
124
125 return [&](Types... types) noexcept {
126 let& t = std::make_tuple(types...);
127 return mp.contains(t) ? mp.at(t) : mp[t] = op(types...);
128 };
129}
130
131/* Sensible IO */
132#include <iostream>
133proc getLine() noexcept -> String;
134
135proc getChar() noexcept -> Char;
136
137proc print(const std::string_view& f) noexcept -> Unit;
138
139proc println(const std::string_view& f) noexcept -> Unit;