use std::rc::Rc;
use super::MethodIndex;
use crate::{
ll::{gc::GcRaw, value::Closure},
Gc,
};
#[derive(Debug)]
pub struct DispatchTable {
pub pretty_name: Rc<str>,
pub type_name: Rc<str>,
pub instance: Option<GcRaw<DispatchTable>>,
methods: Vec<Option<GcRaw<Closure>>>,
}
impl DispatchTable {
fn new(pretty_name: impl Into<Rc<str>>, type_name: impl Into<Rc<str>>) -> Self {
Self {
pretty_name: pretty_name.into(),
type_name: type_name.into(),
instance: None,
methods: Vec::new(),
}
}
pub fn new_for_type(type_name: impl Into<Rc<str>>) -> Self {
let type_name = type_name.into();
Self::new(format!("type {type_name}"), type_name)
}
pub fn new_for_instance(type_name: impl Into<Rc<str>>) -> Self {
let type_name = type_name.into();
Self::new(Rc::clone(&type_name), type_name)
}
pub fn get_method(&self, index: MethodIndex) -> Option<GcRaw<Closure>> {
self.methods.get(index.to_usize()).into_iter().flatten().copied().next()
}
pub fn set_method(&mut self, index: MethodIndex, closure: GcRaw<Closure>) {
let index = index.to_usize();
if index >= self.methods.len() {
self.methods.resize(index + 1, None);
}
self.methods[index] = Some(closure);
}
pub(crate) fn methods(&self) -> impl Iterator<Item = GcRaw<Closure>> + '_ {
self.methods.iter().copied().flatten()
}
}
#[derive(Debug)]
pub struct BuiltinDispatchTables {
pub nil: Gc<DispatchTable>,
pub boolean: Gc<DispatchTable>,
pub number: Gc<DispatchTable>,
pub string: Gc<DispatchTable>,
pub function: Gc<DispatchTable>,
pub list: Gc<DispatchTable>,
pub dict: Gc<DispatchTable>,
}
impl BuiltinDispatchTables {
pub fn empty() -> Self {
Self {
nil: Gc::new(DispatchTable::new("Nil", "Nil")),
boolean: Gc::new(DispatchTable::new("Boolean", "Boolean")),
number: Gc::new(DispatchTable::new("Number", "Boolean")),
string: Gc::new(DispatchTable::new("String", "String")),
function: Gc::new(DispatchTable::new("Function", "Function")),
list: Gc::new(DispatchTable::new("List", "List")),
dict: Gc::new(DispatchTable::new("Dict", "Dict")),
}
}
}