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, } 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), Number(f64), Tuple(Rc>), List(Box>), Dict(Box>), Box(Rc>), Fn(Rc>), } 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::>() .join(", ") ), List(members) => write!( f, "[{}]", members .iter() .map(|x| x.to_string()) .collect::>() .join(", ") ), Dict(members) => write!( f, "#{{{}}}", members .iter() .map(|(k, v)| format!("{k} {v}")) .collect::>() .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::>().join(", "); format!("({members})") } List(l) => { let members = l.iter().map(|e| e.show(ctx)).collect::>().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::>() .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", } } }