use std::fmt::{self, Debug, Display, Formatter};
use crate::value::primitive::binary::{Natural, Integer};
use crate::value::primitive::logical::{LogicalOp, Bool};
#[derive(Clone, Eq, PartialEq)]
pub struct Scope<'a> {
pub definitions: Vec<Let<'a>>,
pub value: Option<Box<Expr<'a>>>
}
impl Debug for Scope<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for Scope<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
if self.definitions.len() == 0 {
return if let Some(value) = &self.value { write!(fmt, "{{ {} }}", value) }
else { write!(fmt, "{{}}")}
}
write!(fmt, "{{\n")?;
for definition in self.definitions.iter() {
write!(fmt, "{}\n", definition)?;
}
if let Some(value) = &self.value { write!(fmt, "{}\n", value)? }
write!(fmt, "}}")
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct Phi<'a>(pub Scope<'a>);
impl Debug for Phi<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for Phi<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> { write!(fmt, "#phi {}", self.0) }
}
#[derive(Clone, Eq, PartialEq)]
pub struct Path<'a> {
pub base: Option<()>,
pub names: Vec<&'a str>
}
impl Debug for Path<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for Path<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
let tail_names = if let Some(base) = self.base {
write!(fmt, "{:?}", base)?; &self.names[..]
} else if self.names.len() > 0 {
write!(fmt, "{}", self.names[0])?;
&self.names[1..]
}
else {
return Ok(())
};
for name in tail_names { write!(fmt, ".{}", name)?; }
Ok(())
}
}
impl<'a> Path<'a> {
pub fn ident<T>(ident: T) -> Path<'a> where T: Into<&'a str> {
Path { base: None, names: vec![ident.into()] }
}
}
impl<'a> From<Vec<&'a str>> for Path<'a> {
fn from(names: Vec<&'a str>) -> Path<'a> { Path { names, base: None } }
}
#[derive(Clone, Eq, PartialEq)]
pub enum Expr<'a> {
Path(Path<'a>),
Scope(Scope<'a>),
Sexpr(Sexpr<'a>),
Lambda(Lambda<'a>),
Pi(Pi<'a>),
Phi(Phi<'a>),
Gamma(Gamma<'a>),
Bool(bool),
BoolTy(Bool),
LogicalOp(LogicalOp),
Natural(Natural),
Integer(Integer)
}
impl<'a> Expr<'a> {
pub fn ident<T>(ident: T) -> Expr<'a> where T: Into<&'a str> {
Expr::Path(Path::ident(ident))
}
pub fn push<T>(self, other: T) -> Expr<'a> where T: Into<Box<Expr<'a>>> {
match self {
Expr::Sexpr(mut s) => { s.push(other); Expr::Sexpr(s) }
atom => {
Expr::Sexpr(Sexpr { ops: vec![Box::new(atom), other.into()] })
},
}
}
}
impl Debug for Expr<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for Expr<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
match self {
Expr::Path(p) => std::fmt::Display::fmt(p, fmt),
Expr::Scope(s) => std::fmt::Display::fmt(s, fmt),
Expr::Sexpr(s) => std::fmt::Display::fmt(s, fmt),
Expr::Lambda(l) => std::fmt::Display::fmt(l, fmt),
Expr::Pi(p) => std::fmt::Display::fmt(p, fmt),
Expr::Phi(p) => std::fmt::Display::fmt(p, fmt),
Expr::Gamma(g) => std::fmt::Display::fmt(g, fmt),
Expr::Bool(b) => write!(fmt, "#{}", b),
Expr::BoolTy(b) => std::fmt::Display::fmt(b, fmt),
Expr::LogicalOp(l) => std::fmt::Display::fmt(l, fmt),
Expr::Natural(n) => std::fmt::Display::fmt(n, fmt),
Expr::Integer(z) => std::fmt::Display::fmt(z, fmt)
}
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct Sexpr<'a> {
pub ops: Vec<Box<Expr<'a>>>
}
impl<'a> From<Vec<Box<Expr<'a>>>> for Sexpr<'a> {
fn from(ops: Vec<Box<Expr<'a>>>) -> Sexpr<'a> { Sexpr { ops } }
}
impl<'a> Sexpr<'a> {
pub fn push<T>(&mut self, op: T) where T: Into<Box<Expr<'a>>> {
self.ops.push(op.into())
}
}
impl Debug for Sexpr<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for Sexpr<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
write!(fmt, "(")?;
let mut first: bool = true;
for op in self.ops.iter().rev() {
write!(fmt, "{}{}", if first {""} else {" "}, op)?;
first = false;
}
write!(fmt, ")")
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct Lambda<'a>(pub Parametrized<'a>);
impl Debug for Lambda<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for Lambda<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
write!(fmt, "#lambda {}", self.0)
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct Pi<'a>(pub Parametrized<'a>);
impl Debug for Pi<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for Pi<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
write!(fmt, "#pi {}", self.0)
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct Parametrized<'a> {
pub args: Vec<(Option<&'a str>, Expr<'a>)>,
pub ret_ty: Option<Box<Expr<'a>>>,
pub result: Box<Expr<'a>>
}
impl Debug for Parametrized<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for Parametrized<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
write!(fmt, "|")?;
let mut first: bool = true;
for (arg, ty) in self.args.iter() {
let sep = if first {""} else {", "};
let arg = if let Some(arg) = arg { arg } else { "_" };
write!(fmt, "{}{} : {}", sep, arg, ty)?;
first = false;
}
write!(fmt, "| ")?;
if let Some(ty) = &self.ret_ty {
write!(fmt, "=> {} ", ty)?;
}
write!(fmt, "{}", self.result)
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct SimpleAssignment<'a> {
pub name: &'a str,
pub ty: Option<Expr<'a>>
}
impl Debug for SimpleAssignment<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for SimpleAssignment<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", self.name)?;
if let Some(ty) = &self.ty { write!(fmt, " : {}", ty) } else { Ok(()) }
}
}
#[derive(Clone, Eq, PartialEq)]
pub enum Pattern<'a> {
Simple(SimpleAssignment<'a>)
}
impl Debug for Pattern<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for Pattern<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
match self {
Pattern::Simple(s) => write!(fmt, "{}", s)
}
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct Let<'a> {
pub pattern: Pattern<'a>,
pub expr: Expr<'a>
}
impl Debug for Let<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for Let<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
write!(fmt, "let {} = {};", self.pattern, self.expr) }
}
#[derive(Clone, Eq, PartialEq)]
pub struct Gamma<'a> {
pub branches: Vec<(Pattern<'a>, Expr<'a>)>
}
impl Debug for Gamma<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
<Self as Display>::fmt(self, fmt)
}
}
impl Display for Gamma<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
write!(fmt, "#match {{\n")?;
let mut first = true;
for (pattern, value) in self.branches.iter() {
write!(fmt, "{}{} => {}", if first { "" } else { ",\n" }, pattern, value)?;
first = false;
}
write!(fmt, "{}}}", if first { "" } else { "\n" })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn expr_push_works_as_expected() {
assert_eq!(
Expr::ident("x").push(Expr::ident("f")),
Expr::Sexpr(vec![Expr::ident("x").into(), Expr::ident("f").into()].into())
);
assert_eq!(
Expr::ident("x").push(Expr::ident("y")).push(Expr::ident("f")),
Expr::Sexpr(vec![
Expr::ident("x").into(),
Expr::ident("y").into(),
Expr::ident("f").into()]
.into())
)
}
}