rewrite morphism search
This commit is contained in:
parent
4ab07df9f2
commit
b6add2b1a2
10 changed files with 1140 additions and 519 deletions
Cargo.toml
src
|
@ -7,5 +7,8 @@ version = "0.1.0"
|
|||
[dependencies]
|
||||
tiny-ansi = { version = "0.1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "*"
|
||||
|
||||
[features]
|
||||
pretty = ["dep:tiny-ansi"]
|
||||
|
|
|
@ -19,6 +19,8 @@ pub type HashMapSubst = std::collections::HashMap<u64, TypeTerm>;
|
|||
|
||||
pub trait SubstitutionMut {
|
||||
fn append(&mut self, other: &Self);
|
||||
fn filter(self, f: impl FnMut(&(u64, TypeTerm)) -> bool) -> Self;
|
||||
fn filter_morphtype(self, ty: &crate::MorphismType) -> Self;
|
||||
}
|
||||
|
||||
impl SubstitutionMut for HashMapSubst {
|
||||
|
@ -27,6 +29,17 @@ impl SubstitutionMut for HashMapSubst {
|
|||
self.insert(*v,t.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn filter(self, f: impl FnMut(&(u64, TypeTerm)) -> bool) -> Self {
|
||||
self.into_iter().filter(f).collect()
|
||||
}
|
||||
|
||||
fn filter_morphtype(self, ty: &crate::MorphismType) -> Self {
|
||||
self.filter(|(v,t)| {
|
||||
ty.src_type.contains_var(*v) ||
|
||||
ty.dst_type.contains_var(*v)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Substitution for HashMapSubst {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use crate::{MorphismType, TypeTerm};
|
||||
use crate::{morphism_graph::MorphismType, TypeTerm};
|
||||
|
||||
impl MorphismType {
|
||||
|
||||
pub fn estimated_cost(&self) -> u64 {
|
||||
|
||||
if let Ok((ψ,σ)) = crate::subtype_unify(&self.src_type, &self.dst_type) {
|
||||
1
|
||||
0
|
||||
} else {
|
||||
match (self.src_type.clone().normalize(),
|
||||
self.dst_type.clone().normalize())
|
||||
|
@ -28,7 +29,7 @@ impl MorphismType {
|
|||
(TypeTerm::Seq{ seq_repr: sr1, items: items1 },
|
||||
TypeTerm::Seq{ seq_repr: sr2, items: items2 }) => {
|
||||
let mut cost = 10;
|
||||
/*
|
||||
/* // todo : add cost seq-repr conversion?
|
||||
estimated_morphism_cost(
|
||||
&MorphismType { src_type: sr1, dst_type: sr2 }
|
||||
);
|
||||
|
@ -40,6 +41,11 @@ impl MorphismType {
|
|||
cost
|
||||
}
|
||||
|
||||
(TypeTerm::Var(_), x)
|
||||
| (x, TypeTerm::Var(_))
|
||||
=> {
|
||||
return 1;
|
||||
}
|
||||
(a, b) => {
|
||||
if a == b {
|
||||
return 0;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
pub mod morphism_base;
|
||||
pub mod morphism_path;
|
||||
pub mod morphism_graph;
|
||||
|
||||
pub use morphism_base::*;
|
||||
pub use morphism_path::*;
|
||||
pub use morphism_graph::*;
|
||||
|
||||
use {
|
||||
crate::{
|
||||
|
@ -230,28 +230,27 @@ pub trait Morphism : Sized {
|
|||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum MorphismInstance<M: Morphism + Clone> {
|
||||
Id { ψ: TypeTerm },
|
||||
Primitive{
|
||||
Id { τ: TypeTerm },
|
||||
Primitive{ m: M },
|
||||
Sub {
|
||||
ψ: TypeTerm,
|
||||
m: Box<MorphismInstance<M>>
|
||||
},
|
||||
Specialize{
|
||||
σ: HashMapSubst,
|
||||
morph: M,
|
||||
},
|
||||
Chain{
|
||||
path: Vec<MorphismInstance<M>>
|
||||
m: Box<MorphismInstance<M>>
|
||||
},
|
||||
Chain{ path: Vec<MorphismInstance<M>> },
|
||||
MapSeq{
|
||||
ψ: TypeTerm,
|
||||
seq_repr: Option<Box<TypeTerm>>,
|
||||
item_morph: Box<MorphismInstance<M>>,
|
||||
},
|
||||
MapStruct{
|
||||
ψ: TypeTerm,
|
||||
src_struct_repr: Option<Box<TypeTerm>>,
|
||||
dst_struct_repr: Option<Box<TypeTerm>>,
|
||||
member_morph: Vec< (String, MorphismInstance<M>) >
|
||||
},
|
||||
MapEnum{
|
||||
ψ: TypeTerm,
|
||||
enum_repr: Option<Box<TypeTerm>>,
|
||||
variant_morph: Vec< (String, MorphismInstance<M>) >
|
||||
}
|
||||
|
@ -263,43 +262,58 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
|
|||
self.get_type().strip_common_rungs()
|
||||
}
|
||||
|
||||
pub fn from_chain(τ: TypeTerm, path: &Vec<MorphismInstance<M>>) -> Self {
|
||||
if path.len() == 0 {
|
||||
MorphismInstance::Id { τ }
|
||||
} else if path.len() == 1 {
|
||||
path[0].clone()
|
||||
} else {
|
||||
MorphismInstance::Chain { path: path.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_weight(&self) -> u64 {
|
||||
match self {
|
||||
MorphismInstance::Id { ψ } => 0,
|
||||
MorphismInstance::Primitive { ψ, σ, morph } => 1,
|
||||
MorphismInstance::Id { τ } => 0,
|
||||
MorphismInstance::Sub { ψ, m } => m.get_weight(),
|
||||
MorphismInstance::Specialize { σ, m } => m.get_weight(),
|
||||
MorphismInstance::Primitive { m } => 10,
|
||||
MorphismInstance::Chain { path } => path.iter().map(|m| m.get_weight()).sum(),
|
||||
MorphismInstance::MapSeq { ψ, seq_repr, item_morph } => item_morph.get_weight() + 1,
|
||||
MorphismInstance::MapStruct { ψ, src_struct_repr, dst_struct_repr, member_morph } => member_morph.iter().map(|m| m.1.get_weight()).sum(),
|
||||
MorphismInstance::MapEnum { ψ, enum_repr, variant_morph } => variant_morph.iter().map(|m| m.1.get_weight()).sum()
|
||||
MorphismInstance::MapSeq { seq_repr, item_morph } => item_morph.get_weight() + 15,
|
||||
MorphismInstance::MapStruct { src_struct_repr, dst_struct_repr, member_morph } => member_morph.iter().map(|m| m.1.get_weight()).sum(),
|
||||
MorphismInstance::MapEnum { enum_repr, variant_morph } => variant_morph.iter().map(|m| m.1.get_weight()).sum()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> MorphismType {
|
||||
match self {
|
||||
MorphismInstance::Id { ψ } => {
|
||||
MorphismInstance::Id { τ } => {
|
||||
MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: ψ.clone(),
|
||||
dst_type: ψ.clone()
|
||||
src_type: τ.clone(),
|
||||
dst_type: τ.clone()
|
||||
}
|
||||
}
|
||||
MorphismInstance::Primitive { ψ, σ, morph } => {
|
||||
MorphismInstance::Primitive { m } => { m.get_type() },
|
||||
MorphismInstance::Sub { ψ, m } =>
|
||||
MorphismType {
|
||||
bounds: morph.get_type().bounds,
|
||||
bounds: m.get_type().bounds,
|
||||
src_type:
|
||||
TypeTerm::Ladder(vec![
|
||||
ψ.clone(),
|
||||
morph.get_type().src_type
|
||||
.apply_subst(σ).clone()
|
||||
]).strip(),
|
||||
|
||||
m.get_type().src_type
|
||||
]),
|
||||
dst_type: TypeTerm::Ladder(vec![
|
||||
ψ.clone(),
|
||||
morph.get_type().dst_type
|
||||
.apply_subst(σ).clone()
|
||||
]).strip(),
|
||||
}
|
||||
}
|
||||
m.get_type().dst_type
|
||||
]),
|
||||
},
|
||||
MorphismInstance::Specialize { σ, m } =>
|
||||
MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: m.get_type().src_type.apply_subst(σ).clone(),
|
||||
dst_type: m.get_type().dst_type.apply_subst(σ).clone(),
|
||||
},
|
||||
MorphismInstance::Chain { path } => {
|
||||
if path.len() > 0 {
|
||||
//let s = self.get_subst();
|
||||
|
@ -309,8 +323,7 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
|
|||
bounds: Vec::new(), // <-- fixme: but first implement variable scopes
|
||||
src_type: path.first().unwrap().get_type().src_type.clone(),
|
||||
dst_type: path.last().unwrap().get_type().dst_type.clone()
|
||||
}
|
||||
//.apply_subst(&s)
|
||||
}//.apply_subst(&s)
|
||||
} else {
|
||||
MorphismType {
|
||||
bounds: Vec::new(),
|
||||
|
@ -319,63 +332,50 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
|
|||
}
|
||||
}
|
||||
}
|
||||
MorphismInstance::MapSeq { ψ, seq_repr, item_morph } => {
|
||||
MorphismInstance::MapSeq { seq_repr, item_morph } => {
|
||||
MorphismType {
|
||||
bounds: item_morph.get_type().bounds,
|
||||
src_type: TypeTerm::Ladder(vec![
|
||||
ψ.clone(),
|
||||
TypeTerm::Seq{ seq_repr: seq_repr.clone(),
|
||||
items: vec![ item_morph.get_type().src_type ]}
|
||||
]),
|
||||
dst_type: TypeTerm::Ladder(vec![
|
||||
ψ.clone(),
|
||||
TypeTerm::Seq{ seq_repr: seq_repr.clone(),
|
||||
items: vec![ item_morph.get_type().dst_type ]}
|
||||
])
|
||||
src_type: TypeTerm::Seq{ seq_repr: seq_repr.clone(),
|
||||
items: vec![ item_morph.get_type().src_type ]},
|
||||
dst_type: TypeTerm::Seq{ seq_repr: seq_repr.clone(),
|
||||
items: vec![ item_morph.get_type().dst_type ]},
|
||||
}
|
||||
}
|
||||
MorphismInstance::MapStruct { ψ, src_struct_repr, dst_struct_repr, member_morph } => {
|
||||
MorphismInstance::MapStruct { src_struct_repr, dst_struct_repr, member_morph } => {
|
||||
MorphismType {
|
||||
bounds: Vec::new(), // <-- fixme: same as with chain
|
||||
src_type: TypeTerm::Ladder(vec![ ψ.clone(),
|
||||
TypeTerm::Struct{
|
||||
src_type: TypeTerm::Struct{
|
||||
struct_repr: src_struct_repr.clone(),
|
||||
members:
|
||||
member_morph.iter().map(|(symbol, morph)| {
|
||||
StructMember{ symbol:symbol.clone(), ty: morph.get_type().src_type }
|
||||
}).collect()
|
||||
}
|
||||
]),
|
||||
dst_type: TypeTerm::Ladder(vec![ ψ.clone(),
|
||||
TypeTerm::Struct{
|
||||
},
|
||||
|
||||
dst_type: TypeTerm::Struct {
|
||||
struct_repr: dst_struct_repr.clone(),
|
||||
members: member_morph.iter().map(|(symbol, morph)| {
|
||||
StructMember { symbol: symbol.clone(), ty: morph.get_type().dst_type}
|
||||
}).collect()
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
MorphismInstance::MapEnum { ψ, enum_repr, variant_morph } => {
|
||||
MorphismInstance::MapEnum { enum_repr, variant_morph } => {
|
||||
MorphismType {
|
||||
bounds: Vec::new(), // <-- fixme: same as with chain
|
||||
src_type: TypeTerm::Ladder(vec![ ψ.clone(),
|
||||
TypeTerm::Struct{
|
||||
src_type: TypeTerm::Struct{
|
||||
struct_repr: enum_repr.clone(),
|
||||
members:
|
||||
variant_morph.iter().map(|(symbol, morph)| {
|
||||
StructMember{ symbol:symbol.clone(), ty: morph.get_type().src_type }
|
||||
}).collect()
|
||||
}
|
||||
]),
|
||||
dst_type: TypeTerm::Ladder(vec![ ψ.clone(),
|
||||
TypeTerm::Struct{
|
||||
},
|
||||
dst_type: TypeTerm::Struct{
|
||||
struct_repr: enum_repr.clone(),
|
||||
members: variant_morph.iter().map(|(symbol, morph)| {
|
||||
StructMember { symbol: symbol.clone(), ty: morph.get_type().dst_type}
|
||||
}).collect()
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}.normalize()
|
||||
|
@ -383,10 +383,14 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
|
|||
|
||||
pub fn get_subst(&self) -> HashMapSubst {
|
||||
match self {
|
||||
MorphismInstance::Id { ψ } => {
|
||||
std::collections::HashMap::new()
|
||||
MorphismInstance::Id { τ } => HashMap::new(),
|
||||
MorphismInstance::Primitive { m } => HashMap::new(),
|
||||
MorphismInstance::Sub { ψ, m } => m.get_subst(),
|
||||
MorphismInstance::Specialize { σ, m } => {
|
||||
let mut σ0 = m.get_subst();
|
||||
σ0.append(σ);
|
||||
σ0
|
||||
}
|
||||
MorphismInstance::Primitive { ψ, σ, morph } => σ.clone(),
|
||||
MorphismInstance::Chain { path } => {
|
||||
path.iter().fold(
|
||||
std::collections::HashMap::new(),
|
||||
|
@ -396,17 +400,17 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
|
|||
}
|
||||
)
|
||||
},
|
||||
MorphismInstance::MapSeq { ψ, seq_repr, item_morph } => {
|
||||
MorphismInstance::MapSeq { seq_repr, item_morph } => {
|
||||
item_morph.get_subst()
|
||||
},
|
||||
MorphismInstance::MapStruct { ψ, src_struct_repr, dst_struct_repr, member_morph } => {
|
||||
MorphismInstance::MapStruct { src_struct_repr, dst_struct_repr, member_morph } => {
|
||||
let mut σ = HashMap::new();
|
||||
for (symbol, m) in member_morph.iter() {
|
||||
σ.append(&mut m.get_subst());
|
||||
}
|
||||
σ
|
||||
},
|
||||
MorphismInstance::MapEnum { ψ, enum_repr, variant_morph } => {
|
||||
MorphismInstance::MapEnum { enum_repr, variant_morph } => {
|
||||
todo!();
|
||||
HashMap::new()
|
||||
},
|
||||
|
@ -416,19 +420,24 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
|
|||
pub fn apply_subst(&mut self, γ: &HashMapSubst) {
|
||||
let ty = self.get_type();
|
||||
match self {
|
||||
MorphismInstance::Id { ψ } => {
|
||||
ψ.apply_subst( γ );
|
||||
MorphismInstance::Id { τ } => {
|
||||
τ.apply_subst( γ );
|
||||
}
|
||||
MorphismInstance::Primitive { ψ, σ, morph } => {
|
||||
MorphismInstance::Primitive { m } => { },
|
||||
MorphismInstance::Sub { ψ, m } => {
|
||||
ψ.apply_subst(γ);
|
||||
for (_,t) in σ.iter_mut() {
|
||||
m.apply_subst(γ);
|
||||
}
|
||||
MorphismInstance::Specialize { σ, m } => {
|
||||
for (n,t) in σ.iter_mut() {
|
||||
t.apply_subst(γ);
|
||||
}
|
||||
for (v,t) in γ.iter() {
|
||||
if morph.get_type().src_type.apply_subst(σ).contains_var(*v)
|
||||
|| morph.get_type().dst_type.apply_subst(σ).contains_var(*v) {
|
||||
σ.insert(*v, t.clone());
|
||||
}
|
||||
for (i,t) in γ.iter() {
|
||||
if m.get_type().src_type.apply_subst(σ).contains_var(*i)
|
||||
|| m.get_type().dst_type.apply_subst(σ).contains_var(*i) {
|
||||
σ.insert(*i, t.clone());
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
MorphismInstance::Chain { path } => {
|
||||
|
@ -436,16 +445,15 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
|
|||
n.apply_subst(γ);
|
||||
}
|
||||
}
|
||||
MorphismInstance::MapSeq { ψ, seq_repr, item_morph } => {
|
||||
ψ.apply_subst(γ);
|
||||
MorphismInstance::MapSeq { seq_repr, item_morph } => {
|
||||
item_morph.apply_subst(γ);
|
||||
}
|
||||
MorphismInstance::MapStruct { ψ, src_struct_repr, dst_struct_repr, member_morph } => {
|
||||
MorphismInstance::MapStruct { src_struct_repr, dst_struct_repr, member_morph } => {
|
||||
for (_,ty) in member_morph {
|
||||
ty.apply_subst(γ);
|
||||
}
|
||||
},
|
||||
MorphismInstance::MapEnum { ψ, enum_repr, variant_morph } => {
|
||||
MorphismInstance::MapEnum { enum_repr, variant_morph } => {
|
||||
for (_,ty) in variant_morph {
|
||||
ty.apply_subst(γ);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,29 @@
|
|||
use {
|
||||
crate::{
|
||||
morphism_path::{ShortestPathProblem},
|
||||
morphism_graph::{MorphismInstance, Morphism, MorphismType},
|
||||
TypeTerm, StructMember, TypeDict
|
||||
}, std::io::{Write}
|
||||
morphism_graph::{Morphism, MorphismInstance, MorphismType}, HashMapSubst, StructMember, TypeDict, TypeTerm
|
||||
}, std::io::Write
|
||||
};
|
||||
|
||||
pub trait MorphBase<
|
||||
Morph: Morphism + Clone,
|
||||
Weight: Eq + Ord + Default
|
||||
> {
|
||||
fn get_morphisms(&self, halo_key: &TypeTerm) -> Vec<MorphismInstance<Morph>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn heuristic(&self, t: &MorphismType) -> Weight {
|
||||
Weight::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum DecomposedMorphismType {
|
||||
SeqMap { item: MorphismType },
|
||||
StructMap { members: Vec<(String, MorphismType)> },
|
||||
EnumMap { variants: Vec<(String, MorphismType)> }
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -26,21 +44,14 @@ impl<M: Morphism + Clone> MorphismBase<M> {
|
|||
self.morphisms.push( m );
|
||||
}
|
||||
|
||||
pub fn get_morphism_instance(&self, ty: &MorphismType) -> Option<MorphismInstance<M>> {
|
||||
if let Some(path) = ShortestPathProblem::new(self, ty.clone()).solve() {
|
||||
if path.len() == 0 {
|
||||
Some(MorphismInstance::Id{ ψ: ty.src_type.clone() })
|
||||
} else if path.len() == 1 {
|
||||
Some(path[0].clone())
|
||||
} else {
|
||||
Some(MorphismInstance::Chain { path })
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn complex_morphism_decomposition(&self, src_type: &TypeTerm, dst_type: &TypeTerm) -> Option< MorphismInstance<M> > {
|
||||
/*
|
||||
given a morphism type (src/dst types),
|
||||
try to match their outer structure (Struct/Seq/Map)
|
||||
and spawn a GraphSearch for each component
|
||||
*/
|
||||
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();
|
||||
|
||||
|
@ -56,7 +67,7 @@ impl<M: Morphism + Clone> MorphismBase<M> {
|
|||
=> {
|
||||
// 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;
|
||||
|
||||
|
@ -65,18 +76,11 @@ 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 {
|
||||
member_morph_types.push((symbol_rhs.clone(), MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: ty_lhs.clone(),
|
||||
dst_type: ty_rhs.clone()
|
||||
}) {
|
||||
if ty_lhs != ty_rhs {
|
||||
necessary = true;
|
||||
}
|
||||
member_morph.push((symbol_lhs.clone(), mm))
|
||||
} else {
|
||||
failed = true;
|
||||
src_type: ty_lhs.clone(), dst_type: ty_rhs.clone() }));
|
||||
if ty_lhs != ty_rhs {
|
||||
necessary = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -90,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
|
||||
}
|
||||
|
@ -105,96 +106,60 @@ 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{
|
||||
bounds: Vec::new(),
|
||||
src_type: ty_lhs.clone(),
|
||||
dst_type: ty_rhs.clone()
|
||||
}) {
|
||||
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{
|
||||
bounds: Vec::new(),
|
||||
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> > {
|
||||
pub fn enum_morphisms_from(&self, src_type: &TypeTerm) -> Vec< (TypeTerm, HashMapSubst, M) > {
|
||||
let mut morphs = Vec::new();
|
||||
|
||||
//eprintln!("enum morphisms from {:?}", src_type);
|
||||
for m in self.morphisms.iter() {
|
||||
let m_src_type = m.get_type().src_type;
|
||||
let m_dst_type = m.get_type().dst_type;
|
||||
let m_src_type = m.get_type().src_type.normalize();
|
||||
let m_dst_type = m.get_type().dst_type.normalize();
|
||||
|
||||
/* 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) {
|
||||
let morph_inst = MorphismInstance::Primitive { ψ, σ, morph: m.clone() };
|
||||
//eprintln!("..found direct morph to {:?}", morph_inst.get_type().dst_type);
|
||||
morphs.push(morph_inst);
|
||||
}
|
||||
|
||||
/* 2. check complex types */
|
||||
else if let Some(complex_morph) = self.complex_morphism_decomposition(src_type, &m_src_type) {
|
||||
//eprintln!("found complex morph to {:?}", complex_morph.get_type().dst_type);
|
||||
morphs.push(complex_morph);
|
||||
morphs.push((ψ, σ, m.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
pub fn to_dot(&self, dict: &mut impl TypeDict) -> String {
|
||||
let mut dot_source = String::new();
|
||||
|
||||
dot_source.push_str("digraph MorphismGraph {");
|
||||
|
||||
pub fn ty_to_dot_label(dict: &mut impl TypeDict, ty: &TypeTerm) -> String {
|
||||
let pretty_str = ty.pretty(dict, 0);
|
||||
let mut child = std::process::Command::new("aha").arg("--no-header")
|
||||
.stdin( std::process::Stdio::piped() )
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.spawn().expect("spawn child");
|
||||
let mut stdin = child.stdin.take().expect("cant get stdin");
|
||||
std::thread::spawn(move ||{ stdin.write_all(pretty_str.as_bytes()).expect("failed to write")});
|
||||
let out = child.wait_with_output().expect("");
|
||||
let html_str = String::from_utf8_lossy(&out.stdout).replace("\n", "<BR/>").replace("span", "B");
|
||||
html_str
|
||||
/* 2. check complex types */
|
||||
if let Some(decomposition) = self.morphism_decomposition(src_type, &m_src_type) {
|
||||
morphs.push(decomposition);
|
||||
}
|
||||
}
|
||||
|
||||
// add vertices
|
||||
for (i,m) in self.morphisms.iter().enumerate() {
|
||||
dot_source.push_str(&format!("
|
||||
SRC{} [label=<{}>]
|
||||
DST{} [label=<{}>]
|
||||
|
||||
SRC{} -> DST{} [label=\"{}\"]
|
||||
", i, ty_to_dot_label(dict, &m.get_type().src_type),
|
||||
i, ty_to_dot_label(dict, &m.get_type().dst_type),
|
||||
i,i,i
|
||||
));
|
||||
}
|
||||
|
||||
// add edges
|
||||
|
||||
|
||||
dot_source.push_str("}");
|
||||
|
||||
dot_source
|
||||
morphs
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
|
541
src/morphism_graph/morphism_graph.rs
Normal file
541
src/morphism_graph/morphism_graph.rs
Normal file
|
@ -0,0 +1,541 @@
|
|||
use {
|
||||
crate::{
|
||||
morphism_graph::DecomposedMorphismType, HashMapSubst, Morphism, MorphismBase, MorphismInstance, MorphismType, SubstitutionMut, TypeDict, TypeTerm
|
||||
},
|
||||
std::{collections::HashMap, sync::{Arc,RwLock}}
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
pub struct MorphismGraph<M: Morphism+Clone> {
|
||||
solved_paths: HashMap< MorphismType, MorphismInstance<M> >,
|
||||
base: MorphismBase<M>
|
||||
}
|
||||
|
||||
pub struct GraphSearch<M: Morphism+Clone> {
|
||||
goal: MorphismType,
|
||||
solution: Option< MorphismInstance<M> >,
|
||||
explore_queue: Vec< Arc<RwLock<SearchNode<M>>> >,
|
||||
|
||||
skip_preview: bool
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum GraphSearchState<M: Morphism+Clone> {
|
||||
Solved( MorphismInstance<M> ),
|
||||
Continue,
|
||||
Err( GraphSearchError )
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum GraphSearchError {
|
||||
NoMorphismFound
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
/// represents a partial path during search in the morphism graph
|
||||
pub struct SearchNode<M: Morphism+Clone> {
|
||||
/// predecessor node
|
||||
pred: Option< Arc<RwLock< SearchNode<M> >> >,
|
||||
|
||||
/// (measured) weight of the preceding path
|
||||
weight: u64,
|
||||
|
||||
ty: MorphismType,
|
||||
|
||||
/// the advancement over pred
|
||||
step: Step<M>,
|
||||
ψ: TypeTerm,
|
||||
}
|
||||
|
||||
pub enum Step<M: Morphism+Clone> {
|
||||
Id { τ: TypeTerm },
|
||||
Inst{ m: MorphismInstance<M> },
|
||||
//Sub{ ψ: TypeTerm },
|
||||
Specialize { σ: HashMapSubst },
|
||||
MapSeq { item: GraphSearch<M> },
|
||||
MapStruct { members: Vec< (String, GraphSearch<M>) > },
|
||||
MapEnum { variants: Vec< (String, GraphSearch<M>) > }
|
||||
}
|
||||
|
||||
pub enum SolvedStep<M: Morphism+Clone> {
|
||||
Id { τ: TypeTerm },
|
||||
Inst{ m: MorphismInstance<M> },
|
||||
Specialize { σ: HashMapSubst },
|
||||
MapSeq { item: MorphismInstance<M> },
|
||||
MapStruct { members: Vec< (String, MorphismInstance<M>) > },
|
||||
MapEnum { variants: Vec< (String, MorphismInstance<M>) > }
|
||||
}
|
||||
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
pub trait SearchNodeExt<M: Morphism+Clone> {
|
||||
fn specialize(&self, σ: HashMapSubst) -> Arc<RwLock<SearchNode<M>>>;
|
||||
fn chain(&self, ψ: TypeTerm, σ: HashMapSubst, m: M) -> Arc<RwLock<SearchNode<M>>>;
|
||||
fn set_sub(&self, ψ: TypeTerm) -> Arc<RwLock<SearchNode<M>>>;
|
||||
fn map_seq(&self, goal: MorphismType) -> Arc<RwLock<SearchNode<M>>>;
|
||||
fn map_struct(&self, goals: Vec<(String, MorphismType)>) -> Arc<RwLock<SearchNode<M>>>;
|
||||
fn map_enum(&self, goals: Vec<(String, MorphismType)>) -> Arc<RwLock<SearchNode<M>>>;
|
||||
|
||||
fn advance(&self, base: &MorphismBase<M>, dict: &mut impl TypeDict) -> Result<bool, GraphSearchError>;
|
||||
fn to_morphism_instance(&self) -> Option< MorphismInstance<M> >;
|
||||
|
||||
fn is_ready(&self) -> bool;
|
||||
fn get_weight(&self) -> u64;
|
||||
fn get_type(&self) -> MorphismType;
|
||||
|
||||
fn creates_loop(&self) -> bool;
|
||||
}
|
||||
|
||||
impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
|
||||
fn get_weight(&self) -> u64 {
|
||||
self.read().unwrap().weight
|
||||
+ match &self.read().unwrap().step {
|
||||
Step::Id { τ } => 0,
|
||||
Step::Inst { m } => m.get_weight(),
|
||||
Step::Specialize { σ } => 0,
|
||||
Step::MapSeq { item } => item.best_path_weight(),
|
||||
Step::MapStruct { members } => todo!(),
|
||||
Step::MapEnum { variants } => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_type(&self) -> MorphismType {
|
||||
let s = self.read().unwrap();
|
||||
MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: TypeTerm::Ladder(vec![ s.ψ.clone(), s.ty.src_type.clone() ]).normalize(),
|
||||
dst_type: TypeTerm::Ladder(vec![ s.ψ.clone(), s.ty.dst_type.clone() ]).normalize(),
|
||||
}
|
||||
}
|
||||
|
||||
// tell if this sub-search already has a solution
|
||||
fn is_ready(&self) -> bool {
|
||||
let n = self.read().unwrap();
|
||||
match &n.step {
|
||||
Step::Id { τ } => true,
|
||||
//Step::Sub { ψ } => n.pred.as_ref().unwrap().is_ready(),
|
||||
Step::Specialize { σ } => true,
|
||||
Step::MapSeq { item } => {
|
||||
item.get_solution().is_some()
|
||||
}
|
||||
Step::MapStruct { members } => {
|
||||
//members.
|
||||
todo!()
|
||||
}
|
||||
Step::MapEnum { variants } => {
|
||||
todo!()
|
||||
}
|
||||
Step::Inst { m } => true
|
||||
}
|
||||
}
|
||||
|
||||
fn creates_loop(&self) -> bool {
|
||||
/*
|
||||
let mut cur_node = self.read().unwrap().pred.clone();
|
||||
while let Some(n) = cur_node {
|
||||
if n.get_type().dst_type == self.get_type().dst_type {
|
||||
return true;
|
||||
}
|
||||
|
||||
cur_node = n.read().unwrap().pred.clone();
|
||||
}
|
||||
*/
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn advance(&self, base: &MorphismBase<M>, dict: &mut impl TypeDict) -> Result<bool, GraphSearchError> {
|
||||
let mut n = self.write().unwrap();
|
||||
match &mut n.step {
|
||||
Step::MapSeq { item } => {
|
||||
eprintln!("advance seq-map");
|
||||
match item.advance(base, dict) {
|
||||
GraphSearchState::Solved(item_morph) => {
|
||||
eprintln!("Sequence-Map Sub Graph Solved!!");
|
||||
n.ty = MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: TypeTerm::Seq { seq_repr: None, items: vec![ item_morph.get_type().src_type ] },
|
||||
dst_type: TypeTerm::Seq { seq_repr: None, items: vec![ item_morph.get_type().dst_type ] },
|
||||
};
|
||||
Ok(false)
|
||||
}
|
||||
GraphSearchState::Continue => Ok(true),
|
||||
GraphSearchState::Err(err) => Err(err)
|
||||
}
|
||||
}
|
||||
Step::MapStruct { members } => {
|
||||
todo!()
|
||||
}
|
||||
Step::MapEnum { variants } => {
|
||||
todo!()
|
||||
}
|
||||
_ => Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
fn specialize(&self, σ: HashMapSubst) -> Arc<RwLock<SearchNode<M>>> {
|
||||
|
||||
let src_type= self.get_type().src_type;
|
||||
let dst_type= self.get_type().dst_type;
|
||||
|
||||
let σ = σ.filter(|(v,t)| src_type.contains_var(*v) || dst_type.contains_var(*v));
|
||||
if σ.is_empty() {
|
||||
self.clone()
|
||||
} else {
|
||||
Arc::new(RwLock::new(SearchNode {
|
||||
pred: Some(self.clone()),
|
||||
weight: self.get_weight(),
|
||||
ty: MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: self.get_type().src_type.apply_subst(&σ).clone().normalize(),
|
||||
dst_type: self.get_type().dst_type.apply_subst(&σ).clone().normalize()
|
||||
},
|
||||
step: Step::Specialize { σ },
|
||||
ψ: self.read().unwrap().ψ.clone()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
fn chain(&self, ψ: TypeTerm, σ: HashMapSubst, m: M) -> Arc<RwLock<SearchNode<M>>> {
|
||||
let m = MorphismInstance::Primitive { m: m.clone() };
|
||||
|
||||
let mut parent = self.clone();
|
||||
|
||||
{
|
||||
let mut σ = σ.clone().filter(|(v,t)|
|
||||
self.get_type().dst_type.contains_var(*v)
|
||||
);
|
||||
parent = parent.specialize(σ);
|
||||
}
|
||||
|
||||
let mut σ_src = σ.clone().filter(|(v,t)|
|
||||
m.get_type().src_type.contains_var(*v) &&
|
||||
!self.get_type().dst_type.contains_var(*v)
|
||||
);
|
||||
|
||||
let mut σ_dst = σ.clone().filter(|(v,t)|
|
||||
m.get_type().dst_type.contains_var(*v)
|
||||
);
|
||||
|
||||
let mut n = Arc::new(RwLock::new(SearchNode {
|
||||
pred: Some(parent),
|
||||
weight: self.get_weight(),
|
||||
ty: MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: self.get_type().src_type,
|
||||
dst_type: m.get_type().dst_type
|
||||
}.apply_subst(&σ_src),
|
||||
step: Step::Inst{
|
||||
m: if σ_src.is_empty() {
|
||||
m
|
||||
} else {
|
||||
MorphismInstance::Specialize { σ: σ_src, m: Box::new(m) }
|
||||
}
|
||||
},
|
||||
ψ: TypeTerm::unit(),
|
||||
}));
|
||||
n.set_sub(ψ);
|
||||
n = n.specialize(σ_dst);
|
||||
n
|
||||
}
|
||||
|
||||
fn set_sub(&self, ψ: TypeTerm) -> Arc<RwLock<SearchNode<M>>> {
|
||||
let oldψ = &mut self.write().unwrap().ψ;
|
||||
*oldψ = TypeTerm::Ladder(vec![ ψ, oldψ.clone() ]).normalize();
|
||||
self.clone()
|
||||
}
|
||||
|
||||
fn map_seq(&self, goal: MorphismType) -> Arc<RwLock<SearchNode<M>>> {
|
||||
Arc::new(RwLock::new(SearchNode {
|
||||
pred: Some(self.clone()),
|
||||
weight: self.get_weight(),
|
||||
ty: MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: TypeTerm::Seq{ seq_repr: None, items: vec![goal.src_type.clone()] },
|
||||
dst_type: TypeTerm::Seq{ seq_repr: None, items: vec![goal.src_type.clone()] }
|
||||
},
|
||||
step: Step::MapSeq { item: GraphSearch::new(goal) },
|
||||
ψ: self.read().unwrap().ψ.clone()
|
||||
}))
|
||||
}
|
||||
|
||||
fn map_struct(&self, goals: Vec<(String, MorphismType)>) -> Arc<RwLock<SearchNode<M>>> {
|
||||
Arc::new(RwLock::new(SearchNode {
|
||||
pred: Some(self.clone()),
|
||||
weight: self.get_weight(),
|
||||
ty: todo!(),
|
||||
step: Step::MapStruct { members: goals.into_iter().map(|(name,goal)| (name, GraphSearch::new(goal))).collect() },
|
||||
ψ: self.read().unwrap().ψ.clone()
|
||||
}))
|
||||
}
|
||||
|
||||
fn map_enum(&self, goals: Vec<(String, MorphismType)>) -> Arc<RwLock<SearchNode<M>>> {
|
||||
Arc::new(RwLock::new(SearchNode {
|
||||
pred: Some(self.clone()),
|
||||
weight: self.get_weight(),
|
||||
ty: todo!(),
|
||||
step: Step::MapEnum { variants: goals.into_iter().map(|(name,goal)| (name, GraphSearch::new(goal))).collect() },
|
||||
ψ: self.read().unwrap().ψ.clone()
|
||||
}))
|
||||
}
|
||||
|
||||
fn to_morphism_instance(&self) -> Option< MorphismInstance<M> > {
|
||||
let mut steps = Vec::new();
|
||||
let mut cur_node = Some(self.clone());
|
||||
while let Some(n) = cur_node {
|
||||
let n = n.read().unwrap();
|
||||
steps.push((n.ψ.clone(),
|
||||
match &n.step {
|
||||
Step::Id { τ } => SolvedStep::Id { τ: τ.clone() },
|
||||
Step::Inst { m } => SolvedStep::Inst { m: m.clone() },
|
||||
Step::Specialize { σ } => SolvedStep::Specialize { σ: σ.clone() },
|
||||
Step::MapSeq { item } => SolvedStep::MapSeq { item: item.get_solution().unwrap() },
|
||||
Step::MapStruct { members } => SolvedStep::MapStruct { members: members.iter().map(|(n,m)| (n.clone(), m.get_solution().unwrap())).collect() },
|
||||
Step::MapEnum { variants } => SolvedStep::MapEnum { variants: variants.iter().map(|(n,m)| (n.clone(), m.get_solution().unwrap())).collect() },
|
||||
}));
|
||||
|
||||
cur_node = n.pred.clone();
|
||||
}
|
||||
|
||||
steps.reverse();
|
||||
|
||||
let mut begin = TypeTerm::unit();
|
||||
let mut path = Vec::new();
|
||||
eprintln!("to_morph_instance:\n==");
|
||||
for (ψ, s) in steps {
|
||||
match s {
|
||||
SolvedStep::Id { τ } => {
|
||||
eprintln!("to_morph_instance: ID {:?}", τ);
|
||||
begin = τ.clone(); },
|
||||
SolvedStep::Inst{ m } => {
|
||||
eprintln!("to_morph_instance: Inst {:?} -- {:?}", ψ, m.get_type());
|
||||
let mut m = m.clone();
|
||||
if ! ψ.is_empty() {
|
||||
m = MorphismInstance::Sub { ψ, m: Box::new(m) };
|
||||
}
|
||||
path.push(m.clone());
|
||||
},
|
||||
SolvedStep::Specialize { σ } => {
|
||||
eprintln!("to_morph_instance: Specialize {:?}", σ);
|
||||
if path.len() > 0 && !σ.is_empty() {
|
||||
let m = MorphismInstance::from_chain(begin.clone(), &path);
|
||||
path = vec![
|
||||
MorphismInstance::Specialize { σ: σ.clone(), m: Box::new(m) }
|
||||
];
|
||||
}
|
||||
}
|
||||
SolvedStep::MapSeq { item } => {
|
||||
let mut m = MorphismInstance::MapSeq {
|
||||
seq_repr: None,
|
||||
item_morph: Box::new(item)
|
||||
};
|
||||
|
||||
if ! ψ.is_empty() {
|
||||
m = MorphismInstance::Sub { ψ, m: Box::new(m) };
|
||||
}
|
||||
path.push(m);
|
||||
}
|
||||
SolvedStep::MapStruct { members } => {
|
||||
todo!();
|
||||
//path.push(MorphismInstance::MapStruct { src_struct_repr: (), dst_struct_repr: (), member_morph: () })
|
||||
}
|
||||
SolvedStep::MapEnum { variants } => {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(MorphismInstance::from_chain(begin, &path))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
impl<M: Morphism+Clone> MorphismGraph<M> {
|
||||
pub fn new(base: MorphismBase<M>) -> Self {
|
||||
MorphismGraph {
|
||||
solved_paths: HashMap::new(),
|
||||
base
|
||||
}
|
||||
}
|
||||
|
||||
pub fn search(&self, goal: MorphismType, dict: &mut impl TypeDict) -> Result<
|
||||
MorphismInstance<M>,
|
||||
GraphSearchError
|
||||
> {
|
||||
let mut search = GraphSearch::<M>::new(goal);
|
||||
loop {
|
||||
match search.advance(&self.base, dict) {
|
||||
GraphSearchState::Solved(m) => { return Ok(m); }
|
||||
GraphSearchState::Continue => { continue; }
|
||||
GraphSearchState::Err(err) => { return Err(err); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Morphism+Clone> GraphSearch<M> {
|
||||
pub fn new(goal: MorphismType) -> Self {
|
||||
GraphSearch {
|
||||
goal: goal.clone(),
|
||||
solution: None,
|
||||
explore_queue: vec![
|
||||
Arc::new(RwLock::new(SearchNode {
|
||||
pred: None,
|
||||
weight: 0,
|
||||
ty: MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: goal.src_type.clone(),
|
||||
dst_type: goal.src_type.clone()
|
||||
},
|
||||
step: Step::Id { τ: goal.src_type.clone() },
|
||||
ψ: TypeTerm::unit()
|
||||
}))
|
||||
],
|
||||
skip_preview: false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_solution(&self) -> Option< MorphismInstance<M> > {
|
||||
self.solution.clone()
|
||||
}
|
||||
|
||||
pub fn best_path_weight(&self) -> u64 {
|
||||
if let Some(best) = self.explore_queue.last() {
|
||||
best.get_weight()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn est_remain(goal: &MorphismType, search_node: &Arc<RwLock<SearchNode<M>>>) -> u64 {
|
||||
MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: goal.src_type.clone(),
|
||||
dst_type: search_node.get_type().src_type.clone()
|
||||
}.estimated_cost()
|
||||
+
|
||||
MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: search_node.get_type().dst_type.clone(),
|
||||
dst_type: goal.dst_type.clone()
|
||||
}.estimated_cost()
|
||||
}
|
||||
|
||||
pub fn choose_next_node(&mut self, dict: &mut impl TypeDict) -> Option<Arc<RwLock<SearchNode<M>>>> {
|
||||
let goal= self.goal.clone();
|
||||
self.explore_queue.sort_by(
|
||||
|a,b| {
|
||||
(Self::est_remain(&goal, b) + b.get_weight() )
|
||||
.cmp(
|
||||
&(Self::est_remain(&goal, a) + a.get_weight())
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
if !self.skip_preview {
|
||||
eprintln!("===== TOP 5 PATHS =====\nGoal:\n {} -> {}",
|
||||
goal.src_type.pretty(dict, 0),
|
||||
goal.dst_type.pretty(dict, 0)
|
||||
);
|
||||
for i in 1 ..= usize::min(self.explore_queue.len(), 5) {
|
||||
let n = &self.explore_queue[self.explore_queue.len() - i];
|
||||
eprintln!("[[ {} ]] (weight: {} + est remain: {}) --- {} --> {}", i,
|
||||
n.get_weight(),
|
||||
Self::est_remain(&goal, &n),
|
||||
n.get_type().src_type.pretty(dict, 0),
|
||||
n.get_type().dst_type.pretty(dict, 0));
|
||||
}
|
||||
} else {
|
||||
self.skip_preview = false;
|
||||
}
|
||||
|
||||
self.explore_queue.pop()
|
||||
}
|
||||
|
||||
pub fn advance(&mut self, base: &MorphismBase<M>, dict: &mut impl TypeDict) -> GraphSearchState<M> {
|
||||
if let Some(node) = self.choose_next_node(dict) {
|
||||
match node.advance(base, dict) {
|
||||
Ok(_) => {
|
||||
if ! node.is_ready() {
|
||||
if ! node.creates_loop() {
|
||||
self.skip_preview = true;
|
||||
self.explore_queue.push(node);
|
||||
}
|
||||
return GraphSearchState::Continue;
|
||||
} else {
|
||||
let w = node.to_morphism_instance().unwrap().get_weight();
|
||||
eprintln!("set Weight of complex morph to {}", w);
|
||||
node.write().unwrap().weight = w;
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
return GraphSearchState::Err(err);
|
||||
}
|
||||
}
|
||||
|
||||
if node.creates_loop() {
|
||||
eprintln!("Creates loop.");
|
||||
return GraphSearchState::Continue;
|
||||
}
|
||||
|
||||
/* 1. Check if goal is already reached by the current path */
|
||||
if let Ok((_ψ, σ)) = crate::constraint_system::subtype_unify( &node.get_type().dst_type, &self.goal.dst_type ) {
|
||||
/* found path */
|
||||
self.solution = Some(
|
||||
if σ.is_empty() {
|
||||
node.to_morphism_instance().unwrap()
|
||||
} else {
|
||||
node
|
||||
.specialize( σ.filter_morphtype(&node.get_type()) )
|
||||
.to_morphism_instance()
|
||||
.unwrap()
|
||||
}
|
||||
);
|
||||
|
||||
return GraphSearchState::Solved(self.get_solution().unwrap());
|
||||
}
|
||||
|
||||
let mut decompositions = base.enum_complex_morphisms(&node.get_type().dst_type);
|
||||
if let Some(d) = base.morphism_decomposition(&node.get_type().dst_type, &self.goal.dst_type) {
|
||||
decompositions.push(d);
|
||||
}
|
||||
|
||||
eprintln!("{} decompositions", decompositions.len());
|
||||
|
||||
let mut done = Vec::new();
|
||||
for (ψ,decomposition) in decompositions {
|
||||
if ! done.contains(&(ψ.clone(),decomposition.clone())) {
|
||||
self.explore_queue.push(
|
||||
match &decomposition {
|
||||
DecomposedMorphismType::SeqMap { item } => { node.map_seq( item.clone() ) },
|
||||
DecomposedMorphismType::StructMap { members } => { node.map_struct(members.clone()) },
|
||||
DecomposedMorphismType::EnumMap { variants } => { node.map_enum(variants.clone()) },
|
||||
}.set_sub(ψ.clone())
|
||||
);
|
||||
done.push((ψ, decomposition));
|
||||
}else {
|
||||
//eprintln!("avoid duplicate decomposition");
|
||||
}
|
||||
}
|
||||
|
||||
/* 2. Try to advance current path */
|
||||
for (ψ,σ,m) in base.enum_morphisms_from(&node.get_type().dst_type) {
|
||||
eprintln!("add direct path");
|
||||
self.explore_queue.push( node.chain(ψ,σ,m) );
|
||||
}
|
||||
|
||||
GraphSearchState::Continue
|
||||
} else {
|
||||
GraphSearchState::Err(GraphSearchError::NoMorphismFound)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
|
@ -1,120 +0,0 @@
|
|||
use {
|
||||
crate::{
|
||||
morphism_graph::{Morphism, MorphismInstance, MorphismType, MorphismBase},
|
||||
term::*,
|
||||
HashMapSubst,
|
||||
heuristic::*,
|
||||
}
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MorphismPath<M: Morphism + Clone> {
|
||||
pub weight: u64,
|
||||
pub est_remain: u64,
|
||||
pub cur_type: TypeTerm,
|
||||
pub morphisms: Vec< MorphismInstance<M> >,
|
||||
}
|
||||
|
||||
|
||||
impl<M: Morphism+Clone> MorphismPath<M> {
|
||||
fn apply_subst(&mut self, σ: &HashMapSubst) {
|
||||
for m in self.morphisms.iter_mut() {
|
||||
m.apply_subst(σ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
pub struct ShortestPathProblem<'a, M: Morphism + Clone> {
|
||||
pub morphism_base: &'a MorphismBase<M>,
|
||||
pub goal: TypeTerm,
|
||||
queue: Vec< MorphismPath<M> >
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
impl<'a, M:Morphism+Clone> ShortestPathProblem<'a, M> {
|
||||
pub fn new(morphism_base: &'a MorphismBase<M>, ty: MorphismType) -> Self {
|
||||
ShortestPathProblem {
|
||||
morphism_base,
|
||||
queue: vec![
|
||||
MorphismPath::<M> { weight: 0, est_remain: ty.estimated_cost(), cur_type: ty.src_type, morphisms: vec![] }
|
||||
],
|
||||
goal: ty.dst_type
|
||||
}
|
||||
}
|
||||
|
||||
pub fn advance(&mut self, prev_path: &MorphismPath<M>, morph_inst: MorphismInstance<M>) {
|
||||
let dst_type = morph_inst.get_type().dst_type;
|
||||
/*
|
||||
eprintln!("try morph to {:?} (weight: {}) (prev: {} + est {})", dst_type.clone(),
|
||||
morph_inst.get_weight(),
|
||||
prev_path.weight,
|
||||
prev_path.est_remain,
|
||||
);//.sugar(type_dict).pretty(type_dict, 0));
|
||||
*/
|
||||
|
||||
let mut creates_loop = false;
|
||||
|
||||
let mut new_path = prev_path.clone();
|
||||
new_path.apply_subst(&morph_inst.get_subst());
|
||||
for m in new_path.morphisms.iter() {
|
||||
if m.get_type().src_type == dst_type {
|
||||
creates_loop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ! creates_loop {
|
||||
new_path.weight += morph_inst.get_weight();
|
||||
new_path.cur_type = dst_type;
|
||||
new_path.est_remain = MorphismType{ bounds: Vec::new(), src_type: new_path.cur_type.clone(), dst_type: self.goal.clone() }.estimated_cost();
|
||||
|
||||
new_path.morphisms.push(morph_inst);
|
||||
self.queue.push(new_path);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn solve(&mut self) -> Option< Vec<MorphismInstance<M>> > {
|
||||
while ! self.queue.is_empty() {
|
||||
/* take the most promising partial path and try to advance it by one step */
|
||||
self.queue.sort_by( |p1,p2| ( p2.weight + p2.est_remain ).cmp(&( p1.weight + p1.est_remain ) ));
|
||||
/*
|
||||
eprintln!("===== TOP 5 PATHS =====\nGoal: {}", self.goal.pretty(dict, 0));
|
||||
for i in 1 ..= usize::min(self.queue.len(), 5) {
|
||||
let path = &self.queue[self.queue.len() - i];
|
||||
eprintln!("[[ {} ]] (w: {}, est remain: {}) --- {}", i, path.weight, path.est_remain, path.cur_type.pretty(dict, 0));
|
||||
}
|
||||
*/
|
||||
if let Some(mut cur_path) = self.queue.pop() {
|
||||
|
||||
/* 1. Check if goal is already reached by the current path */
|
||||
if let Ok((_ψ, σ)) = crate::constraint_system::subtype_unify( &cur_path.cur_type, &self.goal ) {
|
||||
/* found path,
|
||||
* now apply substitution and trim to variables in terms of each step
|
||||
*/
|
||||
|
||||
cur_path.apply_subst(&σ);
|
||||
return Some(cur_path.morphisms);
|
||||
}
|
||||
|
||||
/* 2. Try to advance current path */
|
||||
else if let Some(complex_morph) =
|
||||
self.morphism_base.complex_morphism_decomposition( &cur_path.cur_type, &self.goal )
|
||||
{
|
||||
self.advance(&cur_path, complex_morph);
|
||||
}
|
||||
|
||||
for next_morph_inst in self.morphism_base.enum_morphisms_from(&cur_path.cur_type) {
|
||||
self.advance(&cur_path, next_morph_inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
|
@ -5,17 +5,19 @@ use crate::{term::TypeTerm, constraint_system, EnumVariant, StructMember};
|
|||
pub fn splice_ladders( mut upper: Vec< TypeTerm >, mut lower: Vec< TypeTerm > ) -> Vec< TypeTerm > {
|
||||
eprintln!("splice ladders {:?} <<<====>>> {:?} ", upper, lower);
|
||||
// check for overlap
|
||||
for i in 0 .. upper.len() {
|
||||
if upper[i] == lower[0] {
|
||||
let mut result_ladder = Vec::<TypeTerm>::new();
|
||||
result_ladder.append(&mut upper[0..i].iter().cloned().collect());
|
||||
result_ladder.append(&mut lower);
|
||||
return result_ladder;
|
||||
if lower.len() > 0 {
|
||||
for i in 0 .. upper.len() {
|
||||
if upper[i] == lower[0] {
|
||||
let mut result_ladder = Vec::<TypeTerm>::new();
|
||||
result_ladder.append(&mut upper[0..i].iter().cloned().collect());
|
||||
result_ladder.append(&mut lower);
|
||||
return result_ladder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no overlap found, just concatenate ladders
|
||||
upper.append(&mut lower);
|
||||
// no overlap found, just concatenate ladders
|
||||
upper.append(&mut lower);
|
||||
}
|
||||
upper
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ fn test_heuristic() {
|
|||
src_type: dict.parse("A").expect("parse"),
|
||||
dst_type: dict.parse("A").expect("parse")
|
||||
}.estimated_cost(),
|
||||
1
|
||||
0
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
@ -19,6 +19,6 @@ fn test_heuristic() {
|
|||
src_type: dict.parse("<Digit 10> ~ Char ~ Ascii ~ native.UInt8").expect("parse"),
|
||||
dst_type: dict.parse("<Digit 16> ~ native.UInt8").expect("parse")
|
||||
}.estimated_cost(),
|
||||
41
|
||||
40
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,40 +1,12 @@
|
|||
use {
|
||||
crate::{dict::*, morphism_graph::{Morphism, MorphismInstance, MorphismType}, morphism_base::MorphismBase, morphism_path::ShortestPathProblem, parser::*, HashMapSubst, TypeTerm
|
||||
crate::{dict::*, morphism_graph::*, parser::*,
|
||||
HashMapSubst, TypeTerm
|
||||
},
|
||||
std::collections::HashMap
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
fn print_subst(m: &HashMapSubst, dict: &mut impl TypeDict) {
|
||||
eprintln!("{{");
|
||||
|
||||
for (k,v) in m.iter() {
|
||||
eprintln!(" {} --> {}",
|
||||
dict.get_typename(*k).unwrap(),
|
||||
v.pretty(dict, 0)
|
||||
);
|
||||
}
|
||||
|
||||
eprintln!("}}");
|
||||
}
|
||||
|
||||
fn print_path(dict: &mut impl TypeDict, path: &Vec<MorphismInstance<DummyMorphism>>) {
|
||||
for n in path.iter() {
|
||||
eprintln!("
|
||||
morph {}
|
||||
--> {}
|
||||
with
|
||||
",
|
||||
n.get_type().src_type.pretty(dict, 0),
|
||||
n.get_type().dst_type.pretty(dict, 0),
|
||||
);
|
||||
print_subst(&n.get_subst(), dict)
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
struct DummyMorphism(MorphismType);
|
||||
impl Morphism for DummyMorphism {
|
||||
|
@ -54,227 +26,457 @@ fn morphism_test_setup() -> ( BimapTypeDict, MorphismBase<DummyMorphism> ) {
|
|||
base.add_morphism(
|
||||
DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
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)
|
||||
src_type: dict.parse("<Digit Radix> ~ Char").unwrap(),
|
||||
dst_type: dict.parse("<Digit Radix> ~ ℤ_2^64 ~ machine.UInt64").unwrap()
|
||||
})
|
||||
);
|
||||
base.add_morphism(
|
||||
DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse_desugared("<Digit Radix> ~ ℤ_2^64 ~ machine.UInt64").unwrap().sugar(&mut dict),
|
||||
dst_type: dict.parse_desugared("<Digit Radix> ~ Char").unwrap().sugar(&mut dict)
|
||||
})
|
||||
);
|
||||
base.add_morphism(
|
||||
DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse_desugared("ℕ ~ <PosInt Radix BigEndian> ~ <Seq <Digit Radix>~ℤ_2^64~machine.UInt64>").unwrap().sugar(&mut dict),
|
||||
dst_type: dict.parse_desugared("ℕ ~ <PosInt Radix LittleEndian> ~ <Seq <Digit Radix>~ℤ_2^64~machine.UInt64>").unwrap().sugar(&mut dict)
|
||||
})
|
||||
);
|
||||
base.add_morphism(
|
||||
DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse_desugared("ℕ ~ <PosInt Radix LittleEndian> ~ <Seq <Digit Radix>~ℤ_2^64~machine.UInt64>").unwrap().sugar(&mut dict),
|
||||
dst_type: dict.parse_desugared("ℕ ~ <PosInt Radix BigEndian> ~ <Seq <Digit Radix>~ℤ_2^64~machine.UInt64>").unwrap().sugar(&mut dict)
|
||||
})
|
||||
);
|
||||
base.add_morphism(
|
||||
DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
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)
|
||||
src_type: dict.parse("<Digit Radix> ~ ℤ_2^64 ~ machine.UInt64").unwrap(),
|
||||
dst_type: dict.parse("<Digit Radix> ~ Char").unwrap()
|
||||
})
|
||||
);
|
||||
|
||||
base.add_morphism(
|
||||
DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("ℕ ~ <PosInt Radix BigEndian> ~ <Seq <Digit Radix>~ℤ_2^64~machine.UInt64>").unwrap(),
|
||||
dst_type: dict.parse("ℕ ~ <PosInt Radix LittleEndian> ~ <Seq <Digit Radix>~ℤ_2^64~machine.UInt64>").unwrap()
|
||||
})
|
||||
);
|
||||
base.add_morphism(
|
||||
DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("ℕ ~ <PosInt Radix LittleEndian> ~ <Seq <Digit Radix>~ℤ_2^64~machine.UInt64>").unwrap(),
|
||||
dst_type: dict.parse("ℕ ~ <PosInt Radix BigEndian> ~ <Seq <Digit Radix>~ℤ_2^64~machine.UInt64>").unwrap()
|
||||
})
|
||||
);
|
||||
|
||||
base.add_morphism(
|
||||
DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("ℕ ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix>~ℤ_2^64~machine.UInt64>").unwrap(),
|
||||
dst_type: dict.parse("ℕ ~ <PosInt DstRadix LittleEndian> ~ <Seq <Digit DstRadix>~ℤ_2^64~machine.UInt64>").unwrap()
|
||||
})
|
||||
);
|
||||
|
||||
base.add_morphism(
|
||||
DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("ℤ_2^64 ~ ℕ ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix>~ℤ_2^64~machine.UInt64>").unwrap(),
|
||||
dst_type: dict.parse("ℤ_2^64 ~ machine.UInt64").unwrap()
|
||||
})
|
||||
);
|
||||
base.add_morphism(
|
||||
DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("ℤ_2^64 ~ machine.UInt64").unwrap(),
|
||||
dst_type: dict.parse("ℤ_2^64 ~ ℕ ~ <PosInt 0 LittleEndian> ~ <Seq <Digit 0>~ℤ_2^64~machine.UInt64>").unwrap()
|
||||
})
|
||||
);
|
||||
(dict, base)
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_morphgraph_id() {
|
||||
let (mut dict, mut base) = morphism_test_setup();
|
||||
let morph_graph = MorphismGraph::new(base);
|
||||
|
||||
assert_eq!(
|
||||
morph_graph.search(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("ℤ_2^64 ~ machine.UInt64").expect("parse"),
|
||||
dst_type: dict.parse("ℤ_2^64 ~ machine.UInt64").expect("parse"),
|
||||
}, &mut dict),
|
||||
|
||||
Ok(MorphismInstance::Id {
|
||||
τ: dict.parse("ℤ_2^64 ~ machine.UInt64").expect("parse")
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_morphgraph_prim() {
|
||||
let (mut dict, base) = morphism_test_setup();
|
||||
let morph_graph = MorphismGraph::new(base);
|
||||
|
||||
assert_eq!(
|
||||
morph_graph.search(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("<Digit 10> ~ Char").expect("parse"),
|
||||
dst_type: dict.parse("<Digit 10> ~ ℤ_2^64 ~ machine.UInt64").expect("parse"),
|
||||
}, &mut dict),
|
||||
|
||||
Ok(
|
||||
MorphismInstance::Specialize { σ: vec![
|
||||
(0, TypeTerm::Num(10))
|
||||
].into_iter().collect(), m: Box::new(
|
||||
MorphismInstance::Primitive {
|
||||
m: DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("<Digit Radix> ~ Char").expect("parse"),
|
||||
dst_type: dict.parse("<Digit Radix> ~ ℤ_2^64 ~ machine.UInt64").expect("parse"),
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_morphgraph_chain() {
|
||||
let (mut dict, base) = morphism_test_setup();
|
||||
let morph_graph = MorphismGraph::new(base);
|
||||
|
||||
assert_eq!(
|
||||
morph_graph.search(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("<Digit 10> ~ Char").expect("parse"),
|
||||
dst_type: dict.parse("<Digit 10> ~ ℤ_2^64 ~ ℕ ~ <PosInt 0 LittleEndian> ~ <Seq <Digit 0>~ℤ_2^64~machine.UInt64>").expect("parse"),
|
||||
}, &mut dict),
|
||||
|
||||
Ok(
|
||||
MorphismInstance::Chain {
|
||||
path: vec![
|
||||
MorphismInstance::Specialize {
|
||||
σ: vec![
|
||||
(0, TypeTerm::Num(10)),
|
||||
].into_iter().collect(),
|
||||
m: Box::new(
|
||||
MorphismInstance::Primitive {
|
||||
m: DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("<Digit Radix> ~ Char").expect("parse"),
|
||||
dst_type: dict.parse("<Digit Radix> ~ ℤ_2^64 ~ machine.UInt64").expect("parse"),
|
||||
})
|
||||
})
|
||||
},
|
||||
MorphismInstance::Sub {
|
||||
ψ: dict.parse("<Digit 10>").expect("parse"),
|
||||
m: Box::new(
|
||||
MorphismInstance::Primitive { m: DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("ℤ_2^64 ~ machine.UInt64").unwrap(),
|
||||
dst_type: dict.parse("ℤ_2^64 ~ ℕ ~ <PosInt 0 LittleEndian> ~ <Seq <Digit 0>~ℤ_2^64~machine.UInt64>").unwrap()
|
||||
}) }
|
||||
)
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_morphgraph_spec() {
|
||||
let mut dict = BimapTypeDict::new();
|
||||
let mut base = MorphismBase::<DummyMorphism>::new();
|
||||
|
||||
dict.add_varname("X".into());
|
||||
dict.add_varname("Y".into());
|
||||
|
||||
base.add_morphism(DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("T ~ A").expect(""),
|
||||
dst_type: dict.parse("T ~ <B X> ~ U").expect("")
|
||||
}));
|
||||
base.add_morphism(DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("T ~ <B Y> ~ U").expect(""),
|
||||
dst_type: dict.parse("T ~ <B Y> ~ V").expect("")
|
||||
}));
|
||||
|
||||
let morph_graph = MorphismGraph::new(base);
|
||||
|
||||
assert_eq!(
|
||||
morph_graph.search(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("T ~ A").unwrap(),
|
||||
dst_type: dict.parse("T ~ <B test> ~ U").unwrap(),
|
||||
}, &mut dict),
|
||||
Ok(
|
||||
MorphismInstance::Specialize {
|
||||
σ: vec![
|
||||
(0, dict.parse("test").expect("parse") )
|
||||
].into_iter().collect(),
|
||||
m: Box::new(MorphismInstance::Primitive { m: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("T ~ A").expect("parse"),
|
||||
dst_type: dict.parse("T ~ <B X> ~ U").expect("parse")
|
||||
}) })
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
morph_graph.search(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("T ~ A").unwrap(),
|
||||
dst_type: dict.parse("T ~ <B test> ~ V").unwrap(),
|
||||
}, &mut dict),
|
||||
Ok(
|
||||
MorphismInstance::Specialize {
|
||||
σ: vec![
|
||||
( 1, dict.parse("test").expect("parse") )
|
||||
].into_iter().collect(),
|
||||
m: Box::new(
|
||||
MorphismInstance::Chain {
|
||||
path: vec![
|
||||
MorphismInstance::Specialize {
|
||||
σ: vec![
|
||||
( 0, dict.parse("Y").expect("parse") )
|
||||
].into_iter().collect(),
|
||||
m: Box::new(MorphismInstance::Primitive { m: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("T ~ A").expect("parse"),
|
||||
dst_type: dict.parse("T ~ <B X> ~ U").expect("parse")
|
||||
}) }) },
|
||||
MorphismInstance::Primitive { m: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("T ~ <B Y> ~ U").expect("parse"),
|
||||
dst_type: dict.parse("T ~ <B Y> ~ V").expect("parse")
|
||||
}) }
|
||||
]
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_morphgraph_map_seq() {
|
||||
let mut dict = BimapTypeDict::new();
|
||||
let mut base = MorphismBase::<DummyMorphism>::new();
|
||||
|
||||
base.add_morphism(DummyMorphism(MorphismType{
|
||||
bounds: Vec::new(),
|
||||
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 {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("<Seq A ~ F>").unwrap(),
|
||||
dst_type: dict.parse("<Seq A ~ E>").unwrap(),
|
||||
}, &mut dict),
|
||||
Ok(
|
||||
MorphismInstance::MapSeq { seq_repr: None, item_morph: Box::new(
|
||||
MorphismInstance::Primitive {
|
||||
m: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("A ~ F").unwrap(),
|
||||
dst_type: dict.parse("A ~ E").unwrap()
|
||||
})
|
||||
}
|
||||
) }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_morphism_path1() {
|
||||
let (mut dict, base) = morphism_test_setup();
|
||||
|
||||
let path = ShortestPathProblem::new(&base, MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse_desugared("<Digit 10> ~ Char").unwrap().sugar(&mut dict),
|
||||
dst_type: dict.parse_desugared("<Digit 10> ~ ℤ_2^64 ~ machine.UInt64").unwrap().sugar(&mut dict),
|
||||
}).solve();
|
||||
let morph_graph = MorphismGraph::new(base);
|
||||
|
||||
assert_eq!(
|
||||
path,
|
||||
Some(
|
||||
vec![
|
||||
MorphismInstance::Primitive {
|
||||
σ: vec![
|
||||
(0, TypeTerm::Num(10)),
|
||||
].into_iter().collect(),
|
||||
ψ: TypeTerm::unit(),
|
||||
morph: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
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 {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("ℕ ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10> ~ Char>").unwrap(),
|
||||
dst_type: dict.parse("ℕ ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10> ~ ℤ_2^64 ~ machine.UInt64>").unwrap(),
|
||||
}, &mut dict),
|
||||
Ok(
|
||||
MorphismInstance::Sub {
|
||||
ψ: dict.parse("ℕ ~ <PosInt 10 LittleEndian>").expect(""),
|
||||
m: Box::new(
|
||||
MorphismInstance::MapSeq {
|
||||
seq_repr: None,
|
||||
item_morph: Box::new(
|
||||
MorphismInstance::Specialize {
|
||||
σ: vec![
|
||||
(0, TypeTerm::Num(10)),
|
||||
].into_iter().collect(),
|
||||
m: Box::new(MorphismInstance::Primitive {
|
||||
m: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("<Digit Radix> ~ Char").unwrap(),
|
||||
dst_type: dict.parse("<Digit Radix> ~ ℤ_2^64 ~ machine.UInt64").unwrap()
|
||||
}),
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_morphism_path2() {
|
||||
let (mut dict, base) = morphism_test_setup();
|
||||
|
||||
let path = ShortestPathProblem::new(&base, MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse_desugared("ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10> ~ Char>").unwrap().sugar(&mut dict),
|
||||
dst_type: dict.parse_desugared("ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10> ~ ℤ_2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict),
|
||||
}).solve();
|
||||
let morph_graph = MorphismGraph::new(base);
|
||||
|
||||
assert_eq!(
|
||||
path,
|
||||
Some(
|
||||
vec![
|
||||
MorphismInstance::MapSeq {
|
||||
ψ: dict.parse_desugared("ℕ ~ <PosInt 10 BigEndian>").expect("").sugar(&mut dict),
|
||||
seq_repr: None,
|
||||
item_morph: Box::new(MorphismInstance::Primitive {
|
||||
σ: vec![
|
||||
(0, TypeTerm::Num(10)),
|
||||
].into_iter().collect(),
|
||||
ψ: TypeTerm::unit(),
|
||||
morph: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
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 {
|
||||
bounds: Vec::new(),
|
||||
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::Specialize {
|
||||
σ: vec![
|
||||
(2, TypeTerm::Num(16)),
|
||||
].into_iter().collect(),
|
||||
m: Box::new(
|
||||
MorphismInstance::Chain {
|
||||
path: vec![
|
||||
MorphismInstance::Sub {
|
||||
ψ: dict.parse("ℕ ~ <PosInt 10 LittleEndian>").expect(""),
|
||||
m: Box::new(
|
||||
MorphismInstance::MapSeq {
|
||||
seq_repr: None,
|
||||
item_morph: Box::new(
|
||||
MorphismInstance::Specialize {
|
||||
σ: vec![
|
||||
(0, TypeTerm::Num(10)),
|
||||
].into_iter().collect(),
|
||||
m: Box::new(MorphismInstance::Primitive {
|
||||
m: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("<Digit Radix> ~ Char").unwrap(),
|
||||
dst_type: dict.parse("<Digit Radix> ~ ℤ_2^64 ~ machine.UInt64").unwrap()
|
||||
}),
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
MorphismInstance::Specialize {
|
||||
σ: vec![
|
||||
(1, TypeTerm::Num(10))
|
||||
].into_iter().collect(),
|
||||
m: Box::new(
|
||||
MorphismInstance::Primitive{
|
||||
m: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
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_path3() {
|
||||
let (mut dict, base) = morphism_test_setup();
|
||||
let (mut dict, mut base) = morphism_test_setup();
|
||||
|
||||
let path = ShortestPathProblem::new(&base, MorphismType {
|
||||
let mut morph_graph = MorphismGraph::new(base);
|
||||
|
||||
let result = morph_graph.search(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
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();
|
||||
src_type: dict.parse("ℕ ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10> ~ Char>").unwrap(),
|
||||
dst_type: dict.parse("ℕ ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16> ~ Char>").unwrap()
|
||||
}, &mut dict);
|
||||
|
||||
if let Some(path) = path.as_ref() {
|
||||
print_path(&mut dict, path);
|
||||
}
|
||||
eprintln!("{:#?}", result);
|
||||
|
||||
return;
|
||||
|
||||
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![
|
||||
(0, TypeTerm::Num(10)),
|
||||
].into_iter().collect(),
|
||||
ψ: TypeTerm::unit(),
|
||||
morph: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
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)
|
||||
}),
|
||||
})
|
||||
},
|
||||
result,
|
||||
|
||||
MorphismInstance::Primitive {
|
||||
Ok(
|
||||
MorphismInstance::Specialize {
|
||||
σ: vec![
|
||||
(2, TypeTerm::Num(16)),
|
||||
].into_iter().collect(),
|
||||
|
||||
m: Box::new(
|
||||
MorphismInstance::Chain {
|
||||
path: vec![
|
||||
|
||||
MorphismInstance::Sub {
|
||||
ψ: dict.parse("ℕ ~ <PosInt 10 LittleEndian>").expect(""),
|
||||
m: Box::new(
|
||||
MorphismInstance::MapSeq {
|
||||
seq_repr: None,
|
||||
item_morph: Box::new(
|
||||
MorphismInstance::Specialize {
|
||||
σ: vec![
|
||||
(0, TypeTerm::Num(10)),
|
||||
].into_iter().collect(),
|
||||
m: Box::new(MorphismInstance::Primitive {
|
||||
m: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("<Digit Radix> ~ Char").unwrap(),
|
||||
dst_type: dict.parse("<Digit Radix> ~ ℤ_2^64 ~ machine.UInt64").unwrap()
|
||||
}),
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
MorphismInstance::Specialize {
|
||||
σ: vec![
|
||||
(1, TypeTerm::Num(10)),
|
||||
(2, TypeTerm::Num(16)),
|
||||
// (dict.get_typeid(&"DstRadix".into()).unwrap(), TypeTerm::Num(16)),
|
||||
].into_iter().collect(),
|
||||
ψ: TypeTerm::unit(),
|
||||
morph: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
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)
|
||||
}),
|
||||
}
|
||||
]
|
||||
m: Box::new(
|
||||
MorphismInstance::Primitive{
|
||||
m: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
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::Sub {
|
||||
ψ: dict.parse("ℕ ~ <PosInt DstRadix LittleEndian>").expect(""),
|
||||
m: Box::new(
|
||||
MorphismInstance::MapSeq {
|
||||
seq_repr: None,
|
||||
item_morph: Box::new(
|
||||
MorphismInstance::Specialize {
|
||||
σ: vec![
|
||||
(0, dict.parse("DstRadix").expect("")),
|
||||
].into_iter().collect(),
|
||||
m: Box::new(MorphismInstance::Primitive {
|
||||
m: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse("<Digit Radix> ~ ℤ_2^64 ~ machine.UInt64").unwrap(),
|
||||
dst_type: dict.parse("<Digit Radix> ~ Char").unwrap()
|
||||
}),
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_morphism_path4() {
|
||||
let (mut dict, base) = morphism_test_setup();
|
||||
|
||||
let path = ShortestPathProblem::new(&base, MorphismType {
|
||||
bounds: Vec::new(),
|
||||
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> ~ Char>").unwrap().sugar(&mut dict)
|
||||
}).solve();
|
||||
|
||||
if let Some(path) = path.as_ref() {
|
||||
print_path(&mut dict, path);
|
||||
}
|
||||
|
||||
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![
|
||||
(0, TypeTerm::Num(10)),
|
||||
].into_iter().collect(),
|
||||
ψ: TypeTerm::unit(),
|
||||
morph: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
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)
|
||||
}),
|
||||
})
|
||||
},
|
||||
|
||||
MorphismInstance::Primitive {
|
||||
σ: vec![
|
||||
(1, TypeTerm::Num(10)),
|
||||
(2, TypeTerm::Num(16)),
|
||||
].into_iter().collect(),
|
||||
ψ: TypeTerm::unit(),
|
||||
morph: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
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::MapSeq {
|
||||
ψ: dict.parse_desugared("ℕ ~ <PosInt 16 LittleEndian>").expect("").sugar(&mut dict),
|
||||
seq_repr: None,
|
||||
item_morph: Box::new(MorphismInstance::Primitive {
|
||||
σ: vec![
|
||||
(2, TypeTerm::Num(16)),
|
||||
(0, TypeTerm::Num(16)),
|
||||
].into_iter().collect(),
|
||||
ψ: TypeTerm::unit(),
|
||||
morph: DummyMorphism(MorphismType {
|
||||
bounds: Vec::new(),
|
||||
src_type: dict.parse_desugared("<Digit Radix> ~ ℤ_2^64 ~ machine.UInt64").unwrap().sugar(&mut dict),
|
||||
dst_type: dict.parse_desugared("<Digit Radix> ~ Char").unwrap().sugar(&mut dict)
|
||||
}),
|
||||
})
|
||||
},
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
#[test]
|
||||
fn test_morphism_path_posint() {
|
||||
|
@ -538,3 +740,4 @@ fn test_morphism_path_listedit()
|
|||
);
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue