use super::compound_term::CompoundTermRef;
use crate::language::*;
use crate::symbols::*;
use nar_dev_utils::{if_return, matches_or};
use std::{
fmt::{Display, Formatter},
ops::{Deref, DerefMut},
};
impl Term {
#[inline(always)]
pub fn instanceof_statement(&self) -> bool {
Self::is_statement_identifier(self.identifier())
}
pub fn is_statement_identifier(identifier: &str) -> bool {
matches!(
identifier,
INHERITANCE_RELATION
| SIMILARITY_RELATION
| IMPLICATION_RELATION
| EQUIVALENCE_RELATION
| INSTANCE_RELATION
| PROPERTY_RELATION
| INSTANCE_PROPERTY_RELATION
)
}
#[inline(always)]
pub fn instanceof_inheritance(&self) -> bool {
self.identifier() == INHERITANCE_RELATION
}
#[inline(always)]
pub fn instanceof_similarity(&self) -> bool {
self.identifier() == SIMILARITY_RELATION
}
#[inline(always)]
pub fn instanceof_implication(&self) -> bool {
self.identifier() == IMPLICATION_RELATION
}
#[inline(always)]
pub fn instanceof_equivalence(&self) -> bool {
self.identifier() == EQUIVALENCE_RELATION
}
pub fn is_statement(&self) -> bool {
self.instanceof_statement()
&& matches!(self.components(), TermComponents::Compound(terms) if terms.len() == 2)
}
#[must_use]
pub fn as_statement(&self) -> Option<StatementRef> {
matches_or!(
?self.components(),
TermComponents::Compound(ref terms)
if self.instanceof_statement() && terms.len() == 2
=> StatementRef {
statement: self,
subject: &terms[0],
predicate: &terms[1],
}
)
}
#[must_use]
pub fn as_statement_type(&self, statement_class: impl AsRef<str>) -> Option<StatementRef> {
matches_or! {
?self.as_statement(),
Some(statement)
if statement_class.as_ref() == self.identifier()
=> statement
}
}
#[must_use]
pub fn as_statement_mut(&mut self) -> Option<StatementRefMut> {
matches_or!(
?self.components_mut(),
TermComponents::Compound(ref mut terms) if terms.len() == 2
=> StatementRefMut {
subject: &mut terms[0] as *mut Term,
predicate: &mut terms[1] as *mut Term,
statement: self,
}
)
}
#[must_use]
pub fn unwrap_statement_components(self) -> Option<[Term; 2]> {
matches_or! {
?self.unwrap_compound_components(),
Some(terms) if terms.len() == 2
=> {
let mut terms = terms.into_vec();
let predicate = terms.pop().expect("已经假定了长度为2");
let subject = terms.pop().expect("已经假定了长度为2");
[subject, predicate]
}
}
}
#[must_use]
pub fn unwrap_statement_id_components(self) -> Option<(Term, String, Term)> {
matches_or! {
?self.unwrap_compound_id_components(),
Some((copula, terms)) if terms.len() == 2
=> {
let mut terms = terms.into_vec();
let predicate = terms.pop().expect("已经假定了长度为2");
let subject = terms.pop().expect("已经假定了长度为2");
(subject, copula, predicate)
}
}
}
#[must_use]
pub fn unwrap_statement_type_components(
self,
statement_class: impl AsRef<str>,
) -> Option<[Term; 2]> {
matches_or! {
?self.unwrap_compound_type_components(statement_class),
Some(terms) if terms.len() == 2
=> {
let mut terms = terms.into_vec();
let predicate = terms.pop().expect("已经假定了长度为2");
let subject = terms.pop().expect("已经假定了长度为2");
[subject, predicate]
}
}
}
}
impl<'s> CompoundTermRef<'s> {
pub fn is_statement(&self) -> bool {
self.components.len() == 2
}
pub fn as_statement(self) -> Option<StatementRef<'s>> {
matches_or!(
?self.components,
[ref subject, ref predicate]
=> StatementRef {
statement: self.inner,
subject,
predicate,
}
)
}
}
impl CompoundTermRefMut<'_> {
pub fn as_statement(&mut self) -> Option<StatementRef> {
matches_or!(
? unsafe { &mut *self.components },
[ref mut subject, ref mut predicate]
=> StatementRef {
statement: self.inner,
subject,
predicate,
}
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StatementRef<'a> {
pub statement: &'a Term,
pub subject: &'a Term,
pub predicate: &'a Term,
}
impl<'s> StatementRef<'s> {
pub fn subject(&self) -> &'s Term {
self.subject
}
pub fn predicate(&self) -> &'s Term {
self.predicate
}
pub fn sub_pre(&self) -> [&'s Term; 2] {
[self.subject, self.predicate]
}
pub fn invalid_statement(subject: &Term, predicate: &Term) -> bool {
if_return! {
subject == predicate => true
Self::invalid_reflexive(subject, predicate) => true
Self::invalid_reflexive(predicate, subject) => true
}
matches_or! {
(subject.as_statement(), predicate.as_statement()),
(
Some(StatementRef { subject:ss, predicate:sp,.. }),
Some(StatementRef { subject:ps, predicate:pp,.. })
) if ss == pp && sp == ps => return true,
() }
false
}
pub fn invalid_reflexive(may_container: &Term, may_component: &Term) -> bool {
if let Some(compound) = may_container.as_compound() {
if_return! {
compound.inner.instanceof_image() => false
}
return compound.contain_component(may_component);
}
false
}
pub fn invalid_pair(subject: &Term, predicate: &Term) -> bool {
subject.contain_var_i() != predicate.contain_var_i()
}
pub fn invalid(&self) -> bool {
Self::invalid_statement(self.subject(), self.predicate())
}
pub fn as_conditional(self) -> Option<(StatementRef<'s>, CompoundTermRef<'s>)> {
if !self.instanceof_implication() {
return None;
}
let subject_conjunction = self.subject.as_compound_type(CONJUNCTION_OPERATOR)?;
Some((self, subject_conjunction))
}
pub fn into_compound_ref(self) -> CompoundTermRef<'s> {
debug_assert!(self.is_statement());
unsafe { self.statement.as_compound_unchecked() }
}
}
impl Display for StatementRef<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.statement.fmt(f)
}
}
impl Deref for StatementRef<'_> {
type Target = Term;
fn deref(&self) -> &Self::Target {
self.statement
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StatementRefMut<'a> {
statement: &'a mut Term,
subject: *mut Term,
predicate: *mut Term,
}
impl<'a> StatementRefMut<'a> {
#[doc(alias = "inner")]
pub fn statement(self) -> &'a mut Term {
self.statement
}
pub fn sub_pre(&mut self) -> [&'a mut Term; 2] {
unsafe { [&mut *self.subject, &mut *self.predicate] }
}
pub fn subject(&mut self) -> &'a mut Term {
let [sub, _] = self.sub_pre();
sub
}
pub fn predicate(&mut self) -> &'a mut Term {
let [_, pre] = self.sub_pre();
pre
}
pub fn into_ref<'s>(self) -> StatementRef<'s>
where
Self: 's,
{
debug_assert!(self.statement.is_statement());
StatementRef {
statement: self.statement,
subject: unsafe { &*self.subject },
predicate: unsafe { &*self.predicate },
}
}
pub fn into_compound_ref<'s>(self) -> CompoundTermRefMut<'s>
where
Self: 's,
{
debug_assert!(self.is_statement());
unsafe { self.statement.as_compound_mut_unchecked() }
}
}
impl Display for StatementRefMut<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.statement.fmt(f)
}
}
impl<'s> From<StatementRefMut<'s>> for StatementRef<'s> {
#[inline]
fn from(r: StatementRefMut<'s>) -> Self {
r.into_ref()
}
}
impl<'s> From<StatementRefMut<'s>> for CompoundTermRefMut<'s> {
#[inline]
fn from(r: StatementRefMut<'s>) -> Self {
r.into_compound_ref()
}
}
impl Deref for StatementRefMut<'_> {
type Target = Term;
fn deref(&self) -> &Self::Target {
self.statement
}
}
impl DerefMut for StatementRefMut<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.statement
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Statement {
term: Term,
}
impl Statement {
pub fn get_ref(&self) -> StatementRef {
self.term.as_statement().unwrap()
}
pub fn mut_ref(&mut self) -> StatementRefMut {
self.term.as_statement_mut().unwrap()
}
pub fn sub_pre(&self) -> [&Term; 2] {
let StatementRef {
subject, predicate, ..
} = self.get_ref();
[subject, predicate]
}
pub fn sub_pre_mut(&mut self) -> [&mut Term; 2] {
self.mut_ref().sub_pre()
}
pub fn unwrap_components(self) -> [Term; 2] {
self.term.unwrap_statement_components().unwrap()
}
pub fn unwrap(self) -> (Term, String, Term) {
self.term.unwrap_statement_id_components().unwrap()
}
}
impl TryFrom<Term> for Statement {
type Error = Term;
fn try_from(term: Term) -> Result<Self, Self::Error> {
match term.is_statement() {
true => Ok(Self { term }),
false => Err(term),
}
}
}
impl From<Statement> for Term {
fn from(value: Statement) -> Self {
value.term
}
}
impl Deref for Statement {
type Target = Term;
fn deref(&self) -> &Self::Target {
&self.term
}
}
impl DerefMut for Statement {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.term
}
}
impl Display for Statement {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.term.fmt(f)
}
}
impl StatementRef<'_> {
pub fn to_owned(&self) -> Statement {
debug_assert!(self.statement.is_statement()); Statement {
term: self.statement.clone(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_term as term;
use crate::{ok, util::AResult};
use nar_dev_utils::{asserts, macro_once};
macro_rules! statement {
(box $term:literal) => {
statement!(box term!($term))
};
(box $term:expr) => {
Statement::try_from($term).unwrap()
};
(mut $term:literal) => {
statement!(mut term!($term))
};
(mut $term:expr) => {
$term.as_statement_mut().unwrap()
};
(unwrap $term:literal) => {
statement!(term!(unwrap $term))
};
($term:literal) => {
statement!(term!($term))
};
($term:expr) => {
$term.as_statement().unwrap()
};
}
mod statement_ref {
use super::*;
use nar_dev_utils::fail_tests;
#[test]
fn invalid() -> AResult {
asserts! {
!statement!("<A --> B>").invalid()
!statement!("<A --> [B]>").invalid()
!statement!("<[A] --> B>").invalid()
!statement!("<<A --> B> ==> <B --> C>>").invalid()
!statement!("<<A --> B> ==> <C --> A>>").invalid()
!statement!("<<A --> B> ==> <C --> D>>").invalid()
}
ok!()
}
fail_tests! {
invalid_非陈述词项 statement!(unwrap "(*, A, B)"); invalid_重言式 term!(unwrap "<A --> A>");
invalid_被包含的重言式_主项包含谓项 term!(unwrap "<[A] --> A>");
invalid_被包含的重言式_谓项包含主项 term!(unwrap "<A --> [A]>");
invalid_蕴含重言式 term!(unwrap "<<A --> B> ==> <B --> A>>");
}
#[test]
fn subject_predicate() -> AResult {
macro_once! {
macro test($($statement:expr => [$subject:literal, $predicate:literal])*) {
asserts! {$(
statement!($statement).subject() => &term!($subject)
statement!($statement).predicate() => &term!($predicate)
)*}
}
"<A --> B>" => ["A", "B"]
"<あ ==> α>" => ["あ", "α"]
"<{SELF} --> [good]>" => ["{SELF}", "[good]"]
"<<a --> b> ==> {C}>" => ["<a --> b>", "{C}"]
"<$1 --> [2]>" => ["$1", "[2]"] "<#2 --> {1}>" => ["#2", "{1}"] "<(*, 1, 2, 3) ==> 4>" => ["(*, 1, 2, 3)", "4"]
"<A {-- B>" => ["{A}", "B"]
"<A --] B>" => [ "A", "[B]"]
"<A {-] B>" => ["{A}", "[B]"]
}
ok!()
}
}
mod statement_ref_mut {
use super::*;
#[test]
fn subject_predicate() -> AResult {
macro_once! {
macro test($($statement:expr => [$subject:literal, $predicate:literal])*) {
asserts! {$(
statement!(mut $statement).subject() => &term!($subject)
statement!(mut $statement).predicate() => &term!($predicate)
)*}
}
"<A --> B>" => ["A", "B"]
"<あ ==> α>" => ["あ", "α"]
"<{SELF} --> [good]>" => ["{SELF}", "[good]"]
"<<a --> b> ==> {C}>" => ["<a --> b>", "{C}"]
"<$1 --> [2]>" => ["$1", "[2]"] "<#2 --> {1}>" => ["#2", "{1}"] "<(*, 1, 2, 3) ==> 4>" => ["(*, 1, 2, 3)", "4"]
"<A {-- B>" => ["{A}", "B"]
"<A --] B>" => [ "A", "[B]"]
"<A {-] B>" => ["{A}", "[B]"]
}
ok!()
}
#[test]
fn to_ref() -> AResult {
fn test(mut term: Term) {
if !term.is_statement() {
return;
}
let mut statement = term.as_statement_mut().expect("是陈述了还转换失败");
assert!(!statement.as_statement().unwrap().invalid());
let (id, _) = statement.subject().id_comp_mut();
*id = "".into();
let statement = statement.into_ref();
assert!(!statement.invalid());
}
macro_once! {
macro test($($term:expr)*) {
$(test(term!($term));)*
}
"A"
"A"
}
ok!()
}
}
mod statement {
use super::*;
use std::str::FromStr;
#[test]
fn from_into() -> AResult {
fn test(compound: Statement) {
assert!(compound.is_compound());
let term: Term = (*compound).clone();
let _: Statement = term.try_into().expect("应该是陈述!");
let term: Term = compound.into();
let _: Statement = term.try_into().expect("应该是陈述!");
}
macro_once! {
macro test($( $term:literal )*) {$(
test(statement!(box $term));
)*}
"<A --> B>"
"<A <-> B>"
"<A ==> B>"
"<A <=> B>"
"<(*, A, B) --> P>"
"<(*, A, B) <-> P>"
"<(*, A, B) ==> P>"
"<(*, A, B) <=> P>"
"<S --> (*, A, B)>"
"<S <-> (*, A, B)>"
"<S ==> (*, A, B)>"
"<S <=> (*, A, B)>"
"<X --> <A ==> B>>"
"<X <-> <A <=> B>>"
"<<A --> B> ==> X>"
"<<A <-> B> <=> X>"
"<<A ==> B> --> <C ==> D>>"
"<<A <=> B> <-> <C <=> D>>"
"<<A --> B> ==> <C --> D>>"
"<<A <-> B> <=> <C <-> D>>"
r"<(/, R, A, _) --> (\, R, _, B)>"
r"<(/, R, A, _) <-> (\, R, _, B)>"
r"<(/, R, A, _) ==> (\, R, _, B)>"
r"<(/, R, A, _) <=> (\, R, _, B)>"
}
ok!()
}
#[test]
fn get_ref() -> AResult {
fn test(statement: Statement) {
assert!(statement.is_compound());
let ref_statement = statement.get_ref();
let subject = ref_statement.subject();
let predicate = ref_statement.predicate();
println!("{statement} => [{subject}, {predicate}]");
statement
.get_ref()
.components()
.iter()
.enumerate()
.for_each(|(i, component)| println!(" [{i}] => {component}"))
}
macro_once! {
macro test($( $term:literal )*) {$(
test(statement!(box $term));
)*}
"<A --> B>"
"<A <-> B>"
"<A ==> B>"
"<A <=> B>"
"<(*, A, B) --> P>"
"<(*, A, B) <-> P>"
"<(*, A, B) ==> P>"
"<(*, A, B) <=> P>"
"<S --> (*, A, B)>"
"<S <-> (*, A, B)>"
"<S ==> (*, A, B)>"
"<S <=> (*, A, B)>"
"<X --> <A ==> B>>"
"<X <-> <A <=> B>>"
"<<A --> B> ==> X>"
"<<A <-> B> <=> X>"
"<<A ==> B> --> <C ==> D>>"
"<<A <=> B> <-> <C <=> D>>"
"<<A --> B> ==> <C --> D>>"
"<<A <-> B> <=> <C <-> D>>"
r"<(/, R, A, _) --> (\, R, _, B)>"
r"<(/, R, A, _) <-> (\, R, _, B)>"
r"<(/, R, A, _) ==> (\, R, _, B)>"
r"<(/, R, A, _) <=> (\, R, _, B)>"
}
ok!()
}
#[test]
fn mut_ref() -> AResult {
fn test(mut statement: Statement) -> AResult {
assert!(statement.is_compound());
let old_s = statement.to_string();
let mut mut_ref = statement.mut_ref();
let subject = mut_ref.subject();
let x = term!("X");
*subject = x.clone();
println!("modification: {old_s:?} => \"{statement}\"");
assert_eq!(*statement.get_ref().subject(), x);
let old_s = statement.to_string();
let mut mut_ref = statement.mut_ref();
let predicate = mut_ref.predicate();
let y = term!("Y");
*predicate = y.clone();
println!("modification: {old_s:?} => \"{statement}\"");
assert_eq!(*statement.get_ref().predicate(), y);
statement
.mut_ref()
.into_compound_ref()
.components()
.iter_mut()
.enumerate()
.for_each(|(i, component)| {
*component = Term::from_str(&format!("T{i}")).unwrap()
});
print!(" => \"{statement}\"");
ok!()
}
macro_once! {
macro test($( $term:literal )*) {$(
test(statement!(box $term))?;
)*}
"<A --> B>"
"<A <-> B>"
"<A ==> B>"
"<A <=> B>"
"<(*, A, B) --> P>"
"<(*, A, B) <-> P>"
"<(*, A, B) ==> P>"
"<(*, A, B) <=> P>"
"<S --> (*, A, B)>"
"<S <-> (*, A, B)>"
"<S ==> (*, A, B)>"
"<S <=> (*, A, B)>"
"<X --> <A ==> B>>"
"<X <-> <A <=> B>>"
"<<A --> B> ==> X>"
"<<A <-> B> <=> X>"
"<<A ==> B> --> <C ==> D>>"
"<<A <=> B> <-> <C <=> D>>"
"<<A --> B> ==> <C --> D>>"
"<<A <-> B> <=> <C <-> D>>"
r"<(/, R, A, _) --> (\, R, _, B)>"
r"<(/, R, A, _) <-> (\, R, _, B)>"
r"<(/, R, A, _) ==> (\, R, _, B)>"
r"<(/, R, A, _) <=> (\, R, _, B)>"
}
ok!()
}
}
}