1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#![recursion_limit = "18446744073709551615"]
#![feature(trace_macros)]
trace_macros!(true);
#[macro_export]
macro_rules! named {
( $any:tt ) => {
#[macro_use]
macro_rules! ans {
($var:ident)=>{
$var!($any);
};
($any1:tt $any2:tt) => {
lambda!($any1 $any $any2);
}
}
}
}
#[macro_export]
macro_rules! if_same_else {
([$($a:tt)*] [$($b:tt)*] [$($any0:tt)*] [$($any1:tt)*]) => {
#[macro_use]
macro_rules! if_a_same_as_b_else {
($($b)* ) => {
lambda!($($any0)*);
};
( $($a)*) => {
lambda!($($any1)*);
};
}
if_a_same_as_b_else!($($a)*);
};
}
#[macro_export]
macro_rules! lambda {
($var:ident = $($any:tt)*)=>{
mod $var{
use super::*;
#[macro_use]
macro_rules! named {
( $any1:tt ) => {
#[macro_export]
macro_rules! $var {
($var1:ident)=>{
$var1!($any1);
};
($any2:tt $any3:tt) => {
lambda!($any2 $any1 $any3);
};
}
};
}
lambda!($($any)*);
}
};
({$($any0:tt)*})=>{
lambda!($($any0)*);
};
({$($any0:tt)*},$($any1:tt)*)=>{
lambda!($($any0)*, $($any1)* );
};
([$($any0:tt)*] [$($any1:tt)*] [$($any2:tt)*]) => {
lambda!($($any0)* $($any1)* $($any2)*);
};
(($($any1:tt)*) $($any2:tt)*)=>{
lambda!($($any1:tt)* $($any2:tt)*);
};
( $fun:tt $($var:ident)* , ( $($any1:tt)*) $($any2:tt)* )=> {
lambda!( $($any1)*; $fun $($var)*, _ $($any2)*);
};
($var:ident $($any:tt)*)=>{
$var!([] [$($any)*] );
};
($fun0:tt $($var0:ident)* , $var:ident $($any:tt)*)=> {
$var!([$fun0 $($var0)* ,] [$($any)*] );
};
({[$($any0:tt)*] $($any1:tt)* } $($var0:ident)* , {$($any2:tt)*} $( , $fun2:tt $($var2:ident)* )* $(; $( $fun3:tt $($var3:ident)*),*)* )=>{
lambda!({[$($any0)* ,($($any2)*) ] $($any1)* } $($var0)* $( , $fun2 $($var2)* )* $(; $( $fun3 $($var3)*),*)*);
};
({[,$($any0:tt)*]} $var00:ident $($var01:ident)*, $fun1:tt $($var1:ident)* $( , $fun2:tt $($var2:ident)* )* $(; $( $fun3:tt $($var3:ident)*),*)* )=>{
lambda!( {$($any0)*} $($var01)* $( , $fun2 $($var2)* )* $(; $( $fun3 $($var3)*),*)* );
};
({[$($any0:tt)*], ($($any1:tt)*) $($any2:tt)* } $var00:ident $($var01:ident)* , $fun1:tt $($var1:ident)* $( , $fun2:tt $($var2:ident)* )* $(; $( $fun3:tt $($var3:ident)*),*)* )=>{
lambda!({[$($any0)*] $($any2)* } $var00 $($var01)* , ({$($any1)*} $var00 , $fun1 $($var1)*) , $fun1 $($var1)* $( , $fun2 $($var2)* )* $(; $( $fun3 $($var3)*),*)*);
};
({[$($any0:tt)*], $fun1:tt $($var1:ident)* $( , $fun11:tt $($var11:ident)* )* } $var00:ident $($var01:ident)* , $fun2:tt $($var2:ident)* $( , $fun3:tt $($var3:ident)* )* $(; $( $fun4:tt $($var4:ident)*),*)* )=>{
if_same_else!(
[$fun1 $($var1)*] [$var00][
{[$($any0)*, $fun2 $($var2)*] $( , $fun11 $($var11)* )* } $var00 $($var01)* , $fun2 $($var2)* $( , $fun3 $($var3)* )* $(; $( $fun4 $($var4)*),*)*
] [
{[$($any0)*, $fun1 $($var1)*] $( , $fun11 $($var11)* )* } $var00 $($var01)* , $fun2 $($var2)* $( , $fun3 $($var3)* )* $(; $( $fun4 $($var4)*),*)*
]
);
};
({$($any0:tt)*}$($var0:ident)* , $fun1:tt $($var1:ident)* $( , $fun2:tt $($var2:ident)* )* $(; $( $fun3:tt $($var3:ident)*),*)* )=> {
lambda!({[] , $($any0)*} $($var0)* , $fun1 $($var1)* $( , $fun2 $($var2)* )* $(; $( $fun3 $($var3)*),*)*);
};
( $fun1:tt $($var1:ident)* ; $fun2:tt $($var2:ident)* , _ $($any:tt)* )=>{
lambda!( $fun2 $($var2)* , $fun1 $($var1)* $($any)*);
};
($($any:tt)*)=>{
named!([$($any)*]);
};
}
#[macro_use]
mod into;
#[macro_use]
mod math;
lambda!(add1 = {f, (n , f , x) }n f x );
lambda!(add = {a , add1 , b} add1 a b , add1);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
trace_macros!(true);
println!("{}",lambda!(to_str, add1 ,one));
println!("{}",lambda!(to_str, add , one , zero));
println!("{}",lambda!(to_str, add1 , (add , one , zero)));
}
}