Created
January 31, 2015 15:40
-
-
Save hidez8891/3ee9f1f437b3afebd4f8 to your computer and use it in GitHub Desktop.
tlang | c like language made from c++ template language
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 <tuple> | |
namespace tuple | |
{ | |
// concat | |
template <typename, typename> | |
struct concat; | |
// concat: tuple -> tuple -> tuple | |
template <typename... Ts1, typename... Ts2> | |
struct concat<std::tuple<Ts1...>, std::tuple<Ts2...>> | |
{ | |
using type = std::tuple<Ts1..., Ts2...>; | |
}; | |
// concat: a -> tuple -> tuple | |
template <typename T, typename... Ts> | |
struct concat<T, std::tuple<Ts...>> | |
{ | |
using type = std::tuple<T, Ts...>; | |
}; | |
// element getter | |
template <typename, int> | |
struct get_; | |
// get_: tuple -> int -> value | |
template <typename T, typename... Ts, int I> | |
struct get_<std::tuple<T, Ts...>, I> | |
{ | |
// next step | |
using type = typename get_<std::tuple<Ts...>, I - 1>::type; | |
}; | |
template <typename T, typename... Ts> | |
struct get_<std::tuple<T, Ts...>, 0> | |
{ | |
// return value | |
using type = T; | |
}; | |
template <int I> | |
struct get_<std::tuple<>, I> | |
{ | |
// over access | |
// error | |
}; | |
// element setter | |
template <typename, int, typename> | |
struct set_; | |
// get_: tuple -> int -> value -> tuple | |
template <typename T, typename... Ts, int I, typename V> | |
struct set_<std::tuple<T, Ts...>, I, V> | |
{ | |
// next step | |
using type = typename concat< | |
T, | |
typename set_<std::tuple<Ts...>, I - 1, V>::type | |
>::type; | |
}; | |
template <typename T, typename... Ts, typename V> | |
struct set_<std::tuple<T, Ts...>, 0, V> | |
{ | |
// set value | |
using type = std::tuple<V, Ts...>; | |
}; | |
template <int I, typename V> | |
struct set_<std::tuple<>, I, V> | |
{ | |
// over access | |
// error | |
}; | |
} | |
namespace value | |
{ | |
// tag | |
template <char C> | |
struct name_ | |
{ | |
static const char value = C; | |
}; | |
// integer | |
template <int I> | |
struct int_ | |
{ | |
static const int value = I; | |
}; | |
// variable | |
template <typename K, typename V> | |
struct variable | |
{ | |
using key = K; | |
using value = V; | |
}; | |
} | |
namespace accessor | |
{ | |
using tuple::concat; | |
using value::variable; | |
// variable getter | |
template <typename, typename> | |
struct get_; | |
// get_: key -> environment -> value | |
template <typename K, typename T, typename... Ts> | |
struct get_<K, std::tuple<T, Ts...>> | |
{ | |
// next step | |
using type = typename get_<K, std::tuple<Ts...>>::type; | |
}; | |
template <typename K, typename V, typename... Ts> | |
struct get_<K, std::tuple<variable<K, V>, Ts...>> | |
{ | |
// key hit | |
using type = V; | |
}; | |
template <typename K> | |
struct get_<K, std::tuple<>> | |
{ | |
// key no hit | |
// error | |
}; | |
// variable setter | |
template <typename, typename, typename> | |
struct set_; | |
// set_: key -> value -> environment -> environment | |
template <typename K, typename V, typename T, typename... Ts> | |
struct set_<K, V, std::tuple<T, Ts...>> | |
{ | |
// next step | |
using type = typename concat< | |
T, | |
typename set_<K, V, std::tuple<Ts...>>::type | |
>::type; | |
}; | |
template <typename K, typename Vo, typename V, typename... Ts> | |
struct set_<K, V, std::tuple<variable<K, Vo>, Ts...>> | |
{ | |
// key hit | |
using type = std::tuple<variable<K, V>, Ts...>; | |
}; | |
template <typename K, typename V, typename... Ts> | |
struct set_<K, V, std::tuple<Ts...>> | |
{ | |
// key miss hit | |
// error | |
}; | |
// variable define | |
template <typename, typename, typename> | |
struct def_; | |
// def_: key -> value -> environment -> environment | |
template <typename K, typename V, typename T, typename... Ts> | |
struct def_<K, V, std::tuple<T, Ts...>> | |
{ | |
// next step | |
using type = typename concat< | |
T, | |
typename def_<K, V, std::tuple<Ts...>>::type | |
>::type; | |
}; | |
template <typename K, typename Vo, typename V, typename... Ts> | |
struct def_<K, V, std::tuple<variable<K, Vo>, Ts...>> | |
{ | |
// key hit : already defined | |
// error | |
}; | |
template <typename K, typename V, typename... Ts> | |
struct def_<K, V, std::tuple<Ts...>> | |
{ | |
// key miss hit : variable define | |
using type = std::tuple<variable<K, V>, Ts...>; | |
}; | |
// array element getter | |
template <typename K, int I, typename T> | |
struct get_i | |
{ | |
using type = typename tuple::get_< | |
typename get_<K, T>::type, | |
I | |
>::type; | |
}; | |
// array element setter | |
template <typename K, int I, typename V, typename T> | |
struct set_i | |
{ | |
using type = typename set_< | |
K, | |
typename tuple::set_< | |
typename get_<K, T>::type, | |
I, | |
V | |
>::type, | |
T | |
>::type; | |
}; | |
} | |
namespace rule | |
{ | |
// has F evaluate function ? | |
template <typename F> | |
struct has_eval | |
{ | |
private: | |
template <typename U, typename U::_* = 0> | |
struct aux{}; | |
typedef char yes; | |
typedef short no; | |
template <typename U> | |
static yes test(U*, aux<U, &(typename U::template _<void>())>* = 0); | |
template <typename U> | |
static no test(...); | |
public: | |
static const bool value = (sizeof(test<F>(0)) == sizeof(yes)); | |
}; | |
// evaluate | |
// eval: F -> environment -> result | |
template <typename F, typename T> | |
struct eval_ | |
{ | |
using type = typename F::template _<T>::type; | |
}; | |
// evaluate [value] | |
// eval: F -> environment -> type -> type | |
template <typename F, typename T, typename R> | |
struct eval_v | |
{ | |
static const R value = typename F::template _<T>::value; | |
}; | |
template <typename F, typename T> struct eval_c : public eval_v<F, T, bool>{}; | |
template <typename F, typename T> struct eval_i : public eval_v<F, T, int>{}; | |
// try evaluate | |
// try: F -> environment -> F | result | |
template <typename F, typename T, typename E = void> | |
struct try_eval_; | |
// can eval | |
template <typename F, typename T> | |
struct try_eval_<F, T, typename std::enable_if<has_eval<F>::value>::type> | |
{ | |
using type = typename eval_<F, T>::type; | |
}; | |
// can not eval | |
template <typename F, typename T> | |
struct try_eval_<F, T, typename std::enable_if<!has_eval<F>::value>::type> | |
{ | |
using type = F; | |
}; | |
// try evaluate [value] | |
// try: F -> environment -> type -> F | type | |
template <typename F, typename T, typename R, typename E = void> | |
struct try_eval_v; | |
// can eval | |
template <typename F, typename T, typename R> | |
struct try_eval_v<F, T, R, typename std::enable_if<has_eval<F>::value>::type> | |
{ | |
static const R value = eval_v<F, T, R>::value; | |
}; | |
// can not eval | |
template <typename F, typename T, typename R> | |
struct try_eval_v<F, T, R, typename std::enable_if<!has_eval<F>::value>::type> | |
{ | |
static const R value = F; | |
}; | |
template <typename F, typename T> struct try_eval_c : public try_eval_v<F, T, bool>{}; | |
template <typename F, typename T> struct try_eval_i : public try_eval_v<F, T, int>{}; | |
} | |
namespace context | |
{ | |
//////////////////////////////////////////////////////////////////// | |
// | |
// context block / entry point / identity function / return | |
// | |
// context block | |
template <typename... Fs> | |
struct do_; | |
// do_: environment -> instruction... -> result | |
template <typename F, typename... Fs> | |
struct do_<F, Fs...> | |
{ | |
template <typename T> | |
struct _ | |
{ | |
// serial evaluate | |
using type = typename rule::eval_< | |
do_<Fs...>, | |
typename rule::eval_<F, T>::type | |
>::type; | |
}; | |
}; | |
template <> | |
struct do_<> | |
{ | |
template <typename T> | |
struct _ | |
{ | |
// no evaluate target | |
using type = T; | |
}; | |
}; | |
// entry point | |
// main_: instruction... -> result | |
template <typename... Fs> | |
struct main_ | |
{ | |
using type = typename rule::eval_<do_<Fs...>, std::tuple<>>::type; | |
}; | |
// identity function | |
// id_: T -> T | |
struct id_ | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = T; | |
}; | |
}; | |
// return | |
// return_: T -> environment -> environment' | |
template <typename F> | |
struct return_ | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename rule::try_eval_<F, T>::type; | |
}; | |
}; | |
//////////////////////////////////////////////////////////////////// | |
// | |
// if / while / for | |
// | |
// if block [impl] | |
// _if_impl: bool -> context -> context -> environment -> result | |
template <bool, typename, typename, typename> | |
struct _if_impl; | |
template <typename F1, typename F2, typename T> | |
struct _if_impl<true, F1, F2, T> | |
{ | |
// condition == true | |
using type = typename rule::eval_<F1, T>::type; | |
}; | |
template <typename F1, typename F2, typename T> | |
struct _if_impl<false, F1, F2, T> | |
{ | |
// condition == false | |
using type = typename rule::eval_<F2, T>::type; | |
}; | |
// if block | |
// if_: condition -> context -> context -> result | |
template <typename C, typename F1, typename F2 = do_<>> | |
struct if_ | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename _if_impl< | |
rule::eval_c<C, T>::value, | |
F1, | |
F2, | |
T | |
>::type; | |
}; | |
}; | |
// while block [impl] | |
// _while_impl: bool -> condition -> context -> environment -> result | |
template <bool B, typename C, typename F, typename T> | |
struct _while_impl; | |
template <typename C, typename F, typename T> | |
struct _while_impl<true, C, F, T> | |
{ | |
// condition == true | |
using type = typename _while_impl< | |
rule::eval_c<C, typename rule::eval_<F, T>::type>::value, | |
C, | |
F, | |
typename rule::eval_<F, T>::type | |
>::type; | |
}; | |
template <typename C, typename F, typename T> | |
struct _while_impl<false, C, F, T> | |
{ | |
// condition == false | |
using type = T; | |
}; | |
// while block | |
// while_: condition -> context -> result | |
template <typename C, typename F> | |
struct while_ | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename _while_impl< | |
rule::eval_c<C, T>::value, | |
C, | |
F, | |
T | |
>::type; | |
}; | |
}; | |
// for block | |
// for_: context -> condition -> context -> context -> result | |
template <typename Fi, typename C, typename Fu, typename F> | |
struct for_ | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename rule::eval_<do_< | |
Fi, | |
while_<C, do_< | |
F, | |
Fu | |
>> | |
>, T>::type; | |
}; | |
}; | |
} | |
namespace context { namespace operators | |
{ | |
// variable define | |
// var_: key -> value -> environment -> environment | |
template <typename K, typename V = void> | |
struct var_ | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename accessor::def_< | |
K, | |
typename rule::try_eval_<V, T>::type, | |
T | |
>::type; | |
}; | |
}; | |
// variable getter | |
// get_: key -> environment -> value | |
template <typename K> | |
struct get_ | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename accessor::get_<K, T>::type; | |
}; | |
}; | |
// variable setter | |
// set_: key -> value -> environment -> environment | |
template <typename K, typename V = void> | |
struct set_ | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename accessor::set_< | |
K, | |
typename rule::try_eval_<V, T>::type, | |
T | |
>::type; | |
}; | |
}; | |
// array element getter | |
// get_i: key -> index -> environment -> value | |
template <typename K, typename I> | |
struct get_i | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename accessor::get_i< | |
K, | |
rule::try_eval_<I, T>::type::value, | |
T | |
>::type; | |
}; | |
}; | |
// get_i: integer | |
template <typename K, int I> | |
struct get_i<K, value::int_<I>> | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename accessor::get_i<K, I, T>::type; | |
}; | |
}; | |
// array element setter | |
// set_i: key -> index -> value -> environment -> environment | |
template <typename K, typename I, typename V> | |
struct set_i | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename accessor::set_i< | |
K, | |
rule::try_eval_<I, T>::type::value, | |
typename rule::try_eval_<V, T>::type, | |
T | |
>::type; | |
}; | |
}; | |
// set_i: integer | |
template <typename K, int I, typename V> | |
struct set_i<K, value::int_<I>, V> | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename accessor::set_i< | |
K, | |
I, | |
typename rule::try_eval_<V, T>::type, | |
T | |
>::type; | |
}; | |
}; | |
// integer array | |
template <int...> | |
struct int_a; | |
// int_a: integer... -> tuple | |
template <int N, int... Ns> | |
struct int_a<N, Ns...> | |
{ | |
template <typename T> | |
struct _ | |
{ | |
// next step | |
using type = typename tuple::concat< | |
value::int_<N>, | |
typename rule::eval_<int_a<Ns...>, T>::type | |
>::type; | |
}; | |
}; | |
template <> | |
struct int_a<> | |
{ | |
template <typename T> | |
struct _ | |
{ | |
// stop | |
using type = std::tuple<>; | |
}; | |
}; | |
// value comparator [less] | |
template <typename F1, typename F2> | |
struct less_ | |
{ | |
template <typename T> | |
struct _ | |
{ | |
static const bool value = rule::try_eval_c< | |
less_< | |
typename rule::try_eval_<F1, T>::type, | |
typename rule::try_eval_<F2, T>::type | |
>, | |
T | |
>::value; | |
}; | |
}; | |
// integer | |
template <int A, int B> | |
struct less_<value::int_<A>, value::int_<B>> | |
{ | |
template <typename T> | |
struct _ | |
{ | |
static const bool value = (A < B); | |
}; | |
}; | |
// value comparator [not equal] | |
template <typename F1, typename F2> | |
struct neq_ | |
{ | |
template <typename T> | |
struct _ | |
{ | |
static const bool value = rule::try_eval_c< | |
neq_< | |
typename rule::try_eval_<F1, T>::type, | |
typename rule::try_eval_<F2, T>::type | |
>, | |
T | |
>::value; | |
}; | |
}; | |
// value comparator: integer | |
template <int A, int B> | |
struct neq_<value::int_<A>, value::int_<B>> | |
{ | |
template <typename T> | |
struct _ | |
{ | |
static const bool value = (A != B); | |
}; | |
}; | |
// value operator [plus] | |
template <typename F1, typename F2> | |
struct plus_ | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = typename rule::try_eval_< | |
plus_< | |
typename rule::try_eval_<F1, T>::type, | |
typename rule::try_eval_<F2, T>::type | |
>, | |
T | |
>::type; | |
}; | |
}; | |
// integer | |
template <int A, int B> | |
struct plus_<value::int_<A>, value::int_<B>> | |
{ | |
template <typename T> | |
struct _ | |
{ | |
using type = value::int_<A + B>; | |
}; | |
}; | |
}} | |
int main(void) | |
{ | |
using namespace value; | |
using namespace context; | |
using namespace context::operators; | |
typedef name_<'a'> a; | |
typedef name_<'t'> t; | |
typedef name_<'i'> i; | |
typedef name_<'j'> j; | |
static_assert(std::is_same< | |
// bubble sort | |
main_< | |
var_< a, int_a<4, 1, 6, 3, 5, 2> >, | |
var_< t >, | |
var_< i >, | |
var_< j >, | |
for_< | |
set_< i, int_<0> >, | |
neq_< get_<i>, int_<6> >, | |
set_< i, plus_<get_<i>, int_<1>> >, | |
do_< | |
for_< | |
set_< j, plus_<get_<i>, int_<1>> >, | |
neq_< get_<j>, int_<6>>, | |
set_< j, plus_<get_<j>, int_<1>> >, | |
do_< | |
if_< | |
less_< get_i<a, get_<j>>, get_i<a, get_<i>> >, | |
do_< | |
set_< t, get_i<a, get_<j>> >, | |
set_i< a, get_<j>, get_i<a, get_<i>> >, | |
set_i< a, get_<i>, get_<t> > | |
> | |
> | |
> | |
> | |
> | |
>, | |
return_<get_<a>> | |
>::type, | |
// expect result | |
rule::eval_<int_a< 1, 2, 3, 4, 5, 6 >, void>::type | |
>::value, "fail"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment