2023-10-31 16:26:54 +01:00
|
|
|
|
|
|
|
|
|
use {
|
2025-02-04 14:34:55 +01:00
|
|
|
|
crate::{dict::*, parser::*, unparser::*, term::*, unification::*},
|
2023-10-31 16:26:54 +01:00
|
|
|
|
std::iter::FromIterator
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
|
|
|
|
|
|
|
|
|
fn test_unify(ts1: &str, ts2: &str, expect_unificator: bool) {
|
2025-02-04 14:34:55 +01:00
|
|
|
|
let mut dict = BimapTypeDict::new();
|
2023-10-31 16:26:54 +01:00
|
|
|
|
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() {
|
2025-02-04 14:34:55 +01:00
|
|
|
|
let mut dict = BimapTypeDict::new();
|
2023-10-31 16:26:54 +01:00
|
|
|
|
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()
|
|
|
|
|
})
|
|
|
|
|
);
|
2025-02-15 17:21:12 +01:00
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
})
|
|
|
|
|
);
|
2023-10-31 16:26:54 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[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
|
|
|
|
|
);
|
2023-11-11 16:26:30 +01:00
|
|
|
|
|
2025-02-04 14:34:55 +01:00
|
|
|
|
let mut dict = BimapTypeDict::new();
|
2023-11-11 16:26:30 +01:00
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
)
|
|
|
|
|
);
|
2023-10-31 16:26:54 +01:00
|
|
|
|
}
|
|
|
|
|
|
2025-02-09 16:58:58 +01:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_subtype_unification() {
|
2025-02-04 14:34:55 +01:00
|
|
|
|
let mut dict = BimapTypeDict::new();
|
2025-02-09 16:58:58 +01:00
|
|
|
|
|
|
|
|
|
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(),
|
2025-02-15 17:21:12 +01:00
|
|
|
|
Ok((
|
|
|
|
|
dict.parse("<Seq <Digit 10>>").unwrap(),
|
2025-02-09 16:58:58 +01:00
|
|
|
|
vec![
|
|
|
|
|
// T
|
|
|
|
|
(TypeID::Var(0), dict.parse("<LengthPrefix x86.UInt64>").unwrap())
|
|
|
|
|
].into_iter().collect()
|
2025-02-15 17:21:12 +01:00
|
|
|
|
))
|
2025-02-09 16:58:58 +01:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
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(),
|
2025-02-15 17:21:12 +01:00
|
|
|
|
Ok((
|
|
|
|
|
TypeTerm::unit(),
|
2025-02-09 16:58:58 +01:00
|
|
|
|
vec![
|
|
|
|
|
// T
|
|
|
|
|
(TypeID::Var(0), dict.parse("<Seq <Seq Char>>").unwrap()),
|
|
|
|
|
|
|
|
|
|
// U
|
|
|
|
|
(TypeID::Var(1), dict.parse("<Seq Char>").unwrap())
|
|
|
|
|
].into_iter().collect()
|
2025-02-15 17:21:12 +01:00
|
|
|
|
))
|
2025-02-09 16:58:58 +01:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
UnificationProblem::new(vec![
|
|
|
|
|
(dict.parse("<Seq T>").unwrap(),
|
|
|
|
|
dict.parse("<Seq W~<Seq Char>>").unwrap()),
|
2025-02-25 22:57:50 +01:00
|
|
|
|
(dict.parse("<Seq~<LengthPrefix x86.UInt64> ℕ~<PosInt 10 BigEndian>>").unwrap(),
|
|
|
|
|
dict.parse("<<LengthPrefix x86.UInt64> W>").unwrap()),
|
2025-02-09 16:58:58 +01:00
|
|
|
|
]).solve_subtype(),
|
2025-02-15 17:21:12 +01:00
|
|
|
|
Ok((
|
|
|
|
|
dict.parse("
|
2025-02-25 22:57:50 +01:00
|
|
|
|
<Seq ℕ~<PosInt 10 BigEndian>>
|
2025-02-15 17:21:12 +01:00
|
|
|
|
").unwrap(),
|
2025-02-09 16:58:58 +01:00
|
|
|
|
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()
|
2025-02-15 17:21:12 +01:00
|
|
|
|
))
|
2025-02-09 16:58:58 +01:00
|
|
|
|
);
|
|
|
|
|
}
|