Skip to main content

rstm_core/programs/traits/
ruleset.rs

1/*
2    Appellation: instruction_set <module>
3    Created At: 2026.01.11:12:29:41
4    Contrib: @FL03
5*/
6use crate::rules::{Head, Instruction, InstructionMut, Rule, Tail};
7use rstm_state::{RawState, State};
8
9/// The [`RawRuleset`] trait establishes an interface common to all compatible sets of rules for
10/// the framework.
11pub trait RawRuleset<Q, A>
12where
13    Q: RawState,
14{
15    type Rule: Instruction<Q, A>;
16
17    private! {}
18
19    fn len(&self) -> usize;
20
21    fn is_empty(&self) -> bool {
22        self.len() == 0
23    }
24}
25
26pub trait Ruleset<Q, A>: RawRuleset<Q, A>
27where
28    Q: RawState,
29    Self::Rule: Instruction<Q, A, Head = Head<Q, A>, Tail = Tail<Q, A>>,
30{
31
32    fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>>;
33    
34    fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>>;
35
36    fn find_head(&self, Head { state, symbol }: Head<&Q, &A>) -> Option<&Tail<Q, A>> {
37        self.find_tail(state, symbol)
38    }
39}
40
41pub trait RuleSetMut<Q, A>: RawRuleset<Q, A>
42where
43    Q: RawState,
44    Self::Rule: Instruction<Q, A, Head = Head<Q, A>, Tail = Tail<Q, A>>,
45{
46    fn get_mut(&mut self, head: &Head<Q, A>) -> Option<&mut Tail<Q, A>>;
47}
48/*
49 ************* Implementations *************
50*/
51
52impl<R, I, Q, A> RawRuleset<Q, A> for &R
53where
54    I: Instruction<Q, A>,
55    Q: RawState,
56    R: RawRuleset<Q, A, Rule = I>,
57{
58    type Rule = R::Rule;
59
60    seal! {}
61
62    fn len(&self) -> usize {
63        (*self).len()
64    }
65}
66
67macro_rules! get_tail {
68    ($iter:expr, $head:expr) => {
69        $iter.find_map(|i| {
70            if i.head().state() == $head.state() && i.head().symbol() == $head.symbol() {
71                Some(i.tail())
72            } else {
73                None
74            }
75        })
76    };
77}
78
79macro_rules! find_tail {
80    ($iter:expr, ($state:expr, $sym:expr)) => {
81        $iter.find_map(|i| {
82            if i.head().state().view() == $state && i.head().symbol() == $sym {
83                Some(i.tail())
84            } else {
85                None
86            }
87        })
88    };
89}
90
91impl<I, Q, A> RawRuleset<Q, A> for [I]
92where
93    Q: RawState,
94    I: Instruction<Q, A>,
95{
96    type Rule = I;
97
98    seal! {}
99
100    fn len(&self) -> usize {
101        <[I]>::len(self)
102    }
103
104    fn is_empty(&self) -> bool {
105        <[I]>::is_empty(self)
106    }
107}
108
109impl<I, Q, A> Ruleset<Q, A> for [I]
110where
111    Q: RawState + PartialEq,
112    A: PartialEq,
113    I: Instruction<Q, A, Head = Head<Q, A>, Tail = Tail<Q, A>>,
114{
115    fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>> {
116        get_tail!(self.iter(), head)
117    }
118
119    fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>> {
120        find_tail!(self.iter(), (state, sym))
121    }
122}
123impl<I, Q, A> RawRuleset<Q, A> for &[I]
124where
125    Q: RawState,
126    I: Instruction<Q, A>,
127{
128    type Rule = I;
129
130    seal! {}
131
132    fn len(&self) -> usize {
133        <[I]>::len(self)
134    }
135
136    fn is_empty(&self) -> bool {
137        <[I]>::is_empty(self)
138    }
139}
140
141impl<I, Q, A> Ruleset<Q, A> for &[I]
142where
143    Q: RawState + PartialEq,
144    A: PartialEq,
145    I: Instruction<Q, A, Head = Head<Q, A>, Tail = Tail<Q, A>>,
146{
147    fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>> {
148        get_tail!(self.iter(), head)
149    }
150
151    fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>> {
152        find_tail!(self.iter(), (state, sym))
153    }
154}
155
156impl<I, Q, A> RawRuleset<Q, A> for &mut [I]
157where
158    Q: RawState,
159    I: Instruction<Q, A>,
160{
161    type Rule = I;
162
163    seal! {}
164
165    fn len(&self) -> usize {
166        <[I]>::len(self)
167    }
168
169    fn is_empty(&self) -> bool {
170        <[I]>::is_empty(self)
171    }
172}
173
174impl<I, Q, A> Ruleset<Q, A> for &mut [I]
175where
176    Q: RawState + PartialEq,
177    A: PartialEq,
178    I: Instruction<Q, A, Head = Head<Q, A>, Tail = Tail<Q, A>>,
179{
180    fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>> {
181        get_tail!(self.iter(), head)
182    }
183
184    fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>> {
185        find_tail!(self.iter(), (state, sym))
186    }
187}
188
189impl<I, Q, A> RuleSetMut<Q, A> for &mut [I]
190where
191    Q: RawState + PartialEq,
192    A: PartialEq,
193    I: InstructionMut<Q, A, Head = Head<Q, A>, Tail = Tail<Q, A>>,
194{
195    fn get_mut(&mut self, head: &Head<Q, A>) -> Option<&mut Tail<Q, A>> {
196        self.iter_mut().find_map(|i| {
197            if i.head() == head {
198                Some(i.tail_mut())
199            } else {
200                None
201            }
202        })
203    }
204}
205
206impl<const N: usize, I, Q, A> RawRuleset<Q, A> for [I; N]
207where
208    Q: RawState,
209    I: Instruction<Q, A>,
210{
211    type Rule = I;
212
213    seal! {}
214
215    fn len(&self) -> usize {
216        <[I]>::len(self)
217    }
218
219    fn is_empty(&self) -> bool {
220        <[I]>::is_empty(self)
221    }
222}
223
224impl<const N: usize, I, Q, A> Ruleset<Q, A> for [I; N]
225where
226    Q: RawState + PartialEq,
227    A: PartialEq,
228    I: Instruction<Q, A, Head = Head<Q, A>, Tail = Tail<Q, A>>,
229{
230    fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>> {
231        get_tail!(self.iter(), head)
232    }
233
234    fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>> {
235        find_tail!(self.iter(), (state, sym))
236    }
237}
238
239#[cfg(feature = "alloc")]
240mod impl_alloc {
241    use super::{RawRuleset, Ruleset};
242    use crate::{Head, Instruction, Rule, Tail};
243    use alloc::collections::{BTreeMap, BTreeSet};
244    use alloc::vec::Vec;
245    use rstm_state::{RawState, State};
246
247    impl<I, Q, A> RawRuleset<Q, A> for Vec<I>
248    where
249        Q: RawState,
250        I: Instruction<Q, A>,
251    {
252        type Rule = I;
253
254        seal! {}
255
256        fn len(&self) -> usize {
257            <Vec<I>>::len(self)
258        }
259
260        fn is_empty(&self) -> bool {
261            <Vec<I>>::is_empty(self)
262        }
263    }
264
265    impl<I, Q, A> Ruleset<Q, A> for Vec<I>
266    where
267        Q: RawState + PartialEq,
268        A: PartialEq,
269        I: Instruction<Q, A, Head = Head<Q, A>, Tail = Tail<Q, A>>,
270    {
271        fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>> {
272            get_tail!(self.iter(), head)
273        }
274
275        fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>> {
276            find_tail!(self.iter(), (state, sym))
277        }
278    }
279
280    impl<I, Q, A> RawRuleset<Q, A> for BTreeSet<I>
281    where
282        Q: RawState,
283        I: Instruction<Q, A>,
284    {
285        type Rule = I;
286
287        seal! {}
288
289        fn len(&self) -> usize {
290            <BTreeSet<I>>::len(self)
291        }
292
293        fn is_empty(&self) -> bool {
294            <BTreeSet<I>>::is_empty(self)
295        }
296    }
297
298    impl<I, Q, A> Ruleset<Q, A> for BTreeSet<I>
299    where
300        Q: RawState + PartialEq,
301        A: PartialEq,
302        I: Instruction<Q, A, Head = Head<Q, A>, Tail = Tail<Q, A>>,
303    {
304        fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>> {
305            get_tail!(self.iter(), head)
306        }
307
308        fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>> {
309            find_tail!(self.iter(), (state, sym))
310        }
311    }
312
313    impl<Q, A> RawRuleset<Q, A> for BTreeMap<Head<Q, A>, Tail<Q, A>>
314    where
315        Q: RawState + Ord,
316        A: Ord,
317    {
318        type Rule = Rule<Q, A>;
319
320        seal! {}
321
322        fn len(&self) -> usize {
323            <BTreeMap<Head<Q, A>, Tail<Q, A>>>::len(self)
324        }
325
326        fn is_empty(&self) -> bool {
327            <BTreeMap<Head<Q, A>, Tail<Q, A>>>::is_empty(self)
328        }
329    }
330
331    impl<Q, A> Ruleset<Q, A> for BTreeMap<Head<Q, A>, Tail<Q, A>>
332    where
333        Q: RawState + Ord,
334        A: Ord,
335    {
336        fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>> {
337            self.get(head)
338        }
339
340        fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>> {
341            self.iter().find_map(|(h, t)| {
342                if h.state().view() == state && h.symbol() == sym {
343                    Some(t)
344                } else {
345                    None
346                }
347            })
348        }
349    }
350}
351
352#[cfg(feature = "hashbrown")]
353mod impl_hashbrown {
354    use super::*;
355    use core::hash::Hash;
356    use hashbrown::{HashMap, HashSet};
357
358    impl<I, Q, A> RawRuleset<Q, A> for HashSet<I>
359    where
360        I: Instruction<Q, A>,
361        Q: RawState + Eq + Hash,
362        A: Eq + Hash,
363    {
364        type Rule = Rule<Q, A>;
365
366        seal! {}
367
368        fn len(&self) -> usize {
369            <HashSet<I>>::len(self)
370        }
371
372        fn is_empty(&self) -> bool {
373            <HashSet<I>>::is_empty(self)
374        }
375    }
376
377    impl<Q, A> Ruleset<Q, A> for HashSet<Rule<Q, A>>
378    where
379        Q: RawState + Eq + Hash,
380        A: Eq + Hash,
381    {
382        fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>> {
383            get_tail!(self.iter(), head)
384        }
385
386        fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>> {
387            find_tail!(self.iter(), (state, sym))
388        }
389    }
390
391    impl<Q, A> RawRuleset<Q, A> for HashMap<Head<Q, A>, Tail<Q, A>>
392    where
393        Q: RawState + Eq + Hash,
394        A: Eq + Hash,
395    {
396        type Rule = Rule<Q, A>;
397
398        seal! {}
399
400        fn len(&self) -> usize {
401            <HashMap<Head<Q, A>, Tail<Q, A>>>::len(self)
402        }
403
404        fn is_empty(&self) -> bool {
405            <HashMap<Head<Q, A>, Tail<Q, A>>>::is_empty(self)
406        }
407    }
408
409    impl<Q, A> Ruleset<Q, A> for HashMap<Head<Q, A>, Tail<Q, A>>
410    where
411        Q: RawState + Eq + Hash,
412        A: Eq + Hash,
413    {
414        fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>> {
415            self.get(head)
416        }
417
418        fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>> {
419            self.iter().find_map(|(h, t)| {
420                if h.state().view() == state && h.symbol() == sym {
421                    Some(t)
422                } else {
423                    None
424                }
425            })
426        }
427    }
428}
429
430#[cfg(feature = "std")]
431mod impl_std {
432    use super::*;
433    use core::hash::Hash;
434    use std::collections::{HashMap, HashSet};
435
436    impl<I, Q, A> RawRuleset<Q, A> for HashSet<I>
437    where
438        I: Instruction<Q, A>,
439        Q: RawState + Eq + Hash,
440        A: Eq + Hash,
441    {
442        type Rule = Rule<Q, A>;
443
444        seal! {}
445
446        fn len(&self) -> usize {
447            <HashSet<I>>::len(self)
448        }
449
450        fn is_empty(&self) -> bool {
451            <HashSet<I>>::is_empty(self)
452        }
453    }
454
455    impl<Q, A> Ruleset<Q, A> for HashSet<Rule<Q, A>>
456    where
457        Q: RawState + Eq + Hash,
458        A: Eq + Hash,
459    {
460        fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>> {
461            get_tail!(self.iter(), head)
462        }
463
464        fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>> {
465            find_tail!(self.iter(), (state, sym))
466        }
467    }
468
469    impl<Q, A> RawRuleset<Q, A> for HashMap<Head<Q, A>, Tail<Q, A>>
470    where
471        Q: RawState + Eq + Hash,
472        A: Eq + Hash,
473    {
474        type Rule = Rule<Q, A>;
475
476        seal! {}
477
478        fn len(&self) -> usize {
479            <HashMap<Head<Q, A>, Tail<Q, A>>>::len(self)
480        }
481
482        fn is_empty(&self) -> bool {
483            <HashMap<Head<Q, A>, Tail<Q, A>>>::is_empty(self)
484        }
485    }
486
487    impl<Q, A> Ruleset<Q, A> for HashMap<Head<Q, A>, Tail<Q, A>>
488    where
489        Q: RawState + Eq + Hash,
490        A: Eq + Hash,
491    {
492        fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>> {
493            self.get(head)
494        }
495
496        fn find_tail(&self, state: State<&Q>, sym: &A) -> Option<&Tail<Q, A>> {
497            self.iter().find_map(|(h, t)| {
498                if h.state() == *state && h.symbol() == sym {
499                    Some(t)
500                } else {
501                    None
502                }
503            })
504        }
505    }
506}