This commit is contained in:
Michael Sippel 2025-05-30 13:23:20 +02:00
parent 0126a62e76
commit 27638e3cf8
Signed by: senvas
GPG key ID: F96CF119C34B64A6
3 changed files with 240 additions and 148 deletions

View file

@ -1,9 +1,8 @@
use {
crate::{
//morphism_path::{MorphismPath, ShortestPathProblem},
morphism::{MorphismInstance, Morphism, MorphismType},
TypeTerm, StructMember, TypeDict, TypeID
}, std::io::{Read, Write}
morphism::{Morphism, MorphismInstance, MorphismType}, StructMember, TypeDict, TypeID, TypeTerm
}, std::{char::decode_utf16, io::{Read, Write}}
};
pub trait MorphBase<
@ -19,6 +18,7 @@ pub trait MorphBase<
}
}
#[derive(Debug)]
pub enum DecomposedMorphismType {
SeqMap { item: MorphismType },
StructMap { members: Vec<(String, MorphismType)> },
@ -50,9 +50,8 @@ impl<M: Morphism + Clone> MorphismBase<M> {
try to match their outer structure (Struct/Seq/Map)
and spawn a GraphSearch for each component
*/
/*
pub fn complex_morphism_decomposition(&self, src_type: &TypeTerm, dst_type: &TypeTerm, dict: &mut impl TypeDict) ->
Option< DecomposedMorphismType >
pub fn morphism_decomposition(&self, src_type: &TypeTerm, dst_type: &TypeTerm) ->
Option< (TypeTerm, DecomposedMorphismType) >
{
let (src_ψ, src_floor) = src_type.get_floor_type();
let (dst_ψ, dst_floor) = dst_type.get_floor_type();
@ -63,14 +62,14 @@ impl<M: Morphism + Clone> MorphismBase<M> {
}
}
eprintln!("Attempt Complex Decomposition....");
eprintln!("Attempt Complex Decomposition....");
match (src_floor, dst_floor) {
(TypeTerm::Struct{ struct_repr: struct_repr_lhs, members: members_lhs},
TypeTerm::Struct { struct_repr: struct_repr_rhs, members: members_rhs })
=> {
// todo: optimization: check if struct repr match
let mut member_morph = Vec::new();
let mut member_morph_types = Vec::new();
let mut failed = false;
let mut necessary = false;
@ -79,14 +78,9 @@ impl<M: Morphism + Clone> MorphismBase<M> {
for StructMember{ symbol: symbol_lhs, ty: ty_lhs } in members_lhs.iter() {
if symbol_rhs == symbol_lhs {
found_src_member = true;
if let Some(mm) = self.get_morphism_instance(&MorphismType { src_type: ty_lhs.clone(), dst_type: ty_rhs.clone() }, dict) {
if ty_lhs != ty_rhs {
necessary = true;
}
member_morph.push((symbol_lhs.clone(), mm))
} else {
failed = true;
member_morph_types.push((symbol_rhs.clone(), MorphismType { src_type: ty_lhs.clone(), dst_type: ty_rhs.clone() }));
if ty_lhs != ty_rhs {
necessary = true;
}
break;
}
@ -100,12 +94,9 @@ impl<M: Morphism + Clone> MorphismBase<M> {
}
if ! failed && necessary {
Some(MorphismInstance::MapStruct {
ψ: src_ψ,
src_struct_repr: struct_repr_lhs.clone(),
dst_struct_repr: struct_repr_rhs.clone(),
member_morph
})
Some((src_ψ, DecomposedMorphismType::StructMap {
members: member_morph_types
}))
} else {
None
}
@ -115,23 +106,26 @@ impl<M: Morphism + Clone> MorphismBase<M> {
(TypeTerm::Seq{ seq_repr: seq_repr_lhs, items: items_lhs },
TypeTerm::Seq{ seq_repr: _seq_rerpr_rhs, items: items_rhs })
=> {
//let mut item_morphs = Vec::new();
for (ty_lhs, ty_rhs) in items_lhs.iter().zip(items_rhs.iter()) {
if let Some(item_morph) = self.get_morphism_instance(&MorphismType{ src_type: ty_lhs.clone(), dst_type: ty_rhs.clone() }, dict) {
return Some(MorphismInstance::MapSeq { ψ: src_ψ, seq_repr: seq_repr_lhs.clone(), item_morph: Box::new(item_morph) });
}
break;
return Some((src_ψ, DecomposedMorphismType::SeqMap {
item: MorphismType{ src_type: ty_lhs.clone(), dst_type: ty_rhs.clone() }
}));
}
None
}
(TypeTerm::Enum { enum_repr: enum_repr_lhs, variants: variants_lhs },
TypeTerm::Enum { enum_repr: enum_repr_rhs, variants: variants_rhs }
) => {
todo!()
}
_ => {
None
}
}
}
*/
pub fn enum_morphisms_from(&self, src_type: &TypeTerm) -> Vec< MorphismInstance<M> > {
let mut morphs = Vec::new();
@ -141,7 +135,7 @@ impl<M: Morphism + Clone> MorphismBase<M> {
/* 1. primitive morphisms */
// check if the given start type is compatible with the
// check if the given source type is compatible with the
// morphisms source type,
// i.e. check if `src_type` is a subtype of `m_src_type`
if let Ok((ψ, σ)) = crate::constraint_system::subtype_unify(src_type, &m_src_type) {
@ -158,18 +152,25 @@ impl<M: Morphism + Clone> MorphismBase<M> {
eprintln!("..found direct morph to {:?}", m.get_type().dst_type);
morphs.push(m);
}
/* 2. check complex types */
/*
else if let Some(complex_morph) = self.complex_morphism_decomposition(src_type, &m_src_type, dict) {
eprintln!("found complex morph to {:?}", complex_morph.get_type().dst_type);
morphs.push(complex_morph);
}
*/
}
morphs
}
pub fn enum_complex_morphisms(&self, src_type: &TypeTerm) -> Vec<(TypeTerm, DecomposedMorphismType)> {
let mut morphs = Vec::new();
for m in self.morphisms.iter() {
let m_src_type = m.get_type().src_type.normalize();
/* 2. check complex types */
if let Some(decomposition) = self.morphism_decomposition(src_type, &m_src_type) {
eprintln!("found complex morph to {:?}", decomposition);
morphs.push(decomposition);
}
}
morphs
}
/*
pub fn to_dot(&self, dict: &mut impl TypeDict) -> String {
let mut dot_source = String::new();

View file

@ -1,8 +1,9 @@
use {
crate::{
Morphism, MorphismBase, MorphismInstance, MorphismType, Substitution, TypeID, TypeTerm, TypeDict
Morphism, MorphismBase, MorphismInstance, MorphismType, Substitution, TypeDict, TypeID, TypeTerm,
morphism_base::DecomposedMorphismType
},
std::{collections::HashMap, sync::{Arc,RwLock}}
std::{char::decode_utf16, collections::HashMap, sync::{Arc,RwLock}}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
@ -47,6 +48,7 @@ pub struct SearchNode<M: Morphism+Clone> {
pub enum Step<M: Morphism+Clone> {
Id { τ: TypeTerm },
Inst{ m: MorphismInstance<M> },
Sub{ ψ: TypeTerm },
Specialize { σ: HashMap<TypeID, TypeTerm> },
MapSeq { item: GraphSearch<M> },
MapStruct { members: Vec< (String, GraphSearch<M>) > },
@ -58,27 +60,45 @@ impl<M:Morphism+Clone> SearchNode<M> {
}
pub trait SearchNodeExt<M: Morphism+Clone> {
fn specialize(&self, σ: HashMap<TypeID, TypeTerm>) -> SearchNode<M>;
fn chain(&self, m: &MorphismInstance<M>) -> SearchNode<M>;
fn specialize(&self, σ: HashMap<TypeID, TypeTerm>) -> Arc<RwLock<SearchNode<M>>>;
fn chain(&self, m: &MorphismInstance<M>) -> Arc<RwLock<SearchNode<M>>>;
fn sub(&self, ψ: TypeTerm) -> Arc<RwLock<SearchNode<M>>>;
fn map_seq(&self, goal: MorphismType) -> Arc<RwLock<SearchNode<M>>>;
fn to_morphism_instance(&self) -> Option< MorphismInstance<M> >;
fn get_type(&self) -> MorphismType;
}
impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
fn specialize(&self, σ: HashMap<TypeID, TypeTerm>) -> SearchNode<M> {
SearchNode {
fn specialize(&self, σ: HashMap<TypeID, TypeTerm>) -> Arc<RwLock<SearchNode<M>>> {
Arc::new(RwLock::new(SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight,
step: Step::Specialize { σ }
}
}))
}
fn chain(&self, m: &MorphismInstance<M>) -> SearchNode<M> {
SearchNode {
fn chain(&self, m: &MorphismInstance<M>) -> Arc<RwLock<SearchNode<M>>> {
Arc::new(RwLock::new(SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight + m.get_weight(),
step: Step::Inst{ m: m.clone() }
}
}))
}
fn sub(&self, ψ: TypeTerm) -> Arc<RwLock<SearchNode<M>>> {
Arc::new(RwLock::new(SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight,
step: Step::Sub{ ψ }
}))
}
fn map_seq(&self, goal: MorphismType) -> Arc<RwLock<SearchNode<M>>> {
Arc::new(RwLock::new(SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight,
step: Step::MapSeq { item: GraphSearch::new(goal) }
}))
}
fn to_morphism_instance(&self) -> Option< MorphismInstance<M> > {
@ -86,6 +106,8 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
let mut path = Vec::new();
let mut subst = HashMap::new();
let mut halos = Vec::new();
let mut cur_node = Some(self.clone());
while let Some(n) = cur_node {
let n = n.read().unwrap();
@ -94,6 +116,9 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
Step::Inst{ m } => {
path.push(m.clone());
},
Step::Sub { ψ } => {
halos.push(ψ.clone());
}
Step::Specialize { σ } => {
subst = subst.append(&σ);
}
@ -130,6 +155,10 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
m = MorphismInstance::Specialize { σ: subst, m: Box::new(m) };
}
if halos.len() > 0 {
m = MorphismInstance::Sub { ψ: TypeTerm::Ladder(halos).normalize(), m: Box::new(m) };
}
Some(m)
}
@ -151,6 +180,9 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
}
}
*/
Step::Sub { ψ } => {
todo!()
}
Step::Inst{ m } => m.get_type(),
Step::Specialize { σ } => {
if let Some(p) = self.read().unwrap().pred.as_ref() {
@ -163,20 +195,15 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
}
},
Step::MapSeq { item } => {
if let Some(p) = self.read().unwrap().pred.as_ref() {
MorphismType {
src_type: TypeTerm::Seq{ seq_repr: None, items: vec![p.get_type().src_type] },
dst_type: TypeTerm::Seq{ seq_repr: None, items: vec![p.get_type().dst_type] }
}
} else {
unreachable!()
MorphismType {
src_type: TypeTerm::Seq{ seq_repr: None, items: vec![item.goal.src_type.clone()] },
dst_type: TypeTerm::Seq{ seq_repr: None, items: vec![item.goal.dst_type.clone()] }
}
}
_ => todo!()
}
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
@ -207,6 +234,7 @@ impl<M: Morphism+Clone> MorphismGraph<M> {
impl<M: Morphism+Clone> GraphSearch<M> {
pub fn new(goal: MorphismType) -> Self {
eprintln!("New GraphSearch Problem!");
GraphSearch {
goal: goal.clone(),
solution: None,
@ -265,33 +293,34 @@ impl<M: Morphism+Clone> GraphSearch<M> {
pub fn advance(&mut self, base: &MorphismBase<M>, dict: &mut impl TypeDict) -> GraphSearchState<M> {
if let Some(node) = self.choose_next_node(dict) {
{
let mut n = node.write().unwrap();
match &mut n.step {
Step::MapSeq { item } => {
match item.advance(base, dict) {
GraphSearchState::Solved(item_morph) => {
let map_morph = MorphismInstance::MapSeq {
seq_repr: todo!(),
item_morph: Box::new(item_morph)
};
}
GraphSearchState::Err(err) => {
return GraphSearchState::Err(err);
},
GraphSearchState::Continue => {
self.explore_queue.push(node.clone());
return GraphSearchState::Continue;
let mut n = node.write().unwrap();
match &mut n.step {
Step::MapSeq { item } => {
eprintln!("advance seq-map");
match item.advance(base, dict) {
GraphSearchState::Solved(item_morph) => {
let map_morph = MorphismInstance::MapSeq {
seq_repr: None,
item_morph: Box::new(item_morph)
};
}
GraphSearchState::Err(err) => {
return GraphSearchState::Err(err);
},
GraphSearchState::Continue => {
self.explore_queue.push(node.clone());
return GraphSearchState::Continue;
}
}
}
Step::MapStruct { members } => {
todo!()
}
Step::MapEnum { variants } => {
todo!()
}
_ => {}
}
Step::MapStruct { members } => {
todo!()
}
Step::MapEnum { variants } => {
todo!()
}
_ => {}
}
}
/* 1. Check if goal is already reached by the current path */
@ -301,19 +330,78 @@ impl<M: Morphism+Clone> GraphSearch<M> {
if σ.is_empty() {
node.to_morphism_instance().unwrap()
} else {
Arc::new(RwLock::new(node.specialize(σ))).to_morphism_instance().unwrap()
node.specialize(σ).to_morphism_instance().unwrap()
}
);
return GraphSearchState::Solved(self.get_solution().unwrap())
return GraphSearchState::Solved(self.get_solution().unwrap());
}
else if let Some((ψ, decomposition)) = base.morphism_decomposition(&node.get_type().dst_type, &self.goal.dst_type) {
eprintln!("decomposition to end!");
let final_node = match decomposition {
DecomposedMorphismType::SeqMap { item } => {
eprintln!("decomposed to seq map with item : {} -> {} ", item.src_type.pretty(dict, 0), item.dst_type.pretty(dict,0));
node.map_seq( item )
},
DecomposedMorphismType::StructMap { members } => {
//node.sub(ψ).map_struct( members )
/*
Step::MapStruct { members: members.into_iter().map(
|(symbol, ty)| (symbol, GraphSearch::new(ty))
).collect() }
*/
todo!()
},
DecomposedMorphismType::EnumMap { variants } => {
/*
Step::MapEnum { variants: variants.into_iter().map(
|(symbol, ty)| (symbol, GraphSearch::new(ty))
).collect() }
*/
todo!()
},
};
self.explore_queue.push(final_node);
//return GraphSearchState::Continue;
}
/* 2. Try to advance current path */
for next_morph_inst in base.enum_morphisms_from(&node.get_type().dst_type) {
self.explore_queue.push( Arc::new(RwLock::new( node.chain(&next_morph_inst) )) );
eprintln!("add direct path");
self.explore_queue.push( node.chain(&next_morph_inst) );
}
}
GraphSearchState::Continue
eprintln!("check complex decompositions from {}", node.get_type().dst_type.pretty(dict,0));
for (ψ,decomposition) in base.enum_complex_morphisms(&node.get_type().dst_type) {
eprintln!("add decomposition!");
self.explore_queue.push(
Arc::new(RwLock::new(
SearchNode {
pred: Some(node.clone()),
weight: 0,
step: match decomposition {
DecomposedMorphismType::SeqMap { item } => {
Step::MapSeq { item: GraphSearch::new(item) }
},
DecomposedMorphismType::StructMap { members } => {
Step::MapStruct { members: members.into_iter().map(
|(symbol, ty)| (symbol, GraphSearch::new(ty))
).collect() }
},
DecomposedMorphismType::EnumMap { variants } => {
Step::MapEnum { variants: variants.into_iter().map(
|(symbol, ty)| (symbol, GraphSearch::new(ty))
).collect() }
},
},
}
)).sub(ψ)
);
}
GraphSearchState::Continue
} else {
GraphSearchState::Err(GraphSearchError::NoMorphismFound)
}
}
}

View file

@ -81,13 +81,13 @@ fn morphism_test_setup() -> ( BimapTypeDict, MorphismBase<DummyMorphism> ) {
dst_type: dict.parse_desugared(" ~ <PosInt Radix BigEndian> ~ <Seq <Digit Radix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict)
})
);
*/
base.add_morphism(
DummyMorphism(MorphismType{
src_type: dict.parse_desugared(" ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared(" ~ <PosInt DstRadix LittleEndian> ~ <Seq <Digit DstRadix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict)
})
);
*/
/*
@ -194,88 +194,91 @@ fn test_morphgraph_chain() {
#[test]
fn test_morphgraph_map_seq() {
let (mut dict, mut base) = morphism_test_setup();
let mut dict = BimapTypeDict::new();
let mut base = MorphismBase::<DummyMorphism>::new();
base.add_morphism(DummyMorphism(MorphismType{
src_type: dict.parse("A ~ F").expect(""),
dst_type: dict.parse("A ~ E").expect("")
}));
let morph_graph = MorphismGraph::new(base);
assert_eq!(
morph_graph.search(MorphismType {
src_type: dict.parse(" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10> ~ Char>").unwrap(),
dst_type: dict.parse(" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10> ~ _2^64 ~ machine.UInt64>").unwrap(),
src_type: dict.parse("<Seq A ~ F>").unwrap(),
dst_type: dict.parse("<Seq A ~ E>").unwrap(),
}, &mut dict),
Ok(
MorphismInstance::Sub {
ψ: dict.parse(" ~ <PosInt 10 BigEndian>").expect(""),
m: Box::new(
MorphismInstance::MapSeq { seq_repr: None, item_morph: Box::new(
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"Radix".into()).unwrap(), TypeTerm::Num(10)),
].into_iter().collect(),
m: Box::new(
MorphismInstance::Primitive {
m: DummyMorphism(MorphismType {
src_type: dict.parse("<Digit Radix> ~ Char").unwrap(),
dst_type: dict.parse("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap()
})
}
)
}
) }
) }
MorphismInstance::MapSeq { seq_repr: None, item_morph: Box::new(
MorphismInstance::Primitive {
m: DummyMorphism(MorphismType {
src_type: dict.parse("A ~ F").unwrap(),
dst_type: dict.parse("A ~ E").unwrap()
})
}
) }
)
);
}
/*
#[test]
fn test_morphism_path3() {
let (mut dict, mut base) = morphism_test_setup();
let path = ShortestPathProblem::new(&base, MorphismType {
src_type: dict.parse_desugared(" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10> ~ Char>").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared(" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16> ~ _2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict),
}).solve();
if let Some(path) = path.as_ref() {
print_path(&mut dict, path);
}
let morph_graph = MorphismGraph::new(base);
assert_eq!(
path,
Some(
vec![
MorphismInstance::MapSeq {
ψ: dict.parse_desugared(" ~ <PosInt 10 LittleEndian>").expect("").sugar(&mut dict),
seq_repr: None,
item_morph: Box::new(MorphismInstance::Primitive {
σ: vec![
(dict.get_typeid(&"Radix".into()).unwrap(), TypeTerm::Num(10)),
].into_iter().collect(),
ψ: TypeTerm::unit(),
morph: DummyMorphism(MorphismType {
src_type: dict.parse_desugared("<Digit Radix> ~ Char").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap().sugar(&mut dict)
}),
})
},
morph_graph.search(MorphismType {
src_type: dict.parse(" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10> ~ Char>").unwrap(),
dst_type: dict.parse(" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16> ~ _2^64 ~ machine.UInt64>").unwrap(),
}, &mut dict),
Ok(
MorphismInstance::Chain {
path: vec![
MorphismInstance::MapSeq {
seq_repr: None,
item_morph: Box::new(
MorphismInstance::Sub {
ψ: dict.parse(" ~ <PosInt 10 LittleEndian>").expect(""),
m: Box::new(
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"Radix".into()).unwrap(), TypeTerm::Num(10)),
].into_iter().collect(),
m: Box::new(MorphismInstance::Primitive {
m: DummyMorphism(MorphismType {
src_type: dict.parse("<Digit Radix> ~ Char").unwrap(),
dst_type: dict.parse("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap()
}),
})
}
)
}
)
},
MorphismInstance::Primitive {
σ: vec![
(dict.get_typeid(&"SrcRadix".into()).unwrap(), TypeTerm::Num(10)),
(dict.get_typeid(&"DstRadix".into()).unwrap(), TypeTerm::Num(16)),
].into_iter().collect(),
ψ: TypeTerm::unit(),
morph: DummyMorphism(MorphismType {
src_type: dict.parse_desugared(" ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix> ~ _2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared(" ~ <PosInt DstRadix LittleEndian> ~ <Seq <Digit DstRadix> ~ _2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict)
}),
}
]
));
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"SrcRadix".into()).unwrap(), TypeTerm::Num(10)),
(dict.get_typeid(&"DstRadix".into()).unwrap(), TypeTerm::Num(16)),
].into_iter().collect(),
m: Box::new(
MorphismInstance::Primitive{
m: DummyMorphism(MorphismType {
src_type: dict.parse_desugared(" ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix> ~ _2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared(" ~ <PosInt DstRadix LittleEndian> ~ <Seq <Digit DstRadix> ~ _2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict)
}),
}
)
}
]
}
));
}
/*
#[test]
fn test_morphism_path4() {
let (mut dict, mut base) = morphism_test_setup();