wisp/src/value.rs

115 lines
3.1 KiB
Rust

use crate::list::List;
use ordered_float::OrderedFloat;
use std::{
borrow::Cow,
collections::BTreeMap,
fmt::{Debug, Display, Write},
rc::Rc,
};
/// A Wisp value
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Value<'a> {
List(Box<List<'a>>),
Vector(Vec<Self>),
Map(BTreeMap<Self, Self>),
Module(Module<'a>),
Function(Function<'a>),
InternalFn(fn(&'a List<'a>) -> Value<'a>),
Macro(/* TODO: Bytecode */),
Symbol(Symbol<'a>),
Keyword(Cow<'a, str>),
Bool(bool),
Number(OrderedFloat<f64>),
String(Cow<'a, str>),
Nil,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Module<'a> {
members: BTreeMap<u64, Rc<Value<'a>>>,
symbol_table: BTreeMap<String, u64>,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Function<'a> {
// TODO: bytecode
captures: Box<[Capture<'a>]>,
symbol_table: BTreeMap<Symbol<'a>, SymbolMapping>,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Capture<'a> {
Reference(Rc<Value<'a>>),
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::InternalFn(function) => write!(f, "#internal-fn@{function:p}"),
Value::Macro() => write!(f, "#macro#"),
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<Item = impl Display>,
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}")
}