-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathpeano.alu
120 lines (104 loc) · 3.72 KB
/
peano.alu
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
use std::builtins::generic_args_of;
use std::util::unit;
// Peano integers 0, S(0), S(S(0)), ...
struct Zero {}
struct Succ<T> {}
impl Zero {
fn val(_v: Zero) -> i32 { 0 }
}
impl Succ<T> {
fn val(_v: Succ<T>) -> i32 { unit::<T>().val() + 1 }
}
fn is_zero<T>() -> bool {
std::typing::matches::<T, Zero>()
}
type One = Succ<Zero>;
type Two = Succ<One>;
type Three = Succ<Two>;
type Four = Succ<Three>;
type Five = Succ<Four>;
type Six = Succ<Five>;
type Seven = Succ<Six>;
type Eight = Succ<Seven>;
type Nine = Succ<Eight>;
type Ten = Succ<Nine>;
type Eleven = Succ<Ten>;
type Twelve = Succ<Eleven>;
type Not<T> = when is_zero::<T>() { One } else { Zero };
type And<A, B> = when is_zero::<A>() { Zero } else { B };
type Or<A, B> = when is_zero::<A>() { B } else { One };
type Xor<A, B> = when is_zero::<A>() { B } else { Not<B> };
type Prev<T> = when is_zero::<T>() { Zero } else { generic_args_of<T>.0 };
type Add<A, B> = when is_zero::<B>() { A } else { Succ<Add<A, Prev<B>>> };
type Sub<A, B> = when is_zero::<B>() { A } else { Sub<Prev<A>, Prev<B>> };
type Mul<A, B> = when is_zero::<B>() { Zero } else { Add<A, Mul<A, Prev<B>>> };
type DivT<A, B, Idx> = when is_zero::<B>() {
typeof(compile_fail!("division by zero"))
} else when is_zero::<Sub<Succ<A>, B>>() {
Idx
} else {
DivT<Sub<A, B>, B, Succ<Idx>>
};
type Div<A, B> = DivT<A, B, Zero>;
type Mod<A, B> = Sub<A, Mul<Div<A, B>, B>>;
type Fibonacci<T> = when is_zero::<Prev<T>>() {
T
} else {
Add<Fibonacci<Prev<T>>, Fibonacci<Prev<Prev<T>>>>
};
type IsPrimeT<A, Idx> = when std::typing::matches::<Idx, A>() {
One // = true
} else when is_zero::<Mod<A, Idx>>() {
Zero // = false
} else {
IsPrimeT<A, Succ<Idx>>
};
type IsPrime<A> = when is_zero::<Prev<A>>() {
Zero // = false
} else {
IsPrimeT<A, Two>
};
type Gcd<A, B> = when is_zero::<B>() {
A
} else {
Gcd<B, Mod<A, B>>
};
fn main() {
println!("Arithmetic:");
println!("10 * 5 + (6 * 2) / 3 = {}", unit::<
Add<
Mul<Ten, Five>,
Div<
Mul<Six, Two>,
Three
>
>>()
.val());
println!("Fibonacci:");
println!("fib(0) = {}", unit::<Fibonacci<Zero>>().val());
println!("fib(1) = {}", unit::<Fibonacci<One>>().val());
println!("fib(2) = {}", unit::<Fibonacci<Two>>().val());
println!("fib(3) = {}", unit::<Fibonacci<Three>>().val());
println!("fib(4) = {}", unit::<Fibonacci<Four>>().val());
println!("fib(5) = {}", unit::<Fibonacci<Five>>().val());
println!("fib(6) = {}", unit::<Fibonacci<Six>>().val());
println!("fib(7) = {}", unit::<Fibonacci<Seven>>().val());
println!("fib(8) = {}", unit::<Fibonacci<Eight>>().val());
println!("fib(9) = {}", unit::<Fibonacci<Nine>>().val());
println!("fib(10) = {}", unit::<Fibonacci<Ten>>().val());
println!("fib(11) = {}", unit::<Fibonacci<Eleven>>().val());
println!("fib(12) = {}", unit::<Fibonacci<Twelve>>().val());
println!("Primality:");
println!("is_prime(1) = {}", unit::<IsPrime<One>>().val());
println!("is_prime(2) = {}", unit::<IsPrime<Two>>().val());
println!("is_prime(3) = {}", unit::<IsPrime<Three>>().val());
println!("is_prime(4) = {}", unit::<IsPrime<Four>>().val());
println!("is_prime(5) = {}", unit::<IsPrime<Five>>().val());
println!("is_prime(6) = {}", unit::<IsPrime<Six>>().val());
println!("is_prime(7) = {}", unit::<IsPrime<Seven>>().val());
println!("is_prime(8) = {}", unit::<IsPrime<Eight>>().val());
println!("is_prime(9) = {}", unit::<IsPrime<Nine>>().val());
println!("is_prime(10) = {}", unit::<IsPrime<Ten>>().val());
println!("is_prime(11) = {}", unit::<IsPrime<Eleven>>().val());
println!("is_prime(12) = {}", unit::<IsPrime<Twelve>>().val());
}