114 lines
4.1 KiB
Rust
114 lines
4.1 KiB
Rust
use {
|
||
super::{context::{TYPEID_char, TYPEID_edittree, TYPEID_list, TYPEID_u64, TYPEID_vec}, Context, ReprLeaf, ReprTree, ReprTreeExt}, laddertypes::{steiner_tree, sugar::*, unparser::UnparseLadderType as _, TypeID, TypeTerm}, r3vi::{
|
||
buffer::{singleton::*, vec::*}, view::{
|
||
list::*, port::UpdateTask, sequence::*, singleton::*, AnyInnerViewPort, AnyOuterViewPort, AnyViewPort, Observer, OuterViewPort, View, ViewPort
|
||
}
|
||
}, std::{
|
||
any::Any, collections::HashMap, sync::{Arc, RwLock}
|
||
}
|
||
};
|
||
|
||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
||
#[derive(Clone)]
|
||
pub struct ReprTreeBuilder {
|
||
ctx: Arc<RwLock<Context>>,
|
||
pub required_leaves: Vec<TypeTerm>,
|
||
}
|
||
|
||
#[derive(Debug)]
|
||
pub enum ReprTreeError {
|
||
MissingMorphism
|
||
}
|
||
|
||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||
|
||
impl ReprTreeBuilder {
|
||
pub fn new(ctx: Arc<RwLock<Context>>) -> Self {
|
||
ReprTreeBuilder {
|
||
ctx,
|
||
required_leaves: Vec::new()
|
||
}
|
||
}
|
||
|
||
/// Add a type to the set of required representations.
|
||
pub fn require(mut self, mut t: TypeTerm) -> Self {
|
||
t = t.normalize();
|
||
if !self.required_leaves.contains(&t) {
|
||
self.required_leaves.push(t);
|
||
}
|
||
self
|
||
}
|
||
|
||
/// (re)build steiner tree with `required_leaves`,
|
||
/// and apply it to the projections in the ReprTree.
|
||
/// Updating and keeping existing nodes, while
|
||
/// adding new ones if required.
|
||
pub fn update(
|
||
&self,
|
||
rt: &Arc<RwLock<ReprTree>>,
|
||
master_leaf_type: impl Into<TypeTerm>
|
||
) -> Result< Arc<RwLock<ReprTree>>, ReprTreeError > {
|
||
rt.write().unwrap().detach( &self.ctx );
|
||
|
||
let morphism_base = &self.ctx.read().unwrap().morphisms;
|
||
|
||
let mt = master_leaf_type.into().normalize().param_normalize();
|
||
eprintln!("REBUILD repr tree from {}", self.ctx.read().unwrap().type_term_to_str(&mt));
|
||
let mut leaves = self.required_leaves.clone();
|
||
leaves.retain(|t| t != &mt);
|
||
|
||
let mut st_problem = laddertypes::steiner_tree::PathApproxSteinerTreeSolver::new(
|
||
mt.clone(),
|
||
leaves
|
||
);
|
||
|
||
if let Some( steiner_tree ) = st_problem.solve( &morphism_base ) {
|
||
eprintln!("--> from {}", self.ctx.read().unwrap().type_term_to_str(&mt));
|
||
|
||
let edges = steiner_tree.into_edges();
|
||
eprintln!("steiner tree has {} edges", edges.len());
|
||
for morphism_type in edges {
|
||
eprintln!("--> morph to {}",
|
||
self.ctx.read().unwrap().type_term_to_str(&morphism_type.dst_type));
|
||
|
||
let mut dict = self.ctx.read().unwrap().type_dict.clone();
|
||
|
||
if let Some(morph_inst) =
|
||
morphism_base.find_morphism( &morphism_type, &mut dict )
|
||
{
|
||
eprintln!("setup morph");
|
||
|
||
let halo = laddertypes::common_halo(
|
||
&morphism_type.src_type,
|
||
&morphism_type.dst_type
|
||
).unwrap_or(TypeTerm::unit());
|
||
eprintln!("halo = {}", dict.read().unwrap().unparse(&halo));
|
||
|
||
let mut rt = rt.descend_create( halo ).expect("descend src repr");
|
||
eprintln!("{}", rt.read().unwrap().fmt(&self.ctx, 0));
|
||
(morph_inst.m.setup_projection)( &mut rt, &morph_inst.σ );
|
||
} else {
|
||
eprintln!("failed to get morphism");
|
||
return Err(ReprTreeError::MissingMorphism);
|
||
}
|
||
}
|
||
|
||
Ok( rt.clone() )
|
||
} else {
|
||
eprintln!("could not find steiner tree to build the requested repr tree");
|
||
Err(ReprTreeError::MissingMorphism)
|
||
}
|
||
}
|
||
|
||
/// Build fresh ReprTree from a master representation.
|
||
pub fn build_from(
|
||
&self,
|
||
mut master_rt: Arc<RwLock<ReprTree>>
|
||
) -> Result< Arc<RwLock<ReprTree>>, ReprTreeError > {
|
||
let master_leaf_type = master_rt.get_full_type();
|
||
self.update( &ReprTree::rise( master_rt ), master_leaf_type )
|
||
}
|
||
}
|
||
|
||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|