192 lines
5.3 KiB
Rust
192 lines
5.3 KiB
Rust
|
||
use {
|
||
crate::{dict::*, parser::*, unparser::*, term::*, unification::*},
|
||
std::iter::FromIterator
|
||
};
|
||
|
||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||
|
||
fn test_unify(ts1: &str, ts2: &str, expect_unificator: bool) {
|
||
let mut dict = BimapTypeDict::new();
|
||
dict.add_varname(String::from("T"));
|
||
dict.add_varname(String::from("U"));
|
||
dict.add_varname(String::from("V"));
|
||
dict.add_varname(String::from("W"));
|
||
|
||
let mut t1 = dict.parse(ts1).unwrap();
|
||
let mut t2 = dict.parse(ts2).unwrap();
|
||
let σ = crate::unify( &t1, &t2 );
|
||
|
||
if expect_unificator {
|
||
assert!(σ.is_ok());
|
||
|
||
let σ = σ.unwrap();
|
||
|
||
assert_eq!(
|
||
t1.apply_substitution(&|v| σ.get(v).cloned()),
|
||
t2.apply_substitution(&|v| σ.get(v).cloned())
|
||
);
|
||
} else {
|
||
assert!(! σ.is_ok());
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn test_unification_error() {
|
||
let mut dict = BimapTypeDict::new();
|
||
dict.add_varname(String::from("T"));
|
||
|
||
assert_eq!(
|
||
crate::unify(
|
||
&dict.parse("<A T>").unwrap(),
|
||
&dict.parse("<B T>").unwrap()
|
||
),
|
||
|
||
Err(UnificationError {
|
||
addr: vec![0],
|
||
t1: dict.parse("A").unwrap(),
|
||
t2: dict.parse("B").unwrap()
|
||
})
|
||
);
|
||
|
||
assert_eq!(
|
||
crate::unify(
|
||
&dict.parse("<V <U A> T>").unwrap(),
|
||
&dict.parse("<V <U B> T>").unwrap()
|
||
),
|
||
|
||
Err(UnificationError {
|
||
addr: vec![1, 1],
|
||
t1: dict.parse("A").unwrap(),
|
||
t2: dict.parse("B").unwrap()
|
||
})
|
||
);
|
||
|
||
assert_eq!(
|
||
crate::unify(
|
||
&dict.parse("T").unwrap(),
|
||
&dict.parse("<Seq T>").unwrap()
|
||
),
|
||
|
||
Err(UnificationError {
|
||
addr: vec![],
|
||
t1: dict.parse("T").unwrap(),
|
||
t2: dict.parse("<Seq T>").unwrap()
|
||
})
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn test_unification() {
|
||
test_unify("A", "A", true);
|
||
test_unify("A", "B", false);
|
||
test_unify("<Seq T>", "<Seq Ascii~Char>", true);
|
||
test_unify("<Seq T>", "<U Char>", true);
|
||
|
||
test_unify(
|
||
"<Seq Path~<Seq Char>>~<SepSeq Char '\n'>~<Seq Char>",
|
||
"<Seq T~<Seq Char>>~<SepSeq Char '\n'>~<Seq Char>",
|
||
true
|
||
);
|
||
|
||
let mut dict = BimapTypeDict::new();
|
||
|
||
dict.add_varname(String::from("T"));
|
||
dict.add_varname(String::from("U"));
|
||
dict.add_varname(String::from("V"));
|
||
dict.add_varname(String::from("W"));
|
||
|
||
assert_eq!(
|
||
UnificationProblem::new(vec![
|
||
(dict.parse("U").unwrap(), dict.parse("<Seq Char>").unwrap()),
|
||
(dict.parse("T").unwrap(), dict.parse("<Seq U>").unwrap()),
|
||
]).solve(),
|
||
Ok(
|
||
vec![
|
||
// T
|
||
(TypeID::Var(0), dict.parse("<Seq <Seq Char>>").unwrap()),
|
||
|
||
// U
|
||
(TypeID::Var(1), dict.parse("<Seq Char>").unwrap())
|
||
].into_iter().collect()
|
||
)
|
||
);
|
||
|
||
assert_eq!(
|
||
UnificationProblem::new(vec![
|
||
(dict.parse("<Seq T>").unwrap(), dict.parse("<Seq W~<Seq Char>>").unwrap()),
|
||
(dict.parse("<Seq ℕ>").unwrap(), dict.parse("<Seq W>").unwrap()),
|
||
]).solve(),
|
||
Ok(
|
||
vec![
|
||
// W
|
||
(TypeID::Var(3), dict.parse("ℕ").unwrap()),
|
||
|
||
// T
|
||
(TypeID::Var(0), dict.parse("ℕ~<Seq Char>").unwrap())
|
||
].into_iter().collect()
|
||
)
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn test_subtype_unification() {
|
||
let mut dict = BimapTypeDict::new();
|
||
|
||
dict.add_varname(String::from("T"));
|
||
dict.add_varname(String::from("U"));
|
||
dict.add_varname(String::from("V"));
|
||
dict.add_varname(String::from("W"));
|
||
|
||
assert_eq!(
|
||
UnificationProblem::new(vec![
|
||
(dict.parse("<Seq~T <Digit 10> ~ Char>").unwrap(),
|
||
dict.parse("<Seq~<LengthPrefix x86.UInt64> Char ~ Ascii>").unwrap()),
|
||
]).solve_subtype(),
|
||
Ok((
|
||
dict.parse("<Seq <Digit 10>>").unwrap(),
|
||
vec![
|
||
// T
|
||
(TypeID::Var(0), dict.parse("<LengthPrefix x86.UInt64>").unwrap())
|
||
].into_iter().collect()
|
||
))
|
||
);
|
||
|
||
assert_eq!(
|
||
UnificationProblem::new(vec![
|
||
(dict.parse("U").unwrap(), dict.parse("<Seq Char>").unwrap()),
|
||
(dict.parse("T").unwrap(), dict.parse("<Seq U>").unwrap()),
|
||
]).solve_subtype(),
|
||
Ok((
|
||
TypeTerm::unit(),
|
||
vec![
|
||
// T
|
||
(TypeID::Var(0), dict.parse("<Seq <Seq Char>>").unwrap()),
|
||
|
||
// U
|
||
(TypeID::Var(1), dict.parse("<Seq Char>").unwrap())
|
||
].into_iter().collect()
|
||
))
|
||
);
|
||
|
||
assert_eq!(
|
||
UnificationProblem::new(vec![
|
||
(dict.parse("<Seq T>").unwrap(),
|
||
dict.parse("<Seq W~<Seq Char>>").unwrap()),
|
||
(dict.parse("<Seq~<LengthPrefix x86.UInt64> ℕ~<PosInt 10 BigEndian>>").unwrap(),
|
||
dict.parse("<<LengthPrefix x86.UInt64> W>").unwrap()),
|
||
]).solve_subtype(),
|
||
Ok((
|
||
dict.parse("
|
||
<Seq ℕ~<PosInt 10 BigEndian>>
|
||
").unwrap(),
|
||
vec![
|
||
// W
|
||
(TypeID::Var(3), dict.parse("ℕ~<PosInt 10 BigEndian>").unwrap()),
|
||
|
||
// T
|
||
(TypeID::Var(0), dict.parse("ℕ~<PosInt 10 BigEndian>~<Seq Char>").unwrap())
|
||
].into_iter().collect()
|
||
))
|
||
);
|
||
}
|