├── .gitignore ├── Compiletime ├── list.hpp ├── Iota.hpp ├── Y_combinator.hpp ├── pair.hpp ├── SKI_combinator_calculus.hpp ├── lambda_calculus.hpp ├── BCKW_system.hpp ├── propositional_logic.hpp ├── int.hpp ├── test.hpp ├── parser.hpp └── church_numeral.hpp ├── lambda_calculus.pro ├── README.md ├── Runtime ├── Compiletime_Runtime.hpp └── lambda_calculus.hpp ├── main.cpp └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | .directory 15 | *.pro.user 16 | -------------------------------------------------------------------------------- /Compiletime/list.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_LIST 2 | #define lambda_calculus_Compiletime_LIST 3 | #include "propositional_logic.hpp" 4 | #include "lambda_calculus.hpp" 5 | namespace Compiletime_lambda_calculus 6 | { 7 | typedef abstraction< True > Nil; 8 | typedef 9 | abstraction 10 | < 11 | application 12 | < 13 | variable< 1 >, 14 | abstraction 15 | < 16 | abstraction< False > 17 | > 18 | > 19 | > Null; 20 | } 21 | #endif //lambda_calculus_Compiletime_LIST 22 | -------------------------------------------------------------------------------- /lambda_calculus.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | QMAKE_CXXFLAGS += -std=c++1z 6 | SOURCES += main.cpp 7 | 8 | OTHER_FILES += \ 9 | LICENSE \ 10 | README.md 11 | 12 | HEADERS += \ 13 | RunTime/lambda_calculus.hpp \ 14 | Compiletime/BCKW_system.hpp \ 15 | Compiletime/church_numeral.hpp \ 16 | Compiletime/int.hpp \ 17 | Compiletime/Iota.hpp \ 18 | Compiletime/lambda_calculus.hpp \ 19 | Compiletime/list.hpp \ 20 | Compiletime/pair.hpp \ 21 | Compiletime/parser.hpp \ 22 | Compiletime/propositional_logic.hpp \ 23 | Compiletime/SKI_combinator_calculus.hpp \ 24 | Compiletime/Y_combinator.hpp \ 25 | Runtime/lambda_calculus.hpp \ 26 | Runtime/Compiletime_Runtime.hpp \ 27 | Compiletime/test.hpp 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | lambda_calculus 2 | =================== 3 | A lambda_calculus library with various feature. 4 | 5 | Feature: 6 | =================== 7 | - A parser generator that can generate parser that can parse certain Combinatory Logic code (TMP) 8 | - Parsers of BCKW and Iota using parser generator (TMP) 9 | - Church Numeral (TMP) 10 | - Church Numeral and Boolean logic Interface to C++ TMP code 11 | - Propositional logic (TMP) 12 | - combinator calculus (TMP) 13 | - Data Structure such as list and pair (TMP) 14 | - The Y combinator (TMP) 15 | - Ability to convert TMP lambda calculus code into Runtime lambda calculus object. 16 | - Printing, Sorting and Testing for equality of Runtime lambda calculus object. 17 | 18 | Build and Dependency: 19 | =================== 20 | - Header Only. 21 | - Need Boost. 22 | - Need -std=c++1z. 23 | -------------------------------------------------------------------------------- /Compiletime/Iota.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_IOTA 2 | #define lambda_calculus_Compiletime_IOTA 3 | #include "SKI_combinator_calculus.hpp" 4 | #include "parser.hpp" 5 | #include "boost/mpl/map.hpp" 6 | #include "boost/mpl/pair.hpp" 7 | #include "boost/mpl/char.hpp" 8 | #include "lambda_calculus.hpp" 9 | namespace Compiletime_lambda_calculus 10 | { 11 | namespace Iota_combinator_logic 12 | { 13 | typedef 14 | abstraction 15 | < 16 | application 17 | < 18 | application 19 | < 20 | variable< 1 >, 21 | SKI_combinator_logic::S 22 | >, 23 | SKI_combinator_logic::K 24 | > 25 | > U; 26 | typedef boost::mpl::map< boost::mpl::pair< boost::mpl::char_< 'U' >, U > > Iota_map; 27 | typedef typename parser::parser_generator::apply< Iota_map >::type Iota_parser; 28 | } 29 | } 30 | #endif //lambda_calculus_Compiletime_IOTA 31 | -------------------------------------------------------------------------------- /Compiletime/Y_combinator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_Y_COMBINATOR 2 | #define lambda_calculus_Compiletime_Y_COMBINATOR 3 | #include "lambda_calculus.hpp" 4 | namespace Compiletime_lambda_calculus 5 | { 6 | typedef 7 | abstraction 8 | < 9 | application 10 | < 11 | abstraction 12 | < 13 | application 14 | < 15 | variable< 2 >, 16 | application 17 | < 18 | variable< 1 >, 19 | variable< 1 > 20 | > 21 | > 22 | >, 23 | abstraction 24 | < 25 | application 26 | < 27 | variable< 2 >, 28 | application 29 | < 30 | variable< 1 >, 31 | variable< 1 > 32 | > 33 | > 34 | > 35 | > 36 | > Y; 37 | } 38 | #endif //lambda_calculus_Compiletime_Y_COMBINATOR 39 | -------------------------------------------------------------------------------- /Compiletime/pair.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_PAIR 2 | #define lambda_calculus_Compiletime_PAIR 3 | #include "lambda_calculus.hpp" 4 | #include "propositional_logic.hpp" 5 | namespace Compiletime_lambda_calculus 6 | { 7 | typedef 8 | abstraction 9 | < 10 | abstraction 11 | < 12 | abstraction 13 | < 14 | application 15 | < 16 | application 17 | < 18 | variable< 1 >, 19 | variable< 3 > 20 | >, 21 | variable< 2 > 22 | > 23 | > 24 | > 25 | > Pair; 26 | typedef 27 | abstraction 28 | < 29 | application 30 | < 31 | variable< 1 >, 32 | True 33 | > 34 | > First; 35 | typedef 36 | abstraction 37 | < 38 | application 39 | < 40 | variable< 1 >, 41 | False 42 | > 43 | > Second; 44 | } 45 | #endif //lambda_calculus_Compiletime_PAIR 46 | -------------------------------------------------------------------------------- /Runtime/Compiletime_Runtime.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Runtime_Compiletime_Runtime 2 | #define lambda_calculus_Runtime_Compiletime_Runtime 3 | #include "./Runtime/lambda_calculus.hpp" 4 | #include "./Compiletime/lambda_calculus.hpp" 5 | namespace Runtime_lambda_calculus 6 | { 7 | template< typename type_expression > 8 | struct Compiletime_Runtime_converter; 9 | 10 | template< typename fst, typename snd > 11 | struct Compiletime_Runtime_converter< Compiletime_lambda_calculus::application< fst, snd > > 12 | { 13 | exp operator ( )( ) const 14 | { return app( Compiletime_Runtime_converter< fst >( )( ), Compiletime_Runtime_converter< snd >( )( ) ); } 15 | }; 16 | 17 | template< typename abst > 18 | struct Compiletime_Runtime_converter< Compiletime_lambda_calculus::abstraction< abst > > 19 | { 20 | exp operator ( )( ) const 21 | { return abs( Compiletime_Runtime_converter< abst >( )( ) ); } 22 | }; 23 | 24 | template< size_t i > 25 | struct Compiletime_Runtime_converter< Compiletime_lambda_calculus::variable< i > > 26 | { 27 | exp operator ( )( ) const 28 | { return var( i ); } 29 | }; 30 | } 31 | #endif //lambda_calculus_Runtime_Compiletime_Runtime 32 | -------------------------------------------------------------------------------- /Compiletime/SKI_combinator_calculus.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_SKI_COMBINATOR_CALCULUS 2 | #define lambda_calculus_Compiletime_SKI_COMBINATOR_CALCULUS 3 | #include "lambda_calculus.hpp" 4 | #include "propositional_logic.hpp" 5 | #include "parser.hpp" 6 | namespace Compiletime_lambda_calculus 7 | { 8 | namespace SKI_combinator_logic 9 | { 10 | typedef 11 | abstraction 12 | < 13 | abstraction 14 | < 15 | abstraction 16 | < 17 | application 18 | < 19 | application 20 | < 21 | variable< 3 >, 22 | variable< 1 > 23 | >, 24 | application 25 | < 26 | variable< 2 >, 27 | variable< 1 > 28 | > 29 | > 30 | > 31 | > 32 | > S; 33 | typedef True K; 34 | typedef abstraction< variable< 1 > > I; 35 | typedef 36 | boost::mpl::map 37 | < 38 | boost::mpl::pair< boost::mpl::char_< 'S' >, S >, 39 | boost::mpl::pair< boost::mpl::char_< 'K' >, K >, 40 | boost::mpl::pair< boost::mpl::char_< 'I' >, I > 41 | > SKI_map; 42 | typedef typename parser::parser_generator::apply< SKI_map >::type SKI_parser; 43 | } 44 | } 45 | #endif //lambda_calculus_Compiletime_SKI_COMBINATOR_CALCULUS 46 | -------------------------------------------------------------------------------- /Compiletime/lambda_calculus.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_lambda_calculus 2 | #define lambda_calculus_Compiletime_lambda_calculus 3 | #include 4 | namespace Compiletime_lambda_calculus 5 | { 6 | using namespace std; 7 | template< typename x, typename y > 8 | struct application 9 | { 10 | template< size_t i, size_t depth > 11 | struct update { typedef application< typename x::template update< i, depth >::type, typename y::template update< i, depth >::type > type; }; 12 | template< typename t > 13 | struct apply 14 | { typedef typename x::template apply< y >::type::template apply< t >::type type; }; 15 | template< size_t depth, typename t > 16 | struct rebound 17 | { typedef application< typename x::template rebound< depth, t >::type, typename y::template rebound< depth, t >::type > type; }; 18 | }; 19 | 20 | template< size_t x > 21 | struct variable 22 | { 23 | template< size_t i, size_t depth > 24 | struct update { typedef variable< ( x > depth ) ? ( x + i - 1 ) : x > type; }; 25 | template< size_t depth, typename t > 26 | struct rebound 27 | { typedef typename conditional< x == depth, typename t::template update< depth, 0 >::type, variable< ( x > depth ) ? x - 1 : x > >::type type; }; 28 | }; 29 | 30 | template< typename x > 31 | struct abstraction 32 | { 33 | template< size_t i, size_t depth > 34 | struct update { typedef abstraction< typename x::template update< i, depth + 1 >::type > type; }; 35 | template< typename t > 36 | struct apply 37 | { typedef typename x::template rebound< 1, t >::type type; }; 38 | template< int depth, typename t > 39 | struct rebound 40 | { typedef abstraction< typename x::template rebound< depth + 1, t >::type > type; }; 41 | }; 42 | } 43 | #endif //lambda_calculus_Compiletime_lambda_calculus 44 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "Compiletime/test.hpp" 2 | #include "Runtime/lambda_calculus.hpp" 3 | #include "Runtime/Compiletime_Runtime.hpp" 4 | #include "cassert" 5 | #define Bridge( Name ) exp Name ## _ = Compiletime_Runtime_converter< Name >( )( ) 6 | int main( ) 7 | { 8 | using Runtime_lambda_calculus::abs; 9 | using Runtime_lambda_calculus::app; 10 | using Runtime_lambda_calculus::var; 11 | using Runtime_lambda_calculus::exp; 12 | using Runtime_lambda_calculus::Compiletime_Runtime_converter; 13 | using Runtime_lambda_calculus::eval; 14 | using Runtime_lambda_calculus::eval_step; 15 | using Runtime_lambda_calculus::show; 16 | using namespace Compiletime_lambda_calculus; 17 | using namespace SKI_combinator_logic; 18 | Bridge( Null ); 19 | Bridge( Nil ); 20 | Bridge( Pair ); 21 | Bridge( Y ); 22 | Bridge( First ); 23 | Bridge( Second ); 24 | Bridge( Conditional ); 25 | Bridge( True ); 26 | Bridge( False ); 27 | Bridge( I ); 28 | Bridge( K ); 29 | Bridge( S ); 30 | exp program_inner = abs( abs( abs( app( 31 | app( 32 | app( 33 | Conditional_, 34 | app( Null_, var( 1 ) ) ), 35 | Nil_), 36 | app( 37 | app( 38 | app( 39 | Conditional_, 40 | app( var( 3 ), app( First_, var( 1 ) ) ) ), 41 | app( var( 2 ), app( Second_, var( 1 ) ) ) ), 42 | app( app( Pair_, app( First_, var( 1 ) ) ), app( var( 2 ), app( Second_, var( 1 ) ) ) ) ) ) ) ) ); 43 | exp list_i = app( app( Pair_, Nil_ ), Nil_ ); 44 | exp list_ = app( app( Pair_, list_i ), app( app( Pair_, Nil_ ), list_i ) ); 45 | exp program = abs( abs( app( app( Y_, app( eval( program_inner ), var( 2 ) ) ), var( 1 ) ) ) ); 46 | exp current = app( app( program, Null_ ), list_ ); 47 | std::cout << show( program ) << std::endl; 48 | std::cout << show( current ) << std::endl; 49 | using namespace Runtime_lambda_calculus; 50 | while ( true ) 51 | { 52 | exp temp = eval_step( current ); 53 | if ( temp == current ) { return 0; } 54 | current = temp; 55 | std::cout << show( current ) << std::endl; 56 | std::cin.get( ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Compiletime/BCKW_system.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_BCKW_SYSTEM 2 | #define lambda_calculus_Compiletime_BCKW_SYSTEM 3 | #include "lambda_calculus.hpp" 4 | #include "SKI_combinator_calculus.hpp" 5 | #include "boost/mpl/char.hpp" 6 | #include "boost/mpl/map.hpp" 7 | #include "parser.hpp" 8 | namespace Compiletime_lambda_calculus 9 | { 10 | namespace BCKW_combinator_logic 11 | { 12 | typedef 13 | abstraction 14 | < 15 | abstraction 16 | < 17 | abstraction 18 | < 19 | application 20 | < 21 | variable< 3 >, 22 | application 23 | < 24 | variable< 2 >, 25 | variable< 1 > 26 | > 27 | > 28 | > 29 | > 30 | >B; 31 | typedef 32 | abstraction 33 | < 34 | abstraction 35 | < 36 | abstraction 37 | < 38 | application 39 | < 40 | application 41 | < 42 | variable< 3 >, 43 | variable< 1 > 44 | >, 45 | variable< 2 > 46 | > 47 | > 48 | > 49 | > C; 50 | typedef SKI_combinator_logic::K K; 51 | typedef 52 | abstraction 53 | < 54 | abstraction 55 | < 56 | application 57 | < 58 | application 59 | < 60 | variable< 2 >, 61 | variable< 1 > 62 | >, 63 | variable< 1 > 64 | > 65 | > 66 | >W; 67 | typedef 68 | boost::mpl::map 69 | < 70 | boost::mpl::pair< boost::mpl::char_< 'B' >, B >, 71 | boost::mpl::pair< boost::mpl::char_< 'C' >, C >, 72 | boost::mpl::pair< boost::mpl::char_< 'K' >, K >, 73 | boost::mpl::pair< boost::mpl::char_< 'W' >, W > 74 | > BCKW_map; 75 | typedef typename parser::parser_generator::apply< BCKW_map >::type BCKW_parser; 76 | } 77 | } 78 | #endif //lambda_calculus_Compiletime_BCKW_SYSTEM 79 | -------------------------------------------------------------------------------- /Compiletime/propositional_logic.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_PROPOSITIONAL_LOGIC 2 | #define lambda_calculus_Compiletime_PROPOSITIONAL_LOGIC 3 | #include "lambda_calculus.hpp" 4 | namespace Compiletime_lambda_calculus 5 | { 6 | typedef 7 | abstraction 8 | < 9 | abstraction 10 | < 11 | variable< 2 > 12 | > 13 | > True; 14 | typedef 15 | abstraction 16 | < 17 | abstraction 18 | < 19 | variable< 1 > 20 | > 21 | > False; 22 | typedef 23 | abstraction 24 | < 25 | abstraction 26 | < 27 | application 28 | < 29 | application 30 | < 31 | variable< 2 >, 32 | variable< 1 > 33 | >, 34 | variable< 2 > 35 | > 36 | > 37 | > And; 38 | typedef 39 | abstraction 40 | < 41 | abstraction 42 | < 43 | application 44 | < 45 | application 46 | < 47 | variable< 2 >, 48 | variable< 2 > 49 | >, 50 | variable< 1 > 51 | > 52 | > 53 | > Or; 54 | typedef 55 | abstraction 56 | < 57 | abstraction 58 | < 59 | abstraction 60 | < 61 | application 62 | < 63 | application 64 | < 65 | variable< 3 >, 66 | variable< 1 > 67 | >, 68 | variable< 2 > 69 | > 70 | > 71 | > 72 | > Not; 73 | typedef 74 | abstraction 75 | < 76 | abstraction 77 | < 78 | abstraction 79 | < 80 | application 81 | < 82 | application 83 | < 84 | variable< 3 >, 85 | variable< 2 > 86 | >, 87 | variable< 1 > 88 | > 89 | > 90 | > 91 | > Conditional; 92 | template< typename t > 93 | struct ToBool; 94 | template< > 95 | struct ToBool< True > 96 | { 97 | static constexpr bool value = true; 98 | }; 99 | template< > 100 | struct ToBool< False > 101 | { 102 | static constexpr bool value = false; 103 | }; 104 | template< typename t > 105 | struct ToBool 106 | { 107 | static constexpr bool value = 108 | ToBool< typename t::template apply< True >::type::template apply< False >::type >::value; 109 | }; 110 | } 111 | #endif //lambda_calculus_Compiletime_PROPOSITIONAL_LOGIC 112 | -------------------------------------------------------------------------------- /Compiletime/int.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_int 2 | #define lambda_calculus_Compiletime_int 3 | #include "propositional_logic.hpp" 4 | #include "lambda_calculus.hpp" 5 | namespace Compiletime_lambda_calculus 6 | { 7 | typedef 8 | abstraction 9 | < 10 | abstraction 11 | < 12 | abstraction 13 | < 14 | application 15 | < 16 | variable< 2 >, 17 | application 18 | < 19 | application 20 | < 21 | variable< 3 >, 22 | variable< 2 > 23 | >, 24 | variable< 1 > 25 | > 26 | > 27 | > 28 | > 29 | > Next; 30 | typedef False Zero; 31 | typedef Next::apply< Zero >::value One; 32 | typedef Next::apply< One >::value Two; 33 | typedef Next::apply< Two >::value Three; 34 | typedef Next::apply< Three >::value Four; 35 | typedef Next::apply< Four >::value Five; 36 | typedef Next::apply< Five >::value Six; 37 | typedef Next::apply< Six >::value Seven; 38 | typedef Next::apply< Seven >::value Eight; 39 | typedef Next::apply< Eight >::value Nine; 40 | typedef Next::apply< Nine >::value Ten; 41 | typedef Next::apply< Ten >::value Eleven; 42 | typedef Next::apply< Eleven >::value Twelve; 43 | typedef 44 | abstraction 45 | < 46 | abstraction 47 | < 48 | abstraction 49 | < 50 | abstraction 51 | < 52 | application 53 | < 54 | application 55 | < 56 | variable< 4 >, 57 | variable< 2 > 58 | >, 59 | application 60 | < 61 | application 62 | < 63 | variable< 3 >, 64 | variable< 2 > 65 | >, 66 | variable< 1 > 67 | > 68 | > 69 | > 70 | > 71 | > 72 | > Plus; 73 | typedef 74 | abstraction 75 | < 76 | abstraction 77 | < 78 | application 79 | < 80 | application 81 | < 82 | variable< 2 >, 83 | application 84 | < 85 | Plus, 86 | variable< 1 > 87 | > 88 | >, 89 | Zero 90 | > 91 | > 92 | > Multiply; 93 | typedef 94 | abstraction 95 | < 96 | abstraction 97 | < 98 | application 99 | < 100 | variable< 1 >, 101 | variable< 2 > 102 | > 103 | > 104 | > Power; 105 | template< typename x > 106 | struct ToInt 107 | { 108 | template< int n > 109 | struct num 110 | { 111 | static constexpr int count = n; 112 | template< typename y > 113 | struct apply 114 | { 115 | typedef num value; 116 | }; 117 | }; 118 | 119 | template< typename a > 120 | struct rem_application 121 | { 122 | typedef a value; 123 | }; 124 | 125 | template< typename a, typename b > 126 | struct rem_application< application< a, b > > 127 | { 128 | typedef typename rem_application< typename a::template apply< b >::value >::value value; 129 | }; 130 | 131 | struct accumulate 132 | { 133 | static constexpr int value = 0; 134 | template< typename y > 135 | struct apply { typedef num< rem_application< y >::value::count + 1 > value; }; 136 | template< int d, typename i > 137 | struct rebound { typedef accumulate value; }; 138 | template < size_t l, size_t r > 139 | struct update< l, r > { typedef accumulate type; }; 140 | }; 141 | template < size_t l, size_t r > 142 | struct update< l, r > { typedef ToInt< x > type; }; 143 | static constexpr int value = rem_application< typename x::template apply< accumulate >::value::template apply< num< 0 > >::value >::value::count; 144 | }; 145 | } 146 | #endif //lambda_calculus_Compiletime_int 147 | -------------------------------------------------------------------------------- /Compiletime/test.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_EXAMPLE 2 | #define lambda_calculus_Compiletime_EXAMPLE 3 | #include "type_traits" 4 | #include "boost/mpl/same_as.hpp" 5 | #include "boost/mpl/string.hpp" 6 | #include "lambda_calculus.hpp" 7 | #include "propositional_logic.hpp" 8 | #include "pair.hpp" 9 | #include "list.hpp" 10 | #include "church_numeral.hpp" 11 | #include "SKI_combinator_calculus.hpp" 12 | #include "BCKW_system.hpp" 13 | #include "parser.hpp" 14 | #include "Iota.hpp" 15 | #include "Y_combinator.hpp" 16 | #include 17 | namespace Compiletime_lambda_calculus 18 | { 19 | using namespace SKI_combinator_logic; 20 | using namespace church_numeral; 21 | static_assert( ToBool< True >::value ); 22 | static_assert( ToBool< Not::apply< True >::type >::value == false ); 23 | static_assert( ToBool< Not::apply< Not::apply< True >::type >::type >::value ); 24 | static_assert( ToBool< True::apply< True >::type::apply< False >::type >::value ); 25 | static_assert( ToBool< And::apply< True >::type::apply< False >::type >::value == false ); 26 | static_assert( ToBool< Or::apply< True >::type::apply< False >::type >::value ); 27 | static_assert( ToBool< First::apply< Pair::apply< True >::type::apply< False >::type >::type >::value ); 28 | static_assert( ToBool< Second::apply< Pair::apply< True >::type::apply< False >::type >::type >::value == false ); 29 | static_assert( ToBool< Null::apply< Pair::apply< True >::type::apply< False >::type >::type >::value == false ); 30 | static_assert( ToBool< Null::apply< Nil >::type >::value ); 31 | static_assert( ToInt< Zero >::value == 0 ); 32 | static_assert( ToInt< One >::value == 1 ); 33 | static_assert( ToInt< Two >::value == 2 ); 34 | static_assert( ToInt< Next::apply< Seven >::type >::value == 8 ); 35 | static_assert( ToInt< Plus::apply< Two >::type::apply< Three >::type >::value == 5 ); 36 | static_assert( ToInt< Multiply::apply< Zero >::type::apply< One >::type >::value == 0 ); 37 | static_assert( ToInt< Multiply::apply< Two >::type::apply< Three >::type >::value == 6 ); 38 | static_assert( ToInt< Power::apply< Two >::type::apply< Three >::type >::value == 8 ); 39 | static_assert( ToBool< Equal::apply< Power::apply< Three >::type::apply< Two >::type >::type::apply< Nine >::type >::value ); 40 | static_assert( ToBool< I::apply< True >::type >::value ); 41 | static_assert( ToBool< K::apply< True >::type::apply< False >::type >::value ); 42 | typedef S::apply< K >::type::apply< S >::type::apply< K >::type SKSK; 43 | static_assert( ToBool< SKSK >::value ); 44 | static_assert( ToBool< SKI_parser::apply< boost::mpl::string< '(SK)','(I(I',' )) ',' K ' > >::type >::value ); 45 | static_assert( ToInt< Int< 12 >::type >::value == 12 ); 46 | static_assert( ToBool< BCKW_combinator_logic::BCKW_parser::apply< boost::mpl::string< 'B(B(', 'BW)C', ')(BB',')','KKK' > >::type >::value ); 47 | static_assert( ToBool< Iota_combinator_logic::Iota_parser::apply< boost::mpl::string< '(U(U', '(UU)', ') ) '> >::type >::value ); 48 | static_assert( ToInt< 49 | Conditional::apply< False >::type::apply 50 | < church_numeral::Int< 12 >::type >::type::apply 51 | < church_numeral::Int< 15 >::type >::type >::value == 15 ); 52 | static_assert( ToInt< church_numeral::Before::apply< church_numeral::Eight >::type >::value == 7 ); 53 | static_assert( ! ToBool< church_numeral::IsZero::apply< church_numeral::Eight >::type >::value ); 54 | static_assert( ToBool< church_numeral::IsZero::apply< church_numeral::Zero >::type >::value ); 55 | typedef 56 | abstraction 57 | < 58 | abstraction 59 | < 60 | application 61 | < 62 | application 63 | < 64 | application 65 | < 66 | Conditional, 67 | application 68 | < 69 | application 70 | < 71 | Equal, 72 | variable< 1 > 73 | >, 74 | Four 75 | > 76 | >, 77 | Four 78 | >, 79 | application 80 | < 81 | application 82 | < 83 | Plus, 84 | application 85 | < 86 | variable< 2 >, 87 | application 88 | < 89 | Next, 90 | variable< 1 > 91 | > 92 | > 93 | >, 94 | variable< 1 > 95 | > 96 | > 97 | > 98 | >recursive_test; 99 | static_assert( ToInt< Y::apply< recursive_test >::type::apply< One >::type >::value == 10 ); 100 | } 101 | #endif //lambda_calculus_Compiletime_EXAMPLE 102 | -------------------------------------------------------------------------------- /Runtime/lambda_calculus.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Runtime_lambda_calculus 2 | #define lambda_calculus_Runtime_lambda_calculus 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include <../algebraic_data_type/algebraic_data_type.hpp> 10 | namespace Runtime_lambda_calculus 11 | { 12 | using namespace algebraic_data_type; 13 | typedef algebraic_data_type< size_t, recursive_indicator, std::tuple< recursive_indicator, recursive_indicator > > exp; 14 | DECLARE_CONSTRUCTOR( exp, 0, var, T ); 15 | DECLARE_CONSTRUCTOR( exp, 1, abs, T ); 16 | DECLARE_CONSTRUCTOR( exp, 2, app, T ); 17 | 18 | template< typename INIT, typename FUNCTION, typename FIRST > 19 | auto pack_fold_l( const INIT & init, const FUNCTION & function, const FIRST & first ) { return function( init, first ); } 20 | 21 | template< typename INIT, typename FUNCTION, typename FIRST, typename ... REST > 22 | auto pack_fold_l( const INIT & init, const FUNCTION & function, const FIRST & first, const REST & ... rest ) 23 | { return pack_fold_l( function( init, first ), function, rest ... ); } 24 | 25 | exp update_index( const exp & self, size_t i, size_t current_depth ) 26 | { 27 | return 28 | self.match( 29 | with( var( arg ), [&]( size_t ii ) { return var( ii > current_depth ? ii + i - 1 : ii ); } ), 30 | with( 31 | app( arg, arg ), 32 | [&]( const exp & l, const exp & r ) 33 | { return app( update_index( l, i, current_depth ), update_index( r, i, current_depth ) ); } ), 34 | with( 35 | abs( arg ), 36 | [&]( const exp & ex ) { return abs( update_index( ex, i, current_depth + 1 ) ); } ) ); 37 | } 38 | 39 | exp substitute( const exp & self, size_t i, const exp & ex ) 40 | { 41 | return 42 | self.match( 43 | with( var( arg ), [&]( size_t ii ) { return ii == i ? update_index( ex, i, 0 ) : var( ii > i ? ii - 1 : ii ); } ), 44 | with( app( arg, arg ), [&]( const exp & l, const exp & r ) { return app( substitute( l, i, ex ), substitute( r, i, ex ) ); } ), 45 | with( abs( arg ), [&]( const exp & l ) { return abs( substitute( l, i + 1, ex ) ); } ) ); 46 | } 47 | bool closed_expression( const exp & self, size_t current_depth ) 48 | { 49 | return 50 | self.match( 51 | with( var( arg ), [&]( size_t ii ) { return ii <= current_depth; } ), 52 | with( 53 | app( arg, arg ), 54 | [&]( const exp & l, const exp & r ) 55 | { return closed_expression( l, current_depth ) && closed_expression( r, current_depth ); } ), 56 | with( abs( arg ), [&]( const exp & ex ) { return closed_expression( ex, current_depth + 1 ); } ) ); 57 | } 58 | 59 | exp eval_step( const exp & ex ) 60 | { 61 | return 62 | ex.match( 63 | with( var( arg ), []( size_t ii ) { return var( ii ); } ), 64 | with( abs( arg ), []( const exp & e ) { return abs( eval_step( e ) ); } ), 65 | with( app( abs( arg ), arg ), []( const exp & l, const exp & r ) { return substitute( l, 1, r ); } ), 66 | with( app( arg, arg ), []( const exp & l, const exp & r ) { return app( eval_step( l ), eval_step( r ) ); } ) ); 67 | } 68 | 69 | bool operator == ( const exp & l, const exp & r ) 70 | { 71 | return 72 | l.match( 73 | with( 74 | var( arg ), 75 | [&]( size_t li ) 76 | { 77 | return 78 | r.match( 79 | with( var( arg ), [&]( size_t ri ) { return li == ri; } ), 80 | with( wildstar, []( ) { return false; } ) ); 81 | } ), 82 | with( 83 | abs( arg ), 84 | [&]( const exp & lexp ) 85 | { 86 | return 87 | r.match( 88 | with( abs( arg ), [&]( const exp & rexp ) { return lexp == rexp; } ), 89 | with( wildstar, []( ) { return false; } ) ); 90 | } ), 91 | with( 92 | app( arg, arg ), 93 | [&]( const exp & llexp, const exp & lrexp ) 94 | { 95 | return 96 | r.match( 97 | with( app( arg, arg ), [&]( const exp & rlexp, const exp & rrexp ) { return llexp == rlexp && lrexp == rrexp; } ), 98 | with( wildstar, []( ) { return false; } ) ); 99 | } ) ); 100 | } 101 | 102 | std::string show( const exp & ex ) 103 | { 104 | return 105 | ex.match( 106 | with( app( arg, arg ), []( const exp & l, const exp & r ) { return "(" + show( l ) + " " + show( r ) + ")"; } ), 107 | with( var( arg ), []( size_t i ) { return std::to_string( i ) + " "; } ), 108 | with( abs( arg ), []( const exp & i ) { return "(\\." + show( i ) + ")"; } ) ); 109 | } 110 | 111 | exp eval( const exp & ex ) 112 | { 113 | exp ret = eval_step( ex ); 114 | return ret == ex ? ret : eval( ret ); 115 | } 116 | } 117 | #endif 118 | -------------------------------------------------------------------------------- /Compiletime/parser.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_PARSER 2 | #define lambda_calculus_Compiletime_PARSER 3 | #include "boost/mpl/insert.hpp" 4 | #include "boost/mpl/vector.hpp" 5 | #include "boost/mpl/count.hpp" 6 | #include "boost/mpl/at.hpp" 7 | #include "boost/mpl/apply.hpp" 8 | #include "boost/mpl/contains.hpp" 9 | #include "boost/mpl/find.hpp" 10 | #include "boost/mpl/set_c.hpp" 11 | #include "boost/mpl/set.hpp" 12 | #include "boost/mpl/empty.hpp" 13 | #include "boost/mpl/front.hpp" 14 | #include "boost/mpl/char.hpp" 15 | #include "boost/mpl/map.hpp" 16 | #include "boost/mpl/pair.hpp" 17 | #include "boost/mpl/string.hpp" 18 | #include "boost/mpl/pop_front.hpp" 19 | #include "boost/mpl/if.hpp" 20 | #include "boost/mpl/switch.hpp" 21 | #include "boost/mpl/back_inserter.hpp" 22 | #include "boost/mpl/transform.hpp" 23 | #include "boost/mpl/for_each.hpp" 24 | namespace Compiletime_lambda_calculus 25 | { 26 | namespace parser 27 | { 28 | template< typename str, bool e = boost::mpl::empty< str >::value > 29 | struct is_end; 30 | template< typename str > 31 | struct is_end< str, false > 32 | { static const bool value = boost::mpl::front< str >::type::value == boost::mpl::char_< ')' >::value; }; 33 | template< typename str > 34 | struct is_end< str, true > { static const bool value = true; }; 35 | struct parse_error{ }; 36 | struct parser_generator 37 | { 38 | typedef boost::mpl::set 39 | < 40 | boost::mpl::char_< '(' >, 41 | boost::mpl::char_< ')' > 42 | > init_valid_token; 43 | template< typename MAP > 44 | struct apply 45 | { 46 | struct select_first 47 | { 48 | template< typename t > 49 | struct apply { typedef typename t::first type; }; 50 | }; 51 | typedef typename 52 | boost::mpl::transform 53 | < 54 | MAP, 55 | select_first, 56 | boost::mpl::inserter 57 | < 58 | init_valid_token, 59 | boost::mpl::insert 60 | < 61 | boost::mpl::arg< 1 >, 62 | boost::mpl::arg< 2 > 63 | > 64 | > 65 | >::type valid_token; 66 | template< typename str, bool b = boost::mpl::empty< str >::value > 67 | struct ignore_invalid; 68 | template< typename str > 69 | struct ignore_invalid< str, true > { typedef str type; }; 70 | template< typename str > 71 | struct ignore_invalid< str, false > 72 | { 73 | typedef typename 74 | boost::mpl::if_c 75 | < 76 | boost::mpl::contains< valid_token, typename boost::mpl::front< str >::type >::value, 77 | str, 78 | typename ignore_invalid< typename boost::mpl::pop_front< str >::type >::type 79 | >::type type; 80 | }; 81 | struct type; 82 | typedef type parser; 83 | struct type 84 | { 85 | template< typename ssstr > 86 | struct apply 87 | { 88 | template< typename str, int i = boost::mpl::front< str >::type::value == '(' ? 1 : 0 > 89 | struct skip_bracket 90 | { 91 | typedef typename boost::mpl::pop_front< str >::type next_str; 92 | typedef typename boost::mpl::front< next_str >::type front; 93 | typedef typename skip_bracket< next_str, ( front::value == '(' ? i + 1 : ( front::value == ')' ? i - 1 : i ) ) >::type type; 94 | }; 95 | template< typename str > 96 | struct skip_bracket< str, 0 > 97 | { typedef typename boost::mpl::pop_front< str >::type type; }; 98 | template< typename str, bool b = boost::mpl::front< str >::type::value == '(' > 99 | struct parse_single; 100 | template< typename str > 101 | struct parse_single< str, false > 102 | { 103 | typedef typename boost::mpl::front< str >::type first; 104 | typedef typename boost::mpl::at< MAP, first >::type type; 105 | typedef typename boost::mpl::pop_front< str >::type next; 106 | }; 107 | template< typename str > 108 | struct parse_single< str, true > 109 | { 110 | typedef typename parser::template apply< typename boost::mpl::pop_front< str >::type >::type type; 111 | typedef typename skip_bracket< str >::type next; 112 | }; 113 | template< typename before, typename str, bool b = is_end< typename ignore_invalid< str >::type >::value > 114 | struct parse_continue; 115 | template< typename before, typename str > 116 | struct parse_continue< before, str, false > 117 | { 118 | typedef typename ignore_invalid< str >::type string; 119 | typedef parse_single< string > parse_next; 120 | typedef typename 121 | parse_continue 122 | < 123 | typename before::template apply< typename parse_next::type >::type, 124 | typename parse_next::next 125 | >::type type; 126 | }; 127 | template< typename before, typename str > 128 | struct parse_continue< before, str, true > { typedef before type; }; 129 | typedef typename ignore_invalid< ssstr >::type string; 130 | typedef typename 131 | boost::mpl::if_c 132 | < 133 | is_end< string >::value, 134 | parse_error, 135 | typename parse_continue< typename parse_single< string >::type, typename parse_single< string >::next >::type 136 | >::type type; 137 | }; 138 | }; 139 | }; 140 | }; 141 | } 142 | } 143 | #endif //lambda_calculus_Compiletime_PARSER 144 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /Compiletime/church_numeral.hpp: -------------------------------------------------------------------------------- 1 | #ifndef lambda_calculus_Compiletime_CHURCH_NUMERAL 2 | #define lambda_calculus_Compiletime_CHURCH_NUMERAL 3 | #include "propositional_logic.hpp" 4 | #include "lambda_calculus.hpp" 5 | namespace Compiletime_lambda_calculus 6 | { 7 | namespace church_numeral 8 | { 9 | typedef 10 | abstraction 11 | < 12 | abstraction 13 | < 14 | abstraction 15 | < 16 | application 17 | < 18 | variable< 2 >, 19 | application 20 | < 21 | application 22 | < 23 | variable< 3 >, 24 | variable< 2 > 25 | >, 26 | variable< 1 > 27 | > 28 | > 29 | > 30 | > 31 | > Next; 32 | typedef False Zero; 33 | typedef Next::apply< Zero >::type One; 34 | typedef Next::apply< One >::type Two; 35 | typedef Next::apply< Two >::type Three; 36 | typedef Next::apply< Three >::type Four; 37 | typedef Next::apply< Four >::type Five; 38 | typedef Next::apply< Five >::type Six; 39 | typedef Next::apply< Six >::type Seven; 40 | typedef Next::apply< Seven >::type Eight; 41 | typedef Next::apply< Eight >::type Nine; 42 | typedef Next::apply< Nine >::type Ten; 43 | typedef Next::apply< Ten >::type Eleven; 44 | typedef Next::apply< Eleven >::type Twelve; 45 | template< unsigned int i > 46 | struct Int { typedef typename Next::apply< typename Int< i - 1 >::type >::type type; }; 47 | template< > struct Int< 0 > { typedef Zero type; }; 48 | typedef 49 | abstraction 50 | < 51 | abstraction 52 | < 53 | abstraction 54 | < 55 | abstraction 56 | < 57 | application 58 | < 59 | application 60 | < 61 | variable< 4 >, 62 | variable< 2 > 63 | >, 64 | application 65 | < 66 | application 67 | < 68 | variable< 3 >, 69 | variable< 2 > 70 | >, 71 | variable< 1 > 72 | > 73 | > 74 | > 75 | > 76 | > 77 | > Plus; 78 | typedef 79 | abstraction 80 | < 81 | abstraction 82 | < 83 | application 84 | < 85 | application 86 | < 87 | variable< 2 >, 88 | application 89 | < 90 | Plus, 91 | variable< 1 > 92 | > 93 | >, 94 | Zero 95 | > 96 | > 97 | > Multiply; 98 | typedef 99 | abstraction 100 | < 101 | abstraction 102 | < 103 | abstraction 104 | < 105 | application 106 | < 107 | application 108 | < 109 | application 110 | < 111 | variable< 3 >, 112 | abstraction 113 | < 114 | abstraction 115 | < 116 | application 117 | < 118 | variable< 1 >, 119 | application 120 | < 121 | variable< 2 >, 122 | variable< 4 > 123 | > 124 | > 125 | > 126 | > 127 | >, 128 | abstraction 129 | < 130 | variable< 2 > 131 | > 132 | >, 133 | abstraction 134 | < 135 | variable< 1 > 136 | > 137 | > 138 | > 139 | > 140 | > Before; 141 | typedef 142 | abstraction 143 | < 144 | abstraction 145 | < 146 | application 147 | < 148 | application 149 | < 150 | variable< 1 >, 151 | Before 152 | >, 153 | variable< 2 > 154 | > 155 | > 156 | > Minus; 157 | typedef 158 | abstraction 159 | < 160 | abstraction 161 | < 162 | application 163 | < 164 | variable< 1 >, 165 | variable< 2 > 166 | > 167 | > 168 | > Power; 169 | typedef 170 | abstraction 171 | < 172 | application 173 | < 174 | Not, 175 | application 176 | < 177 | application 178 | < 179 | variable< 1 >, 180 | application 181 | < 182 | Or, 183 | True 184 | > 185 | >, 186 | False 187 | > 188 | > 189 | > IsZero; 190 | typedef 191 | abstraction 192 | < 193 | abstraction 194 | < 195 | application 196 | < 197 | Not, 198 | application 199 | < 200 | IsZero, 201 | application 202 | < 203 | application 204 | < 205 | Minus, 206 | variable< 2 > 207 | >, 208 | variable< 1 > 209 | > 210 | > 211 | > 212 | > 213 | > Larger; 214 | typedef 215 | abstraction 216 | < 217 | abstraction 218 | < 219 | application 220 | < 221 | Not, 222 | application 223 | < 224 | IsZero, 225 | application 226 | < 227 | application 228 | < 229 | Minus, 230 | variable< 1 > 231 | >, 232 | variable< 2 > 233 | > 234 | > 235 | > 236 | > 237 | > Smaller; 238 | typedef 239 | abstraction 240 | < 241 | abstraction 242 | < 243 | application 244 | < 245 | application 246 | < 247 | And, 248 | application 249 | < 250 | Not, 251 | application 252 | < 253 | application 254 | < 255 | Larger, 256 | variable< 2 > 257 | >, 258 | variable< 1 > 259 | > 260 | > 261 | >, 262 | application 263 | < 264 | Not, 265 | application 266 | < 267 | application 268 | < 269 | Smaller, 270 | variable< 2 > 271 | >, 272 | variable< 1 > 273 | > 274 | > 275 | > 276 | > 277 | > Equal; 278 | template< typename x > 279 | struct ToInt 280 | { 281 | template< int n > 282 | struct num 283 | { 284 | static constexpr int count = n; 285 | template< typename y > 286 | struct apply 287 | { typedef num type; }; 288 | template< int depth, typename t > 289 | struct rebound 290 | { typedef num< n > type; }; 291 | template< size_t l, size_t r > 292 | struct update { typedef num type; }; 293 | }; 294 | 295 | template< size_t depth, typename t > 296 | struct rebound { typedef ToInt< typename x::template rebound< depth, t >::type > type; }; 297 | 298 | template< typename a > 299 | struct rem_application { typedef a type; }; 300 | 301 | template< typename a, typename b > 302 | struct rem_application< application< a, b > > { typedef typename rem_application< typename a::template apply< b >::type >::type type; }; 303 | 304 | struct accumulate 305 | { 306 | static constexpr int value = 0; 307 | template< typename y > 308 | struct apply { typedef num< rem_application< y >::type::count + 1 > type; }; 309 | template< size_t d, typename i > 310 | struct rebound { typedef accumulate type; }; 311 | template< size_t l, size_t r > 312 | struct update { typedef accumulate type; }; 313 | }; 314 | static constexpr int value = rem_application< typename x::template apply< accumulate >::type::template apply< num< 0 > >::type >::type::count; 315 | }; 316 | } 317 | } 318 | #endif //lambda_calculus_Compiletime_CHURCH_NUMERAL 319 | --------------------------------------------------------------------------------