use super::*;
use crate::ir::{IrForm, IrTerm};
use nibli_types::ast::{
Argument, Determiner, Marker, Predicate, Pronoun, Proposition, RelClause, RelClauseKind,
Sentence,
};
fn compile_one(
predicates: Vec<Predicate>,
arguments: Vec<Argument>,
proposition: Proposition,
) -> (IrForm, SemanticCompiler) {
let sentences = vec![Sentence::Simple(proposition)];
let mut compiler = SemanticCompiler::new();
let form = compiler.compile_proposition(
match &sentences[0] {
Sentence::Simple(b) => b,
_ => unreachable!(),
},
&predicates,
&arguments,
&sentences,
);
(form, compiler)
}
fn resolve(compiler: &SemanticCompiler, spur: &lasso::Spur) -> String {
compiler.interner.resolve(spur).to_string()
}
fn collect_predicates(form: &IrForm, compiler: &SemanticCompiler) -> Vec<(String, Vec<IrTerm>)> {
let mut result = Vec::new();
collect_predicates_inner(form, compiler, &mut result);
result
}
fn collect_predicates_inner(
form: &IrForm,
compiler: &SemanticCompiler,
result: &mut Vec<(String, Vec<IrTerm>)>,
) {
match form {
IrForm::Predicate { relation, args } => {
result.push((resolve(compiler, relation), args.clone()));
}
IrForm::And(l, r) | IrForm::Or(l, r) | IrForm::Biconditional(l, r) | IrForm::Xor(l, r) => {
collect_predicates_inner(l, compiler, result);
collect_predicates_inner(r, compiler, result);
}
IrForm::Not(inner)
| IrForm::Exists(_, inner)
| IrForm::ForAll(_, inner)
| IrForm::Past(inner)
| IrForm::Present(inner)
| IrForm::Future(inner)
| IrForm::Obligatory(inner)
| IrForm::Permitted(inner) => {
collect_predicates_inner(inner, compiler, result);
}
IrForm::Count { body, .. } => {
collect_predicates_inner(body, compiler, result);
}
}
}
fn has_pred(form: &IrForm, name: &str, compiler: &SemanticCompiler) -> bool {
collect_predicates(form, compiler)
.iter()
.any(|(n, _)| n == name)
}
fn get_pred_args(form: &IrForm, name: &str, compiler: &SemanticCompiler) -> Option<Vec<IrTerm>> {
collect_predicates(form, compiler)
.into_iter()
.find(|(n, _)| n == name)
.map(|(_, args)| args)
}
fn const_str(compiler: &SemanticCompiler, term: &IrTerm) -> String {
match term {
IrTerm::Constant(c) => resolve(compiler, c),
other => panic!("expected Constant, got {:?}", other),
}
}
fn free_vars(form: &IrForm, compiler: &SemanticCompiler) -> Vec<String> {
let mut bound: Vec<lasso::Spur> = Vec::new();
let mut out: Vec<String> = Vec::new();
free_vars_inner(form, compiler, &mut bound, &mut out);
out
}
fn free_vars_inner(
form: &IrForm,
compiler: &SemanticCompiler,
bound: &mut Vec<lasso::Spur>,
out: &mut Vec<String>,
) {
match form {
IrForm::Predicate { args, .. } => {
for arg in args {
if let IrTerm::Variable(spur) = arg {
if !bound.contains(spur) {
out.push(resolve(compiler, spur));
}
}
}
}
IrForm::And(l, r) | IrForm::Or(l, r) | IrForm::Biconditional(l, r) | IrForm::Xor(l, r) => {
free_vars_inner(l, compiler, bound, out);
free_vars_inner(r, compiler, bound, out);
}
IrForm::Not(inner)
| IrForm::Past(inner)
| IrForm::Present(inner)
| IrForm::Future(inner)
| IrForm::Obligatory(inner)
| IrForm::Permitted(inner) => {
free_vars_inner(inner, compiler, bound, out);
}
IrForm::Exists(v, body) | IrForm::ForAll(v, body) => {
bound.push(*v);
free_vars_inner(body, compiler, bound, out);
bound.pop();
}
IrForm::Count { var, body, .. } => {
bound.push(*var);
free_vars_inner(body, compiler, bound, out);
bound.pop();
}
}
}
fn count_exists_binding(form: &IrForm, name: &str, compiler: &SemanticCompiler) -> usize {
match form {
IrForm::Exists(v, body) => {
let here = usize::from(resolve(compiler, v) == name);
here + count_exists_binding(body, name, compiler)
}
IrForm::ForAll(_, body) => count_exists_binding(body, name, compiler),
IrForm::And(l, r) | IrForm::Or(l, r) | IrForm::Biconditional(l, r) | IrForm::Xor(l, r) => {
count_exists_binding(l, name, compiler) + count_exists_binding(r, name, compiler)
}
IrForm::Not(inner)
| IrForm::Past(inner)
| IrForm::Present(inner)
| IrForm::Future(inner)
| IrForm::Obligatory(inner)
| IrForm::Permitted(inner) => count_exists_binding(inner, name, compiler),
IrForm::Count { body, .. } => count_exists_binding(body, name, compiler),
IrForm::Predicate { .. } => 0,
}
}
#[derive(Debug, PartialEq)]
enum Binder {
Exists(String),
ForAll,
Count(u32),
}
fn binder_spine(form: &IrForm, compiler: &SemanticCompiler) -> Vec<Binder> {
let mut out = Vec::new();
let mut cur = form;
loop {
match cur {
IrForm::Exists(v, body) => {
out.push(Binder::Exists(resolve(compiler, v)));
cur = body;
}
IrForm::ForAll(_, body) => {
out.push(Binder::ForAll);
cur = body;
}
IrForm::Count { count, body, .. } => {
out.push(Binder::Count(*count));
cur = body;
}
IrForm::Not(inner)
| IrForm::Past(inner)
| IrForm::Present(inner)
| IrForm::Future(inner)
| IrForm::Obligatory(inner)
| IrForm::Permitted(inner) => cur = inner,
_ => break,
}
}
out
}
fn subtree_has_forall(form: &IrForm) -> bool {
match form {
IrForm::ForAll(_, _) => true,
IrForm::Exists(_, b)
| IrForm::Not(b)
| IrForm::Past(b)
| IrForm::Present(b)
| IrForm::Future(b)
| IrForm::Obligatory(b)
| IrForm::Permitted(b) => subtree_has_forall(b),
IrForm::Count { body, .. } => subtree_has_forall(body),
IrForm::And(l, r) | IrForm::Or(l, r) | IrForm::Biconditional(l, r) | IrForm::Xor(l, r) => {
subtree_has_forall(l) || subtree_has_forall(r)
}
IrForm::Predicate { .. } => false,
}
}
fn exists_outscopes_forall(form: &IrForm, name: &str, compiler: &SemanticCompiler) -> bool {
match form {
IrForm::Exists(v, body) => {
(resolve(compiler, v) == name && subtree_has_forall(body))
|| exists_outscopes_forall(body, name, compiler)
}
IrForm::ForAll(_, body) => exists_outscopes_forall(body, name, compiler),
IrForm::Count { body, .. } => exists_outscopes_forall(body, name, compiler),
IrForm::Not(b)
| IrForm::Past(b)
| IrForm::Present(b)
| IrForm::Future(b)
| IrForm::Obligatory(b)
| IrForm::Permitted(b) => exists_outscopes_forall(b, name, compiler),
IrForm::And(l, r) | IrForm::Or(l, r) | IrForm::Biconditional(l, r) | IrForm::Xor(l, r) => {
exists_outscopes_forall(l, name, compiler) || exists_outscopes_forall(r, name, compiler)
}
IrForm::Predicate { .. } => false,
}
}
fn compile_sentence_full(
predicates: Vec<Predicate>,
arguments: Vec<Argument>,
sentences: Vec<Sentence>,
) -> (IrForm, SemanticCompiler) {
let mut compiler = SemanticCompiler::new();
let form = compiler.compile_sentence(0, &predicates, &arguments, &sentences);
(form, compiler)
}
mod abstractions;
mod injection;
mod lowering;
mod modals;
mod regressions;
mod rel_clauses;
mod scoping;
mod terms_misc;