materialized_view/builders/
goal.rs

1use std::hash::Hash;
2use byteorder::ByteOrder;
3use crate::interning::hash::reproducible_hash_one;
4use crate::rewriting::atom::{EncodedFact, EncodedGoal};
5use crate::rewriting::rewrite::get_ith_term;
6
7#[allow(dead_code)]
8pub const ANY_VALUE: Option<()> = None;
9
10type GoalIR = [u64; 3];
11
12pub struct Goal { pub(crate) goal_ir: GoalIR }
13
14impl<T> From<(Option<T>,)> for Goal where T: Hash {
15    fn from(value: (Option<T>,)) -> Self {
16        let first = if value.0.is_none() { 0 } else { reproducible_hash_one(&value.0.unwrap()) };
17
18        return Self { goal_ir: [first, 0, 0] }
19    }
20}
21
22impl<T, R> From<(Option<T>, Option<R>)> for Goal where T: Hash, R: Hash {
23    fn from(value: (Option<T>, Option<R>)) -> Self {
24        let first = if value.0.is_none() { 0 } else { reproducible_hash_one(&value.0.unwrap()) };
25        let second = if value.1.is_none() { 0 } else { reproducible_hash_one(&value.1.unwrap()) };
26
27        return Self { goal_ir: [first, second, 0] }
28    }
29}
30
31impl<T, R, S> From<(Option<T>, Option<R>, Option<S>)> for Goal where T: Hash, R: Hash, S: Hash {
32    fn from(value: (Option<T>, Option<R>, Option<S>)) -> Self {
33        let first = if value.0.is_none() { 0 } else { reproducible_hash_one(&value.0.unwrap()) };
34        let second = if value.1.is_none() { 0 } else { reproducible_hash_one(&value.1.unwrap()) };
35        let third = if value.2.is_none() { 0 } else { reproducible_hash_one(&value.2.unwrap()) };
36
37        return Self { goal_ir: [first, second, third] }
38    }
39}
40
41pub(crate) fn pattern_match(goal: &EncodedGoal, fact: &EncodedFact) -> bool {
42    let first_goal_constant = byteorder::NativeEndian::read_u24(get_ith_term(goal, 0).1);
43    let first_fact_constant = byteorder::NativeEndian::read_u24(get_ith_term(fact, 0).1) >> 1;
44    if first_goal_constant != 0 && first_goal_constant != first_fact_constant {
45        return false
46    }
47
48    let second_goal_constant = byteorder::NativeEndian::read_u24(get_ith_term(goal, 1).1);
49    let second_fact_constant = byteorder::NativeEndian::read_u24(get_ith_term(fact, 1).1) >> 1;
50    if second_goal_constant != 0 && second_goal_constant != second_fact_constant {
51        return false
52    }
53
54    let third_goal_constant = byteorder::NativeEndian::read_u24(get_ith_term(goal, 2).1);
55    let third_fact_constant = byteorder::NativeEndian::read_u24(get_ith_term(fact, 2).1) >> 1;
56    if third_goal_constant != 0 && third_goal_constant != third_fact_constant {
57        return false
58    }
59
60    true
61}
62
63#[cfg(test)]
64mod tests {
65    use crate::builders::goal::pattern_match;
66    use crate::rewriting::atom::{encode_fact, encode_goal};
67
68    #[test]
69    fn test_pattern_match() {
70        let goal_one = encode_goal(&[1usize, 0, 0]);
71        let goal_two = encode_goal(&[0usize, 0, 0]);
72        let goal_three = encode_goal(&[467000usize, 510000, 511000]);
73
74        let fact_one = encode_fact(&[1usize, 4, 0]);
75        let fact_two = encode_fact(&[3usize, 4, 0]);
76        let fact_three = encode_fact(&[467000usize, 510000, 511000]);
77
78        assert!(pattern_match(&goal_one, &fact_one));
79        assert!(!pattern_match(&goal_one, &fact_two));
80        assert!(!pattern_match(&goal_one, &fact_three));
81
82        assert!(pattern_match(&goal_two, &fact_one));
83        assert!(pattern_match(&goal_two, &fact_two));
84        assert!(pattern_match(&goal_two, &fact_three));
85
86        assert!(!pattern_match(&goal_three, &fact_one));
87        assert!(!pattern_match(&goal_three, &fact_two));
88        assert!(pattern_match(&goal_three, &fact_three));
89    }
90}