rstm_core/macros/
rules.rs

1/*
2    Appellation: ruleset <module>
3    Contrib: @FL03
4*/
5/// The [`head!`] macro simplifies the creation of a [`Head`](crate::Head) struct
6/// by providing a concise syntax for specifying the state and symbol.
7#[macro_export]
8macro_rules! head {
9    ($state:expr, $symbol:expr) => {
10        $crate::Head {
11            state: $crate::State($state),
12            symbol: $symbol,
13        }
14    };
15}
16///! the [`tail!`] macro facilitates the creation of a [`Tail`](crate::Tail) struct
17///! by providing a concise syntax for specifying the direction, next state, and symbol to
18/// write. As with other macros in this module, the variants of the [`Direction`](crate::Direction)
19/// are hygenically imported based on usage, meaning one only needs to specify the variant name
20///! directly, i.e. `Left`, `Right`, or `Stay`.
21#[macro_export]
22macro_rules! tail {
23    ($direction:ident, $state:expr, $symbol:expr) => {
24        $crate::Tail {
25            direction: $crate::Direction::$direction,
26            next_state: $crate::State($state),
27            write_symbol: $symbol,
28        }
29    };
30}
31
32/// The [`rule!`] macro enables the definition of a single, Turing compatible rule using the
33/// following syntax:
34///
35/// ```ignore
36///     (state, symbol) -> Direction(next_state, next_symbol)
37/// ```
38///
39/// The syntax is directly inspired by the simplified definition of a Turing machine as a
40/// dynamical system, as described in the paper [On the Topological Dynamics of Turing Machines](https://doi.org/10.1016/S0304-3975(96)00025-4)
41/// by Petr Kůrka. Specifically,
42///
43/// ```math
44/// \delta:Q\times{A}\rightarrow{Q}\times{A}\times\lbrace{0,\pm{1}\rbrace}
45/// ```
46///
47/// **note:** it is unnecessary for you to import the [`Direction`](crate::Direction) enum, as
48/// the macro hygenically imports each of its variants directly based on your usage.
49///
50/// ### _Basic Usage_
51///
52/// Let's use the macro to define some rule, `a`, that considers a head that is in a state of
53/// `0` reading some value `'a'` from the tape, and then writes a `c` to the tape, moves right,
54/// and updates the state to `1`.
55///
56/// ```rust
57/// let rule = rstm_core::rule![(0, 'a') -> Right(1, 'c')];
58/// ```
59#[macro_export]
60macro_rules! rule {
61    [($state:expr, $symbol:literal) -> $direction:ident($next_state:expr, $write_symbol:literal)] => {
62        $crate::Rule {
63            head: $crate::head!($state, $symbol),
64            tail: $crate::tail!($direction, $next_state, $write_symbol),
65        }
66    };
67}
68/// [`ruleset!`] is a macro that simplifies the creation of an array of [`Rules`](crate::Rule).
69///
70/// The syntax follows the [`rule!`] macro, allowing for multiple rules to be defined in a
71/// single invocation.
72///
73/// ```ignore
74/// ruleset![(state, symbol) -> direction(next_state, write_symbol), ...]
75/// ```
76///
77/// ## Basic Usage
78///
79/// The following example demonstrates the usage of the macro to create a ruleset using three
80/// states `{-1, 0, 1}` and two symbols `{0, 1}`.
81///
82/// ```rust
83/// let rule = rstm_core::ruleset![
84///     (0, 0) -> Right(1, 1),
85///     (0, 1) -> Left(-1, 0),
86///     (1, 0) -> Right(1, 1),
87///     (1, 1) -> Left(-1, 1),
88///     (-1, 0) -> Right(0, 0),
89///     (-1, 1) -> Left(0, 1),
90/// ];
91/// ```
92#[macro_export]
93macro_rules! ruleset {
94    {$(($state:expr, $symbol:literal $(,)?) -> $dir:ident($next:expr, $write:literal $(,)?)),* $(,)?} => {
95        [$($crate::rule! { ($state, $symbol) -> $dir($next, $write) }),*]
96    };
97}
98
99#[cfg(any(feature = "hashbrown", feature = "std"))]
100/// a macro to create a `HashMap` of rules for a Turing machine.
101/// The macro takes a list of rules in the form of
102///
103/// ```ignore
104///     (state, symbol) -> Direction(next_state, next_symbol)
105/// ```
106///
107/// ## Basic Usage
108///
109/// ```rust
110/// let rules = rstm_core::head_map! {
111///     (0, 1) -> Right(0, 1),
112///     (0, 0) -> Left(1, 1),
113///     (1, 1) -> Right(0, 0),
114/// };
115/// ```
116#[macro_export]
117macro_rules! head_map {
118    {$(($state:expr, $symbol:literal) -> $direction:ident($next:expr, $write:literal)),* $(,)?} => {
119        {
120            let mut map = $crate::HeadMap::new();
121            $(
122                map.insert(
123                    $crate::head!($state, $symbol),
124                    $crate::tail!($direction, $next, $write)
125                );
126            )*
127            map
128        }
129    };
130}