1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
//! The primary extension mechanism.
//!
//! Rukt builtins are a specific kind of declarative macros that can participate
//! in the evaluation of [`rukt`](crate::rukt) blocks.
//!
//! Rukt expressions can refer to builtins by name using simple paths comprised
//! of identifiers joined by `::`.
//!
//! This module provides some common utilities but you can create your own
//! builtins anywhere.
//!
//! ```
//! macro_rules! example {
//! ($T:tt $S:tt ($F:path; $($C:tt)*) $P:tt $V:tt $D:tt) => {
//! $F!($T "hello world" $($C)* $P $V $);
//! };
//! }
//! ```
//!
//! This is an example of a simple builtin that resolves to the token `"hello
//! world"`. The macro follows the [calling
//! convention](crate::eval#calling-convention) of the Rukt evaluator. As long
//! as the macro is accessible from the surrounding Rust code, the evaluator
//! will know how to invoke it during the expansion of [`rukt`](crate::rukt)
//! blocks.
//!
//! ```
//! # macro_rules! example {
//! # ($T:tt $S:tt ($F:path; $($C:tt)*) $P:tt $V:tt $D:tt) => {
//! # $F!($T "hello world" $($C)* $P $V $);
//! # };
//! # }
//! # use rukt::rukt;
//! rukt! {
//! let message = example;
//! expand {
//! assert_eq!($message, "hello world");
//! }
//! }
//! ```
/// Dump evaluation state using [`compile_error`].
///
/// Each field shows the corresponding fragment matched by the evaluator's
/// [calling convention](crate::eval#calling-convention).
///
/// ```compile_fail
/// # use rukt::rukt;
/// rukt! {
/// let message = "hello";
/// let value = rukt::builtins::breakpoint;
/// expand {
/// println!($message);
/// }
/// }
/// ```
/// ```text
/// error: rukt: breakpoint
/// tokens = { ; expand { println!($message); } }
/// subject = ()
/// next = ($crate :: eval_let_binding; value /)
/// patterns = [$ message : tt]
/// values = ["hello"]
/// ```
pub use builtin_breakpoint as breakpoint;
$S:tt $N:tt $P:tt $V:tt $D:tt) =>
__rukt_transcribe!;
};
}
/// Parse tokens into a specific syntax fragment according to the given
/// [specifier](https://doc.rust-lang.org/reference/macros-by-example.html#metavariables).
///
/// ```
/// # use rukt::rukt;
/// use rukt::builtins::parse;
/// rukt! {
/// let result = parse::<expr>(1 + 2 + 3);
/// }
/// ```
///
/// This is equivalent to destructuring a token tree using the same fragment
/// specifier.
///
/// ```
/// # use rukt::rukt;
/// rukt! {
/// let ($result:expr) = (1 + 2 + 3);
/// }
/// ```
///
/// Using the [`parse`] builtin can be more convenient if you're in the middle
/// of an expression or if you want to directly export a valid piece of Rust
/// syntax.
///
/// ```
/// # use rukt::rukt;
/// use rukt::builtins::parse;
/// rukt! {
/// pub(crate) let define_struct = parse::<item>(
/// struct MyStruct {
/// value: u32,
/// }
/// );
/// }
/// define_struct!();
/// assert_eq!(MyStruct { value: 42 }.value, 42);
/// ```
///
/// Another use case which can be covered by either [`parse`] or destructuring
/// is calling regular macros. Note that in most cases since the returned token
/// will be opaque you won't be able to inspect it further, but it can still be
/// useful.
///
/// ```
/// # use rukt::rukt;
/// use rukt::builtins::parse;
/// rukt! {
/// let a = "hello";
/// let b = "world";
/// pub(crate) let message = parse::<expr>(
/// concat!($a, " ", $b)
/// );
/// }
/// assert_eq!(message!(), "hello world");
/// ```
pub use builtin_parse as parse;
$S:tt $N:tt $P:tt $V:tt $D:tt) =>
}
/// Return `true` if the given tokens form a prefix of this token tree and
/// `false` otherwise.
///
/// ```
/// # use rukt::rukt;
/// use rukt::builtins::starts_with;
/// rukt! {
/// let value = [1 2 3];
/// let condition = value.starts_with(1 2);
/// expand {
/// assert_eq!($condition, true);
/// }
/// }
/// ```
///
/// Note that `starts_with` can only be applied to a delimiter-enclosed token tree.
///
/// ```compile_fail
/// # use rukt::rukt;
/// use rukt::builtins::starts_with;
/// rukt! {
/// let value = "1 2 3";
/// let condition = value.starts_with(1 2); // error: no rules expected the token `"1 2 3"`
/// expand {
/// assert_eq!($condition, true);
/// }
/// }
/// ```
pub use builtin_starts_with as starts_with;