用皮亚诺公里做了一个C++模板元编程语言

1-不支持负数
2-只能处理100以内的整数
3-只有整型和布尔值两种数据类型
4-有bug
5-支持常见的函数式编程如

i0, i1, ..., i9, i10 --- 表示数字0到10

Succ<N> --- 后继
Pred<N> --- 前驱

Add<N1, N2> --- 加
Sub<N1, N2> --- 减
Mul<N1, N2> --- 乘
Div<N1, N2> --- 除

True, False --- 布尔值
And<Bool, Bool> --- 与
Or<Bool, Bool> --- 或
Not<Bool> --- 非

Equal<N1, N2> --- 等于
LessThan<N1, N2> --- 小于
LessEqual<N1, N2> --- 小于等于
GreaterThan<N1, N2> --- 大于
GreaterEqual<N1, N2> --- 大于等于

If<Bool, Expr1, Expr2> --- 若Bool为真则值为Expr1否则为Expr2

Pair<H, T> --- 二元组
Head<Pair> --- 二元组第一个元素
Tail<Pair> --- 二元组第二个元素

List<Args...> --- 列表
Length<List> --- 列表长度
Nth<N, List> --- 列表第N个元素

Take<N, List> --- 截取列表前N个元素
Drop<N, List> --- 舍弃列表前N个元素
Concat<List1, List2> --- 链接两个列表

Map<Func, List> --- 函数式map
Filter<Func, List> --- 函数式filter
FoldLeft<Func, List> --- 函数式foldleft

Is_Integer<N> --- 辨别数字
Is_Boolean<Bool> --- 辨别布尔值
Is_Odd<N> --- 是奇数
Is_Even<N> --- 是偶数
Is_Pair<Pair> --- 是二元组

Max<N1, N2> --- 最大值
Min<N1, N2> --- 最小值

6-一些测试用函数
Assert<Bool>::True() --- 断言Bool为真
Integer<N>::ToInt --- 获得整型值
Boolean<B>::ToBool --- 获得布尔值
DisplayInteger<N>::Display() --- 显示整型值
DisplayBoolean<B>::Display() --- 显示布尔值
DisplayList<L>::Display() --- 显示列表
#pragma once

#include <iostream>

namespace raven {

    /************************************************* Peano *************************************************/

    // Undefined
    struct Undefined {
        using Pred = Undefined;
    };

    // Zero
    struct Zero {
        using Pred = Zero;
    };

    // Succ
    template <class N>
    struct Succ;

    template <>
    struct Succ < Zero > { 
        using Pred = Zero;
    };

    template <>
    struct Succ < Undefined > {
        using Pred = Undefined;
    };

    template <class N>
    struct Succ < Succ<N> > { 
        using Pred = Succ<N>;
    };

    // Pred
    template <class N>
    struct Pred;

    template<>
    struct Pred < Zero > {
        using Value = Zero;
    };

    template<>
    struct Pred < Undefined > {
        using Value = Undefined;
    };

    template<class N>
    struct Pred < Succ<N> > {
        using Value = N;
    };

    /************************************************* Boolean Logic *************************************************/

    // True False
    struct True {
        const static bool ToBool = true;
    };
    struct False {
        const static bool ToBool = false;
    };

    // And
    template <class B1, class B2>
    struct And {
        using Value = False;
    };

    template <>
    struct And < True, True > {
        using Value = True;
    };

    // Or
    template <class B1, class B2>
    struct Or {
        using Value = True;
    };

    template <>
    struct Or < False, False > {
        using Value = False;
    };

    // Not
    template <class B>
    struct Not {
        using Value = False;
    };

    template <>
    struct Not < False > {
        using Value = True;
    };

    /************************************************* Operator *************************************************/

    // Equal
    template <class T1, class T2>
    struct Equal {
        using Value = False;
    };

    template <class T>
    struct Equal < T, T > {
        using Value = True;
    };

    // Less Than
    template <class N1, class N2>
    struct LessThan {
        using Value = typename LessThan<typename N1::Pred, typename N2::Pred>::Value;
    };

    template <class N>
    struct LessThan < Zero, N > {
        using Value = True;
    };

    template <class N>
    struct LessThan < N, Zero > {
        using Value = False;
    };

    template <>
    struct LessThan < Zero, Zero > {
        using Value = False;
    };

    // Less Equal
    template <class N1, class N2>
    struct LessEqual {
        using Value = typename Or<typename Equal<N1, N2>::Value, typename LessThan<N1, N2>::Value>::Value;
    };

    // Greater Than
    template <class N1, class N2>
    struct GreaterThan {
        using Value = typename GreaterThan<typename N1::Pred, typename N2::Pred>::Value;
    };

    template <class N>
    struct GreaterThan < Zero, N > {
        using Value = False;
    };

    template <class N>
    struct GreaterThan < N, Zero > {
        using Value = True;
    };

    template <>
    struct GreaterThan < Zero, Zero > {
        using Value = False;
    };

    // Greater Equal
    template <class N1, class N2>
    struct GreaterEqual {
        using Value = typename Or<typename Equal<N1, N2>::Value, typename GreaterThan<N1, N2>::Value>::Value;
    };

    /************************************************* Statement *************************************************/

    // If
    template <class B, class S1, class S2>
    struct If;

    template <class S1, class S2>
    struct If < True, S1, S2 > {
        using Value = S1;
    };

    template <class S1, class S2>
    struct If < False, S1, S2 > {
        using Value = S2;
    };

    /************************************************* Calculate *************************************************/

    // Add
    template <class N1, class N2>
    struct Add;

    template <class N>
    struct Add < Zero, N > {
        using Value = N;
    };

    template <class N1, class N2>
    struct Add < Succ<N1>, N2 > {
        using Value = typename Add<N1, Succ<N2>>::Value;
    };

    // Mul
    template <class N1, class N2>
    struct Mul;

    template <class N>
    struct Mul < Zero, N > {
        using Value = Zero;
    };

    template <class N1, class N2>
    struct Mul < Succ<N1>, N2 > {
        using Value = typename Add<N2, typename Mul<N1, N2>::Value>::Value;
    };

    // Sub
    template <class N1, class N2>
    struct Sub {
        using Value = typename Sub<typename N1::Pred, typename N2::Pred>::Value;
    };

    template <class N>
    struct Sub < N, Zero > {
        using Value = N;
    };

    template <class N>
    struct Sub < Zero, N > {
        using Value = Zero;
    };

    template <>
    struct Sub < Zero, Zero > {
        using Value = Zero;
    };

    // Div
    template <class N1, class N2>
    struct Div {
        using Value = typename If<typename GreaterEqual<N1, N2>::Value, Succ<typename Div<typename Sub<N1, N2>::Value, N2>::Value>, Zero>::Value;
        using Rem = typename If<typename GreaterEqual<N1, N2>::Value, typename Div<typename Sub<N1, N2>::Value, N2>::Rem, N1>::Value;
    };

    template <class N>
    struct Div < Zero, N > {
        using Value = Zero;
        using Rem = Zero;
    };

    template <class N>
    struct Div < N, Zero > {
        using Value = Undefined;
        using Rem = Undefined;
    };

    // Number
    using i0 = Zero;
    using i1 = Succ < Zero > ;
    using i2 = Succ < i1 > ;
    using i3 = Succ < i2 > ;
    using i4 = Succ < i3 > ;
    using i5 = Succ < i4 > ;
    using i6 = Succ < i5 >;
    using i7 = Succ < i6 >;
    using i8 = Succ < i7 >;
    using i9 = Succ < i8 >;
    using i10 = Succ < i9 >;

    // Decimal
    /* template <class N, class D, class...R> struct Decimal_X { using Value = typename Decimal_X<typename Add<typename Mul<i10, N>::Value, D>::Value, R...>::Value; }; template <class N, class D> struct Decimal_X < N, D > { using Value = typename Add<typename Mul<i10, N>::Value, D>::Value; }; template <class D, class... R> struct Decimal { using Value = typename Decimal_X<Zero, D, R...>::Value; }; */

    /************************************************* Data Struct *************************************************/

    // Pair
    struct Nil { 
        using Length = Zero;
    };

    template<class First, class Rest>
    struct Pair { 
        using Head = First;
        using Tail = Rest;
        using Length = Succ < typename Rest::Length > ;
    };

    // Pair Head
    template <class Pair>
    struct Head;

    template <class H, class T>
    struct Head < Pair<H, T> > {
        using Value = H;
    };

    // Pair Tail
    template <class Pair>
    struct Tail;

    template <class H, class T>
    struct Tail < Pair<H, T> > {
        using Value = T;
    };

    // List
    template <class Head, class... Tail>
    struct List {
        using Value = Pair < Head, typename List<Tail...>::Value > ;
        using Length = typename Value::Length;
    };

    template<class Head>
    struct List < Head > {
        using Value = Pair < Head, Nil > ;
        using Length = i1;
    };

    // ListToDecimal
    template <class N, class List>
    struct ListToDecimal_X;

    template <class N, class H, class T>
    struct ListToDecimal_X < N, Pair<H, T> > {
        using Value = typename ListToDecimal_X<typename Add<typename Mul<i10, N>::Value, H>::Value, T>::Value;
    };

    template <class N>
    struct ListToDecimal_X < N, Nil > {
        using Value = N;
    };

    template <class List>
    struct ListToDecimal {
        using Value = typename ListToDecimal_X<i0, List>::Value;
    };
    /************************************************* Algorithm *************************************************/

    // List Length
    template <class List>
    struct Length;

    template <class H, class T>
    struct Length < Pair<H, T> > {
        using Value = Succ < typename Length<T>::Value > ;
    };

    template <>
    struct Length < Nil > {
        using Value = Zero;
    };

    // List Take
    template <class N, class List>
    struct Take {
        using Value = Pair < typename List::Head, typename Take<typename N::Pred, typename List::Tail>::Value > ;
        using Length = typename Value::Length;
    };

    template <class N>
    struct Take < N, Nil > {
        using Value = Nil;
        using Length = Zero;
    };

    template <class List>
    struct Take < Zero, List > {
        using Value = Nil;
        using Length = Zero;
    };

    // List Nth
    template <class N, class List>
    struct Nth;

    template <class H, class T, class N>
    struct Nth < Succ<N>, Pair<H, T> > {
        using Value = typename Nth<N, T>::Value;
    };

    template <class N>
    struct Nth < N,Nil > {
        using Value = Nil;
    };

    template <class H, class T>
    struct Nth < Zero, Pair<H, T> > {
        using Value = H;
    };

    // List Drop
    template <class N, class List>
    struct Drop;

    template <class N, class H, class T>
    struct Drop < Succ<N>, Pair<H, T> > {
        using Value = typename Drop<N, T>::Value;
    };

    template <class List>
    struct Drop < Zero, List > {
        using Value = List;
    };

    template <class N>
    struct Drop < N, Nil > {
        using Value = Nil;
    };

    // List Concat
    template <class L1, class L2>
    struct Concat;

    template <class H, class T, class List>
    struct Concat < Pair<H, T>, List > {
        using Value = Pair < H, typename Concat<T, List>::Value > ;
    };

    template <class List>
    struct Concat < Nil, List > {
        using Value = List;
    };

    /************************************************* Lambda *************************************************/

    template <template <class A> class F, class L>
    struct Map;

    template <template <class A> class F, class H, class T>
    struct Map < F, Pair<H, T> > {
        using Value = Pair < typename F<H>::Value, typename Map<F, T>::Value > ;
    };

    template <template<class A> class F>
    struct Map < F, Nil > {
        using Value = Nil;
    };

    template <template <class A, class B> class F, class I, class L>
    struct FoldLeft {
        using Value = typename FoldLeft<F, typename F<I, typename L::Head>::Value, typename L::Tail>::Value;
    };

    template <template <class A, class B> class F, class I>
    struct FoldLeft < F, I, Nil > {
        using Value = I;
    };

    template <template <class A> class F, class L>
    struct Filter {
        using Value = typename If<typename F<typename L::Head>::Value, 
                                    Pair<typename L::Head, typename Filter<F, typename L::Tail>::Value>, 
                                    typename Filter<F, typename L::Tail>::Value>::Value;
    };

    template <template <class A> class F>
    struct Filter < F, Nil > {
        using Value = Nil;
    };

    /************************************************* Function *************************************************/

    // Max
    template <class N1, class N2>
    struct Max {
        using Value = typename If<typename GreaterThan<N1, N2>::Value, N1, N2>::Value;
    };

    // Min
    template <class N1, class N2>
    struct Min {
        using Value = typename If<typename LessThan<N1, N2>::Value, N1, N2>::Value;
    };

    // Is_Odd
    template <class N>
    struct Is_Odd {
        using Value = typename Equal<typename Div<N, i2>::Rem, i1>::Value;
    };

    // Is_Even
    template <class N>
    struct Is_Even {
        using Value = typename Equal<typename Div<N, i2>::Rem, i0>::Value;
    };

    // Is_Integer
    template <class N>
    struct Is_Integer {
        using Value = False;
    };

    template <class N>
    struct Is_Integer < Succ<N> > {
        using Value = True;
    };

    template <>
    struct Is_Integer < Zero > {
        using Value = True;
    };

    // Is_Boolean
    template <class B>
    struct Is_Boolean {
        using Value = False;
    };

    template <>
    struct Is_Boolean < True > {
        using Value = True;
    };

    template <>
    struct Is_Boolean < False > {
        using Value = True;
    };

    // Is_Nil
    template <class X>
    struct Is_Nil {
        using Value = False;
    };

    template <>
    struct Is_Nil < Nil > {
        using Value = True;
    };

    // Is_Pair
    template <class P>
    struct Is_Pair {
        using Value = False;
    };
    template <class X, class Y>
    struct Is_Pair < Pair<X, Y> > {
        using Value = True;
    };

    /************************************************* Test Tool *************************************************/

    // Assert
    template <class E>
    struct Assert {
        inline static void True() { throw 0; }
    };

    template <>
    struct Assert < True > {
        inline static void True() {}
    };

    // Integer
    template <class N>
    struct Integer {
        const static int ToInt = -65536;
    };

    template <>
    struct Integer < Zero > {
        const static int ToInt = 0;
    };

    template <class N>
    struct Integer < Succ<N> > {
        const static int ToInt = Integer<N>::ToInt + 1;
    };

    // Boolean
    template <class B>
    struct Boolean {
        const static bool ToBool = false;
    };

    template <>
    struct Boolean < True > {
        const static bool ToBool = true;
    };

    template <>
    struct Boolean < False > {
        const static bool ToBool = false;
    };

    // Display Integer
    template <class N>
    struct DisplayInteger {
        inline static void Display() {
            std::cout << Integer<N>::ToInt << std::endl;
        }
    };

    // Display Boolean
    template <class B>
    struct DisplayBoolean {
        inline static void Display() {
            if (Boolean<B>::ToBool) std::cout << "true" << std::endl;
            else std::cout << "false" << std::endl;
        }
    };

    // Display List
    template <class P>
    struct DisplayList;

    template <class H, class T>
    struct DisplayList < Pair<H, T> > {
        inline static void Display() {
            if (Is_Integer<H>::Value::ToBool) {
                std::cout << Integer<H>::ToInt << " ";
            }
            else if (Is_Boolean<H>::Value::ToBool) {
                if (Boolean<H>::ToBool) std::cout << "true ";
                else std::cout << "false ";
            }
            DisplayList<T>::Display();
        }
    };

    template <>
    struct DisplayList < Nil > {
        inline static void Display() {
            std::cout << std::endl;
        }
    };

}
    cout << "[Pred 2] " << Integer<i2::Pred>::ToInt << endl;
    cout << "[Pred 3] " << Integer<Pred<i3>::Value>::ToInt << endl;
    cout << "[And True False] " << Boolean<And<True, False>::Value>::ToBool << endl;
    cout << "[Or False False] " << Boolean<Or<False, False>::Value>::ToBool << endl;
    cout << "[If True 1+2 3+4] " << Integer<If<True, Add<i1, i2>::Value, Add<i3, i4>::Value>::Value>::ToInt << endl;
    cout << "[LessThan 1 2] " << Boolean<LessThan<i1, i2>::Value>::ToBool << endl;
    cout << "[GreaterThan 2 1] " << Boolean<GreaterThan<i2, i1>::Value>::ToBool << endl;
    cout << "[If (LessThan 1 2) 1 2] " << Integer<If<LessThan<i1, i2>::Value, i1, i2>::Value>::ToInt << endl;
    cout << endl;

    cout << "[Length (List 1 2 3 4 5)] " << Integer<Length<List<i1, i2, i3, i4, i5>::Value>::Value>::ToInt << endl;
    cout << "[Head (Pair 3 6)] " << Integer<Head<Pair<i3, i6>>::Value>::ToInt << endl;
    cout << "[Tail (Pair 3 6)] " << Integer<Tail<Pair<i3, i6>>::Value>::ToInt << endl;
    cout << "[Head (List 1 2 3 4 5)] " << Integer<Head<List<i1, i2, i3, i4, i5>::Value>::Value>::ToInt << endl;
    cout << endl;

    cout << "[take 1 (list 1 2 3 4 5)] " << Integer<Take<i1, List<i1, i2, i3, i4, i5>::Value>::Value::Length>::ToInt << endl;
    cout << "[Nth 3 (List 1 2 3 4 5)] " << Integer<Nth<i3, List<i1, i2, i3, i4, i5>::Value>::Value>::ToInt << endl;
    cout << "[Head (Drop 2 (List 1 2 3 4 5))] " << Integer<Head<Drop<i2, List<i1, i2, i3, i4, i5>::Value>::Value>::Value>::ToInt << endl;
    cout << "[Nth 2 (Concat (List 1 2) (List 3 4)] " << Integer<Nth<i2, Concat<List<i1, i2>::Value, List<i3, i4>::Value>::Value>::Value>::ToInt << endl;
    cout << "[Nth 2 (Map F (List 1 2 3))] " << Integer<Nth<i2, Map<F, List<i1, i2, i3>::Value>::Value>::Value>::ToInt << endl;
    cout << endl;

    cout << "[LessThan 1 3] " << Boolean<LessThan<i1, i3>::Value>::ToBool << endl;
    cout << "[LessEqual 2 2] " << Boolean<LessEqual<i2, i2>::Value>::ToBool << endl;
    cout << "[GreaterThan 1 3] " << Boolean<GreaterThan<i1, i3>::Value>::ToBool << endl;
    cout << "[GreaterEqual 3 1] " << Boolean<GreaterEqual<i3, i1>::Value>::ToBool << endl;
    cout << "[GreaterEqual 1 2] " << Boolean<GreaterEqual<i1, i2>::Value>::ToBool << endl;
    cout << "[GreaterThan 1 2] " << Boolean<GreaterThan<i1, i2>::Value>::ToBool << endl;
    cout << "[Equal 1 2] " << Boolean<Equal<i1, i2>::Value>::ToBool << endl;
    cout << "[greaterEqual 1 2] " << Boolean<GreaterEqual<i1, i2>::Value>::ToBool << endl;
    cout << "[Or (GreatThan 1 2) (Equal 1 2)] " << Boolean<Or<GreaterThan<i1, i2>::Value, Equal<i1, i2>::Value>::Value>::ToBool << endl;
    cout << endl;

    cout << "[Add 4 7] " << Integer<Add<i4, i7>::Value>::ToInt << endl;
    cout << "[Sub 4 7] " << Integer<Sub<i4, i7>::Value>::ToInt << endl;
    cout << "[Sub 7 4] " << Integer<Sub<i7, i4>::Value>::ToInt << endl;
    cout << "[Div 8 3] " << Integer<Div<i8, i3>::Value>::ToInt << endl;
    cout << endl;

    cout << "[FoldLeft Add 0 (list 1 2 3 4 5)] " << Integer<FoldLeft<Add, i0, List<i1, i2, i3, i4, i5>::Value>::Value>::ToInt << endl;
    cout << "[Length (Filter Is_Odd (List 1 2 3 4 5))] " << Integer<Length<Filter<Is_Odd, List<i1, i2, i3, i4, i5>::Value>::Value>::Value>::ToInt << endl;
    DisplayList<List<i1, True, i3, i4, i5>::Value>::Display();
    cout << endl;

    DisplayInteger<ListToDecimal<List<i2, i2, i3>::Value>::Value>::Display();

你可能感兴趣的:(用皮亚诺公里做了一个C++模板元编程语言)