LISP_in_templates/main.cpp

327 lines
7.9 KiB
C++

#include<iostream>
namespace S { //S-Expressions
template<int Name> struct Atom {const static int name = Name;};
#define name(N,S) template<> struct Atom<-N> {const static int name = -N; char* str = #S;}; Atom<-N> typedef S;
name( 1,NIL)
name( 2,CONS)
name( 3,ATOM)
name( 4,T)
name( 5,F)
name( 6,CAR)
name( 7,CDR)
name( 8,LAMBDA)
name( 9,LABEL)
name(10,QUOTE)
name(11,COND)
name(12,EQ)
name(13,EQUAL)
name(14,LIST)
#undef name
// cons
template<typename L, typename R>
struct Cons {};
// bool to Symbolic Bool conversion
template<bool B>
struct ToSbool {};
template<>
struct ToSbool<true> {
T typedef value;
};
template<>
struct ToSbool<false> {
F typedef value;
};
// Sybolic Bool to bool conversion
template<typename B>
struct ToBool {};
template<>
struct ToBool<T> {
const static bool value = true;
};
template<>
struct ToBool<F> {
const static bool value = false;
};
}
namespace M { //M-Expressions
// atom
template<typename E>
struct Atom {
S::F typedef value;
};
template<int I>
struct Atom<S::Atom<I> > {
S::T typedef value;
};
// car
template<typename E>
struct Car {};
template<typename A, typename D>
struct Car<S::Cons<A, D> > {
A typedef value;
};
// cdr
template<typename E>
struct Cdr {};
template<typename A, typename D>
struct Cdr<S::Cons<A, D> > {
D typedef value;
};
// eq
template<typename E1, typename E2>
struct Eq {};
template<int I1, int I2>
struct Eq<S::Atom<I1>, S::Atom<I2> > {
S::F typedef value;
};
template<int I>
struct Eq<S::Atom<I>, S::Atom<I> > {
S::T typedef value;
};
// equal
template<typename E1, typename E2>
struct Equal {
S::F typedef value;
};
template<typename A1, typename A2, typename D1, typename D2>
struct Equal<S::Cons<A1, D1>, S::Cons<A2, D2> > {
typename Equal<A1, A2>::value typedef EA;
typename Equal<D1, D2>::value typedef ED;
typename S::ToSbool<
S::ToBool<EA>::value && S::ToBool<ED>::value
>::value typedef value;
};
template<int I1, int I2>
struct Equal<S::Atom<I1>, S::Atom<I2> > {
typename Eq<S::Atom<I1>, S::Atom<I2> >::value typedef value;
};
// eval (prototype)
template<typename X, typename E>
struct Eval {};
// evlist
template<typename L, typename E>
struct Evlist {};
template<typename E>
struct Evlist<S::NIL, E> {
S::NIL typedef value;
};
template<typename H, typename R, typename E>
struct Evlist<S::Cons<H, R>, E> {
S::Cons<typename Eval<H, E>::value, typename Evlist<R, E>::value> typedef value;
};
// assoc
template<typename X, typename E>
struct Assoc {};
template<typename X, typename V, typename R>
struct Assoc<X, S::Cons<S::Cons<X, V>, R> > {
V typedef value;
};
template<typename X, typename WX, typename WV, typename R>
struct Assoc<X, S::Cons<S::Cons<WX, WV>, R> > {
typename Assoc<X, R>::value typedef value;
};
// evcond
template<typename C, typename E>
struct Evcond {};
template<typename V, typename R, typename E>
struct Evcond<S::Cons<S::Cons<S::T, S::Cons<V, S::NIL> >, R>, E> {
typename Eval<V, E>::value typedef value;
};
template<typename V, typename R, typename E>
struct Evcond<S::Cons<S::Cons<S::F, S::Cons<V, S::NIL> >, R>, E> {
typename Evcond<R, E>::value typedef value;
};
template<typename Tr, typename V, typename R, typename E>
struct Evcond<S::Cons<S::Cons<Tr, S::Cons<V, S::NIL> >, R>, E> {
typename Evcond<S::Cons<S::Cons<typename Eval<Tr, E>::value, S::Cons<V, S::NIL> >, R>, E>::value typedef value;
};
// pairlist
template<typename As, typename Ds, typename E>
struct Pairlist {};
template<typename Ds, typename E>
struct Pairlist<S::NIL, Ds, E> {
E typedef value;
};
template<typename A, typename RA, typename D, typename RD, typename E>
struct Pairlist<S::Cons<A, RA>, S::Cons<D, RD>, E> {
S::Cons<S::Cons<A, D>, typename Pairlist<RA, RD, E>::value> typedef value;
};
// eval
template<int I, typename E>
struct Eval<S::Atom<I>, E> {
typename Assoc<S::Atom<I>, E>::value typedef value;
};
template<typename R, typename E>
struct Eval<S::Cons<S::QUOTE, R>, E> {
typename Car<R>::value typedef value;
};
template<typename R, typename E>
struct Eval<S::Cons<S::ATOM, R>, E> {
typename Atom<typename Eval<typename Car<R>::value, E>::value>::value typedef value;
};
template<typename R, typename E>
struct Eval<S::Cons<S::COND, R>, E> {
typename Evcond<R, E>::value typedef value;
};
template<typename R, typename E>
struct Eval<S::Cons<S::EQ, R>, E> {
typename Eq<
typename Eval<typename Car<R>::value, E>::value,
typename Eval<typename Car<typename Cdr<R>::value>::value, E>::value
>::value typedef value;
};
template<typename R, typename E>
struct Eval<S::Cons<S::EQUAL, R>, E> {
typename Equal<
typename Eval<typename Car<R>::value, E>::value,
typename Eval<typename Car<typename Cdr<R>::value>::value, E>::value
>::value typedef value;
};
template<typename R, typename E>
struct Eval<S::Cons<S::CAR, R>, E> {
typename Car<
typename Eval<typename Car<R>::value, E>::value
>::value typedef value;
};
template<typename R, typename E>
struct Eval<S::Cons<S::CDR, R>, E> {
typename Cdr<
typename Eval<typename Car<R>::value, E>::value
>::value typedef value;
};
template<typename R, typename E>
struct Eval<S::Cons<S::CONS, R>, E> {
S::Cons<
typename Eval<typename Car<R>::value, E>::value,
typename Eval<typename Car<typename Cdr<R>::value>::value, E>::value
> typedef value;
};
template<typename R, typename E>
struct Eval<S::Cons<S::LIST, R>, E> {
typename Evlist<R, E>::value typedef value;
};
template<int N, typename R, typename E>
struct Eval<S::Cons<S::Atom<N>, R>, E> {
typename Eval<S::Cons<typename Eval<S::Atom<N>, E>::value, R>, E>::value typedef value;
};
template<typename Names, typename Body, typename R, typename E>
struct Eval<S::Cons<S::Cons<S::LAMBDA, S::Cons<Names, S::Cons<Body, S::NIL> > >, R>, E> {
typename Eval<
Body,
typename Pairlist<Names, typename Evlist<R, E>::value, E>::value
>::value typedef value;
};
template<int N, typename Body, typename R, typename E>
struct Eval<S::Cons<S::Cons<S::LABEL, S::Cons<S::Atom<N>, S::Cons<Body, S::NIL> > >, R>, E> {
typename Eval<
S::Cons<Body, R>,
S::Cons<S::Cons<S::Atom<N>, Body>, E>
>::value typedef value;
};
}
int main() {
/* Human-readable version of the following expression
Eval[
((LABEL Atom0
(LAMBDA (Atom1 Atom2) (COND
((EQUAL Atom1 'NIL) Atom2)
(T (CONS (CAR Atom1) (Atom0 (CDR Atom1) Atom2)))
)))
'(Atom3 Atom4)
'(Atom5 Atom6));
NIL
]
*/
typename M::Eval<
S::Cons<
S::Cons<
S::LABEL,
S::Cons<
S::Atom<0>,//concat
S::Cons<
S::Cons<
S::LAMBDA,
S::Cons<
S::Cons<
S::Atom<1>,
S::Cons<
S::Atom<2>,
S::NIL> >,
S::Cons<
S::Cons<
S::COND,
S::Cons<
S::Cons<
S::Cons<
S::EQUAL,
S::Cons<
S::Atom<1>,
S::Cons<
S::Cons<
S::QUOTE,
S::Cons<
S::NIL,
S::NIL> >,
S::NIL> > >,
S::Cons<
S::Atom<2>,
S::NIL> >,
S::Cons<
S::Cons<
S::T,
S::Cons<
S::Cons<
S::CONS,
S::Cons<
S::Cons<
S::CAR,
S::Cons<
S::Atom<1>,
S::NIL> >,
S::Cons<
S::Cons<
S::Atom<0>,
S::Cons<
S::Cons<
S::CDR,
S::Cons<
S::Atom<1>,
S::NIL> >,
S::Cons<
S::Atom<2>,
S::NIL> > >,
S::NIL> > >,
S::NIL> >,
S::NIL> > >,
S::NIL> > >,
S::NIL> > >,
S::Cons<
S::Cons<
S::QUOTE,
S::Cons<
S::Cons<
S::Atom<3>,
S::Cons<
S::Atom<4>,
S::NIL> >,
S::NIL> >,
S::Cons<
S::Cons<
S::QUOTE,
S::Cons<
S::Cons<
S::Atom<5>,
S::Cons<
S::Atom<6>,
S::NIL> >,
S::NIL> >,
S::NIL> > >,
S::NIL
>::value typedef X; //X is the result of the computation
X::print_by_error; //print_by_error doesn't exist, so a compiler with good feedback will represent the type "X" in an error
return 0;
}