machine_check_common/iir/
property.rs1use std::collections::BTreeSet;
2
3use super::func::IFn;
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
8pub struct ISubpropertyFunc {
9 pub parent: Option<usize>,
10 pub func: IFn,
11 pub children: Vec<usize>,
12 pub dependencies: BTreeSet<usize>,
13 pub display: Option<String>,
14}
15
16#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub struct ISubpropertyNext {
18 pub parent: Option<usize>,
19 pub universal: bool,
20 pub inner: usize,
21 pub display: Option<String>,
22}
23
24#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
25pub struct ISubpropertyFixedPoint {
26 pub parent: Option<usize>,
27 pub universal: bool,
28 pub inner: usize,
29 pub dependents: Vec<usize>,
30 pub display: Option<String>,
31}
32
33#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
34pub enum ISubproperty {
35 Func(ISubpropertyFunc),
36 Next(ISubpropertyNext),
37 FixedPoint(ISubpropertyFixedPoint),
38}
39
40impl ISubproperty {
41 pub fn parent(&self) -> Option<usize> {
42 match self {
43 ISubproperty::Func(subproperty) => subproperty.parent,
44 ISubproperty::Next(subproperty) => subproperty.parent,
45 ISubproperty::FixedPoint(subproperty) => subproperty.parent,
46 }
47 }
48
49 pub fn children(&self) -> &[usize] {
50 match self {
51 ISubproperty::Func(subproperty) => &subproperty.children,
52 ISubproperty::Next(subproperty) => std::slice::from_ref(&subproperty.inner),
53 ISubproperty::FixedPoint(subproperty) => std::slice::from_ref(&subproperty.inner),
54 }
55 }
56
57 pub fn display_str(&self) -> Option<&str> {
58 match self {
59 ISubproperty::Func(subproperty) => subproperty.display.as_ref(),
60 ISubproperty::Next(subproperty) => subproperty.display.as_ref(),
61 ISubproperty::FixedPoint(subproperty) => subproperty.display.as_ref(),
62 }
63 .map(|v| v.as_str())
64 }
65}
66
67#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
68pub struct IProperty {
69 pub subproperties: Vec<ISubproperty>,
70}
71
72impl IProperty {
73 pub fn num_subproperties(&self) -> usize {
74 self.subproperties.len()
75 }
76
77 pub fn subproperty_entry(&self, index: usize) -> &ISubproperty {
78 &self.subproperties[index]
79 }
80
81 pub fn transition_depth(&self) -> usize {
82 let (open_number, max_closed_number) = self.subproperty_transition_depth(0);
83
84 open_number.max(max_closed_number)
85 }
86
87 fn subproperty_transition_depth(&self, subproperty_index: usize) -> (usize, usize) {
88 let subproperty = &self.subproperties[subproperty_index];
89 match subproperty {
90 ISubproperty::Func(subproperty) => {
91 let mut open_number = 0;
93 let mut max_closed_number = 0;
94
95 for child_index in subproperty.children.iter().cloned() {
96 let (candidate_open_number, candidate_max_closed_number) =
97 self.subproperty_transition_depth(child_index);
98
99 open_number = open_number.max(candidate_open_number);
100 max_closed_number = max_closed_number.max(candidate_max_closed_number);
101 }
102
103 (open_number, max_closed_number)
104 }
105 ISubproperty::Next(subproperty) => {
106 let (mut open_number, max_closed_number) =
108 self.subproperty_transition_depth(subproperty.inner);
109 open_number += 1;
110 (open_number, max_closed_number)
111 }
112 ISubproperty::FixedPoint(subproperty) => {
113 let (open_number, max_closed_number) =
115 self.subproperty_transition_depth(subproperty.inner);
116 let max_closed_number = max_closed_number.max(open_number);
117 (0, max_closed_number)
118 }
119 }
120 }
121
122 pub fn is_subproperty_closed_form(&self, subproperty_index: usize) -> bool {
123 let mut self_descendants = BTreeSet::new();
124 let mut dependencies = BTreeSet::new();
125
126 self.compute_self_descendants_and_dependencies(
127 subproperty_index,
128 &mut self_descendants,
129 &mut dependencies,
130 );
131 self_descendants == dependencies
132 }
133
134 fn compute_self_descendants_and_dependencies(
135 &self,
136 subproperty_index: usize,
137 self_descendants: &mut BTreeSet<usize>,
138 dependencies: &mut BTreeSet<usize>,
139 ) {
140 self_descendants.insert(subproperty_index);
141 dependencies.insert(subproperty_index);
142 let subproperty = &self.subproperties[subproperty_index];
143 match subproperty {
144 ISubproperty::Func(subproperty) => {
145 dependencies.extend(subproperty.dependencies.iter().cloned());
146 for child_index in subproperty.children.iter().cloned() {
147 self.compute_self_descendants_and_dependencies(
148 child_index,
149 self_descendants,
150 dependencies,
151 );
152 }
153 }
154 ISubproperty::Next(subproperty) => {
155 self.compute_self_descendants_and_dependencies(
156 subproperty.inner,
157 self_descendants,
158 dependencies,
159 );
160 }
161 ISubproperty::FixedPoint(subproperty) => {
162 self.compute_self_descendants_and_dependencies(
163 subproperty.inner,
164 self_descendants,
165 dependencies,
166 );
167 }
168 };
169 }
170}