use std::collections::BTreeMap;
use std::rc::Rc;
use either::Either;
pub type Level = u32;
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Expression {
Unit,
One,
Type(Level),
Void,
Var(String),
Sum(Branch),
Split(Branch),
Merge(Box<Self>, Box<Self>),
Pi(Typed, Box<Self>),
Sigma(Typed, Box<Self>),
Lambda(Pattern, Option<AnonymousValue>, Box<Self>),
First(Box<Self>),
Second(Box<Self>),
Application(Box<Self>, Box<Self>),
Pair(Box<Self>, Box<Self>),
Constructor(String, Box<Self>),
Constant(Pattern, Box<Self>, Box<Self>),
Declaration(Box<Declaration>, Box<Self>),
}
#[derive(Debug, Clone)]
pub struct AnonymousValue {
pub internal: Box<Value>,
}
impl AnonymousValue {
pub fn new(value: Value) -> Self {
Self {
internal: Box::new(value),
}
}
pub fn some(value: Value) -> Option<Self> {
Some(Self::new(value))
}
}
impl Eq for AnonymousValue {}
impl PartialEq<AnonymousValue> for AnonymousValue {
fn eq(&self, _other: &Self) -> bool {
true
}
}
pub type GenericBranch<T> = BTreeMap<String, Box<T>>;
pub type Branch = GenericBranch<Expression>;
pub fn branch_to_righted(branch: Branch, context: Telescope) -> CaseTree {
let mut case_tree: CaseTree = Default::default();
for (name, expression) in branch.into_iter() {
let case = GenericCase::new(Either::Right(*expression), context.clone());
case_tree.insert(name, Box::new(case));
}
case_tree
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Typed {
pub pattern: Pattern,
pub expression: Box<Expression>,
}
impl Typed {
pub fn new(pattern: Pattern, expression: Expression) -> Self {
Self {
pattern,
expression: Box::new(expression),
}
}
pub fn destruct(self) -> (Pattern, Expression) {
let pattern = self.pattern;
let expression = *self.expression;
(pattern, expression)
}
}
#[derive(Debug, Clone)]
pub enum Value {
Lambda(Closure),
Unit,
One,
Type(Level),
Pi(Box<Self>, Closure),
Sigma(Box<Self>, Closure),
Pair(Box<Self>, Box<Self>),
Constructor(String, Box<Self>),
Split(CaseTree),
Sum(CaseTree),
Neutral(Neutral),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum GenericNeutral<Value: Clone> {
Generated(u32),
Application(Box<Self>, Box<Value>),
First(Box<Self>),
Second(Box<Self>),
Split(
GenericBranch<GenericCase<Either<Value, Expression>, Value>>,
Box<Self>,
),
}
pub type Neutral = GenericNeutral<Value>;
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum Pattern {
Pair(Box<Self>, Box<Self>),
Unit,
Var(String),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Declaration {
pub pattern: Pattern,
pub prefix_parameters: Vec<Typed>,
pub signature: Expression,
pub body: Expression,
pub is_recursive: bool,
}
impl Declaration {
pub fn new(
pattern: Pattern,
prefix_parameters: Vec<Typed>,
signature: Expression,
body: Expression,
is_recursive: bool,
) -> Self {
Self {
pattern,
prefix_parameters,
signature,
body,
is_recursive,
}
}
pub fn simple(
pattern: Pattern,
prefix_parameters: Vec<Typed>,
signature: Expression,
body: Expression,
) -> Self {
Self::new(pattern, prefix_parameters, signature, body, false)
}
pub fn recursive(
pattern: Pattern,
prefix_parameters: Vec<Typed>,
signature: Expression,
body: Expression,
) -> Self {
Self::new(pattern, prefix_parameters, signature, body, true)
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum GenericTelescope<Value: Clone> {
Nil,
UpDec(Rc<Self>, Declaration),
UpVar(Rc<Self>, Pattern, Value),
}
pub type TelescopeRc<Value> = Rc<GenericTelescope<Value>>;
pub type Telescope = Rc<GenericTelescope<Value>>;
pub fn up_var_rc<Value: Clone>(
me: TelescopeRc<Value>,
pattern: Pattern,
value: Value,
) -> TelescopeRc<Value> {
Rc::new(GenericTelescope::UpVar(me, pattern, value))
}
pub fn up_dec_rc<Value: Clone>(
me: TelescopeRc<Value>,
declaration: Declaration,
) -> TelescopeRc<Value> {
Rc::new(GenericTelescope::UpDec(me, declaration))
}
pub fn nil_rc<Value: Clone>() -> TelescopeRc<Value> {
Rc::new(GenericTelescope::Nil)
}
#[derive(Debug, Clone)]
pub enum Closure {
Abstraction(Pattern, Option<Box<Value>>, Expression, Box<Telescope>),
Value(Box<Value>),
Choice(Box<Self>, String),
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct GenericCase<Expression, Value: Clone> {
pub expression: Expression,
pub context: TelescopeRc<Value>,
}
impl<Expression, Value: Clone> GenericCase<Expression, Value> {
pub fn new(expression: Expression, context: TelescopeRc<Value>) -> Self {
Self {
expression,
context,
}
}
}
pub type Case = GenericCase<Either<Value, Expression>, Value>;
pub type CaseTree = GenericBranch<Case>;
impl GenericCase<Either<Value, Expression>, Value> {
pub fn reduce_to_value(self) -> Value {
let GenericCase {
expression,
context,
} = self;
expression.either(|l| l, |r| r.eval(context))
}
}