2025-06-03 22:54:33 +00:00
|
|
|
use crate::base::BaseFn;
|
2024-12-15 22:54:40 +00:00
|
|
|
use crate::compiler::Chunk;
|
|
|
|
use crate::parser::Ast;
|
|
|
|
use crate::spans::Spanned;
|
|
|
|
use imbl::{HashMap, Vector};
|
2025-06-04 21:53:38 +00:00
|
|
|
use std::cell::RefCell;
|
2024-11-01 03:53:48 +00:00
|
|
|
use std::rc::Rc;
|
2024-10-31 20:59:26 +00:00
|
|
|
|
2024-12-15 22:54:40 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
2025-06-04 21:53:38 +00:00
|
|
|
pub enum LFn {
|
|
|
|
Declared {
|
|
|
|
name: &'static str,
|
|
|
|
},
|
|
|
|
Defined {
|
|
|
|
name: &'static str,
|
|
|
|
doc: Option<&'static str>,
|
|
|
|
chunks: Vec<(u8, Chunk)>,
|
|
|
|
closed: RefCell<Vec<Value>>,
|
|
|
|
},
|
2024-12-24 17:35:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl LFn {
|
2025-06-04 21:53:38 +00:00
|
|
|
pub fn close(&self, value: Value) {
|
|
|
|
match self {
|
|
|
|
LFn::Declared { .. } => unreachable!(),
|
|
|
|
LFn::Defined { closed, .. } => {
|
|
|
|
closed.borrow_mut().push(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn doc(&self) -> Value {
|
|
|
|
match self {
|
|
|
|
LFn::Declared { name } => {
|
|
|
|
Value::String(Rc::new(format!("fn {name}: undefined function")))
|
|
|
|
}
|
|
|
|
LFn::Defined {
|
|
|
|
name,
|
|
|
|
doc: Some(doc),
|
|
|
|
..
|
|
|
|
} => Value::String(Rc::new(format!("fn {name}\n{doc}"))),
|
|
|
|
LFn::Defined { name, .. } => {
|
|
|
|
Value::String(Rc::new(format!("fn {name}: no documentation")))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
LFn::Declared { name } | LFn::Defined { name, .. } => name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn chunk(&self, arity: u8) -> &Chunk {
|
|
|
|
match self {
|
|
|
|
LFn::Declared { .. } => unreachable!(),
|
|
|
|
LFn::Defined { chunks, .. } => &chunks.iter().find(|(a, _)| *a == arity).unwrap().1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn upvalue(&self, idx: u8) -> Value {
|
|
|
|
match self {
|
|
|
|
LFn::Declared { .. } => unreachable!(),
|
|
|
|
LFn::Defined { closed, .. } => closed.borrow()[idx as usize].clone(),
|
|
|
|
}
|
2024-12-24 17:35:44 +00:00
|
|
|
}
|
2024-10-31 20:59:26 +00:00
|
|
|
}
|
|
|
|
|
2025-06-05 20:10:40 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct Partial {
|
|
|
|
args: Vec<Value>,
|
|
|
|
name: &'static str,
|
|
|
|
function: Value,
|
|
|
|
}
|
|
|
|
|
2025-06-03 22:54:33 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2024-12-15 22:54:40 +00:00
|
|
|
pub enum Value {
|
2025-05-26 13:16:47 +00:00
|
|
|
Nothing,
|
2024-10-31 20:59:26 +00:00
|
|
|
Nil,
|
2024-12-16 04:28:57 +00:00
|
|
|
True,
|
|
|
|
False,
|
2025-06-03 20:23:37 +00:00
|
|
|
Keyword(&'static str),
|
|
|
|
Interned(&'static str),
|
2024-12-15 22:54:40 +00:00
|
|
|
String(Rc<String>),
|
2024-10-31 20:59:26 +00:00
|
|
|
Number(f64),
|
2024-12-16 04:28:57 +00:00
|
|
|
Tuple(Rc<Vec<Value>>),
|
2024-12-15 22:54:40 +00:00
|
|
|
List(Box<Vector<Value>>),
|
2025-06-03 20:23:37 +00:00
|
|
|
Dict(Box<HashMap<&'static str, Value>>),
|
2024-12-23 00:07:42 +00:00
|
|
|
Box(Rc<RefCell<Value>>),
|
2025-06-04 21:53:38 +00:00
|
|
|
Fn(Rc<LFn>),
|
2025-06-03 22:54:33 +00:00
|
|
|
BaseFn(BaseFn),
|
2025-06-05 20:10:40 +00:00
|
|
|
Partial(Rc<Partial>),
|
2025-06-03 22:54:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq for Value {
|
|
|
|
fn eq(&self, other: &Value) -> bool {
|
|
|
|
use Value::*;
|
|
|
|
match (self, other) {
|
|
|
|
(Nothing, Nothing) | (Nil, Nil) | (True, True) | (False, False) => true,
|
|
|
|
(Keyword(str1), Keyword(str2)) | (Interned(str1), Interned(str2)) => str1 == str2,
|
|
|
|
(String(x), String(y)) => x == y,
|
|
|
|
(String(x), Interned(y)) => x.as_ref() == y,
|
|
|
|
(Interned(x), String(y)) => x == y.as_ref(),
|
|
|
|
(Number(x), Number(y)) => x == y,
|
|
|
|
(Tuple(x), Tuple(y)) => x == y,
|
|
|
|
(List(x), List(y)) => x == y,
|
|
|
|
(Dict(x), Dict(y)) => x == y,
|
|
|
|
(Box(x), Box(y)) => std::ptr::eq(x.as_ref().as_ptr(), y.as_ref().as_ptr()),
|
|
|
|
(Fn(x), Fn(y)) => x == y,
|
|
|
|
(BaseFn(x), BaseFn(y)) => std::ptr::eq(x, y),
|
2025-06-05 20:10:40 +00:00
|
|
|
(Partial(x), Partial(y)) => x == y,
|
2025-06-03 22:54:33 +00:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2024-11-01 03:53:48 +00:00
|
|
|
}
|
|
|
|
|
2024-12-18 06:28:23 +00:00
|
|
|
impl std::fmt::Display for Value {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
|
use Value::*;
|
|
|
|
match self {
|
2025-05-26 13:16:47 +00:00
|
|
|
Nothing => write!(f, "_"),
|
2024-12-18 06:28:23 +00:00
|
|
|
Nil => write!(f, "nil"),
|
|
|
|
True => write!(f, "true"),
|
|
|
|
False => write!(f, "false"),
|
2025-06-03 20:23:37 +00:00
|
|
|
Keyword(str) => write!(f, ":{str}"),
|
|
|
|
Interned(str) => write!(f, "\"{str}\""),
|
2025-05-30 15:44:32 +00:00
|
|
|
String(str) => write!(f, "\"{str}\""),
|
2024-12-18 06:28:23 +00:00
|
|
|
Number(n) => write!(f, "{n}"),
|
2024-12-23 00:07:42 +00:00
|
|
|
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(", ")
|
|
|
|
),
|
2025-06-04 22:27:17 +00:00
|
|
|
Box(value) => write!(f, "box {{ {} }}", value.as_ref().borrow()),
|
2025-06-04 21:53:38 +00:00
|
|
|
Fn(lfn) => write!(f, "fn {}", lfn.name()),
|
2025-06-03 22:54:33 +00:00
|
|
|
BaseFn(_) => write!(f, "base fn"),
|
2025-06-05 20:10:40 +00:00
|
|
|
Partial(partial) => write!(f, "fn {}/partial", partial.name),
|
2024-12-18 06:28:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-15 22:54:40 +00:00
|
|
|
impl Value {
|
2025-06-03 20:23:37 +00:00
|
|
|
pub fn show(&self) -> String {
|
2024-12-15 22:54:40 +00:00
|
|
|
use Value::*;
|
|
|
|
match &self {
|
2024-12-16 04:28:57 +00:00
|
|
|
Nil => "nil".to_string(),
|
|
|
|
True => "true".to_string(),
|
|
|
|
False => "false".to_string(),
|
|
|
|
Number(n) => format!("{n}"),
|
2025-06-03 20:23:37 +00:00
|
|
|
Interned(str) => format!("\"{str}\""),
|
2025-05-30 15:44:32 +00:00
|
|
|
String(str) => {
|
|
|
|
let str_str = str.to_string();
|
|
|
|
format!("\"{str_str}\"")
|
|
|
|
}
|
2025-06-03 20:23:37 +00:00
|
|
|
Keyword(str) => format!(":{str}"),
|
2024-12-16 04:28:57 +00:00
|
|
|
Tuple(t) => {
|
2025-06-03 20:23:37 +00:00
|
|
|
let members = t.iter().map(|e| e.show()).collect::<Vec<_>>().join(", ");
|
2024-12-16 04:28:57 +00:00
|
|
|
format!("({members})")
|
|
|
|
}
|
|
|
|
List(l) => {
|
2025-06-03 20:23:37 +00:00
|
|
|
let members = l.iter().map(|e| e.show()).collect::<Vec<_>>().join(", ");
|
2024-12-16 04:28:57 +00:00
|
|
|
format!("[{members}]")
|
|
|
|
}
|
|
|
|
Dict(d) => {
|
|
|
|
let members = d
|
|
|
|
.iter()
|
|
|
|
.map(|(k, v)| {
|
2025-06-03 20:23:37 +00:00
|
|
|
let key_show = Value::Keyword(k).show();
|
|
|
|
let value_show = v.show();
|
2024-12-16 04:28:57 +00:00
|
|
|
format!("{key_show} {value_show}")
|
|
|
|
})
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.join(", ");
|
|
|
|
format!("#{{{members}}}")
|
|
|
|
}
|
2025-06-03 20:23:37 +00:00
|
|
|
Box(x) => format!("box {{ {} }}", x.as_ref().borrow().show()),
|
2025-06-04 21:53:38 +00:00
|
|
|
Fn(lfn) => format!("fn {}", lfn.name()),
|
2025-06-05 20:10:40 +00:00
|
|
|
Partial(partial) => format!("fn {}/partial", partial.name),
|
2025-06-03 22:54:33 +00:00
|
|
|
BaseFn(_) => "base fn".to_string(),
|
|
|
|
Nothing => unreachable!(),
|
2024-12-05 00:07:03 +00:00
|
|
|
}
|
|
|
|
}
|
2024-12-27 04:33:57 +00:00
|
|
|
|
2025-06-03 20:23:37 +00:00
|
|
|
pub fn stringify(&self) -> String {
|
2025-05-30 15:44:32 +00:00
|
|
|
use Value::*;
|
|
|
|
match &self {
|
|
|
|
Nil => "nil".to_string(),
|
|
|
|
True => "true".to_string(),
|
|
|
|
False => "false".to_string(),
|
|
|
|
Number(n) => format!("{n}"),
|
2025-06-03 20:23:37 +00:00
|
|
|
Interned(str) => str.to_string(),
|
|
|
|
Keyword(str) => str.to_string(),
|
2025-05-30 15:44:32 +00:00
|
|
|
Tuple(t) => {
|
|
|
|
let members = t
|
|
|
|
.iter()
|
2025-06-03 20:23:37 +00:00
|
|
|
.map(|e| e.stringify())
|
2025-05-30 15:44:32 +00:00
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.join(", ");
|
|
|
|
members.to_string()
|
|
|
|
}
|
|
|
|
List(l) => {
|
|
|
|
let members = l
|
|
|
|
.iter()
|
2025-06-03 20:23:37 +00:00
|
|
|
.map(|e| e.stringify())
|
2025-05-30 15:44:32 +00:00
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.join(", ");
|
|
|
|
members.to_string()
|
|
|
|
}
|
|
|
|
Dict(d) => {
|
|
|
|
let members = d
|
|
|
|
.iter()
|
|
|
|
.map(|(k, v)| {
|
2025-06-03 20:23:37 +00:00
|
|
|
let key_show = Value::Keyword(k).stringify();
|
|
|
|
let value_show = v.stringify();
|
2025-05-30 15:44:32 +00:00
|
|
|
format!("{key_show} {value_show}")
|
|
|
|
})
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.join(", ");
|
|
|
|
members.to_string()
|
|
|
|
}
|
|
|
|
String(s) => s.as_ref().clone(),
|
2025-06-03 20:23:37 +00:00
|
|
|
Box(x) => x.as_ref().borrow().stringify(),
|
2025-06-04 21:53:38 +00:00
|
|
|
Fn(lfn) => format!("fn {}", lfn.name()),
|
2025-05-30 15:44:32 +00:00
|
|
|
_ => todo!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-27 04:33:57 +00:00
|
|
|
pub fn type_of(&self) -> &'static str {
|
|
|
|
use Value::*;
|
|
|
|
match self {
|
2025-05-26 13:16:47 +00:00
|
|
|
Nothing => unreachable!(),
|
2024-12-27 04:33:57 +00:00
|
|
|
Nil => "nil",
|
|
|
|
True => "bool",
|
|
|
|
False => "bool",
|
|
|
|
Keyword(..) => "keyword",
|
|
|
|
Interned(..) => "string",
|
|
|
|
String(..) => "string",
|
|
|
|
Number(..) => "number",
|
|
|
|
Tuple(..) => "tuple",
|
|
|
|
List(..) => "list",
|
|
|
|
Dict(..) => "dict",
|
|
|
|
Box(..) => "box",
|
|
|
|
Fn(..) => "fn",
|
2025-06-03 22:54:33 +00:00
|
|
|
BaseFn(..) => "fn",
|
2025-06-05 20:10:40 +00:00
|
|
|
Partial(..) => "fn",
|
2024-12-27 04:33:57 +00:00
|
|
|
}
|
|
|
|
}
|
2024-12-05 00:07:03 +00:00
|
|
|
}
|