use crate::list::List; use ordered_float::OrderedFloat; use std::{ borrow::Cow, collections::BTreeMap, fmt::{Display, Write}, rc::Rc, }; /// A Wisp value #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Value<'a> { List(Box>), Vector(Vec), Map(BTreeMap), Module(Module<'a>), Function(Function<'a>), Symbol(Symbol<'a>), Keyword(Cow<'a, str>), Bool(bool), Number(OrderedFloat), String(Cow<'a, str>), Nil, } #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Module<'a> { members: BTreeMap>>, symbol_table: BTreeMap, } #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Function<'a> { // TODO: bytecode captures: Box<[Capture<'a>]>, symbol_table: BTreeMap, SymbolMapping>, } #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Capture<'a> { Reference(Rc>), Owned(Value<'a>), } #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum SymbolMapping { Local(u64), Capture(u64), } #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Symbol<'a> { Interned(u64), String(Cow<'a, str>), } impl<'a> From<&'a str> for Symbol<'a> { fn from(s: &'a str) -> Self { Self::String(Cow::Borrowed(s)) } } impl<'a> Display for Symbol<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Symbol::Interned(n) => write!(f, "#{n}"), Symbol::String(s) => write!(f, "{s}"), } } } impl<'a> Display for Value<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Value::List(list) => write!(f, "{list}"), Value::Vector(vec) => write_seq(f, vec, "[", "]"), Value::Map(map) => write_seq( f, map.into_iter().map(|(k, v)| format!("{k} {v}")), "[", "]", ), Value::Module(_) => write!(f, "#module#"), Value::Symbol(sym) => write!(f, "{sym}"), Value::Keyword(kw) => write!(f, ":{kw}"), Value::Function { .. } => write!(f, "fn"), Value::Bool(b) => write!(f, "{b}"), Value::Number(n) => write!(f, "{n}"), Value::String(s) => write!(f, "\"{s}\""), Value::Nil => write!(f, "nil"), } } } pub(crate) fn write_seq( f: &mut impl Write, iterable: impl IntoIterator, delimiter_left: &str, delimiter_right: &str, ) -> std::fmt::Result { let mut iter = iterable.into_iter(); write!(f, "{delimiter_left}")?; if let Some(x) = iter.next() { write!(f, "{x}")?; } for x in iter { write!(f, " {x}")?; } write!(f, "{delimiter_right}") }