Created
July 10, 2020 02:30
-
-
Save xsduan/638b62591a6d5b06536cfe9d29e2006c to your computer and use it in GitHub Desktop.
This file contains 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
#include <iostream> | |
#include <utility> | |
// ----- prelude ----- | |
// --- control flow --- | |
// ~~ if ~~ | |
// control flow | |
template <bool cond, typename then_res, typename else_res> struct __if; | |
template <typename then_res, typename else_res> | |
struct __if<true, then_res, else_res> { | |
using then = then_res; | |
}; | |
template <typename then_res, typename else_res> | |
struct __if<false, then_res, else_res> { | |
using then = else_res; | |
}; | |
// --- boolean --- | |
// ~~ and ~~ | |
// logical and | |
template <bool p, bool q> struct __and { | |
enum { val = true }; | |
}; | |
template <bool p> struct __and<p, false> { | |
enum { val = false }; | |
}; | |
template <bool q> struct __and<false, q> { | |
enum { val = false }; | |
}; | |
template <> struct __and<false, false> { | |
enum { val = false }; | |
}; | |
// ~~ or ~~ | |
// logical or | |
template <bool p, bool q> struct __or { | |
enum { val = true }; | |
}; | |
template <bool p> struct __or<p, false> { | |
enum { val = true }; | |
}; | |
template <bool q> struct __or<false, q> { | |
enum { val = true }; | |
}; | |
template <> struct __or<false, false> { | |
enum { val = false }; | |
}; | |
// --- binary cmp --- | |
// ~~ eq ~~ | |
// equals to | |
template <char l, char r> struct __eq { | |
enum { val = __eq<l - 1, r - 1>::val }; | |
}; | |
template <char l> struct __eq<l, 0> { | |
enum { val = false }; | |
}; | |
template <char r> struct __eq<0, r> { | |
enum { val = false }; | |
}; | |
template <> struct __eq<0, 0> { | |
enum { val = true }; | |
}; | |
// ~~ gt ~~ | |
// greater than | |
template <char l, char r> struct __gt { | |
enum { val = __gt<l - 1, r - 1>::val }; | |
}; | |
// | |
template <char l> struct __gt<l, 0> { | |
enum { val = true }; | |
}; | |
template <char r> struct __gt<0, r> { | |
enum { val = false }; | |
}; | |
template <> struct __gt<0, 0> { | |
enum { val = false }; | |
}; | |
// ~~ gte ~~ | |
// greater than or equals | |
template <char l, char r> struct __gte { | |
enum { val = __or<__gt<l, r>::val, __eq<l, r>::val>::val }; | |
}; | |
// ~~ lte ~~ | |
// less than or equals | |
template <char l, char r> struct __lte { | |
enum { val = __gte<r, l>::val }; | |
}; | |
// --- arithmetic --- | |
// ~~ add ~~ | |
// integer addition | |
template <char l, char r> struct __add { | |
enum { val = __add<l + 1, r - 1>::val }; | |
}; | |
template <char l> struct __add<l, 0> { | |
enum { val = l }; | |
}; | |
// --- misc --- | |
// ~~ str ~~ | |
// accumulate char params into a string | |
template <char... chars> struct __str { | |
static constexpr char val[]{chars..., '\0'}; | |
}; | |
namespace impl { | |
// ~~ cat ~~ | |
// concatenate template strings | |
template <typename... p> struct __cat { using type = __str<>; }; | |
template <typename a, typename b, typename... p> struct __cat<a, b, p...> { | |
using res = __cat<typename __cat<a, b>::res, p...>; | |
}; | |
template <char... a, char... b> struct __cat<__str<a...>, __str<b...>> { | |
using res = __str<a..., b...>; | |
}; | |
template <char... a> struct __cat<__str<a...>> { using res = __str<a...>; }; | |
template <typename t> struct __cat<t> { using res = t; }; | |
// ~~ repeat ~~ | |
// repeat `c` `reps` times into `acc` | |
template <typename c, int reps, typename acc> struct __repeat { | |
using res = __str<>; | |
}; | |
template <char c, int reps, char... acc> | |
struct __repeat<__str<c>, reps, __str<acc...>> { | |
using res = typename __repeat<__str<c>, reps - 1, __str<c, acc...>>::res; | |
}; | |
template <char c, char... acc> struct __repeat<__str<c>, 1, __str<acc...>> { | |
using res = __str<c, acc...>; | |
}; | |
} // namespace impl | |
template <typename... p> using __cat = typename impl::__cat<p...>::res; | |
template <typename c, int reps, typename acc> | |
using __repeat = typename impl::__repeat<c, reps, acc>::res; | |
// ----- end prelude ----- | |
template <char c> struct num_map { using res = __str<'?'>; }; | |
template <> struct num_map<'.'> { using res = __str<'1'>; }; | |
template <> struct num_map<','> { | |
using res = __repeat<__str<'1'>, 2, __str<>>; | |
}; | |
template <> struct num_map<'?'> { | |
using res = __repeat<__str<'1'>, 3, __str<>>; | |
}; | |
template <> struct num_map<'!'> { | |
using res = __repeat<__str<'1'>, 4, __str<>>; | |
}; | |
template <> struct num_map<'1'> { | |
using res = __repeat<__str<'1'>, 5, __str<>>; | |
}; | |
template <> struct num_map<'a'> { using res = __str<'2'>; }; | |
template <> struct num_map<'b'> { | |
using res = __repeat<__str<'2'>, 2, __str<>>; | |
}; | |
template <> struct num_map<'c'> { | |
using res = __repeat<__str<'2'>, 3, __str<>>; | |
}; | |
template <> struct num_map<'2'> { | |
using res = __repeat<__str<'2'>, 4, __str<>>; | |
}; | |
template <> struct num_map<'d'> { using res = __str<'3'>; }; | |
template <> struct num_map<'e'> { | |
using res = __repeat<__str<'3'>, 2, __str<>>; | |
}; | |
template <> struct num_map<'f'> { | |
using res = __repeat<__str<'3'>, 3, __str<>>; | |
}; | |
template <> struct num_map<'3'> { | |
using res = __repeat<__str<'3'>, 4, __str<>>; | |
}; | |
template <> struct num_map<'g'> { using res = __str<'4'>; }; | |
template <> struct num_map<'h'> { | |
using res = __repeat<__str<'4'>, 2, __str<>>; | |
}; | |
template <> struct num_map<'i'> { | |
using res = __repeat<__str<'4'>, 3, __str<>>; | |
}; | |
template <> struct num_map<'4'> { | |
using res = __repeat<__str<'4'>, 4, __str<>>; | |
}; | |
template <> struct num_map<'j'> { using res = __str<'5'>; }; | |
template <> struct num_map<'k'> { | |
using res = __repeat<__str<'5'>, 2, __str<>>; | |
}; | |
template <> struct num_map<'l'> { | |
using res = __repeat<__str<'5'>, 3, __str<>>; | |
}; | |
template <> struct num_map<'5'> { | |
using res = __repeat<__str<'5'>, 4, __str<>>; | |
}; | |
template <> struct num_map<'m'> { using res = __str<'6'>; }; | |
template <> struct num_map<'n'> { | |
using res = __repeat<__str<'6'>, 2, __str<>>; | |
}; | |
template <> struct num_map<'o'> { | |
using res = __repeat<__str<'6'>, 3, __str<>>; | |
}; | |
template <> struct num_map<'6'> { | |
using res = __repeat<__str<'6'>, 4, __str<>>; | |
}; | |
template <> struct num_map<'p'> { using res = __str<'7'>; }; | |
template <> struct num_map<'q'> { | |
using res = __repeat<__str<'7'>, 2, __str<>>; | |
}; | |
template <> struct num_map<'r'> { | |
using res = __repeat<__str<'7'>, 3, __str<>>; | |
}; | |
template <> struct num_map<'s'> { | |
using res = __repeat<__str<'7'>, 4, __str<>>; | |
}; | |
template <> struct num_map<'7'> { | |
using res = __repeat<__str<'7'>, 5, __str<>>; | |
}; | |
template <> struct num_map<'t'> { using res = __str<'8'>; }; | |
template <> struct num_map<'u'> { | |
using res = __repeat<__str<'8'>, 2, __str<>>; | |
}; | |
template <> struct num_map<'v'> { | |
using res = __repeat<__str<'8'>, 3, __str<>>; | |
}; | |
template <> struct num_map<'8'> { | |
using res = __repeat<__str<'8'>, 4, __str<>>; | |
}; | |
template <> struct num_map<'w'> { using res = __str<'9'>; }; | |
template <> struct num_map<'x'> { | |
using res = __repeat<__str<'9'>, 2, __str<>>; | |
}; | |
template <> struct num_map<'y'> { | |
using res = __repeat<__str<'9'>, 3, __str<>>; | |
}; | |
template <> struct num_map<'z'> { | |
using res = __repeat<__str<'9'>, 4, __str<>>; | |
}; | |
template <> struct num_map<'9'> { | |
using res = __repeat<__str<'9'>, 5, __str<>>; | |
}; | |
template <> struct num_map<'\''> { using res = __str<'*'>; }; | |
template <> struct num_map<'-'> { | |
using res = __repeat<__str<'*'>, 2, __str<>>; | |
}; | |
template <> struct num_map<'+'> { | |
using res = __repeat<__str<'*'>, 3, __str<>>; | |
}; | |
template <> struct num_map<'='> { | |
using res = __repeat<__str<'*'>, 4, __str<>>; | |
}; | |
template <> struct num_map<'*'> { | |
using res = __repeat<__str<'*'>, 5, __str<>>; | |
}; | |
template <> struct num_map<' '> { using res = __str<'0'>; }; | |
template <> struct num_map<'0'> { | |
using res = __repeat<__str<'0'>, 2, __str<>>; | |
}; | |
template <char c> struct parse_char_lower { | |
using res = typename num_map<c>::res; | |
}; | |
template <char c> struct parse_char_upper { | |
using res = | |
__cat<__str<'#', ' '>, typename parse_char_lower<__add<c, 32>::val>::res>; | |
}; | |
template <char c> struct parse_char { | |
using res = | |
typename __if<__and<__gte<c, 'A'>::val, __lte<c, 'Z'>::val>::val, | |
parse_char_upper<c>, parse_char_lower<c>>::then::res; | |
}; | |
template <typename str> struct take_last { static const char val = '\0'; }; | |
template <char first, char... acc> struct take_last<__str<first, acc...>> { | |
static const char val = take_last<__str<acc...>>::val; | |
}; | |
template <char first> struct take_last<__str<first>> { | |
static const char val = first; | |
}; | |
template <typename str> struct take_first { static const char val = '\0'; }; | |
template <char first, char... acc> struct take_first<__str<first, acc...>> { | |
static const char val = first; | |
}; | |
template <char a, char b> struct separator { | |
using res = | |
typename __if<__eq<take_last<typename parse_char<a>::res>::val, | |
take_first<typename parse_char<b>::res>::val>::val, | |
__str<'_'>, __str<' '>>::then; | |
}; | |
template <typename str> struct letter_map_forward { using res = __str<>; }; | |
template <char a, char b> struct letter_map_forward<__str<a, b>> { | |
using res = __cat<typename parse_char<a>::res, typename separator<a, b>::res>; | |
}; | |
template <typename str> struct letter_map { using res = __str<>; }; | |
template <char a, char b, char... acc> struct letter_map<__str<a, b, acc...>> { | |
using res = __cat<typename letter_map_forward<__str<a, b>>::res, | |
typename letter_map<__str<b, acc...>>::res>; | |
}; | |
template <char a, char b> struct letter_map<__str<a, b>> { | |
using res = __cat<typename letter_map_forward<__str<a, b>>::res, | |
typename parse_char<b>::res>; | |
}; | |
template <typename T> void letter_mapify() { | |
std::cout << "to_t9('" << T::val << "') //" << letter_map<T>::res::val | |
<< '\n'; | |
} | |
int main() { | |
using hello = __str<'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'>; | |
using hello_caps = | |
__str<'H', 'E', 'L', 'L', 'O', ' ', 'W', 'O', 'R', 'L', 'D'>; | |
using abba = __str<'a', 'b', 'b', 'a', ' ', 'f', 'e', 'e', 'd', ' ', 'h', 'i', | |
'g', 'h'>; | |
using no_you_dont = __str<'I', ' ', 'l', 'o', 'v', 'e', ' ', 'P', 'H', 'P'>; | |
using lights = __str<'t', 'h', 'e', 'r', 'e', ' ', 'r', ' ', '4', ' ', 'l', | |
'i', 'g', 'h', 't', 's', '!'>; | |
letter_mapify<hello>(); | |
letter_mapify<hello_caps>(); | |
letter_mapify<abba>(); | |
letter_mapify<no_you_dont>(); | |
letter_mapify<lights>(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment