argumentation/aspic/
rules.rs1use super::language::Literal;
4
5#[derive(Debug, Clone, PartialEq, Eq, Hash)]
7pub struct Rule {
8 pub id: RuleId,
10 pub premises: Vec<Literal>,
12 pub conclusion: Literal,
14 pub kind: RuleKind,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
20pub struct RuleId(pub usize);
21
22impl std::fmt::Display for RuleId {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 write!(f, "r{}", self.0)
25 }
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30pub enum RuleKind {
31 Strict,
33 Defeasible,
35}
36
37impl Rule {
38 pub fn strict(id: RuleId, premises: Vec<Literal>, conclusion: Literal) -> Self {
40 Self {
41 id,
42 premises,
43 conclusion,
44 kind: RuleKind::Strict,
45 }
46 }
47
48 pub fn defeasible(id: RuleId, premises: Vec<Literal>, conclusion: Literal) -> Self {
50 Self {
51 id,
52 premises,
53 conclusion,
54 kind: RuleKind::Defeasible,
55 }
56 }
57
58 pub fn is_defeasible(&self) -> bool {
60 matches!(self.kind, RuleKind::Defeasible)
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn strict_rule_is_not_defeasible() {
70 let r = Rule::strict(RuleId(0), vec![Literal::atom("p")], Literal::atom("q"));
71 assert!(!r.is_defeasible());
72 }
73
74 #[test]
75 fn defeasible_rule_is_defeasible() {
76 let r = Rule::defeasible(RuleId(1), vec![Literal::atom("p")], Literal::atom("q"));
77 assert!(r.is_defeasible());
78 }
79
80 #[test]
81 fn rule_id_displays_as_r_prefix() {
82 assert_eq!(format!("{}", RuleId(0)), "r0");
83 assert_eq!(format!("{}", RuleId(17)), "r17");
84 }
85}