lib-nested/nested/src/core/context.rs

134 lines
3.2 KiB
Rust
Raw Normal View History

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.)
}
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()
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>