#![deny(missing_docs)]
use std::sync::Arc;
use std::fmt;
use std::collections::HashMap;
use std::cmp;
use std::hash::Hash;
use Expr::*;
pub use monotonic_solver::*;
pub use parsing::*;
mod parsing;
pub trait IsVar {
fn is_var(val: &str) -> bool {
if let Some(c) = val.chars().next() {c.is_uppercase()} else {false}
}
}
pub trait Symbol:
IsVar +
From<Arc<String>> +
Clone +
fmt::Debug +
fmt::Display +
cmp::PartialEq +
cmp::Eq +
cmp::PartialOrd +
Hash {
}
impl IsVar for Arc<String> {}
impl<T> Symbol for T
where T: IsVar +
From<Arc<String>> +
Clone +
fmt::Debug +
fmt::Display +
cmp::PartialEq +
cmp::Eq +
cmp::PartialOrd +
Hash
{}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Expr<T: Symbol = Arc<String>> {
Sym(T),
Var(Arc<String>),
Rel(Box<Expr<T>>, Box<Expr<T>>),
Ava(Box<Expr<T>>, Box<Expr<T>>),
Inner(Box<Expr<T>>),
UniqAva(Box<Expr<T>>),
RoleOf(Box<Expr<T>>, Box<Expr<T>>),
Eq(Box<Expr<T>>, Box<Expr<T>>),
Neq(Box<Expr<T>>, Box<Expr<T>>),
Has(Box<Expr<T>>, Box<Expr<T>>),
App(Box<Expr<T>>, Box<Expr<T>>),
AmbiguousRole(Box<Expr<T>>, Box<Expr<T>>, Box<Expr<T>>),
AmbiguousRel(Box<Expr<T>>, Box<Expr<T>>, Box<Expr<T>>),
Rule(Box<Expr<T>>, Vec<Expr<T>>),
Ambiguity(bool),
Tail,
TailVar(Arc<String>),
List(Vec<Expr<T>>),
}
impl<T: Symbol> fmt::Display for Expr<T> {
fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
match self {
Sym(a) => write!(w, "{}", a)?,
Var(a) => write!(w, "{}", a)?,
Rel(a, b) => write!(w, "({}, {})", a, b)?,
Ava(a, b) => write!(w, "{}'({})", a, b)?,
Inner(a) => write!(w, ".{}", a)?,
UniqAva(a) => write!(w, "uniq {}", a)?,
RoleOf(a, b) => write!(w, "{} : {}", a, b)?,
Eq(a, b) => write!(w, "{} = {}", a, b)?,
Neq(a, b) => write!(w, "{} != {}", a, b)?,
Has(a, b) => write!(w, "{} => {}", a, b)?,
App(a, b) => {
let mut expr = a;
let mut args = vec![];
let mut found_f = false;
while let App(a1, a2) = &**expr {
if let App(_, _) = &**a1 {} else {
found_f = true;
write!(w, "{}(", a1)?;
}
args.push(a2);
expr = a1;
}
if !found_f {
write!(w, "{}(", a)?;
}
let mut first = true;
for arg in args.iter().rev() {
if !first {
write!(w, ", ")?;
}
first = false;
write!(w, "{}", arg)?;
}
if !first {
write!(w, ", ")?;
}
write!(w, "{})", b)?;
}
AmbiguousRole(a, b, c) => write!(w, "amb_role({}, {}, {})", a, b, c)?,
AmbiguousRel(a, b, c) => write!(w, "amb_rel({}, {}, {})", a, b, c)?,
Ambiguity(v) => if *v {write!(w, "amb")?} else {write!(w, "no amb")?},
Rule(a, b) => {
write!(w, "{} :- ", a)?;
let mut first = true;
for arg in b {
if !first {
write!(w, ", ")?;
}
first = false;
write!(w, "{}", arg)?;
}
write!(w, ".")?;
}
Tail => write!(w, "..")?,
TailVar(a) => write!(w, "..{}", a)?,
List(a) => {
write!(w, "[")?;
let mut first = true;
for item in a {
if !first {
write!(w, ", ")?;
}
first = false;
write!(w, "{}", item)?;
}
write!(w, "]")?;
}
}
Ok(())
}
}
pub fn uniq_ava<T, S>(a: T) -> Expr<S>
where T: Into<Expr<S>>, S: Symbol
{
UniqAva(Box::new(a.into()))
}
pub fn role_of<T, U, S>(a: T, b: U) -> Expr<S>
where T: Into<Expr<S>>, U: Into<Expr<S>>, S: Symbol
{
RoleOf(Box::new(a.into()), Box::new(b.into()))
}
pub fn rel<T, U, S>(a: T, b: U) -> Expr<S>
where T: Into<Expr<S>>, U: Into<Expr<S>>, S: Symbol
{
Rel(Box::new(a.into()), Box::new(b.into()))
}
pub fn ava<T, U, S>(a: T, b: U) -> Expr<S>
where T: Into<Expr<S>>, U: Into<Expr<S>>, S: Symbol
{
Ava(Box::new(a.into()), Box::new(b.into()))
}
pub fn eq<T, U, S>(a: T, b: U) -> Expr<S>
where T: Into<Expr<S>>, U: Into<Expr<S>>, S: Symbol
{
Eq(Box::new(a.into()), Box::new(b.into()))
}
pub fn neq<T, U, S>(a: T, b: U) -> Expr<S>
where T: Into<Expr<S>>, U: Into<Expr<S>>, S: Symbol
{
Neq(Box::new(a.into()), Box::new(b.into()))
}
pub fn has<T, U, S>(a: T, b: U) -> Expr<S>
where T: Into<Expr<S>>, U: Into<Expr<S>>, S: Symbol
{
Has(Box::new(a.into()), Box::new(b.into()))
}
pub fn app<T, U, S>(a: T, b: U) -> Expr<S>
where T: Into<Expr<S>>, U: Into<Expr<S>>, S: Symbol
{
App(Box::new(a.into()), Box::new(b.into()))
}
pub fn inner<T: Into<Expr<S>>, S: Symbol>(a: T) -> Expr<S> {
Inner(Box::new(a.into()))
}
pub fn ambiguous_role<T, U, V, S>(a: T, b: U, c: V) -> Expr<S>
where T: Into<Expr<S>>, U: Into<Expr<S>>, V: Into<Expr<S>>, S: Symbol
{
let b = b.into();
let c = c.into();
let (b, c) = if b < c {(b, c)} else {(c, b)};
AmbiguousRole(Box::new(a.into()), Box::new(b), Box::new(c))
}
pub fn ambiguous_rel<T, U, V, S>(a: T, b: U, c: V) -> Expr<S>
where T: Into<Expr<S>>, U: Into<Expr<S>>, V: Into<Expr<S>>, S: Symbol
{
let b = b.into();
let c = c.into();
let (b, c) = if b < c {(b, c)} else {(c, b)};
AmbiguousRel(Box::new(a.into()), Box::new(b), Box::new(c))
}
impl<T: Symbol> Expr<T> {
pub fn eval_lift(&self, eval: &T, top: bool) -> Expr<T> {
match self {
Rel(a, b) => rel(a.eval_lift(eval, true), b.eval_lift(eval, true)),
App(a, b) => {
if top {
app(a.eval_lift(eval, true), b.eval_lift(eval, false))
} else {
app(Sym(eval.clone()),
app(a.eval_lift(eval, true), b.eval_lift(eval, false))
)
}
}
Rule(res, arg) => {
let new_res = res.eval_lift(eval, true);
let new_arg: Vec<Expr<T>> = arg.iter().map(|a| a.eval_lift(eval, true)).collect();
Rule(Box::new(new_res), new_arg)
}
Sym(_) | Var(_) => self.clone(),
UniqAva(_) => self.clone(),
Ambiguity(_) => self.clone(),
Tail => self.clone(),
TailVar(_) => self.clone(),
RoleOf(a, b) => {
role_of(a.eval_lift(eval, false), b.eval_lift(eval, false))
}
Ava(a, b) => ava((**a).clone(), b.eval_lift(eval, false)),
Inner(a) => inner(a.eval_lift(eval, false)),
Eq(a, b) => {
if let App(a1, a2) = &**a {
eq(app((**a1).clone(), a2.eval_lift(eval, true)), b.eval_lift(eval, false))
} else {
self.clone()
}
}
Neq(_, _) => self.clone(),
Has(_, _) => self.clone(),
AmbiguousRole(_, _, _) => self.clone(),
AmbiguousRel(_, _, _) => self.clone(),
List(_) => self.clone(),
}
}
pub fn is_const(&self) -> bool {
match self {
Var(_) => false,
Sym(_) => true,
App(ref a, ref b) => a.is_const() && b.is_const(),
Ava(ref a, ref b) => a.is_const() && b.is_const(),
_ => false
}
}
pub fn is_tail(&self) -> bool {
match self {
Tail | TailVar(_) => true,
_ => false
}
}
pub fn arity(&self) -> usize {
if let App(a, _) = self {a.arity() + 1} else {0}
}
}
pub fn bind<T: Symbol>(
e: &Expr<T>,
a: &Expr<T>,
vs: &mut Vec<(Arc<String>, Expr<T>)>,
tail: &mut Vec<Expr<T>>
) -> bool {
match (e, a) {
(&Rel(ref a1, ref b1), &Rel(ref a2, ref b2)) => {
bind(a1, a2, vs, tail) &&
bind(b1, b2, vs, tail)
}
(&RoleOf(ref a1, ref b1), &RoleOf(ref a2, ref b2)) => {
bind(a1, a2, vs, tail) &&
bind(b1, b2, vs, tail)
}
(&Eq(ref a1, ref b1), &Eq(ref a2, ref b2)) => {
bind(a1, a2, vs, tail) &&
bind(b1, b2, vs, tail)
}
(&Has(ref a1, ref b1), &Has(ref a2, ref b2)) => {
bind(a1, a2, vs, tail) &&
bind(b1, b2, vs, tail)
}
(&App(ref a1, ref b1), &App(ref a2, ref b2)) if b1.is_tail() &&
a2.arity() >= a1.arity() && b2.is_const() => {
tail.push((**b2).clone());
if a2.arity() > a1.arity() {
bind(e, a2, vs, tail)
} else {
bind(a1, a2, vs, tail) &&
if let TailVar(b1_sym) = &**b1 {
if tail.len() > 0 {
tail.reverse();
vs.push((b1_sym.clone(), List(tail.clone())));
tail.clear();
true
} else {
tail.clear();
false
}
} else {
true
}
}
}
(&App(ref a1, ref b1), &App(ref a2, ref b2)) => {
bind(a1, a2, vs, tail) &&
bind(b1, b2, vs, tail)
}
(&Sym(ref a1), &Sym(ref a2)) => a1 == a2,
(&Var(ref a1), &Sym(_)) => {
let mut found = false;
for &(ref b, ref b_expr) in &*vs {
if b == a1 {
if let Some(true) = equal(b_expr, a) {
found = true;
break;
} else {
return false;
}
}
}
if !found {
vs.push((a1.clone(), a.clone()));
}
true
}
(&Var(ref a1), _) if a.is_const() => {
vs.push((a1.clone(), a.clone()));
true
}
(&Ava(ref a1, ref b1), &Ava(ref a2, ref b2)) => {
bind(a1, a2, vs, tail) &&
bind(b1, b2, vs, tail)
}
_ => false
}
}
fn substitute<T: Symbol>(r: &Expr<T>, vs: &Vec<(Arc<String>, Expr<T>)>) -> Expr<T> {
match r {
Rel(a1, b1) => {
rel(substitute(a1, vs), substitute(b1, vs))
}
Var(a1) => {
for v in vs {
if &v.0 == a1 {
return v.1.clone();
}
}
r.clone()
}
Sym(_) => r.clone(),
Ava(a1, b1) => {
ava(substitute(a1, vs), substitute(b1, vs))
}
RoleOf(a, b) => {
role_of(substitute(a, vs), substitute(b, vs))
}
Eq(a, b) => {
eq(substitute(a, vs), substitute(b, vs))
}
Neq(a, b) => {
neq(substitute(a, vs), substitute(b, vs))
}
Has(a, b) => {
has(substitute(a, vs), substitute(b, vs))
}
App(a, b) => {
let a_expr = substitute(a, vs);
if let Var(a1) = &**b {
for v in vs {
if &v.0 == a1 {
if let List(args) = &v.1 {
let mut expr = a_expr;
for arg in args {
expr = app(expr, arg.clone());
}
return expr;
}
}
}
}
app(a_expr, substitute(b, vs))
}
Ambiguity(_) => r.clone(),
UniqAva(a) => {
uniq_ava(substitute(a, vs))
}
Inner(a) => {
inner(substitute(a, vs))
}
x => unimplemented!("{:?}", x)
}
}
fn equal<T: Symbol>(a: &Expr<T>, b: &Expr<T>) -> Option<bool> {
fn false_or_none(val: Option<bool>) -> bool {
if let Some(val) = val {!val} else {true}
}
if a.is_const() && b.is_const() {Some(a == b)}
else {
match (a, b) {
(&Sym(_), &Sym(_)) |
(&Sym(_), &Var(_)) | (&Var(_), &Sym(_)) |
(&Var(_), &Var(_)) |
(&Var(_), &Ava(_, _)) | (&Ava(_, _), &Var(_)) |
(&App(_, _), &Sym(_)) | (&Sym(_), &App(_, _)) |
(&App(_, _), &Var(_)) | (&Var(_), &App(_, _)) |
(&App(_, _), &Ava(_, _)) | (&Ava(_, _), &App(_, _)) => None,
(&Sym(_), &Ava(_, _)) | (&Ava(_, _), &Sym(_)) => Some(false),
(&Ava(ref a1, ref b1), &Ava(ref a2, ref b2)) |
(&App(ref a1, ref b1), &App(ref a2, ref b2)) => {
let cmp_a = equal(a1, a2);
if false_or_none(cmp_a) {return cmp_a};
equal(b1, b2)
}
x => unimplemented!("{:?}", x)
}
}
}
fn match_rule<T: Symbol>(r: &Expr<T>, rel: &Expr<T>) -> Option<Expr<T>> {
if let Rule(res, args) = r {
let mut vs = vec![];
let mut tail: Vec<Expr<T>> = vec![];
if bind(&args[0], rel, &mut vs, &mut tail) {
if args.len() > 1 {
let mut new_args = vec![];
for e in &args[1..] {
let new_e = substitute(e, &vs);
if let Neq(a, b) = &new_e {
match equal(a, b) {
Some(true) => return None,
Some(false) => continue,
None => {}
}
}
new_args.push(new_e);
}
let new_res = substitute(res, &vs);
if new_args.len() > 0 {
return Some(Rule(Box::new(new_res), new_args));
} else {
return Some(new_res);
}
} else {
let new_res = substitute(res, &vs);
return Some(new_res);
}
}
None
} else {
None
}
}
fn apply<T: Symbol>(e: &Expr<T>, facts: &[Expr<T>]) -> Option<Expr<T>> {
match e {
App(a, b) => {
for e2 in facts {
if let Eq(b2, b3) = e2 {
if &**b2 == e {
return Some((**b3).clone());
}
}
}
match (apply(a, facts), apply(b, facts)) {
(Some(a), Some(b)) => return Some(app(a, b)),
(None, Some(b)) => return Some(app((**a).clone(), b)),
(Some(a), None) => return Some(app(a, (**b).clone())),
(None, None) => {}
}
}
Rel(a, b) => {
match (apply(a, facts), apply(b, facts)) {
(Some(a), Some(b)) => return Some(rel(a, b)),
(None, Some(b)) => return Some(rel((**a).clone(), b)),
(Some(a), None) => return Some(rel(a, (**b).clone())),
(None, None) => {}
}
}
Ava(a, b) => {
match (apply(a, facts), apply(b, facts)) {
(Some(a), Some(b)) => return Some(ava(a, b)),
(None, Some(b)) => return Some(ava((**a).clone(), b)),
(Some(a), None) => return Some(ava(a, (**b).clone())),
(None, None) => {}
}
}
Eq(a, b) => {
let new_b = apply(b, facts)?;
return Some(eq((**a).clone(), new_b))
}
Has(a, b) => {
let new_b = apply(b, facts)?;
return Some(has((**a).clone(), new_b))
}
Inner(a) => {
let new_a = apply(a, facts);
if new_a.is_some() {return new_a.map(|n| inner(n))};
if let Ava(_, b) = &**a {
if let Some(new_b) = apply(b, facts) {
return Some(new_b);
} else {
return Some((**b).clone());
}
} else {
return Some(inner(apply(a, facts)?));
}
}
_ => {}
}
None
}
pub struct Accelerator<T: Symbol> {
pub index: HashMap<Expr<T>, Vec<usize>>,
pub len: usize,
pub last_rule: Option<usize>,
}
impl<T: Symbol> Accelerator<T> {
pub fn new() -> Accelerator<T> {
Accelerator {index: HashMap::new(), len: 0, last_rule: None}
}
pub fn constructor() -> fn(&[Expr<T>], &[Expr<T>]) -> Accelerator<T> {
|_, _| Accelerator::new()
}
pub fn update(&mut self, facts: &[Expr<T>])
where T: Clone + std::hash::Hash + std::cmp::Eq
{
let accelerator_len = self.len;
let ref mut index = self.index;
let mut insert = |i: usize, e: &Expr<T>| {
index.entry(e.clone()).or_insert(vec![]).push(i);
};
for (i, e) in facts[accelerator_len..].iter().enumerate() {
let i = i + accelerator_len;
match e {
RoleOf(a, b) | Rel(a, b) | Ava(a, b) | Eq(a, b) |
Neq(a, b) | Has(a, b) | App(a, b) => {
insert(i, a);
insert(i, b);
}
Sym(_) | Var(_) | Inner(_) | UniqAva(_) => {
insert(i, e);
}
AmbiguousRel(_, _, _) |
AmbiguousRole(_, _, _) |
Rule(_, _) |
Ambiguity(_) |
Tail | TailVar(_) | List(_) => {}
}
}
self.len = facts.len();
}
}
pub fn infer<T: Symbol>(
solver: Solver<Expr<T>, Accelerator<T>>,
facts: &[Expr<T>]
) -> Option<Expr<T>> {
solver.accelerator.update(facts);
let find = |e: &Expr<T>| {
solver.accelerator.index.get(e).unwrap().iter().map(|&i| &facts[i])
};
for e in facts.iter().rev() {
if let RoleOf(a, b) = e {
for e2 in find(a) {
if let RoleOf(a2, b2) = e2 {
if a2 == a && b2 != b {
let new_expr = ambiguous_role((**a).clone(), (**b).clone(), (**b2).clone());
if solver.can_add(&new_expr) {return Some(new_expr)};
let new_expr = Ambiguity(true);
if solver.can_add(&new_expr) {return Some(new_expr)};
}
}
}
}
if let Has(a, b) = e {
if let Ava(b1, _) = &**b {
let uniq_expr = uniq_ava((**b1).clone());
if solver.cache.contains(&uniq_expr) {
let new_expr = eq((**a).clone(), (**b).clone());
if solver.can_add(&new_expr) {return Some(new_expr)};
}
} else {
let new_expr = eq((**a).clone(), (**b).clone());
if solver.can_add(&new_expr) {return Some(new_expr)};
}
}
if let Eq(a, b) = e {
let new_expr = has((**a).clone(), (**b).clone());
if solver.can_add(&new_expr) {return Some(new_expr)};
}
if let Rel(a, b) = e {
if let Ava(av, _) = &**b {
let mut b_role: Option<Expr<T>> = None;
let mut uniq = false;
for e2 in find(b) {
if let RoleOf(b2, r) = e2 {
if b2 == b {
if solver.cache.contains(&uniq_ava((**av).clone())) {
uniq = true;
let new_expr = eq(app((**r).clone(), (**a).clone()), (**b).clone());
if solver.can_add(&new_expr) {return Some(new_expr)};
}
let new_expr = has(app((**r).clone(), (**a).clone()), (**b).clone());
if solver.can_add(&new_expr) {return Some(new_expr)};
b_role = Some((**r).clone());
}
}
}
if let Some(b_role) = &b_role {
for e1 in find(a) {
if let Rel(a2, b2) = e1 {
if a2 == a && b2 != b {
if let Ava(av2, _) = &**b2 {
if uniq || av2 != av {
for e2 in find(b2) {
if let RoleOf(a3, b3) = e2 {
if a3 == b2 && &**b3 == b_role {
let new_expr = ambiguous_rel((**a).clone(),
(**b).clone(), (**b2).clone());
if solver.can_add(&new_expr) {
return Some(new_expr)
}
let new_expr = Ambiguity(true);
if solver.can_add(&new_expr) {
return Some(new_expr)
}
}
}
}
}
}
}
}
}
}
} else {
let mut b_role: Option<Expr<T>> = None;
for e2 in find(b) {
if let RoleOf(b2, r) = e2 {
if b2 == b {
let new_expr = eq(app((**r).clone(), (**a).clone()), (**b).clone());
if solver.can_add(&new_expr) {return Some(new_expr)};
let new_expr = has(app((**r).clone(), (**a).clone()), (**b).clone());
if solver.can_add(&new_expr) {return Some(new_expr)};
b_role = Some((**r).clone());
}
}
}
if let Some(b_role) = &b_role {
for e1 in find(a) {
if let Rel(a2, b2) = e1 {
if a2 == a && b2 != b {
if solver.cache.contains(&role_of((**b2).clone(), b_role.clone())) {
let new_expr = ambiguous_rel((**a).clone(),
(**b).clone(), (**b2).clone());
if solver.can_add(&new_expr) {return Some(new_expr)};
let new_expr = Ambiguity(true);
if solver.can_add(&new_expr) {return Some(new_expr)};
}
}
}
}
}
}
}
}
for e in facts {
if let Some(new_expr) = apply(e, facts) {
if solver.can_add(&new_expr) {return Some(new_expr)};
}
}
match solver.accelerator.last_rule {
None => {
for (i, e) in facts.iter().enumerate() {
if let Rule(_, _) = e {
for e2 in facts {
if let Some(new_expr) = match_rule(e, e2) {
solver.accelerator.last_rule = Some(i);
if solver.can_add(&new_expr) {return Some(new_expr)};
}
}
}
}
}
Some(i) => {
for (j, e) in facts[i + 1..].iter().enumerate() {
if let Rule(_, _) = e {
for e2 in facts {
if let Some(new_expr) = match_rule(e, e2) {
solver.accelerator.last_rule = Some(i + 1 + j);
if solver.can_add(&new_expr) {return Some(new_expr)};
}
}
}
}
for (j, e) in facts[..i + 1].iter().enumerate() {
if let Rule(_, _) = e {
for e2 in facts {
if let Some(new_expr) = match_rule(e, e2) {
solver.accelerator.last_rule = Some(j);
if solver.can_add(&new_expr) {return Some(new_expr)};
}
}
}
}
}
}
if !solver.cache.contains(&Ambiguity(true)) {
let mut amb = false;
for e in facts {
if let AmbiguousRel(_, _, _) = e {
amb = true;
break;
} else if let AmbiguousRole(_, _, _) = e {
amb = true;
break;
}
}
let new_expr = Ambiguity(amb);
if solver.can_add(&new_expr) {return Some(new_expr)};
}
None
}