Last active
December 21, 2015 14:09
-
-
Save PkmX/6317480 to your computer and use it in GitHub Desktop.
Using C++ template meta-programming to transform Brainfuck program into a C++ function.
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
// WTFPL, PkmX, 2013 | |
// Using C++ template meta-programming to transform Brainfuck program into a C++ function. | |
#include <iostream> | |
#include <vector> | |
template<char... C> | |
struct source; | |
//////////////////////////////////////////////////////////////////////////////// | |
namespace detail | |
{ | |
template<typename, typename, std::size_t> | |
struct find_loop_end; | |
template<char... Body, char C, char... Tail, std::size_t Level> | |
struct find_loop_end<source<Body...>, source<C, Tail...>, Level> | |
{ | |
typedef find_loop_end<source<Body..., C>, source<Tail...>, Level> t; | |
typedef typename t::body body; | |
typedef typename t::tail tail; | |
}; | |
template<char... Body, char... Tail, std::size_t Level> | |
struct find_loop_end<source<Body...>, source<'[', Tail...>, Level> | |
{ | |
typedef find_loop_end<source<Body..., '['>, source<Tail...>, Level + 1> t; | |
typedef typename t::body body; | |
typedef typename t::tail tail; | |
}; | |
template<char... Body, char... Tail, std::size_t Level> | |
struct find_loop_end<source<Body...>, source<']', Tail...>, Level> | |
{ | |
typedef find_loop_end<source<Body..., ']'>, source<Tail...>, Level - 1> t; | |
typedef typename t::body body; | |
typedef typename t::tail tail; | |
}; | |
template<char... Body, char... Tail> | |
struct find_loop_end<source<Body...>, source<']', Tail...>, 0> | |
{ | |
typedef source<Body...> body; | |
typedef source<Tail...> tail; | |
}; | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
template<typename> | |
struct body; | |
template<char... C> | |
struct body<source<C...>> | |
{ | |
typedef typename detail::find_loop_end<source<>, source<C...>, 0>::body type; | |
}; | |
template<typename> | |
struct tail; | |
template<char... C> | |
struct tail<source<C...>> | |
{ | |
typedef typename detail::find_loop_end<source<>, source<C...>, 0>::tail type; | |
}; | |
//////////////////////////////////////////////////////////////////////////////// | |
template<typename> | |
struct compile; | |
template<char... C> | |
struct compile<source<'>', C...>> | |
{ | |
template<typename BidirectionalIterator, typename InputIterator, typename OutputIterator> | |
static void run(BidirectionalIterator&& p, InputIterator&& in, OutputIterator&& out) | |
{ | |
++p; | |
compile<source<C...>>::run(p, in, out); | |
} | |
}; | |
template<char... C> | |
struct compile<source<'<', C...>> | |
{ | |
template<typename BidirectionalIterator, typename InputIterator, typename OutputIterator> | |
static void run(BidirectionalIterator&& p, InputIterator&& in, OutputIterator&& out) | |
{ | |
--p; | |
compile<source<C...>>::run(p, in, out); | |
} | |
}; | |
template<char... C> | |
struct compile<source<'+', C...>> | |
{ | |
template<typename BidirectionalIterator, typename InputIterator, typename OutputIterator> | |
static void run(BidirectionalIterator&& p, InputIterator&& in, OutputIterator&& out) | |
{ | |
++*p; | |
compile<source<C...>>::run(p, in, out); | |
} | |
}; | |
template<char... C> | |
struct compile<source<'-', C...>> | |
{ | |
template<typename BidirectionalIterator, typename InputIterator, typename OutputIterator> | |
static void run(BidirectionalIterator&& p, InputIterator&& in, OutputIterator&& out) | |
{ | |
--*p; | |
compile<source<C...>>::run(p, in, out); | |
} | |
}; | |
template<char... C> | |
struct compile<source<'.', C...>> | |
{ | |
template<typename BidirectionalIterator, typename InputIterator, typename OutputIterator> | |
static void run(BidirectionalIterator&& p, InputIterator&& in, OutputIterator&& out) | |
{ | |
*out = *p; ++out; | |
compile<source<C...>>::run(p, in, out); | |
} | |
}; | |
template<char... C> | |
struct compile<source<',', C...>> | |
{ | |
template<typename BidirectionalIterator, typename InputIterator, typename OutputIterator> | |
static void run(BidirectionalIterator&& p, InputIterator&& in, OutputIterator&& out) | |
{ | |
*p = *in; ++in; | |
compile<source<C...>>::run(p, in, out); | |
} | |
}; | |
template<char... C> | |
struct compile<source<'[', C...>> | |
{ | |
template<typename BidirectionalIterator, typename InputIterator, typename OutputIterator> | |
static void run(BidirectionalIterator&& p, InputIterator&& in, OutputIterator&& out) | |
{ | |
while (*p) | |
{ | |
compile<typename body<source<C...>>::type>::run(p, in, out); | |
} | |
compile<typename tail<source<C...>>::type>::run(p, in, out); | |
} | |
}; | |
template<char... C> | |
struct compile<source<']', C...>>; | |
// Ignore all other characters. | |
template<char C, char... CC> | |
struct compile<source<C, CC...>> | |
{ | |
template<typename BidirectionalIterator, typename InputIterator, typename OutputIterator> | |
static void run(BidirectionalIterator&& p, InputIterator&& in, OutputIterator&& out) | |
{ | |
compile<source<CC...>>::run(p, in, out); | |
} | |
}; | |
template<> | |
struct compile<source<>> | |
{ | |
template<typename BidirectionalIterator, typename InputIterator, typename OutputIterator> | |
static void run(BidirectionalIterator&&, InputIterator&&, OutputIterator&&) | |
{ | |
} | |
}; | |
//////////////////////////////////////////////////////////////////////////////// | |
template<typename, typename> | |
struct append; | |
template<char... C1, char C, char... C2> | |
struct append<source<C1...>, source<C, C2...>> | |
{ | |
typedef typename append<source<C1..., C>, source<C2...>>::type type; | |
}; | |
template<char... C> | |
struct append<source<C...>, source<>> | |
{ | |
typedef source<C...> type; | |
}; | |
namespace detail | |
{ | |
template<std::size_t N, char C0, char... C> | |
struct take_n | |
{ | |
typedef typename append<source<C0>, typename take_n<N-1, C...>::type>::type type; | |
}; | |
template<char C0, char... C> | |
struct take_n<1, C0, C...> | |
{ | |
typedef source<C0> type; | |
}; | |
constexpr char eat(const char* s, std::size_t n, std::size_t sz) | |
{ | |
return n < sz ? s[n] : 0; | |
} | |
} | |
// TODO: Use Boost.PP | |
#define make_source(S) detail::take_n<sizeof(S) - 1, \ | |
detail::eat(S, 0, sizeof(S)), \ | |
detail::eat(S, 1, sizeof(S)), \ | |
detail::eat(S, 2, sizeof(S)), \ | |
detail::eat(S, 3, sizeof(S)), \ | |
detail::eat(S, 4, sizeof(S)), \ | |
detail::eat(S, 5, sizeof(S)), \ | |
detail::eat(S, 6, sizeof(S)), \ | |
detail::eat(S, 7, sizeof(S)), \ | |
detail::eat(S, 8, sizeof(S)), \ | |
detail::eat(S, 9, sizeof(S)), \ | |
detail::eat(S, 10, sizeof(S)), \ | |
detail::eat(S, 11, sizeof(S)), \ | |
detail::eat(S, 12, sizeof(S)), \ | |
detail::eat(S, 13, sizeof(S)), \ | |
detail::eat(S, 14, sizeof(S)), \ | |
detail::eat(S, 15, sizeof(S)), \ | |
detail::eat(S, 16, sizeof(S)), \ | |
detail::eat(S, 17, sizeof(S)), \ | |
detail::eat(S, 18, sizeof(S)), \ | |
detail::eat(S, 19, sizeof(S)), \ | |
detail::eat(S, 20, sizeof(S)), \ | |
detail::eat(S, 21, sizeof(S)), \ | |
detail::eat(S, 22, sizeof(S)), \ | |
detail::eat(S, 23, sizeof(S)), \ | |
detail::eat(S, 24, sizeof(S)), \ | |
detail::eat(S, 25, sizeof(S)), \ | |
detail::eat(S, 26, sizeof(S)), \ | |
detail::eat(S, 27, sizeof(S)), \ | |
detail::eat(S, 28, sizeof(S)), \ | |
detail::eat(S, 29, sizeof(S)), \ | |
detail::eat(S, 30, sizeof(S)), \ | |
detail::eat(S, 31, sizeof(S)), \ | |
detail::eat(S, 32, sizeof(S)), \ | |
detail::eat(S, 33, sizeof(S)), \ | |
detail::eat(S, 34, sizeof(S)), \ | |
detail::eat(S, 35, sizeof(S)), \ | |
detail::eat(S, 36, sizeof(S)), \ | |
detail::eat(S, 37, sizeof(S)), \ | |
detail::eat(S, 38, sizeof(S)), \ | |
detail::eat(S, 39, sizeof(S)), \ | |
detail::eat(S, 40, sizeof(S)), \ | |
detail::eat(S, 41, sizeof(S)), \ | |
detail::eat(S, 42, sizeof(S)), \ | |
detail::eat(S, 43, sizeof(S)), \ | |
detail::eat(S, 44, sizeof(S)), \ | |
detail::eat(S, 45, sizeof(S)), \ | |
detail::eat(S, 46, sizeof(S)), \ | |
detail::eat(S, 47, sizeof(S)), \ | |
detail::eat(S, 48, sizeof(S)), \ | |
detail::eat(S, 49, sizeof(S)), \ | |
detail::eat(S, 50, sizeof(S)), \ | |
detail::eat(S, 51, sizeof(S)), \ | |
detail::eat(S, 52, sizeof(S)), \ | |
detail::eat(S, 53, sizeof(S)), \ | |
detail::eat(S, 54, sizeof(S)), \ | |
detail::eat(S, 55, sizeof(S)), \ | |
detail::eat(S, 56, sizeof(S)), \ | |
detail::eat(S, 57, sizeof(S)), \ | |
detail::eat(S, 58, sizeof(S)), \ | |
detail::eat(S, 59, sizeof(S)), \ | |
detail::eat(S, 60, sizeof(S)), \ | |
detail::eat(S, 61, sizeof(S)), \ | |
detail::eat(S, 62, sizeof(S)), \ | |
detail::eat(S, 63, sizeof(S)), \ | |
detail::eat(S, 64, sizeof(S)), \ | |
detail::eat(S, 65, sizeof(S)), \ | |
detail::eat(S, 66, sizeof(S)), \ | |
detail::eat(S, 67, sizeof(S)), \ | |
detail::eat(S, 68, sizeof(S)), \ | |
detail::eat(S, 69, sizeof(S)), \ | |
detail::eat(S, 70, sizeof(S)), \ | |
detail::eat(S, 71, sizeof(S)), \ | |
detail::eat(S, 72, sizeof(S)), \ | |
detail::eat(S, 73, sizeof(S)), \ | |
detail::eat(S, 74, sizeof(S)), \ | |
detail::eat(S, 75, sizeof(S)), \ | |
detail::eat(S, 76, sizeof(S)), \ | |
detail::eat(S, 77, sizeof(S)), \ | |
detail::eat(S, 78, sizeof(S)), \ | |
detail::eat(S, 79, sizeof(S)), \ | |
detail::eat(S, 80, sizeof(S)), \ | |
detail::eat(S, 81, sizeof(S)), \ | |
detail::eat(S, 82, sizeof(S)), \ | |
detail::eat(S, 83, sizeof(S)), \ | |
detail::eat(S, 84, sizeof(S)), \ | |
detail::eat(S, 85, sizeof(S)), \ | |
detail::eat(S, 86, sizeof(S)), \ | |
detail::eat(S, 87, sizeof(S)), \ | |
detail::eat(S, 88, sizeof(S)), \ | |
detail::eat(S, 89, sizeof(S)), \ | |
detail::eat(S, 90, sizeof(S)), \ | |
detail::eat(S, 91, sizeof(S)), \ | |
detail::eat(S, 92, sizeof(S)), \ | |
detail::eat(S, 93, sizeof(S)), \ | |
detail::eat(S, 94, sizeof(S)), \ | |
detail::eat(S, 95, sizeof(S)), \ | |
detail::eat(S, 96, sizeof(S)), \ | |
detail::eat(S, 97, sizeof(S)), \ | |
detail::eat(S, 98, sizeof(S)), \ | |
detail::eat(S, 99, sizeof(S)), \ | |
detail::eat(S, 100, sizeof(S)), \ | |
detail::eat(S, 101, sizeof(S)), \ | |
detail::eat(S, 102, sizeof(S)), \ | |
detail::eat(S, 103, sizeof(S)), \ | |
detail::eat(S, 104, sizeof(S)), \ | |
detail::eat(S, 105, sizeof(S)), \ | |
detail::eat(S, 106, sizeof(S)), \ | |
detail::eat(S, 107, sizeof(S)), \ | |
detail::eat(S, 108, sizeof(S)), \ | |
detail::eat(S, 109, sizeof(S)), \ | |
detail::eat(S, 110, sizeof(S)), \ | |
detail::eat(S, 111, sizeof(S)), \ | |
detail::eat(S, 112, sizeof(S)), \ | |
detail::eat(S, 113, sizeof(S)), \ | |
detail::eat(S, 114, sizeof(S)), \ | |
detail::eat(S, 115, sizeof(S)), \ | |
detail::eat(S, 116, sizeof(S)), \ | |
detail::eat(S, 117, sizeof(S)), \ | |
detail::eat(S, 118, sizeof(S)), \ | |
detail::eat(S, 119, sizeof(S)), \ | |
detail::eat(S, 120, sizeof(S)), \ | |
detail::eat(S, 121, sizeof(S)), \ | |
detail::eat(S, 122, sizeof(S)), \ | |
detail::eat(S, 123, sizeof(S)), \ | |
detail::eat(S, 124, sizeof(S)), \ | |
detail::eat(S, 125, sizeof(S)), \ | |
detail::eat(S, 126, sizeof(S)), \ | |
detail::eat(S, 127, sizeof(S)), \ | |
detail::eat(S, 128, sizeof(S)), \ | |
detail::eat(S, 129, sizeof(S)), \ | |
detail::eat(S, 130, sizeof(S)), \ | |
detail::eat(S, 131, sizeof(S)), \ | |
detail::eat(S, 132, sizeof(S)), \ | |
detail::eat(S, 133, sizeof(S)), \ | |
detail::eat(S, 134, sizeof(S)), \ | |
detail::eat(S, 135, sizeof(S)), \ | |
detail::eat(S, 136, sizeof(S)), \ | |
detail::eat(S, 137, sizeof(S)), \ | |
detail::eat(S, 138, sizeof(S)), \ | |
detail::eat(S, 139, sizeof(S)), \ | |
detail::eat(S, 140, sizeof(S)), \ | |
detail::eat(S, 141, sizeof(S)), \ | |
detail::eat(S, 142, sizeof(S)), \ | |
detail::eat(S, 143, sizeof(S)), \ | |
detail::eat(S, 144, sizeof(S)), \ | |
detail::eat(S, 145, sizeof(S)), \ | |
detail::eat(S, 146, sizeof(S)), \ | |
detail::eat(S, 147, sizeof(S)), \ | |
detail::eat(S, 148, sizeof(S)), \ | |
detail::eat(S, 149, sizeof(S)), \ | |
detail::eat(S, 150, sizeof(S)), \ | |
detail::eat(S, 151, sizeof(S)), \ | |
detail::eat(S, 152, sizeof(S)), \ | |
detail::eat(S, 153, sizeof(S)), \ | |
detail::eat(S, 154, sizeof(S)), \ | |
detail::eat(S, 155, sizeof(S)), \ | |
detail::eat(S, 156, sizeof(S)), \ | |
detail::eat(S, 157, sizeof(S)), \ | |
detail::eat(S, 158, sizeof(S)), \ | |
detail::eat(S, 159, sizeof(S)), \ | |
detail::eat(S, 160, sizeof(S)), \ | |
detail::eat(S, 161, sizeof(S)), \ | |
detail::eat(S, 162, sizeof(S)), \ | |
detail::eat(S, 163, sizeof(S)), \ | |
detail::eat(S, 164, sizeof(S)), \ | |
detail::eat(S, 165, sizeof(S)), \ | |
detail::eat(S, 166, sizeof(S)), \ | |
detail::eat(S, 167, sizeof(S)), \ | |
detail::eat(S, 168, sizeof(S)), \ | |
detail::eat(S, 169, sizeof(S)), \ | |
detail::eat(S, 170, sizeof(S)), \ | |
detail::eat(S, 171, sizeof(S)), \ | |
detail::eat(S, 172, sizeof(S)), \ | |
detail::eat(S, 173, sizeof(S)), \ | |
detail::eat(S, 174, sizeof(S)), \ | |
detail::eat(S, 175, sizeof(S)), \ | |
detail::eat(S, 176, sizeof(S)), \ | |
detail::eat(S, 177, sizeof(S)), \ | |
detail::eat(S, 178, sizeof(S)), \ | |
detail::eat(S, 179, sizeof(S)), \ | |
detail::eat(S, 180, sizeof(S)), \ | |
detail::eat(S, 181, sizeof(S)), \ | |
detail::eat(S, 182, sizeof(S)), \ | |
detail::eat(S, 183, sizeof(S)), \ | |
detail::eat(S, 184, sizeof(S)), \ | |
detail::eat(S, 185, sizeof(S)), \ | |
detail::eat(S, 186, sizeof(S)), \ | |
detail::eat(S, 187, sizeof(S)), \ | |
detail::eat(S, 188, sizeof(S)), \ | |
detail::eat(S, 189, sizeof(S)), \ | |
detail::eat(S, 190, sizeof(S)), \ | |
detail::eat(S, 191, sizeof(S)), \ | |
detail::eat(S, 192, sizeof(S)), \ | |
detail::eat(S, 193, sizeof(S)), \ | |
detail::eat(S, 194, sizeof(S)), \ | |
detail::eat(S, 195, sizeof(S)), \ | |
detail::eat(S, 196, sizeof(S)), \ | |
detail::eat(S, 197, sizeof(S)), \ | |
detail::eat(S, 198, sizeof(S)), \ | |
detail::eat(S, 199, sizeof(S)), \ | |
detail::eat(S, 200, sizeof(S)), \ | |
detail::eat(S, 201, sizeof(S)), \ | |
detail::eat(S, 202, sizeof(S)), \ | |
detail::eat(S, 203, sizeof(S)), \ | |
detail::eat(S, 204, sizeof(S)), \ | |
detail::eat(S, 205, sizeof(S)), \ | |
detail::eat(S, 206, sizeof(S)), \ | |
detail::eat(S, 207, sizeof(S)), \ | |
detail::eat(S, 208, sizeof(S)), \ | |
detail::eat(S, 209, sizeof(S)), \ | |
detail::eat(S, 210, sizeof(S)), \ | |
detail::eat(S, 211, sizeof(S)), \ | |
detail::eat(S, 212, sizeof(S)), \ | |
detail::eat(S, 213, sizeof(S)), \ | |
detail::eat(S, 214, sizeof(S)), \ | |
detail::eat(S, 215, sizeof(S)), \ | |
detail::eat(S, 216, sizeof(S)), \ | |
detail::eat(S, 217, sizeof(S)), \ | |
detail::eat(S, 218, sizeof(S)), \ | |
detail::eat(S, 219, sizeof(S)), \ | |
detail::eat(S, 220, sizeof(S)), \ | |
detail::eat(S, 221, sizeof(S)), \ | |
detail::eat(S, 222, sizeof(S)), \ | |
detail::eat(S, 223, sizeof(S)), \ | |
detail::eat(S, 224, sizeof(S)), \ | |
detail::eat(S, 225, sizeof(S)), \ | |
detail::eat(S, 226, sizeof(S)), \ | |
detail::eat(S, 227, sizeof(S)), \ | |
detail::eat(S, 228, sizeof(S)), \ | |
detail::eat(S, 229, sizeof(S)), \ | |
detail::eat(S, 230, sizeof(S)), \ | |
detail::eat(S, 231, sizeof(S)), \ | |
detail::eat(S, 232, sizeof(S)), \ | |
detail::eat(S, 233, sizeof(S)), \ | |
detail::eat(S, 234, sizeof(S)), \ | |
detail::eat(S, 235, sizeof(S)), \ | |
detail::eat(S, 236, sizeof(S)), \ | |
detail::eat(S, 237, sizeof(S)), \ | |
detail::eat(S, 238, sizeof(S)), \ | |
detail::eat(S, 239, sizeof(S)), \ | |
detail::eat(S, 240, sizeof(S)), \ | |
detail::eat(S, 241, sizeof(S)), \ | |
detail::eat(S, 242, sizeof(S)), \ | |
detail::eat(S, 243, sizeof(S)), \ | |
detail::eat(S, 244, sizeof(S)), \ | |
detail::eat(S, 245, sizeof(S)), \ | |
detail::eat(S, 246, sizeof(S)), \ | |
detail::eat(S, 247, sizeof(S)), \ | |
detail::eat(S, 248, sizeof(S)), \ | |
detail::eat(S, 249, sizeof(S)), \ | |
detail::eat(S, 250, sizeof(S)), \ | |
detail::eat(S, 251, sizeof(S)), \ | |
detail::eat(S, 252, sizeof(S)), \ | |
detail::eat(S, 253, sizeof(S)), \ | |
detail::eat(S, 254, sizeof(S)), \ | |
detail::eat(S, 255, sizeof(S)) \ | |
>::type | |
//////////////////////////////////////////////////////////////////////////////// | |
#define STRINGIFY(S) #S | |
#define XSTRINGIFY(S) STRINGIFY(S) | |
//////////////////////////////////////////////////////////////////////////////// | |
#define MEM_SIZE 30000 | |
#define BRAINFUCK_SOURCE \ | |
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. \ | |
This should print out "Hello World!" and this line is ignored | |
//////////////////////////////////////////////////////////////////////////////// | |
int main() | |
{ | |
std::vector<char> mem(MEM_SIZE, 0); | |
typedef compile<make_source(XSTRINGIFY(BRAINFUCK_SOURCE))> program; | |
program::run(mem.begin(), std::istreambuf_iterator<char>(std::cin), std::ostreambuf_iterator<char>(std::cout)); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment