use crate::combinators::{I, Z};
use crate::data::num::convert::Encoding;
use crate::data::num::convert::Encoding::*;
use crate::data::num::{church, parigot, scott, stumpfu};
use crate::data::pair::{fst, pair, snd, swap};
use crate::term::Term::*;
use crate::term::{abs, app, Term};
pub fn to_signed(encoding: Encoding) -> Term {
let zero = match encoding {
Church => church::zero(),
Scott => scott::zero(),
Parigot => parigot::zero(),
StumpFu => stumpfu::zero(),
Binary => panic!("signed binary numbers are not supported"),
};
abs(app!(pair(), Var(1), zero))
}
pub fn neg() -> Term {
swap()
}
pub fn simplify(encoding: Encoding) -> Term {
let is_zero = || match encoding {
Church => church::is_zero(),
Scott => scott::is_zero(),
Parigot => parigot::is_zero(),
StumpFu => stumpfu::is_zero(),
Binary => panic!("signed binary numbers are not supported"),
};
let pred = || match encoding {
Church => church::pred(),
Scott => scott::pred(),
Parigot => parigot::pred(),
StumpFu => stumpfu::pred(),
Binary => panic!("signed binary numbers are not supported"),
};
app(
Z(),
abs!(
2,
app!(
is_zero(),
app(fst(), Var(1)),
abs(Var(2)),
abs(app!(
is_zero(),
app(snd(), Var(2)),
Var(2),
app(
Var(3),
app!(
pair(),
app(pred(), app(fst(), Var(2))),
app(pred(), app(snd(), Var(2)))
)
)
)),
I()
)
),
)
}
pub fn modulus(encoding: Encoding) -> Term {
let is_zero = match encoding {
Church => church::is_zero(),
Scott => scott::is_zero(),
Parigot => parigot::is_zero(),
StumpFu => stumpfu::is_zero(),
Binary => panic!("signed binary numbers are not supported"),
};
abs(app(
abs(app!(
is_zero,
app(fst(), Var(1)),
app(snd(), Var(1)),
app(fst(), Var(1))
)),
app(simplify(encoding), Var(1)),
))
}
pub fn add(encoding: Encoding) -> Term {
let add = || match encoding {
Church => church::add(),
Scott => scott::add(),
Parigot => parigot::add(),
StumpFu => stumpfu::add(),
Binary => panic!("signed binary numbers are not supported"),
};
abs!(
2,
app(
simplify(encoding),
app!(
pair(),
app!(add(), app(fst(), Var(2)), app(fst(), Var(1))),
app!(add(), app(snd(), Var(2)), app(snd(), Var(1)))
)
)
)
}
pub fn sub(encoding: Encoding) -> Term {
let add = || match encoding {
Church => church::add(),
Scott => scott::add(),
Parigot => parigot::add(),
StumpFu => stumpfu::add(),
Binary => panic!("signed binary numbers are not supported"),
};
abs!(
2,
app(
simplify(encoding),
app!(
pair(),
app!(add(), app(fst(), Var(2)), app(snd(), Var(1))),
app!(add(), app(snd(), Var(2)), app(fst(), Var(1)))
)
)
)
}
pub fn mul(encoding: Encoding) -> Term {
let mul = || match encoding {
Church => church::mul(),
Scott => scott::mul(),
Parigot => parigot::mul(),
StumpFu => stumpfu::mul(),
Binary => panic!("signed binary numbers are not supported"),
};
let add = || match encoding {
Church => church::add(),
Scott => scott::add(),
Parigot => parigot::add(),
StumpFu => stumpfu::add(),
Binary => panic!("signed binary numbers are not supported"),
};
abs!(
2,
app(
simplify(encoding),
app!(
pair(),
app!(
add(),
app!(mul(), app(fst(), Var(2)), app(fst(), Var(1))),
app!(mul(), app(snd(), Var(2)), app(snd(), Var(1)))
),
app!(
add(),
app!(mul(), app(fst(), Var(2)), app(snd(), Var(1))),
app!(mul(), app(snd(), Var(2)), app(fst(), Var(1)))
)
)
)
)
}