Skip to content

Instantly share code, notes, and snippets.

@hidez8891
Created January 31, 2015 15:40
Show Gist options
  • Save hidez8891/3ee9f1f437b3afebd4f8 to your computer and use it in GitHub Desktop.
Save hidez8891/3ee9f1f437b3afebd4f8 to your computer and use it in GitHub Desktop.
tlang | c like language made from c++ template language
#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