forked from egraphs-good/egg
-
Notifications
You must be signed in to change notification settings - Fork 1
/
datalog.rs
74 lines (66 loc) · 2.3 KB
/
datalog.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use egg::*;
define_language! {
enum Lang {
"true" = True,
Int(i32),
Relation(Symbol, Box<[Id]>),
}
}
trait DatalogExtTrait {
fn assert(&mut self, s: &str);
fn check(&mut self, s: &str);
fn check_not(&mut self, s: &str);
}
impl DatalogExtTrait for EGraph<Lang, ()> {
fn assert(&mut self, s: &str) {
let true_id = self.add(Lang::True);
for e in s.split(',') {
let exp = e.trim().parse().unwrap();
let id = self.add_expr(&exp);
self.union(true_id, id);
}
}
fn check(&mut self, s: &str) {
let true_id = self.add(Lang::True);
for e in s.split(',') {
let exp = e.trim().parse().unwrap();
let id = self.add_expr(&exp);
assert_eq!(true_id, id, "{} is not true", e);
}
}
fn check_not(&mut self, s: &str) {
let true_id = self.add(Lang::True);
for e in s.split(',') {
let exp = e.trim().parse().unwrap();
let id = self.add_expr(&exp);
assert!(true_id != id, "{} is true", e);
}
}
}
#[test]
fn path() {
let mut egraph = EGraph::<Lang, ()>::default();
egraph.assert("(edge 1 2), (edge 2 3), (edge 3 4)");
let rules = vec![
multi_rewrite!("base-case"; "?x = true = (edge ?a ?b)" => "?x = (path ?a ?b)"),
multi_rewrite!("transitive"; "?x = true = (path ?a ?b) = (edge ?b ?c)" => "?x = (path ?a ?c)"),
];
let mut runner = Runner::default().with_egraph(egraph).run(&rules);
runner.egraph.check("(path 1 4)");
runner.egraph.check_not("(path 4 1)");
}
#[test]
fn path2() {
// `pred` function symbol allows us to insert without truth.
let mut egraph = EGraph::<Lang, ()>::default();
egraph.assert("(edge 1 2), (edge 2 3), (edge 3 4), (edge 1 4)");
let rules = vec![
multi_rewrite!("base-case"; "?x = (edge ?a ?b), ?t = true" => "?t = (pred (path ?a ?b))"),
multi_rewrite!("transitive"; "?x = (path ?a ?b), ?y = (edge ?b ?c), ?t = true" => "?t = (pred (path ?a ?c))"),
];
let mut runner = Runner::default().with_egraph(egraph).run(&rules);
runner.egraph.check("(pred (path 1 4))");
runner.egraph.check("(pred (path 2 3))");
runner.egraph.check_not("(pred (path 4 1))");
runner.egraph.check_not("(pred (path 3 1))");
}