115 lines
3.1 KiB
Rust
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}")
|
|
}
|