1use core::{convert::TryFrom, fmt, mem};
5use alloc::boxed::Box;
6use hashbrown::HashMap;
7
8#[deny(clippy::unwrap_used)]
9#[deny(clippy::expect_used)]
10#[deny(clippy::panic)]
11#[allow(clippy::empty_line_after_outer_attr)]
12
13pub type ID = usize;
17pub type ZtaFn = for<'a> fn(inp: &'a mut Kind) -> Result<Kind, &'a mut Kind>;
18
19#[derive(Clone)]
20pub enum Kind {
21 Alp {id: ID},
22 Zta {sid: Option<ID>, hid: ID, fnc: ZtaFn},
23 Pir {l: Box<Kind>, r: Box<Kind>}
24}
25impl From<ID> for Kind {
26 fn from(val: ID) -> Self {
27 Self::Alp {id: val}
28 }
29}
30impl TryFrom<(ZtaFn, ID)> for Kind {
31 type Error = ();
32 fn try_from(val: (ZtaFn, ID)) -> Result<Self, Self::Error> {
33 if val.1 < 2 { return Err(()) }
34 Ok(Self::Zta {sid: None, hid: val.1, fnc: val.0})
35 }
36}
37impl From<(Kind, Kind)> for Kind {
38 fn from(val: (Kind, Kind)) -> Self {
39 Self::Pir {l: Box::new(val.0), r: Box::new(val.1)}
40 }
41}
42impl fmt::Debug for Kind {
43 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
44 match self {
45 Kind::Alp { id } => write!(f, "I:{id}"),
46 Kind::Zta { sid, hid, ..} => match sid {
47 Some(id) => write!(f, "Z:{hid}:{id}"),
48 None => write!(f, "Z:{hid}"),
49 },
50 Kind::Pir { l, r } => write!(f, "({l:?} {r:?})"),
51 }
52 }
53}
54
55struct MapIDK {
59 map: HashMap<ID, Option<Kind>>
60}
61impl MapIDK {
62 fn new() -> Self { Self {map: HashMap::new()} }
63 fn get(&mut self, id: ID) -> Option<Kind> {
64 self.map.get_mut(&id).and_then(|k| k.take())
65 }
66 fn set(&mut self, id: ID, v: Kind) {
67 self.map.insert(id, Some(v));
68 }
69}
70
71struct Mtc {
75 map: MapIDK
76}
77impl Mtc {
78 fn new() -> Self { Self { map: MapIDK::new() } }
79 fn alp(&mut self, x: &mut Kind, n: &mut Kind) -> bool {
80 match n {
81 Kind::Alp { id } => match self.map.get(*id) {
82 Some(mut ol) => {
83 if self.mtc(x, &mut ol) {
84 self.map.set(*id, ol); return true
86 }
87 false
89 },
90 None => {
91 let mut k = x.clone();
92 if let Kind::Zta { sid, ..} = &mut k {
93 *sid = Some(*id);
94 }
95
96 self.map.set(*id, k);
97 true
98 },
99 },
100 _ => false
101 }
102 }
103 fn zta(&mut self, x: &mut Kind, n: &mut Kind) -> bool {
104 match x {
105 Kind::Pir { l: mz, r: inp } => match mz.as_mut() {
106 Kind::Zta {fnc, ..}
107 => match fnc(inp) {
108 Ok(xr) => {
109 *x = xr;
110 self.mtc(x, n)
111 },
112 Err(_) => false,
113 },
114 _ => false
115 },
116 _ => false
117 }
118 }
119 fn rec(&mut self, x: &mut Kind, n: &mut Kind) -> bool {
120 match (x, n) {
121 (
122 Kind::Zta {hid: xid, ..},
123 Kind::Zta {hid: nid, ..}
124 ) => {xid == nid},
125 (
126 Kind::Pir {l: xl, r: xr},
127 Kind::Pir {l: nl, r: nr}
128 ) => {
129 if !self.mtc(xl, nl) {return false}
130 self.mtc(xr, nr)
131 },
132 _ => false
133 }
134 }
135 fn mtc(&mut self, x: &mut Kind, n: &mut Kind) -> bool {
136 if self.alp(x, n) {return true}
137 if self.rec(x, n) {return true}
138 self.zta(x, n)
139 }
140 fn ins(&mut self, b: &mut Kind) {
141 match b {
142 Kind::Alp {id} => match self.map.get(*id) {
143 Some(k) => {
144 self.map.set(*id, k.clone()); *b = k
146 },
147 None => (),
148 },
149 Kind::Pir {l, r} => {
150 self.ins(l);
151 self.ins(r)
152 },
153 _ => ()
154 }
155 }
156}
157
158pub fn eta<'a>(inp: &'a mut Kind) -> Result<Kind, &'a mut Kind> {
162 let (n, b, x) = match inp {
163 Kind::Pir {l: nb, r: x} => {
164 match nb.as_mut() {
165 Kind::Pir {l: n, r: b} => (n, b, x),
166 _ => return Err(inp)
167 }
168 },
169 _ => return Err(inp)
170 };
171
172 let mut mt = Mtc::new();
173 if !mt.mtc(x, n) {return Err(inp)}
174 mt.ins(b);
175
176 let bb = mem::replace(b, Box::new(new_omi_kind()));
178
179 Ok(*bb)
180}
181
182pub fn omi<'a>(inp: &'a mut Kind) -> Result<Kind, &'a mut Kind> { Err(inp) }
184
185pub fn new_eta_kind() -> Kind { Kind::Zta {sid:None, hid:1, fnc:eta} }
186pub fn new_omi_kind() -> Kind { Kind::Zta {sid:None, hid:0, fnc:omi} }
187
188pub fn lore(end: Kind) -> Kind {
192 Kind::from((
193 Kind::from((new_omi_kind(), new_omi_kind())),
194 Kind::from((new_eta_kind(), end))
195 ))
196}
197
198pub fn lore_end() -> Kind {
199 Kind::from((
200 new_eta_kind(),
201 Kind::from((
202 Kind::from((new_omi_kind(), new_omi_kind())),
203 new_eta_kind()
204 ))
205 ))
206}
207
208