basic formatting

This commit is contained in:
Erin 2022-08-06 00:49:25 +02:00 committed by ondra05
parent bc445db1c9
commit a547dc711c

View file

@ -7,12 +7,14 @@ pub use pair::DotPair;
pub use string::Str; pub use string::Str;
use crate::syntax::ast::{Expr, Spanned}; use crate::syntax::ast::{Expr, Spanned};
use std::{collections::BTreeMap, rc::Rc}; use std::{collections::BTreeMap, fmt::Display, rc::Rc};
pub type OrderedF64 = ordered_float::OrderedFloat<f64>; pub type OrderedF64 = ordered_float::OrderedFloat<f64>;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Default, Clone, PartialEq, Eq)]
pub enum Value<'s> { pub enum Value<'s> {
#[default]
Nil,
DotPair(Rc<DotPair<'s>>), DotPair(Rc<DotPair<'s>>),
Vector(Rc<Vec<Self>>), Vector(Rc<Vec<Self>>),
Map(Rc<BTreeMap<Self, Self>>), Map(Rc<BTreeMap<Self, Self>>),
@ -22,7 +24,6 @@ pub enum Value<'s> {
String(Str<'s>), String(Str<'s>),
Function(Function), Function(Function),
Macro(Function), Macro(Function),
Nil,
} }
impl<'s> From<Spanned<Expr<'s>>> for Value<'s> { impl<'s> From<Spanned<Expr<'s>>> for Value<'s> {
@ -34,7 +35,9 @@ impl<'s> From<Spanned<Expr<'s>>> for Value<'s> {
impl<'s> From<Expr<'s>> for Value<'s> { impl<'s> From<Expr<'s>> for Value<'s> {
fn from(e: Expr<'s>) -> Self { fn from(e: Expr<'s>) -> Self {
match e { match e {
Expr::List(_) => todo!(), Expr::List(v) => v.into_iter().rev().fold(Self::Nil, |acc, x| {
Value::DotPair(Rc::new(DotPair(x.into(), acc)))
}),
Expr::Vector(v) => Self::Vector(Rc::new(v.into_iter().map(Into::into).collect())), Expr::Vector(v) => Self::Vector(Rc::new(v.into_iter().map(Into::into).collect())),
Expr::Pair((l, r)) => Self::DotPair(Rc::new(DotPair((*l).into(), (*r).into()))), Expr::Pair((l, r)) => Self::DotPair(Rc::new(DotPair((*l).into(), (*r).into()))),
Expr::Quote(e) => Self::DotPair(Rc::new(DotPair( Expr::Quote(e) => Self::DotPair(Rc::new(DotPair(
@ -48,3 +51,41 @@ impl<'s> From<Expr<'s>> for Value<'s> {
} }
} }
} }
impl<'s> Display for Value<'s> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Value::Nil => "nil".fmt(f),
Value::DotPair(p) => write!(f, "({} . {})", p.0, p.1),
Value::Vector(v) => fmt_sequence(f, v.as_ref(), "#(", ")", |i, f| i.fmt(f)),
Value::Map(m) => {
fmt_sequence(f, m.as_ref(), "(", ")", |(k, v), f| write!(f, "{k} -> {v}"))
}
Value::Symbol(s) => s.fmt(f),
Value::Keyword(k) => write!(f, ":{k}"),
Value::Number(n) => n.fmt(f),
Value::String(s) => write!(f, "\"{s}\""),
Value::Function(_) => "#fun#".fmt(f),
Value::Macro(_) => "#macro#".fmt(f),
}
}
}
fn fmt_sequence<'s, T>(
f: &mut std::fmt::Formatter<'_>,
s: impl IntoIterator<Item = T>,
start: &str,
end: &str,
it_fmt: impl Fn(T, &mut std::fmt::Formatter<'_>) -> std::fmt::Result,
) -> std::fmt::Result {
let mut it = s.into_iter();
start.fmt(f)?;
if let Some(i) = it.next() {
it_fmt(i, f)?;
}
for i in it {
" ".fmt(f)?;
it_fmt(i, f)?;
}
end.fmt(f)
}