-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompile_time_context.hpp
128 lines (110 loc) · 4.62 KB
/
compile_time_context.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#pragma once
#include "allocator.hpp"
#include "auto_definition.hpp"
#include "mutils/cstring.hpp"
#include "utils.hpp"
namespace compile_time {
#ifdef ALLOCATOR_SIZE
constexpr inline std::size_t allocator_size = ALLOCATOR_SIZE;
#else
constexpr inline std::size_t allocator_size = 100;
#endif
namespace ctctx {
template <typename top, typename... specs>
using Allocator =
compile_time::Allocator<allocator_size, value::convert_to_instance_t<top>,
value::convert_to_instance_t<specs>...>;
template <typename Allocator_holder> struct i {
using Allocator = DECT(Allocator_holder::allocator);
static const constexpr Allocator &allocator{Allocator_holder::allocator};
template <typename Fvalue> static constexpr auto convert_to_type_f();
template <typename Fvalue>
using convert_to_type = typename DECT(convert_to_type_f<Fvalue>().value);
};
template <typename T, typename A> constexpr decltype(auto) allocate(A &&a) {
return a.template allocate<value::convert_to_instance_t<T>>();
}
template <typename T, typename A>
constexpr decltype(auto) get_single_allocator(A &&a) {
return a.template get<value::convert_to_instance_t<T>>();
}
template <typename top, typename... specs> struct compile_time_workspace {
template <typename T> using ct = value::convert_to_instance_t<T>;
using Allocator =
::compile_time::ctctx::Allocator<maybe_error<ct<top>>, specs...>;
Allocator allocator{};
DECT(allocator.top) & value{allocator.top};
constexpr compile_time_workspace() = default;
constexpr compile_time_workspace(const compile_time_workspace &) = default;
constexpr compile_time_workspace(compile_time_workspace &&) = default;
constexpr compile_time_workspace &
operator=(const compile_time_workspace &) = default;
constexpr compile_time_workspace &
operator=(compile_time_workspace &&) = default;
template <typename T> constexpr decltype(auto) allocate() {
static_assert(((std::is_same_v<specs, T>)+... + 0) == 1,
"Error: attempt to allocate unregistered type");
return ctctx::allocate<T>(allocator);
}
template <typename T> constexpr decltype(auto) single_allocator() {
static_assert(((std::is_same_v<specs, T>)+... + 0) == 1,
"Error: attempt to use unregistered type");
return allocator.template as_single_allocator<ct<T>>();
}
template <typename T> constexpr decltype(auto) top_allocate() {
static_assert(((std::is_same_v<specs, T>)+... + 0) == 1,
"Error: attempt to use unregistered type");
value::top_pointer ret;
ret.set(allocate<T>(), single_allocator<T>());
return ret;
}
template <typename T>
constexpr decltype(auto) deref(value::pointer<value::instance<T>> &p) {
static_assert(((std::is_same_v<specs, T>)+... + 0) == 1,
"Error: attempt to use unregistered type");
return p.get(allocator);
}
template <typename T>
constexpr decltype(auto) deref_as(value::top_pointer &p) {
static_assert(((std::is_same_v<specs, T>)+... + 0) == 1,
"Error: attempt to use unregistered type");
using target = value::instance<T>;
assert(p.template is_this_type<target>(allocator));
auto &sa = allocator.template as_single_allocator<target>();
return p.get(sa);
}
template <typename T> constexpr bool is(value::top_pointer &p) const {
return p.template is_this_type<value::instance<T>>(allocator);
}
template <typename T>
constexpr decltype(auto) set_pointer(value::top_pointer e,
value::pointer<value::instance<T>> &&p) {
static_assert(((std::is_same_v<specs, T>)+... + 0) == 1,
"Error: attempt to use unregistered type");
return e.set(std::move(p), single_allocator<T>());
}
template <typename T>
constexpr decltype(auto) upcast(value::pointer<value::instance<T>> &&p) {
return value::top_pointer{std::move(p), single_allocator<T>()};
}
template <typename T> constexpr decltype(auto) set_return(T &&t) {
allocator.top.value = t;
}
constexpr ct<top> ¤t_return() { return allocator.top.value; }
constexpr void error(const char *str) {
mutils::cstring::str_cpy(allocator.top.error.msg, str);
allocator.top.error_set = true;
}
template <typename... T>
constexpr void error(const char *str1, const char *str2, T &&... more_strs) {
using namespace mutils::cstring;
using str_nc = char[1000];
str_nc combined = {0};
combine_strings(combined, str1, str2);
error(combined, std::forward<T>(more_strs)...);
}
};
} // namespace ctctx
template <typename Allocator_holder>
using compile_time_context = ctctx::i<Allocator_holder>;
} // namespace compile_time