134 lines
3.2 KiB
Rust
134 lines
3.2 KiB
Rust
|
use {
|
||
|
std::{
|
||
|
collections::HashMap,
|
||
|
sync::{Arc, RwLock},
|
||
|
any::Any
|
||
|
},
|
||
|
crate::{
|
||
|
bimap::Bimap,
|
||
|
core::type_term::{TypeID, TypeTerm}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
|
||
|
pub enum ReprTree {
|
||
|
Leaf(Arc<dyn Any + Send + Sync>),
|
||
|
Branch(HashMap<TypeTerm, Arc<RwLock<ReprTree>>>)
|
||
|
}
|
||
|
|
||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
|
||
|
#[derive(Clone)]
|
||
|
pub struct Object {
|
||
|
type_tag: TypeTerm,
|
||
|
repr: Arc<RwLock<ReprTree>>
|
||
|
}
|
||
|
|
||
|
impl Object {
|
||
|
fn downcast(&self, repr_type: TypeTerm) -> Option<Object> {
|
||
|
match &*self.repr.read().unwrap() {
|
||
|
ReprTree::Leaf(data) =>
|
||
|
if self.type_tag == repr_type {
|
||
|
Some(self.clone())
|
||
|
} else {
|
||
|
None
|
||
|
},
|
||
|
ReprTree::Branch(reprs) =>
|
||
|
Some(Object{
|
||
|
type_tag: repr_type.clone(),
|
||
|
repr: reprs.get(&repr_type)?.clone()
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn downcast_chain<'a>(
|
||
|
&self,
|
||
|
repr_chain: impl Iterator<Item = &'a TypeTerm>
|
||
|
) -> Option<Object> {
|
||
|
repr_chain.fold(
|
||
|
Some(self.clone()),
|
||
|
|s, t| s?.downcast(t.clone())
|
||
|
)
|
||
|
}
|
||
|
|
||
|
fn get_data<T: Any + Send + Sync>(&self) -> Option<Arc<T>> {
|
||
|
match &*self.repr.read().unwrap() {
|
||
|
ReprTree::Leaf(data) => Arc::downcast::<T>(data.clone()).ok(),
|
||
|
_ => None
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
|
||
|
pub struct TypeDict {
|
||
|
typenames: Bimap::<String, u64>,
|
||
|
type_id_counter: u64
|
||
|
}
|
||
|
|
||
|
impl TypeDict {
|
||
|
pub fn new() -> Self {
|
||
|
TypeDict {
|
||
|
typenames: Bimap::new(),
|
||
|
type_id_counter: 0
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn add_typename(&mut self, tn: String) {
|
||
|
self.typenames.insert(tn, self.type_id_counter);
|
||
|
self.type_id_counter += 1;
|
||
|
}
|
||
|
|
||
|
pub fn type_term_from_str(&self, typename: &str) -> Option<TypeTerm> {
|
||
|
TypeTerm::from_str(typename, &self.typenames.mλ)
|
||
|
}
|
||
|
|
||
|
pub fn type_term_to_str(&self, term: &TypeTerm) -> String {
|
||
|
term.to_str(&self.typenames.my)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
|
||
|
pub struct Context {
|
||
|
type_dict: TypeDict,
|
||
|
|
||
|
// map type_id -> constructor
|
||
|
constructors: HashMap<u64, Box<Fn() -> Arc<dyn Any + Send + Sync>>>,
|
||
|
|
||
|
objects: HashMap<String, Object>
|
||
|
}
|
||
|
|
||
|
impl Context {
|
||
|
pub fn add_obj(
|
||
|
&mut self,
|
||
|
name: String,
|
||
|
typename: &str
|
||
|
) {
|
||
|
self.objects.insert(
|
||
|
name,
|
||
|
Object {
|
||
|
type_tag: self.type_dict.type_term_from_str(typename).unwrap(),
|
||
|
repr: Arc::new(RwLock::new(ReprTree::Branch(HashMap::new())))
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
|
||
|
pub fn add_repr(&mut self, name: &String, typename: &str, repr: Arc<RwLock<ReprTree>>) {
|
||
|
match &mut *self.objects.get_mut(name).unwrap().repr.write().unwrap() {
|
||
|
ReprTree::Leaf(_) => {/*error*/},
|
||
|
ReprTree::Branch(repr_map) => {
|
||
|
repr_map.insert(self.type_dict.type_term_from_str(typename).unwrap(), repr.clone());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn get_obj(&self, name: &String) -> Option<Object> {
|
||
|
self.objects.get(name).cloned()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
|