dot-pair pretty-print
This commit is contained in:
parent
d1d7ab4067
commit
a592cf80f2
|
@ -7,6 +7,7 @@ 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 pair::list;
|
||||||
use std::{collections::BTreeMap, fmt::Display, rc::Rc};
|
use std::{collections::BTreeMap, fmt::Display, rc::Rc};
|
||||||
|
|
||||||
pub type OrderedF64 = ordered_float::OrderedFloat<f64>;
|
pub type OrderedF64 = ordered_float::OrderedFloat<f64>;
|
||||||
|
@ -15,7 +16,7 @@ pub type OrderedF64 = ordered_float::OrderedFloat<f64>;
|
||||||
pub enum Value<'s> {
|
pub enum Value<'s> {
|
||||||
#[default]
|
#[default]
|
||||||
Nil,
|
Nil,
|
||||||
DotPair(Rc<DotPair<'s>>),
|
DotPair(DotPair<'s>),
|
||||||
Vector(Rc<Vec<Self>>),
|
Vector(Rc<Vec<Self>>),
|
||||||
Map(Rc<BTreeMap<Self, Self>>),
|
Map(Rc<BTreeMap<Self, Self>>),
|
||||||
Symbol(Str<'s>),
|
Symbol(Str<'s>),
|
||||||
|
@ -36,14 +37,11 @@ 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(v) => v.into_iter().rev().fold(Self::Nil, |acc, x| {
|
Expr::List(v) => v.into_iter().rev().fold(Self::Nil, |acc, x| {
|
||||||
Value::DotPair(Rc::new(DotPair(x.into(), acc)))
|
Value::DotPair(DotPair::new(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(DotPair::new((*l).into(), (*r).into())),
|
||||||
Expr::Quote(e) => Self::DotPair(Rc::new(DotPair(
|
Expr::Quote(e) => list!(Self::Symbol("quote".into()), (*e).into()),
|
||||||
Self::Symbol("quote".into()),
|
|
||||||
Self::DotPair(Rc::new(DotPair((*e).into(), Self::Nil))),
|
|
||||||
))),
|
|
||||||
Expr::Symbol("nil") => Self::Nil,
|
Expr::Symbol("nil") => Self::Nil,
|
||||||
Expr::Symbol(s) => Self::Symbol(s.into()),
|
Expr::Symbol(s) => Self::Symbol(s.into()),
|
||||||
Expr::Keyword(s) => Self::Keyword(s.into()),
|
Expr::Keyword(s) => Self::Keyword(s.into()),
|
||||||
|
@ -57,7 +55,7 @@ impl<'s> Display for Value<'s> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Value::Nil => "nil".fmt(f),
|
Value::Nil => "nil".fmt(f),
|
||||||
Value::DotPair(p) => write!(f, "({} . {})", p.0, p.1),
|
Value::DotPair(p) => p.fmt(f),
|
||||||
Value::Vector(v) => fmt_sequence(f, v.as_ref(), "#(", ")", |i, f| i.fmt(f)),
|
Value::Vector(v) => fmt_sequence(f, v.as_ref(), "#(", ")", |i, f| i.fmt(f)),
|
||||||
Value::Map(m) => {
|
Value::Map(m) => {
|
||||||
fmt_sequence(f, m.as_ref(), "(", ")", |(k, v), f| write!(f, "{k} -> {v}"))
|
fmt_sequence(f, m.as_ref(), "(", ")", |(k, v), f| write!(f, "{k} -> {v}"))
|
||||||
|
|
|
@ -1,4 +1,60 @@
|
||||||
use super::Value;
|
use super::Value;
|
||||||
|
use std::{fmt::Display, rc::Rc};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct DotPair<'s>(pub Value<'s>, pub Value<'s>);
|
pub struct DotPair<'s>(pub Rc<(Value<'s>, Value<'s>)>);
|
||||||
|
impl<'s> DotPair<'s> {
|
||||||
|
pub fn new(first: Value<'s>, second: Value<'s>) -> Self {
|
||||||
|
Self(Rc::new((first, second)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn first(&self) -> &Value<'s> {
|
||||||
|
&self.0 .0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn second(&self) -> &Value<'s> {
|
||||||
|
&self.0 .1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> Display for DotPair<'s> {
|
||||||
|
fn fmt(mut self: &Self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
"(".fmt(f)?;
|
||||||
|
loop {
|
||||||
|
self.first().fmt(f)?;
|
||||||
|
match self.second() {
|
||||||
|
Value::Nil => break,
|
||||||
|
Value::DotPair(p) => {
|
||||||
|
" ".fmt(f)?;
|
||||||
|
self = p;
|
||||||
|
}
|
||||||
|
val => break write!(f, " . {val}")?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
")".fmt(f)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! list {
|
||||||
|
() => {
|
||||||
|
$crate::interpreter::value::Value::Nil
|
||||||
|
};
|
||||||
|
|
||||||
|
($item: expr $(,)?) => {
|
||||||
|
Value::DotPair(
|
||||||
|
$crate::interpreter::value::DotPair::new($item, $crate::interpreter::value::Value::Nil)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
($first: expr, $($rest: expr),* $(,)?) => {
|
||||||
|
Value::DotPair(
|
||||||
|
$crate::interpreter::value::DotPair::new(
|
||||||
|
$first,
|
||||||
|
$crate::interpreter::value::pair::list!($($rest),*)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use list;
|
||||||
|
|
Loading…
Reference in a new issue