use { std::{ collections::HashMap, sync::{Arc, RwLock}, any::Any }, crate::{ bimap::Bimap, core::type_term::{TypeID, TypeTerm} } }; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub enum ReprTree { Leaf(Arc), Branch(HashMap>>) } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> #[derive(Clone)] pub struct Object { type_tag: TypeTerm, repr: Arc> } impl Object { fn downcast(&self, repr_type: TypeTerm) -> Option { 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 ) -> Option { repr_chain.fold( Some(self.clone()), |s, t| s?.downcast(t.clone()) ) } fn get_data(&self) -> Option> { match &*self.repr.read().unwrap() { ReprTree::Leaf(data) => Arc::downcast::(data.clone()).ok(), _ => None } } } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub struct TypeDict { typenames: Bimap::, 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::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 Arc>>, objects: HashMap } 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>) { 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 { self.objects.get(name).cloned() } } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>