-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconsteval-bfc.cpp
163 lines (148 loc) · 4.48 KB
/
consteval-bfc.cpp
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
#include <algorithm>
#include <array>
#include <compare>
#include <functional>
#include <ranges>
#include <span>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <string_view>
#include <tuple>
using namespace std;
// https://www.quora.com/How-do-you-pass-a-string-literal-as-a-parameter-to-a-C-template-class
template <int N> struct FixedString {
constexpr static int len = N - 1;
constexpr FixedString(char const (&s)[N]) { std::copy_n(s, N, this->elems); }
constexpr FixedString(char const *s, size_t offset) {
std::copy_n(s + offset, N, this->elems);
}
constexpr std::strong_ordering
operator<=>(FixedString const &) const = default;
char elems[N];
};
template <int N> FixedString(char const (&)[N]) -> FixedString<N>;
template <int N, int M>
consteval FixedString<N> subFixedString(FixedString<M> s, int64_t offset) {
return FixedString<N>(s.elems, offset);
}
// using FixedString = pair<const char *const, size_t>;
template <FixedString src> consteval bool program_parses() {
size_t depth = 0;
for (size_t i = 0; i < decltype(src)::len; ++i) {
char c = src.elems[i];
if (c == '[') {
depth++;
} else if (c == ']') {
depth--;
}
}
return depth == 0;
}
// Find the index of the first closing bracket at the current depth after start.
template <FixedString src>
consteval size_t find_matching_bracket(size_t start) {
size_t depth = 0;
size_t i = start;
while (i < decltype(src)::len) {
if (src.elems[i] == '[')
depth++;
else if (src.elems[i] == ']')
depth--;
if (depth == 0)
return i;
i++;
}
return i;
}
struct Machine {
array<uint8_t, 30000> memory;
size_t sc = 0;
};
template <FixedString source, int64_t start, int64_t end>
consteval auto compile() {
if constexpr (start >= end || start >= decltype(source)::len) {
return [](Machine &mch) {
// printf("finished at %ld %ld %c\n", start, end, source.elems[start]);
};
} else if constexpr (source.elems[start] == '+') {
return [](Machine &mch) {
// printf("+ %ld %ld\n", start, end);
mch.memory[mch.sc]++;
compile<source, start + 1, end>()(mch);
};
} else if constexpr (source.elems[start] == '-') {
return [](Machine &mch) {
// printf("+ %ld %ld\n", start, end);
mch.memory[mch.sc]--;
compile<source, start + 1, end>()(mch);
};
} else if constexpr (source.elems[start] == '<') {
return [](Machine &mch) {
// printf("< %ld %ld\n", start, end);
mch.sc--;
compile<source, start + 1, end>()(mch);
};
} else if constexpr (source.elems[start] == '>') {
return [](Machine &mch) {
// printf("> %ld %ld\n", start, end);
mch.sc++;
compile<source, start + 1, end>()(mch);
};
} else if constexpr (source.elems[start] == '.') {
return [](Machine &mch) {
putchar(mch.memory[mch.sc]);
// printf("output %ld %ld: %d\n", start, end, mch.memory[mch.sc]);
compile<source, start + 1, end>()(mch);
};
} else if constexpr (source.elems[start] == ',') {
return [](Machine &mch) {
// printf("input %ld %ld:\n", start, end);
mch.memory[mch.sc] = getchar();
compile<source, start + 1, end>()(mch);
};
} else if constexpr (source.elems[start] == '[') {
return [](Machine &mch) {
constexpr size_t match = find_matching_bracket<source>(start);
// printf("start loop %ld %ld -> %ld\n", start, end, match);
// constexpr auto loop_body = subFixedString<match-1,
// decltype(source)::len>(source, 1); constexpr auto remainder =
// subFixedString<decltype(source)::len - match - 1,
// decltype(source)::len>(source, match + 1);
while (mch.memory[mch.sc]) {
compile<source, start + 1, match>()(mch);
}
compile<source, match + 1, end>()(mch);
};
} else {
return [](Machine &mch) {
// printf("other %ld %ld: %d\n", start, end, source.elems[start]);
compile<source, start + 1, end>()(mch);
};
}
}
template <FixedString source> consteval auto brainfuck() {
static_assert(program_parses<source>(), "unmatched bracket");
return []() {
Machine mch;
compile<source, 0, decltype(source)::len>()(mch);
};
}
int main() {
brainfuck<R"(
>++++++++[<+++++++++>-]<. H
>++++[<+++++++>-]<+. e
+++++++.. ll
+++. o
>>++++++[<+++++++>-]<++. comma
------------. space
>++++++[<+++++++++>-]<+. W
<. o
+++. r
------. l
--------. d
>>>++++[<++++++++>-]<+. !
)">()();
putchar('\n');
}