#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Sym(usize);
impl Sym {
#[inline(always)]
pub fn ord(self) -> usize {
self.0
}
#[inline(always)]
pub fn from_ord(ord: usize) -> Sym {
Sym(ord)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Var(usize);
impl Var {
#[inline(always)]
pub fn ord(self) -> usize {
self.0
}
#[inline(always)]
pub fn from_ord(ord: usize) -> Var {
Var(ord)
}
pub fn offset(self, offset: usize) -> Var {
Var(self.0 + offset)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Term {
Var(Var),
App(AppTerm),
Int(i64),
Cut,
}
impl Term {
pub fn count_var_slots(&self) -> usize {
match self {
Term::Var(v) => v.0 + 1,
Term::App(app) => app.count_var_slots(),
Term::Int(_) => 0,
Term::Cut => 0,
}
}
}
impl From<Var> for Term {
fn from(v: Var) -> Self {
Term::Var(v)
}
}
impl From<Sym> for Term {
fn from(s: Sym) -> Self {
Term::App(s.into())
}
}
impl From<AppTerm> for Term {
fn from(at: AppTerm) -> Self {
Term::App(at)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AppTerm {
pub functor: Sym,
pub args: Vec<Term>,
}
impl From<Sym> for AppTerm {
fn from(s: Sym) -> Self {
Self {
functor: s,
args: vec![],
}
}
}
impl AppTerm {
pub fn new(functor: Sym, args: Vec<Term>) -> Self {
Self { functor, args }
}
pub fn count_var_slots(&self) -> usize {
self.args
.iter()
.map(|t| t.count_var_slots())
.max()
.unwrap_or(0)
}
}
pub fn app(functor: Sym, args: Vec<Term>) -> Term {
Term::App(AppTerm::new(functor, args))
}
pub fn var(var: Var) -> Term {
Term::Var(var)
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Rule {
pub head: AppTerm,
pub tail: Vec<Term>,
pub scope: Option<VarScope>,
}
impl Rule {
pub fn fact(pred: Sym, args: Vec<Term>) -> Self {
let head = AppTerm {
functor: pred,
args,
};
Self {
head,
tail: vec![],
scope: None,
}
}
pub fn when(mut self, pred: Sym, args: Vec<Term>) -> Self {
let app_term = AppTerm {
functor: pred,
args,
};
self.tail.push(Term::App(app_term));
self
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Query {
pub goals: Vec<Term>,
pub scope: Option<VarScope>,
}
impl Query {
pub fn empty() -> Query {
Query::new(vec![], None)
}
pub fn new(goals: Vec<Term>, scope: Option<VarScope>) -> Query {
Query { goals, scope }
}
pub fn single_app(pred: Sym, args: Vec<Term>) -> Query {
Query::single(Term::App(AppTerm::new(pred, args)))
}
pub fn single(pred: Term) -> Query {
Query::new(vec![pred], None)
}
pub fn and_app(self, pred: Sym, args: Vec<Term>) -> Self {
self.and(Term::App(AppTerm {
functor: pred,
args,
}))
}
pub fn and(mut self, pred: Term) -> Self {
self.goals.push(pred);
self
}
pub fn count_var_slots(&self) -> usize {
self.goals
.iter()
.map(|t| t.count_var_slots())
.max()
.unwrap_or(0)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VarScope {
names: Vec<Option<String>>,
}
impl VarScope {
pub fn new() -> Self {
Self { names: Vec::new() }
}
pub fn get(&self, name: &str) -> Option<Var> {
self.names
.iter()
.position(|n| match n {
Some(n) => n == name,
_ => false,
})
.map(Var::from_ord)
}
pub fn get_or_insert(&mut self, name: &str) -> Var {
self.get(name).unwrap_or_else(|| {
let ord = self.names.len();
self.names.push(Some(name.to_string()));
Var::from_ord(ord)
})
}
pub fn insert_wildcard(&mut self) -> Var {
let ord = self.names.len();
self.names.push(None);
Var::from_ord(ord)
}
pub fn get_name(&self, var: Var) -> Option<&str> {
self.names.get(var.ord()).and_then(|n| n.as_deref())
}
pub fn iter_names(&self) -> impl Iterator<Item = &str> {
self.names
.iter()
.filter_map(|n| n.as_ref())
.map(|n| n.as_str())
}
}
impl Default for VarScope {
fn default() -> Self {
Self::new()
}
}
fn quantify<R, const N: usize>(f: impl FnOnce([Var; N]) -> R) -> R {
let mut vars = [Var::from_ord(0); N];
vars.iter_mut()
.enumerate()
.for_each(|(i, var)| *var = Var::from_ord(i));
f(vars)
}
pub fn forall<const N: usize>(f: impl FnOnce([Var; N]) -> Rule) -> Rule {
quantify(f)
}
pub fn exists<const N: usize>(f: impl FnOnce([Var; N]) -> Query) -> Query {
quantify(f)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn scope_getter() {
let scope = VarScope {
names: vec![Some("A".into()), None, Some("C".into())],
};
assert_eq!(scope.get("A"), Some(Var(0)));
assert_eq!(scope.get("B"), None);
assert_eq!(scope.get("C"), Some(Var(2)));
assert_eq!(scope.get("D"), None);
}
#[test]
fn scope_get_insertter() {
let mut scope = VarScope {
names: vec![Some("A".into()), None, Some("C".into())],
};
assert_eq!(scope.get("B"), None);
let var = scope.get_or_insert("B");
assert_eq!(scope.get("B"), Some(var));
}
#[test]
fn scope_iter() {
let scope = VarScope {
names: vec![Some("A".into()), None, Some("C".into())],
};
assert_eq!(scope.iter_names().collect::<Vec<_>>(), vec!["A", "C"]);
}
}