diff --git a/src/byte_values.rs b/src/byte_values.rs deleted file mode 100644 index 077e646..0000000 --- a/src/byte_values.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::compiler::Chunk; -use crate::parser::Ast; -use crate::spans::Spanned; -use imbl::{HashMap, Vector}; -use std::cell::RefCell; -use std::rc::Rc; - -#[derive(Clone, Debug, PartialEq)] -pub struct LBox { - pub name: usize, - pub cell: RefCell, -} - -#[derive(Clone, Debug, PartialEq)] -pub struct LFn { - pub name: &'static str, - pub body: Vec>, - pub doc: Option<&'static str>, - pub enclosing: Vec<(usize, Value)>, - pub has_run: bool, - pub input: &'static str, - pub src: &'static str, -} - -#[derive(Clone, Debug, PartialEq)] -pub enum Value { - Nil, - Boolean(bool), - Keyword(usize), // use an idx, rather than a raw index - Interned(usize), - FnDecl(usize), - String(Rc), - Number(f64), - List(Box>), - Dict(Box>), - Box(Rc), - Fn(Rc>), -} - -impl Value { - fn show(&self, ctx: &Chunk) -> String { - use Value::*; - match &self { - Nil => format!("nil"), - } - } -} diff --git a/src/main.rs b/src/old_main.rs similarity index 100% rename from src/main.rs rename to src/old_main.rs diff --git a/src/old_value.rs b/src/old_value.rs new file mode 100644 index 0000000..5b4aec1 --- /dev/null +++ b/src/old_value.rs @@ -0,0 +1,193 @@ +use crate::base::*; +use crate::parser::*; +use crate::spans::*; +use imbl::*; +use std::cell::RefCell; +use std::fmt; +use std::rc::Rc; +use struct_scalpel::Dissectible; + +#[derive(Clone, Debug)] +pub struct Fn<'src> { + pub name: String, + pub body: &'src Vec>, + pub doc: Option, + pub enclosing: Vec<(String, Value<'src>)>, + pub has_run: bool, + pub input: &'static str, + pub src: &'static str, +} + +#[derive(Debug, Dissectible)] +pub enum Value<'src> { + Nil, + Placeholder, + Boolean(bool), + Number(f64), + Keyword(&'static str), + InternedString(&'static str), + AllocatedString(Rc), + // on the heap for now + Tuple(Rc>), + Args(Rc>), + List(Vector), + Dict(HashMap<&'static str, Self>), + Box(&'static str, Rc>), + Fn(Rc>>), + FnDecl(&'static str), + Base(BaseFn<'src>), + Recur(Vec), + // Set(HashSet), + // 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 +} + +impl<'src> Clone for Value<'src> { + fn clone(&self) -> Value<'src> { + match self { + Value::Nil => Value::Nil, + Value::Boolean(b) => Value::Boolean(*b), + Value::InternedString(s) => Value::InternedString(s), + Value::AllocatedString(s) => Value::AllocatedString(s.clone()), + Value::Keyword(s) => Value::Keyword(s), + Value::Number(n) => Value::Number(*n), + Value::Tuple(t) => Value::Tuple(t.clone()), + Value::Args(a) => Value::Args(a.clone()), + Value::Fn(f) => Value::Fn(f.clone()), + Value::FnDecl(name) => Value::FnDecl(name), + Value::List(l) => Value::List(l.clone()), + Value::Dict(d) => Value::Dict(d.clone()), + Value::Box(name, b) => Value::Box(name, b.clone()), + Value::Placeholder => Value::Placeholder, + Value::Base(b) => Value::Base(b.clone()), + Value::Recur(..) => unreachable!(), + } + } +} + +impl fmt::Display for Value<'_> { + 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::InternedString(s) => write!(f, "\"{s}\""), + Value::AllocatedString(s) => write!(f, "\"{s}\""), + Value::Fn(fun) => write!(f, "fn {}", fun.borrow().name), + Value::FnDecl(name) => write!(f, "fn {name}"), + Value::Tuple(t) | Value::Args(t) => write!( + f, + "({})", + t.iter() + .map(|x| x.to_string()) + .collect::>() + .join(", ") + ), + Value::List(l) => write!( + f, + "[{}]", + l.iter() + .map(|x| x.to_string()) + .collect::>() + .join(", ") + ), + Value::Dict(d) => write!( + f, + "#{{{}}}", + d.iter() + .map(|(k, v)| format!(":{k} {v}")) + .collect::>() + .join(", ") + ), + Value::Box(name, value) => { + write!( + f, + "box {}: [{}]", + name, + &value.try_borrow().unwrap().to_string() + ) + } + Value::Placeholder => write!(f, "_"), + Value::Base(..) => unreachable!(), + Value::Recur(..) => unreachable!(), + } + } +} + +impl Value<'_> { + pub fn bool(&self) -> bool { + !matches!(self, Value::Nil | Value::Boolean(false)) + } +} + +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::InternedString(x), Value::InternedString(y)) => x == y, + (Value::AllocatedString(x), Value::AllocatedString(y)) => x == y, + (Value::InternedString(x), Value::AllocatedString(y)) => *x == **y, + (Value::AllocatedString(x), Value::InternedString(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::>>::as_ptr(x) == Rc::>>::as_ptr(y) + } + (Value::Box(_, x), Value::Box(_, y)) => { + Rc::>>::as_ptr(x) == Rc::>>::as_ptr(y) + } + _ => false, + } + } +} + +impl Eq for Value<'_> {} + +impl Value<'_> { + pub fn interpolate(&self) -> String { + match self { + Value::Nil => String::new(), + Value::Boolean(b) => format!("{b}"), + Value::Number(n) => format!("{n}"), + Value::Keyword(k) => format!(":{k}"), + Value::AllocatedString(s) => format!("{s}"), + Value::InternedString(s) => s.to_string(), + Value::Box(_, x) => x.borrow().interpolate(), + Value::Tuple(xs) => xs + .iter() + .map(|x| x.interpolate()) + .collect::>() + .join(", "), + Value::List(xs) => xs + .iter() + .map(|x| x.interpolate()) + .collect::>() + .join(", "), + Value::Dict(xs) => xs + .iter() + .map(|(k, v)| format!(":{} {}", k, v.interpolate())) + .collect::>() + .join(", "), + Value::Fn(x) => format!("fn {}", x.borrow().name), + Value::FnDecl(name) => format!("fn {name}"), + Value::Placeholder => unreachable!(), + Value::Args(_) => unreachable!(), + Value::Recur(_) => unreachable!(), + Value::Base(_) => unreachable!(), + } + } +} diff --git a/src/vm.rs b/src/old_vm.rs similarity index 100% rename from src/vm.rs rename to src/old_vm.rs diff --git a/src/value.rs b/src/value.rs index 5b4aec1..077e646 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,193 +1,47 @@ -use crate::base::*; -use crate::parser::*; -use crate::spans::*; -use imbl::*; +use crate::compiler::Chunk; +use crate::parser::Ast; +use crate::spans::Spanned; +use imbl::{HashMap, Vector}; use std::cell::RefCell; -use std::fmt; use std::rc::Rc; -use struct_scalpel::Dissectible; -#[derive(Clone, Debug)] -pub struct Fn<'src> { - pub name: String, - pub body: &'src Vec>, - pub doc: Option, - pub enclosing: Vec<(String, Value<'src>)>, +#[derive(Clone, Debug, PartialEq)] +pub struct LBox { + pub name: usize, + pub cell: RefCell, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct LFn { + pub name: &'static str, + pub body: Vec>, + pub doc: Option<&'static str>, + pub enclosing: Vec<(usize, Value)>, pub has_run: bool, pub input: &'static str, pub src: &'static str, } -#[derive(Debug, Dissectible)] -pub enum Value<'src> { +#[derive(Clone, Debug, PartialEq)] +pub enum Value { Nil, - Placeholder, Boolean(bool), + Keyword(usize), // use an idx, rather than a raw index + Interned(usize), + FnDecl(usize), + String(Rc), Number(f64), - Keyword(&'static str), - InternedString(&'static str), - AllocatedString(Rc), - // on the heap for now - Tuple(Rc>), - Args(Rc>), - List(Vector), - Dict(HashMap<&'static str, Self>), - Box(&'static str, Rc>), - Fn(Rc>>), - FnDecl(&'static str), - Base(BaseFn<'src>), - Recur(Vec), - // Set(HashSet), - // 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 + List(Box>), + Dict(Box>), + Box(Rc), + Fn(Rc>), } -impl<'src> Clone for Value<'src> { - fn clone(&self) -> Value<'src> { - match self { - Value::Nil => Value::Nil, - Value::Boolean(b) => Value::Boolean(*b), - Value::InternedString(s) => Value::InternedString(s), - Value::AllocatedString(s) => Value::AllocatedString(s.clone()), - Value::Keyword(s) => Value::Keyword(s), - Value::Number(n) => Value::Number(*n), - Value::Tuple(t) => Value::Tuple(t.clone()), - Value::Args(a) => Value::Args(a.clone()), - Value::Fn(f) => Value::Fn(f.clone()), - Value::FnDecl(name) => Value::FnDecl(name), - Value::List(l) => Value::List(l.clone()), - Value::Dict(d) => Value::Dict(d.clone()), - Value::Box(name, b) => Value::Box(name, b.clone()), - Value::Placeholder => Value::Placeholder, - Value::Base(b) => Value::Base(b.clone()), - Value::Recur(..) => unreachable!(), - } - } -} - -impl fmt::Display for Value<'_> { - 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::InternedString(s) => write!(f, "\"{s}\""), - Value::AllocatedString(s) => write!(f, "\"{s}\""), - Value::Fn(fun) => write!(f, "fn {}", fun.borrow().name), - Value::FnDecl(name) => write!(f, "fn {name}"), - Value::Tuple(t) | Value::Args(t) => write!( - f, - "({})", - t.iter() - .map(|x| x.to_string()) - .collect::>() - .join(", ") - ), - Value::List(l) => write!( - f, - "[{}]", - l.iter() - .map(|x| x.to_string()) - .collect::>() - .join(", ") - ), - Value::Dict(d) => write!( - f, - "#{{{}}}", - d.iter() - .map(|(k, v)| format!(":{k} {v}")) - .collect::>() - .join(", ") - ), - Value::Box(name, value) => { - write!( - f, - "box {}: [{}]", - name, - &value.try_borrow().unwrap().to_string() - ) - } - Value::Placeholder => write!(f, "_"), - Value::Base(..) => unreachable!(), - Value::Recur(..) => unreachable!(), - } - } -} - -impl Value<'_> { - pub fn bool(&self) -> bool { - !matches!(self, Value::Nil | Value::Boolean(false)) - } -} - -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::InternedString(x), Value::InternedString(y)) => x == y, - (Value::AllocatedString(x), Value::AllocatedString(y)) => x == y, - (Value::InternedString(x), Value::AllocatedString(y)) => *x == **y, - (Value::AllocatedString(x), Value::InternedString(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::>>::as_ptr(x) == Rc::>>::as_ptr(y) - } - (Value::Box(_, x), Value::Box(_, y)) => { - Rc::>>::as_ptr(x) == Rc::>>::as_ptr(y) - } - _ => false, - } - } -} - -impl Eq for Value<'_> {} - -impl Value<'_> { - pub fn interpolate(&self) -> String { - match self { - Value::Nil => String::new(), - Value::Boolean(b) => format!("{b}"), - Value::Number(n) => format!("{n}"), - Value::Keyword(k) => format!(":{k}"), - Value::AllocatedString(s) => format!("{s}"), - Value::InternedString(s) => s.to_string(), - Value::Box(_, x) => x.borrow().interpolate(), - Value::Tuple(xs) => xs - .iter() - .map(|x| x.interpolate()) - .collect::>() - .join(", "), - Value::List(xs) => xs - .iter() - .map(|x| x.interpolate()) - .collect::>() - .join(", "), - Value::Dict(xs) => xs - .iter() - .map(|(k, v)| format!(":{} {}", k, v.interpolate())) - .collect::>() - .join(", "), - Value::Fn(x) => format!("fn {}", x.borrow().name), - Value::FnDecl(name) => format!("fn {name}"), - Value::Placeholder => unreachable!(), - Value::Args(_) => unreachable!(), - Value::Recur(_) => unreachable!(), - Value::Base(_) => unreachable!(), +impl Value { + fn show(&self, ctx: &Chunk) -> String { + use Value::*; + match &self { + Nil => format!("nil"), } } }