-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconvert_to_type.hpp
207 lines (193 loc) · 7.23 KB
/
convert_to_type.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#pragma once
#include "compile_time_context.hpp"
#include "mutils/CTString.hpp"
#include "mutils/cstring.hpp"
#include "specification.hpp"
#include "types.hpp"
#include <tuple>
namespace compile_time {
namespace types {
template <typename T, typename... fields> struct instance_build {
constexpr instance_build() = default;
template <typename... morefields>
constexpr static auto append(instance_build<T, morefields...>) {
return instance_build<T, fields..., morefields...>{};
}
};
} // namespace types
namespace value_to_type {
using namespace value;
template <typename FValue, std::size_t field> struct get_field {
constexpr static auto &value = FValue::value.template get<field>();
constexpr auto &operator()() const { return value; }
};
template <typename FValue> struct simple_wrapper {
static constexpr const DECT(FValue::value) &value = FValue::value;
constexpr simple_wrapper() = default;
constexpr auto &operator()() const { return value; }
};
template <typename T1, typename... T>
constexpr types::instance<T1, T...> *instance_indirection() {
return nullptr;
}
template <typename FValue, typename ctcx, typename T, std::size_t... indexes>
constexpr auto
convert_to_type_instance(const typename ctcx::Allocator &debug_allocator,
std::integer_sequence<std::size_t, indexes...>) {
using Value = simple_wrapper<FValue>;
// DEBUG
(void)debug_allocator;
((ctcx::template convert_to_type_f<get_field<Value, indexes>>()), ...);
struct_wrap(
return_t,
types::instance<
T, DECT(ctcx::template convert_to_type_f<get_field<Value, indexes>>()
.value)...>{};);
return simple_wrapper<return_t>{};
}
template <typename FValue, typename Allocator_holder, typename T>
constexpr auto convert_to_type_f(
const typename compile_time_context<Allocator_holder>::Allocator
&debug_allocator,
instance<T> const *const inst) {
(void)inst;
using ctctx = compile_time_context<Allocator_holder>;
return convert_to_type_instance<FValue, ctctx, T>(
debug_allocator, std::make_index_sequence<struct_size<T>>{});
}
template <typename FValue, typename ctcx, std::size_t size, typename top,
typename spec1, typename... specs>
constexpr auto convert_to_type_erased_ref(
const typename ctcx::Allocator &debug_allocator,
compile_time::Allocator<size, top, spec1, specs...> * = nullptr) {
if constexpr (FValue{}()) {
constexpr auto &ptr = FValue::value;
if constexpr (ptr.template is_this_type<spec1>(ctcx::allocator)) {
auto &as_single_allocator =
ctcx::allocator.template as_single_allocator<spec1>();
auto &value = FValue::value;
auto &gotten = value.get(as_single_allocator);
(void)gotten;
(void)value;
(void)as_single_allocator;
struct_wrap(converted,
FValue::value.get(
ctcx::allocator.template as_single_allocator<spec1>()));
auto converted_value = converted{}();
(void)converted_value;
using wrapped = simple_wrapper<converted>;
auto wrapped_value = wrapped::value;
(void)wrapped_value;
return ctcx::template convert_to_type_f<wrapped>();
} else
return convert_to_type_erased_ref<FValue, ctcx, size, top, specs...>(
debug_allocator);
// no base-case, because we should never run past the end of this list!
} else {
struct_wrap(ret, types::null_type{});
return simple_wrapper<ret>{};
}
}
template <typename FValue, typename Allocator_holder>
constexpr auto convert_to_type_f(
const typename compile_time_context<Allocator_holder>::Allocator
&debug_allocator,
erased_ref const *const) {
using ctcx = compile_time_context<Allocator_holder>;
return convert_to_type_erased_ref<FValue, ctcx>(
debug_allocator, (typename ctcx::Allocator *)nullptr);
}
template <typename FValue, typename Allocator_holder, typename T>
constexpr auto convert_to_type_f(
const typename compile_time_context<Allocator_holder>::Allocator
&debug_allocator,
allocated_ref<T> const *const) {
using ctcx = compile_time_context<Allocator_holder>;
struct_wrap(
converted,
FValue::value.get(ctcx::allocator.template as_single_allocator<T>()));
using wrapped = simple_wrapper<converted>;
return ctcx::template convert_to_type_f<wrapped>(debug_allocator);
}
template <typename FValue, typename Allocator_holder>
constexpr auto convert_to_type_f(
const typename compile_time_context<Allocator_holder>::Allocator
&debug_allocator,
string const *const) {
struct val {
constexpr val() = default;
constexpr const char *operator()() const { return FValue{}.value.strbuf; }
};
struct_wrap(ret, mutils::cstring::build_type_string<val>());
return simple_wrapper<ret>{};
(void)debug_allocator;
}
template <typename FValue, typename Allocator_holder, typename T,
std::size_t offset>
constexpr auto
convert_list(const typename compile_time_context<Allocator_holder>::Allocator
&debug_allocator = Allocator_holder::allocator) {
if constexpr (offset == FValue{}.value.size) {
return types::list<>{};
} else {
using ctcx = compile_time_context<Allocator_holder>;
struct_wrap(converted, FValue::value.values[offset]);
using wrapped = simple_wrapper<converted>;
using curr = typename ctcx::template convert_to_type<wrapped>;
auto next =
convert_list<FValue, Allocator_holder, T, offset + 1>(debug_allocator);
return types::list<curr>::append(next);
}
}
template <typename FValue, typename Allocator_holder, typename T,
std::size_t offset = 0>
constexpr auto convert_to_type_f(
const typename compile_time_context<Allocator_holder>::Allocator
&debug_allocator,
list<T> const *const,
std::integral_constant<std::size_t, offset> * = nullptr) {
(void)debug_allocator;
struct_wrap(ret, convert_list<FValue, Allocator_holder, T, offset>());
return simple_wrapper<ret>{};
}
template <typename FValue, typename Allocator_holder, typename T>
constexpr auto convert_to_type_f(
const typename compile_time_context<Allocator_holder>::Allocator
&debug_allocator,
maybe_error<T> const *const) {
if constexpr (!FValue{}.value.error_set) {
struct_wrap(ret, FValue{}.value.value);
return convert_to_type_f<simple_wrapper<ret>, Allocator_holder>(
debug_allocator, &FValue{}.value.value);
} else {
struct_wrap(err, FValue{}.value.error);
struct return_t {
types::error_from_value_error<err> value{};
constexpr return_t() = default;
};
return return_t{};
}
}
} // namespace value_to_type
namespace ctctx {
template <typename Allocator_holder>
template <typename FValue>
constexpr auto i<Allocator_holder>::convert_to_type_f() {
// debug
auto &allocator_ref = allocator;
using namespace value_to_type;
constexpr const auto &value = FValue::value;
using value_t = DECT(value);
if constexpr (specification::is_permitted_raw<value_t>) {
constexpr const auto _value = FValue::value;
struct return_t {
types::raw_value<value_t, _value> value{};
constexpr return_t() = default;
};
return return_t{};
} else
return value_to_type::convert_to_type_f<FValue, Allocator_holder>(
allocator_ref, &value);
}
} // namespace ctctx
} // namespace compile_time