Last active
June 28, 2020 12:14
-
-
Save qookei/b7f29e483c5c11c06ebcf6f1c8d2cb8e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* compile with: g++ gorbitsa.cpp -o gorbitsa -ftemplate-depth=99999999 -std=c++2a | |
* Tested with GCC 10.1, does *not* work with Clang 10 | |
*/ | |
#include <iostream> | |
#include <string_view> | |
#include <cctype> | |
#include <array> | |
#include <type_traits> | |
#include <tuple> | |
// From https://github.com/managarm/frigg/blob/master/include/frg/array.hpp, lines 92-124 | |
// s/frg::/std::/ | |
namespace details { | |
template<typename ...Ts> | |
struct concat_size; | |
template<typename ...Ts> | |
inline constexpr size_t concat_size_v = concat_size<Ts...>::value; | |
template<typename T, typename ...Ts> | |
struct concat_size<T, Ts...> | |
: std::integral_constant<size_t, std::tuple_size_v<T> + concat_size_v<Ts...>> { }; | |
template<> | |
struct concat_size<> | |
: std::integral_constant<size_t, 0> { }; | |
template<typename X, size_t N> | |
constexpr void concat_insert(std::array<X, N> &, size_t) { } | |
template<typename X, size_t N, typename T, typename... Ts> | |
constexpr void concat_insert(std::array<X, N> &res, size_t at, const T &other, const Ts &...tail) { | |
size_t n = std::tuple_size_v<T>; | |
for(size_t i = 0; i < n; ++i) | |
res[at + i] = other[i]; | |
concat_insert(res, at + n, tail...); | |
} | |
} // namespace details | |
template<typename X, typename ...Ts> | |
constexpr auto array_concat(const Ts &...arrays) { | |
std::array<X, details::concat_size_v<Ts...>> res{}; | |
details::concat_insert(res, 0, arrays...); | |
return res; | |
} | |
template <size_t I> | |
constexpr auto set(auto a, auto b) { | |
a[I] = b; | |
return a; | |
} | |
template <size_t PC, uint8_t X, size_t I, std::array<uint8_t, 256> Ram, uint8_t ...Ts> | |
constexpr auto run_impl(std::array<uint8_t, I> out) { | |
if constexpr (PC + 1 >= sizeof...(Ts)) | |
return out; | |
else { | |
constexpr uint8_t op = std::get<PC>(std::make_tuple(Ts...)); | |
constexpr uint8_t arg = std::get<PC + 1>(std::make_tuple(Ts...)); | |
if constexpr (op == 'G') | |
return run_impl<PC + 2, Ram[arg], out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'O') | |
return run_impl<PC + 2, X, out.size(), set<arg>(Ram, X), Ts...>(out); | |
else if constexpr (op == 'R') | |
return run_impl<PC + 2, /*input*/ 0, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'B') | |
return run_impl<X ? PC + 2 : arg * 2, X, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'I') | |
return run_impl<PC + 2, (X + arg) & 0xFF, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'T') | |
return run_impl<PC + 2, X, out.size() + 1, Ram, Ts...>( | |
array_concat<uint8_t>(out, std::array<uint8_t, 1>{X})); | |
else if constexpr (op == 'S') | |
return run_impl<PC + 2, arg, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'A') | |
return run_impl<PC + 2, (X + Ram[arg]) & 0xFF, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'g') | |
return run_impl<PC + 2, Ram[Ram[arg]], out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'o') | |
return run_impl<PC + 2, X, out.size(), set<Ram[arg]>(Ram, X), Ts...>(out); | |
else if constexpr (op == 'r') | |
return run_impl<PC + 2, X, out.size(), set<arg>(Ram, /*input*/ 0), Ts...>(out); | |
else if constexpr (op == 'b') | |
return run_impl<X ? PC + 2 : Ram[arg] * 2, X, out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'i') | |
return run_impl<PC + 2, X, out.size(), set<arg>(Ram, (Ram[arg] + X) & 0xFF), Ts...>(out); | |
else if constexpr (op == 't') | |
return run_impl<PC + 2, X, out.size() + 1, Ram, Ts...>( | |
array_concat<uint8_t>(out, std::array<uint8_t, 1>{Ram[arg]})); | |
else if constexpr (op == 's') | |
return run_impl<PC + 2, X ^ Ram[arg], out.size(), Ram, Ts...>(out); | |
else if constexpr (op == 'a') | |
return run_impl<PC + 2, (X + Ram[Ram[arg]]) & 0xFF, out.size(), Ram, Ts...>(out); | |
else | |
return std::array<uint8_t, 9>{'E', 'r', 'r', 'o', 'r', 'O', op, 'A', arg}; | |
} | |
} | |
template <size_t N> | |
struct constant_string { | |
constexpr constant_string(const char (&str)[N]) { | |
std::copy_n(str, N - 1, data_); | |
} | |
constexpr const char *data() const { | |
return data_; | |
} | |
constexpr size_t size() const { | |
return N - 1; | |
} | |
char data_[N - 1]; | |
}; | |
template <constant_string Str, bool Parsing_command, uint8_t Tmp, size_t I, uint8_t ...c> | |
constexpr auto run_parser() { | |
if constexpr (Str.size() > I) { | |
if constexpr (Str.data()[I] == 'R' || Str.data()[I] == 'T') { | |
if constexpr (Str.size() > I + 1) | |
static_assert(Str.data()[I + 1] == ' '); | |
return run_parser<Str, true, 0, I + 2, c..., Str.data()[I], 0>(); | |
} else { | |
if constexpr (Parsing_command) | |
return run_parser<Str, false, 0, I + 1, c..., Str.data()[I]>(); | |
else if constexpr (Str.data()[I] >= '0' && Str.data()[I] <= '9') | |
return run_parser<Str, false, (Tmp * 10 + Str.data()[I] - '0') & 0xFF, I + 1, c...>(); | |
else { | |
static_assert(Str.data()[I] == ' '); | |
return run_parser<Str, true, 0, I + 1, c..., Tmp>(); | |
} | |
} | |
} else { | |
return run_impl<0, 0, 0, std::array<uint8_t, 256>{}, c...>({}); | |
} | |
} | |
template <constant_string Str> | |
constexpr auto run() { | |
return run_parser<Str, true, 0, 0>(); | |
} | |
int main() { | |
// Hello | |
//auto output = run<"S72 T S101 T S108 T T S111 T">(); | |
// A 10x10 Box (By Megarev) | |
//auto output = run<"S10 O0 G0 I255 O0 B19 S10 T S10 O1 G1 I255 O1 S35 T G1 B2 S0 B10 S10 T">(); | |
// Simple stairs (By Megarev) | |
//auto output = run<"S10 O10 S0 O1 S6 O0 G0 I255 O0 B24 t10 G1 I1 O1 O2 G2 I255 O2 S35 T G2 B6 S0 B15 t10">(); | |
// Sauron's eye (By TrolledWoods) (Broken) | |
//auto output = run<"S206 O132 S10 T S156 O97 S1 i97 S0 O7 G97 I237 O131 G97 i7 S1 i131 G131 B42 S0 B26 S0 O105 G132 I45 O131 G132 i105 S1 i131 G131 B68 S0 B52 G105 i7 S200 O105 G7 B94 G105 B102 S255 i7 i105 S0 B76 S46 T S0 B110 S35 T S0 B110 G97 B118 S0 B12 S1 i132 G132 B255 S0 B4">(); | |
// Snake (By Horsey) (Never completes?) | |
auto output = run<"S255 O95 S27 O1 S28 O2 S29 O3 S255 O165 S3 O33 S20 O34 S27 T S91 T S50 T S74 T S10 T S34 O151 S95 T G151 I255 O151 B34 S0 B26 S10 T S16 O152 S255 O156 O157 S124 T S16 O153 G33 O158 g158 O255 B73 S16 O159 S0 O160 G160 A152 O160 G159 I255 O159 B63 S0 B54 G160 I240 A153 O160 O254 G255 s95 I1 A254 B108 G158 I255 O158 B79 S0 B47 G160 O255 G34 O254 G255 s95 I1 A254 B90 S0 B104 S27 T S91 T S57 T S49 T S109 T S219 T S0 B120 S32 T S0 B120 S27 T S91 T S57 T S50 T S109 T S219 T G157 s156 O157 i153 G153 B128 S0 B45 S27 T S91 T S48 T S109 T S124 T S10 T G152 I255 O152 B146 S0 B41 S34 O154 S196 T G154 I255 O154 B156 S0 B148 G33 O161 G1 O163 g33 O170 G161 I255 O162 g162 o161 G162 O161 B172 S0 B162 R I152 B183 I254 B191 I255 B187 I255 B195 S0 B197 S1 O165 S0 B197 S16 O165 S0 B197 S240 O165 S0 B197 S255 O165 G163 A165 O1 G34 O255 G1 O254 G255 s95 I1 A254 B211 S0 B217 S1 i33 G170 o33 s254 O34 G33 O166 G33 O167 G167 O255 G166 O254 G255 s95 I1 A254 B239 g167 O255 g166 O254 G255 s95 I1 A254 B255 G167 I255 O167 B245 S0 B221 G166 I255 O166 B251 S0 B219 S0 B14 S0">(); | |
for (auto c : output) | |
std::putchar(c); | |
std::putchar('\n'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment