use std::ops::{Not, BitAnd, BitOr, BitXor};
use crate::{Expression, Abstraction};
use crate::normal::Strategy;
impl From<bool> for Expression {
fn from(p: bool) -> Self {
if p { λ!{a.λ!{b.a}} } else { λ!{a.λ!{b.b}} }
}
}
impl From<Expression> for bool {
fn from(e: Expression) -> bool {
let s = Strategy::Applicative(true);
if let Expression::Abs(Abstraction(a, box e1)) = e.normalize(&s) {
if let Expression::Abs(Abstraction(_, box e2)) = e1 {
if let Expression::Var(p) = e2 {
return p == a
}
}
}
false
}
}
impl Not for Expression {
type Output = Self;
fn not(self) -> Self {
let not_app = λ!{p.λ!{a.λ!{b.γ!(γ!(p,b),a)}}};
γ!({not_app},{self}).normalize(&Strategy::Applicative(true))
}
}
impl BitOr for Expression {
type Output = Self;
fn bitor(self, other: Self) -> Self {
let or = λ!{p.λ!{q.γ!(γ!(p,p),q)}};
γ!(γ!({or},{self}),{other}).normalize(&Strategy::Applicative(false))
}
}
impl BitAnd for Expression {
type Output = Self;
fn bitand(self, other: Self) -> Self {
let and = λ!{p.λ!{q.γ!(γ!(p,q),p)}};
γ!(γ!({and},{self}),{other}).normalize(&Strategy::Applicative(false))
}
}
impl BitXor for Expression {
type Output = Self;
fn bitxor(self, other: Self) -> Self {
let not_app = λ!{p.λ!{a.λ!{b.γ!(γ!(p,b),a)}}};
let xor = λ!{p.λ!{q.γ!(γ!(p,γ!({not_app},q)),q)}};
γ!(γ!({xor},{self}),{other}).normalize(&Strategy::Applicative(false))
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn true_() {
assert_eq!(true, Expression::from(true).into());
}
#[test]
fn false_() {
assert_eq!(false, Expression::from(false).into());
}
#[test]
fn not() {
assert_eq!(false, (!Expression::from(true)).into());
}
#[test]
fn or() {
assert_eq!(Expression::from(true), Expression::from(true) |
Expression::from(true));
assert_eq!(Expression::from(true), Expression::from(false) |
Expression::from(true));
assert_eq!(Expression::from(true), Expression::from(true) |
Expression::from(false));
assert_eq!(Expression::from(false), Expression::from(false) |
Expression::from(false));
}
#[test]
fn and() {
assert_eq!(Expression::from(true), Expression::from(true) &
Expression::from(true));
assert_eq!(Expression::from(false), Expression::from(false) &
Expression::from(true));
assert_eq!(Expression::from(false), Expression::from(true) &
Expression::from(false));
assert_eq!(Expression::from(false), Expression::from(false) &
Expression::from(false));
}
#[test]
fn xor() {
assert_eq!(Expression::from(false), Expression::from(true) ^
Expression::from(true));
assert_eq!(Expression::from(true), Expression::from(false) ^
Expression::from(true));
assert_eq!(Expression::from(true), Expression::from(true) ^
Expression::from(false));
assert_eq!(Expression::from(false), Expression::from(false) ^
Expression::from(false));
}
}