use std::collections::BTreeMap;
use std::fmt::Display;
use std::rc::Rc;
use either::Either;
use crate::ast::*;
pub type NormalTelescope = Rc<GenericTelescope<NormalExpression>>;
pub type NormalCase = GenericCase<Either<NormalExpression, Expression>, NormalExpression>;
pub type NormalCaseTree = GenericBranch<NormalCase>;
pub type NormalNeutral = GenericNeutral<NormalExpression>;
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum NormalExpression {
Lambda(u32, Box<Self>),
Pair(Box<Self>, Box<Self>),
Unit,
One,
Type(Level),
Pi(Box<Self>, u32, Box<Self>),
Sigma(Box<Self>, u32, Box<Self>),
Constructor(String, Box<Self>),
Split(NormalCaseTree),
Sum(NormalCaseTree),
Neutral(NormalNeutral),
}
pub fn generate_value(id: u32) -> Value {
use crate::ast::GenericNeutral as Neutral;
Value::Neutral(Neutral::Generated(id))
}
pub trait ReadBack: Sized {
type NormalForm: Eq + Display;
fn read_back(self, index: u32) -> Self::NormalForm;
fn read_back_please(self) -> Self::NormalForm {
self.read_back(0)
}
fn normal(index: u32, me: Self, other: Self) -> (Self::NormalForm, Self::NormalForm) {
let me_read_back = me.read_back(index);
let other_read_back = other.read_back(index);
(me_read_back, other_read_back)
}
}
impl ReadBack for Value {
type NormalForm = NormalExpression;
fn read_back(self, index: u32) -> Self::NormalForm {
use crate::check::read_back::NormalExpression::*;
match self {
Value::Lambda(closure) => {
let closure = closure
.instantiate(generate_value(index))
.read_back(index + 1);
Lambda(index, Box::new(closure))
}
Value::Unit => Unit,
Value::One => One,
Value::Type(level) => Type(level),
Value::Pi(input, output) => {
let output = output
.instantiate(generate_value(index))
.read_back(index + 1);
Pi(Box::new(input.read_back(index)), index, Box::new(output))
}
Value::Sigma(first, second) => {
let second = second
.instantiate(generate_value(index))
.read_back(index + 1);
Sigma(Box::new(first.read_back(index)), index, Box::new(second))
}
Value::Pair(first, second) => Pair(
Box::new(first.read_back(index)),
Box::new(second.read_back(index)),
),
Value::Constructor(name, body) => Constructor(name, Box::new(body.read_back(index))),
Value::Split(case_tree) => Split(read_back_branches(index, case_tree)),
Value::Sum(constructors) => Sum(read_back_branches(index, constructors)),
Value::Neutral(neutral) => Neutral(neutral.read_back(index)),
}
}
}
fn read_back_branches(index: u32, branches: CaseTree) -> NormalCaseTree {
let mut read_back_constructors = BTreeMap::new();
for (name, case) in branches.into_iter() {
read_back_constructors.insert(name, Box::new(case.read_back(index)));
}
read_back_constructors
}
impl ReadBack for Case {
type NormalForm = NormalCase;
fn read_back(self, index: u32) -> Self::NormalForm {
Self::NormalForm::new(
self.expression.map_left(|l| l.read_back(index)),
self.context.read_back(index),
)
}
}
impl ReadBack for &GenericTelescope<Value> {
type NormalForm = NormalTelescope;
fn read_back(self, index: u32) -> Self::NormalForm {
use crate::ast::GenericTelescope::*;
match self {
Nil => Rc::new(Nil),
UpDec(context, declaration) => {
Rc::new(UpDec(context.read_back(index), declaration.clone()))
}
UpVar(context, pattern, val) => Rc::new(UpVar(
context.read_back(index),
pattern.clone(),
val.clone().read_back(index),
)),
}
}
}
impl ReadBack for Neutral {
type NormalForm = NormalNeutral;
fn read_back(self, index: u32) -> Self::NormalForm {
use crate::ast::GenericNeutral::*;
match self {
Generated(index) => Generated(index),
Application(function, argument) => Application(
Box::new(function.read_back(index)),
Box::new(argument.read_back(index)),
),
First(neutral) => First(Box::new(neutral.read_back(index))),
Second(neutral) => Second(Box::new(neutral.read_back(index))),
Split(case_tree, body) => Split(
read_back_branches(index, case_tree),
Box::new(body.read_back(index)),
),
}
}
}