rudus/src/value.rs
2024-12-26 23:33:57 -05:00

149 lines
4.3 KiB
Rust

use crate::compiler::Chunk;
use crate::parser::Ast;
use crate::spans::Spanned;
use imbl::{HashMap, Vector};
use std::cell::{OnceCell, RefCell};
use std::rc::Rc;
#[derive(Clone, Debug, PartialEq)]
pub struct LFn {
pub name: &'static str,
pub doc: Option<&'static str>,
// pub enclosing: Vec<(usize, Value)>,
// pub has_run: bool,
// pub input: &'static str,
// pub src: &'static str,
pub chunk: Chunk,
pub closed: Vec<Value>,
}
impl LFn {
pub fn close(&mut self, val: Value) {
self.closed.push(val);
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
Nil,
True,
False,
Keyword(usize),
Interned(usize),
FnDecl(usize),
String(Rc<String>),
Number(f64),
Tuple(Rc<Vec<Value>>),
List(Box<Vector<Value>>),
Dict(Box<HashMap<usize, Value>>),
Box(Rc<RefCell<Value>>),
Fn(Rc<OnceCell<LFn>>),
}
impl std::fmt::Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
use Value::*;
match self {
Nil => write!(f, "nil"),
True => write!(f, "true"),
False => write!(f, "false"),
Keyword(idx) => write!(f, ":{idx}"),
Interned(idx) => write!(f, "\"@{idx}\""),
Number(n) => write!(f, "{n}"),
Tuple(members) => write!(
f,
"({})",
members
.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", ")
),
List(members) => write!(
f,
"[{}]",
members
.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", ")
),
Dict(members) => write!(
f,
"#{{{}}}",
members
.iter()
.map(|(k, v)| format!("{k} {v}"))
.collect::<Vec<_>>()
.join(", ")
),
Box(value) => write!(f, "box {}", value.as_ref().borrow()),
Fn(lfn) => write!(f, "fn {}", lfn.get().unwrap().name),
_ => todo!(),
}
}
}
impl Value {
pub fn show(&self, ctx: &Chunk) -> String {
use Value::*;
match &self {
Nil => "nil".to_string(),
True => "true".to_string(),
False => "false".to_string(),
Number(n) => format!("{n}"),
Interned(i) => {
let str_str = ctx.strings[*i];
format!("\"{str_str}\"")
}
Keyword(i) => {
let kw_str = ctx.keywords[*i];
format!(":{kw_str}")
}
Tuple(t) => {
let members = t.iter().map(|e| e.show(ctx)).collect::<Vec<_>>().join(", ");
format!("({members})")
}
List(l) => {
let members = l.iter().map(|e| e.show(ctx)).collect::<Vec<_>>().join(", ");
format!("[{members}]")
}
Dict(d) => {
let members = d
.iter()
.map(|(k, v)| {
let key_show = Value::Keyword(*k).show(ctx);
let value_show = v.show(ctx);
format!("{key_show} {value_show}")
})
.collect::<Vec<_>>()
.join(", ");
format!("#{{{members}}}")
}
String(s) => s.as_ref().clone(),
Box(x) => format!("box {{ {} }}", x.as_ref().borrow().show(ctx)),
Fn(lfn) => format!("fn {}", lfn.get().unwrap().name),
_ => todo!(),
}
}
pub fn type_of(&self) -> &'static str {
use Value::*;
match self {
Nil => "nil",
True => "bool",
False => "bool",
Keyword(..) => "keyword",
Interned(..) => "string",
FnDecl(..) => "fn",
String(..) => "string",
Number(..) => "number",
Tuple(..) => "tuple",
List(..) => "list",
Dict(..) => "dict",
Box(..) => "box",
Fn(..) => "fn",
}
}
}