Skip to content

Instantly share code, notes, and snippets.

@PkmX
Last active December 21, 2015 14:09
Show Gist options
  • Save PkmX/6317480 to your computer and use it in GitHub Desktop.
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.
// 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