use ascent::ascent;
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct Var(&'static str);
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct Obj(&'static str);
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct Field(&'static str);
ascent! {
relation assign(Var, Var);
relation new(Var, Obj);
relation ld(Var, Var, Field);
relation st(Var, Field, Var);
relation alias(Var, Var);
alias(x, x) <-- assign(x, _);
alias(x, x) <-- assign(_, x);
alias(x, y) <-- assign(x, y);
alias(x, y) <-- ld(x, a, f), alias(a, b), st(b, f, y);
relation points_to(Var, Obj);
points_to(x, y) <-- new(x, y);
points_to(x, y) <-- alias(x, z), points_to(z, y);
}
fn main() {
let mut prog = AscentProgram::default();
prog.assign = vec![(Var("v1"), Var("v2"))];
prog.new = vec![(Var("v1"), Obj("h1")), (Var("v2"), Obj("h2")), (Var("v3"), Obj("h3"))];
prog.st = vec![(Var("v1"), Field("f"), Var("v3"))];
prog.ld = vec![(Var("v4"), Var("v1"), Field("f"))];
prog.run();
let AscentProgram { mut alias, mut points_to, .. } = prog;
alias.sort_by_key(|(_, key)| key.0);
alias.sort_by_key(|(key, _)| key.0);
assert_eq!(alias, vec![
(Var("v1"), Var("v1")),
(Var("v1"), Var("v2")),
(Var("v2"), Var("v2")),
(Var("v4"), Var("v3")),
]);
points_to.sort_by_key(|(_, key)| key.0);
points_to.sort_by_key(|(key, _)| key.0);
assert_eq!(points_to, vec![
(Var("v1"), Obj("h1")),
(Var("v1"), Obj("h2")),
(Var("v2"), Obj("h2")),
(Var("v3"), Obj("h3")),
(Var("v4"), Obj("h3")),
]);
}