use crate::Formula;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Sequent {
pub linear: Vec<Formula>,
pub unrestricted: Vec<Formula>,
pub focus: Option<Formula>,
}
impl Sequent {
pub fn new(formulas: Vec<Formula>) -> Self {
Sequent {
linear: formulas,
unrestricted: vec![],
focus: None,
}
}
pub fn is_empty(&self) -> bool {
self.linear.is_empty() && self.focus.is_none()
}
pub fn focus_on(&self, idx: usize) -> Option<Sequent> {
if idx >= self.linear.len() {
return None;
}
let mut new_linear = self.linear.clone();
let focused = new_linear.remove(idx);
Some(Sequent {
linear: new_linear,
unrestricted: self.unrestricted.clone(),
focus: Some(focused),
})
}
pub fn unfocus(&self) -> Sequent {
let mut new_linear = self.linear.clone();
if let Some(f) = &self.focus {
new_linear.push(f.clone());
}
Sequent {
linear: new_linear,
unrestricted: self.unrestricted.clone(),
focus: None,
}
}
pub fn pretty(&self) -> String {
let formulas: Vec<String> = self.linear.iter().map(|f| f.pretty()).collect();
format!("⊢ {}", formulas.join(", "))
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TwoSidedSequent {
pub antecedent: Vec<Formula>,
pub succedent: Vec<Formula>,
}
impl TwoSidedSequent {
pub fn new(antecedent: Vec<Formula>, succedent: Vec<Formula>) -> Self {
TwoSidedSequent {
antecedent,
succedent,
}
}
pub fn to_one_sided(&self) -> Sequent {
let mut formulas: Vec<Formula> = self.antecedent.iter().map(|f| f.negate()).collect();
formulas.extend(self.succedent.clone());
Sequent::new(formulas)
}
pub fn pretty(&self) -> String {
let left: Vec<String> = self.antecedent.iter().map(|f| f.pretty()).collect();
let right: Vec<String> = self.succedent.iter().map(|f| f.pretty()).collect();
format!("{} ⊢ {}", left.join(", "), right.join(", "))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_two_sided_to_one_sided() {
let seq = TwoSidedSequent::new(
vec![Formula::Atom("A".to_string())],
vec![Formula::Atom("B".to_string())],
);
let one_sided = seq.to_one_sided();
assert_eq!(one_sided.linear.len(), 2);
assert_eq!(one_sided.linear[0], Formula::NegAtom("A".to_string()));
assert_eq!(one_sided.linear[1], Formula::Atom("B".to_string()));
}
#[test]
fn test_focus_unfocus() {
let seq = Sequent::new(vec![
Formula::Atom("A".to_string()),
Formula::Atom("B".to_string()),
]);
let focused = seq.focus_on(0).unwrap();
assert_eq!(focused.focus, Some(Formula::Atom("A".to_string())));
assert_eq!(focused.linear.len(), 1);
let unfocused = focused.unfocus();
assert_eq!(unfocused.linear.len(), 2);
assert!(unfocused.focus.is_none());
}
}