use crate::language::{CompoundTerm, Statement, Term};
pub fn cast_compound(term: Term) -> CompoundTerm {
debug_assert!(
term.is_compound(),
"强制转换失败:词项\"{term}\"必须是复合词项"
);
term.try_into().expect("必定是复合词项")
}
pub fn cast_statement(term: Term) -> Statement {
debug_assert!(
term.is_statement(),
"强制转换失败:词项\"{term}\"必须是陈述"
);
term.try_into().expect("必定是陈述")
}
pub trait Opposite: Sized {
fn opposite(self) -> Self;
fn and_opposite(self) -> [Self; 2]
where
Self: Clone,
{
[self.clone(), self.opposite()]
}
}
pub trait Select {
fn select<T>(&self, left_right: [T; 2]) -> [T; 2];
fn select_one<T>(&self, left_right: [T; 2]) -> T {
let [selected, _] = self.select(left_right);
selected
}
fn select_another<T>(&self, left_right: [T; 2]) -> T {
let [_, selected] = self.select(left_right);
selected
}
}
impl Select for bool {
fn select<T>(&self, [false_side, true_side]: [T; 2]) -> [T; 2] {
match self {
true => [true_side, false_side],
false => [false_side, true_side],
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PremiseSource {
Task,
Belief,
}
impl Select for PremiseSource {
fn select<T>(&self, [task_thing, belief_thing]: [T; 2]) -> [T; 2] {
use PremiseSource::*;
match self {
Task => [task_thing, belief_thing],
Belief => [belief_thing, task_thing],
}
}
}
#[doc(alias = "SyllogismLocation")]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SyllogismPosition {
Subject = 0,
Predicate = 1,
}
impl Opposite for SyllogismPosition {
fn opposite(self) -> Self {
match self {
Subject => Predicate,
Predicate => Subject,
}
}
}
impl SyllogismPosition {
pub fn from_index(index: usize) -> Self {
match index {
0 => Subject,
1 => Predicate,
_ => panic!("无效索引"),
}
}
pub fn build_figure(self, other: Self) -> SyllogismFigure {
[self, other]
}
}
use SyllogismPosition::*;
impl Select for SyllogismPosition {
fn select<T>(&self, [subject, predicate]: [T; 2]) -> [T; 2] {
match self {
Subject => [subject, predicate],
Predicate => [predicate, subject],
}
}
}
pub type SyllogismFigure = [SyllogismPosition; 2];
impl Opposite for SyllogismFigure {
fn opposite(self) -> Self {
let [subject, predicate] = self;
[subject.opposite(), predicate.opposite()]
}
}
pub mod syllogistic_figures {
use super::*;
#[doc(alias = "SUBJECT_SUBJECT")]
pub const SS: SyllogismFigure = [Subject, Subject];
#[doc(alias = "SUBJECT_PREDICATE")]
pub const SP: SyllogismFigure = [Subject, Predicate];
#[doc(alias = "PREDICATE_SUBJECT")]
pub const PS: SyllogismFigure = [Predicate, Subject];
#[doc(alias = "PREDICATE_PREDICATE")]
pub const PP: SyllogismFigure = [Predicate, Predicate];
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SyllogismSide {
Subject = 0,
Predicate = 1,
Whole = -1,
}
impl SyllogismSide {
pub fn from_index(index: Option<usize>) -> Self {
use SyllogismSide::*;
match index {
Some(0) => Subject,
Some(1) => Predicate,
None => Whole,
_ => panic!("无效索引"),
}
}
pub fn select_exclusive(self, term: &Term) -> [Option<&Term>; 2] {
use SyllogismSide::*;
match (self, term.as_statement()) {
(Subject, Some(s)) => [Some(s.subject), Some(s.predicate)], (Predicate, Some(s)) => [Some(s.predicate), Some(s.subject)], (Whole, _) => [Some(term), None], _ => [None, None], }
}
}
impl From<SyllogismPosition> for SyllogismSide {
fn from(value: SyllogismPosition) -> Self {
match value {
Subject => Self::Subject,
Predicate => Self::Predicate,
}
}
}
impl Opposite for SyllogismSide {
fn opposite(self) -> Self {
use SyllogismSide::*;
match self {
Subject => Predicate,
Predicate => Subject,
Whole => Whole, }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Symmetry {
Symmetric = 0,
Asymmetric = 1,
}
use nar_dev_utils::asserts;
use Symmetry::*;
impl Opposite for Symmetry {
fn opposite(self) -> Self {
match self {
Symmetric => Asymmetric,
Asymmetric => Symmetric,
}
}
}
impl Select for Symmetry {
fn select<T>(&self, [left, right]: [T; 2]) -> [T; 2] {
match self {
Symmetric => [left, right],
Asymmetric => [right, left],
}
}
}
#[test]
fn test_opposite() {
asserts! {
Symmetric.opposite() => Asymmetric,
Asymmetric.opposite() => Symmetric,
}
}
#[test]
fn test_select() {
asserts! {
Symmetric.select([0, 1]) => [0, 1],
Asymmetric.select([0, 1]) => [1, 0],
Symmetric.select(["0", "1"]) => ["0", "1"],
Asymmetric.select(["0", "1"]) => ["1", "0"],
}
}
}