rudus/src/value.rs

168 lines
5.4 KiB
Rust
Raw Normal View History

use crate::base::*;
2024-10-31 20:59:26 +00:00
use crate::parser::*;
use imbl::*;
use std::cell::RefCell;
2024-10-31 20:59:26 +00:00
use std::fmt;
use std::rc::Rc;
2024-10-31 20:59:26 +00:00
#[derive(Clone, Debug)]
2024-10-31 20:59:26 +00:00
pub struct Fn<'src> {
2024-11-11 01:12:19 +00:00
pub name: &'src str,
pub body: &'src Vec<MatchClause<'src>>,
2024-10-31 20:59:26 +00:00
}
#[derive(Debug)]
2024-11-06 22:37:57 +00:00
pub enum Value<'src> {
2024-10-31 20:59:26 +00:00
Nil,
2024-11-11 01:12:19 +00:00
Placeholder,
2024-10-31 20:59:26 +00:00
Boolean(bool),
Number(f64),
2024-11-06 22:37:57 +00:00
Keyword(&'src str),
String(&'src str),
// on the heap for now
Tuple(Rc<Vec<Self>>),
2024-11-11 01:12:19 +00:00
Args(Rc<Vec<Self>>),
// ref-counted, immutable, persistent
2024-11-09 19:10:08 +00:00
List(Vector<Self>),
// ref-counted, immutable, persistent
2024-11-09 19:10:08 +00:00
Dict(HashMap<&'src str, Self>),
Box(&'src str, Rc<RefCell<Self>>),
2024-11-11 01:12:19 +00:00
Fn(Rc<Fn<'src>>),
Base(&Base<'src>),
2024-10-31 20:59:26 +00:00
// Set(HashSet<Self>),
// Sets are hard
// Sets require Eq
// Eq is not implemented on f64, because NaNs
// We could use ordered_float::NotNan
// Let's defer that
// We're not really using sets in Ludus
// Other things we're not implementing yet:
// pkgs, nses, tests
}
2024-11-06 22:37:57 +00:00
impl<'src> Clone for Value<'src> {
fn clone(&self) -> Value<'src> {
match self {
Value::Nil => Value::Nil,
Value::Boolean(b) => Value::Boolean(b.clone()),
Value::String(s) => Value::String(s),
Value::Keyword(s) => Value::Keyword(s),
Value::Number(n) => Value::Number(n.clone()),
Value::Tuple(t) => Value::Tuple(t.clone()),
2024-11-11 01:12:19 +00:00
Value::Args(a) => Value::Args(a.clone()),
Value::Fn(f) => Value::Fn(f.clone()),
Value::List(l) => Value::List(l.clone()),
Value::Dict(d) => Value::Dict(d.clone()),
Value::Box(name, b) => Value::Box(name, b.clone()),
2024-11-11 01:12:19 +00:00
Value::Placeholder => Value::Placeholder,
Value::Base(b) => Value::Base(b.clone()),
}
}
}
2024-11-06 22:37:57 +00:00
impl<'src> fmt::Display for Value<'src> {
2024-10-31 20:59:26 +00:00
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Value::Nil => write!(f, "nil"),
Value::Boolean(b) => write!(f, "{}", b),
Value::Number(n) => write!(f, "{}", n),
Value::Keyword(k) => write!(f, ":{}", k),
Value::String(s) => write!(f, "\"{}\"", s),
2024-11-11 01:12:19 +00:00
Value::Fn(fun) => write!(f, "fn {}", fun.name),
Value::Tuple(t) | Value::Args(t) => write!(
2024-10-31 20:59:26 +00:00
f,
"({})",
t.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", ")
),
Value::List(l) => write!(
f,
"[{}]",
l.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", ")
),
2024-11-11 01:12:19 +00:00
Value::Dict(d) => write!(
f,
"#{{{}}}",
d.iter()
.map(|(k, v)| format!(":{k} {v}"))
.collect::<Vec<_>>()
.join(", ")
),
Value::Box(name, value) => {
write!(
f,
"box {}: [{}]",
name,
&value.try_borrow().unwrap().to_string()
)
}
2024-11-11 01:12:19 +00:00
Value::Placeholder => write!(f, "_"),
Value::Base(base) => {
let name = match base {
Base::Unary(name, _) => name,
Base::Binary(name, _) => name,
Base::Ternary(name, _) => name,
};
write!(f, "base fn {}", name)
}
2024-10-31 20:59:26 +00:00
}
}
}
2024-11-06 22:37:57 +00:00
impl<'src> Value<'src> {
pub fn bool(&self) -> bool {
match self {
Value::Nil | Value::Boolean(false) => false,
_ => true,
}
}
pub fn ludus_type(&self) -> Value {
match self {
Value::Nil => Value::Keyword("nil"),
Value::Number(_) => Value::Keyword("number"),
Value::Boolean(_) => Value::Keyword("boolean"),
Value::Keyword(_) => Value::Keyword("keyword"),
Value::Tuple(_) => Value::Keyword("tuple"),
Value::String(_) => Value::Keyword("string"),
Value::List(_) => Value::Keyword("list"),
Value::Dict(_) => Value::Keyword("dict"),
Value::Fn(_) => Value::Keyword("fn"),
Value::Box(_, _) => Value::Keyword("box"),
Value::Placeholder => unreachable!(),
Value::Args(_) => unreachable!(),
Value::Base(_) => Value::Keyword("fn"),
}
}
}
impl<'src> PartialEq for Value<'src> {
fn eq(&self, other: &Value<'src>) -> bool {
match (self, other) {
// value equality types
(Value::Nil, Value::Nil) => true,
(Value::Boolean(x), Value::Boolean(y)) => x == y,
(Value::Number(x), Value::Number(y)) => x == y,
(Value::String(x), Value::String(y)) => x == y,
(Value::Keyword(x), Value::Keyword(y)) => x == y,
(Value::Tuple(x), Value::Tuple(y)) => x == y,
(Value::List(x), Value::List(y)) => x == y,
(Value::Dict(x), Value::Dict(y)) => x == y,
// reference equality types
(Value::Fn(x), Value::Fn(y)) => Rc::<Fn<'_>>::as_ptr(x) == Rc::<Fn<'_>>::as_ptr(y),
(Value::Box(_, x), Value::Box(_, y)) => {
Rc::<RefCell<Value<'_>>>::as_ptr(x) == Rc::<RefCell<Value<'_>>>::as_ptr(y)
}
_ => false,
}
}
}
impl<'src> Eq for Value<'src> {}