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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
//! Abstract Syntax Tree (AST) node types for the template language.
//!
//! The AST is produced by the [`Parser`](super::Parser) and consumed by
//! the executor. In Go's implementation, nodes use an interface with a tree
//! of concrete types. In Rust, we use enums, the natural way to represent
//! sum types.
//!
//! The top-level enum is [`Node`], with expression-level atoms in [`Expr`].
use Box;
use Arc;
use Vec;
/// Byte-level position in the template source, used for error reporting.
///
/// Carried by every AST node so that execution errors can point back to
/// the originating source location.
/// A top-level AST node produced by the parser.
///
/// Each variant corresponds to a syntactic construct in the Go template language.
/// The executor walks a tree of these nodes to produce output.
/// A sequence of [`Node`]s, the body of a template or a branch.
/// Raw text outside delimiters, emitted verbatim during execution.
/// A `{{ pipeline }}` action that evaluates and prints.
///
/// If [`PipeNode::decl`] is non-empty, the result is assigned to those variables
/// instead of being printed.
/// A pipeline: one or more [`CommandNode`]s separated by `|`.
///
/// Optionally declares or assigns variables:
/// - `$x := pipeline`: declare with `:=`
/// - `$x = pipeline`: assign with `=`
/// - `$i, $v := range .Items`: multiple declarations in range
/// - `$i, $v = range .Items`: multiple assignments in range
///
/// When piped, each command's result becomes the **last** argument of the
/// next command (matching Go's convention).
/// A single command in a pipeline, either a function call or a bare value.
///
/// The first element of [`args`](Self::args) determines the command type:
/// - [`Expr::Identifier`]: a function call; remaining args are its arguments.
/// - Any other [`Expr`]: a bare value (only valid as the first or sole command).
/// A parsed numeric literal — either an integer or a floating-point value.
///
/// Produced by the parser from [`TokenKind::Number`](crate::parse::lexer::TokenKind)
/// and [`TokenKind::Char`](crate::parse::lexer::TokenKind) tokens. Character
/// literals are stored as `Int` holding the Unicode code point.
/// An expression, the atomic building blocks of commands.
///
/// Each variant carries a [`Pos`] for error reporting.
/// Shared structure for `{{if}}`, `{{with}}`, and `{{range}}` nodes.
///
/// All three have the same shape: a condition/value pipeline, a body to execute
/// when the condition is truthy (or for each iteration), and an optional else branch.
///
/// The type aliases [`IfNode`], [`WithNode`], and [`RangeNode`] all resolve to this type.
/// Type alias for an `{{if}}` node. See [`BranchNode`] for fields.
pub type IfNode = BranchNode;
/// Type alias for a `{{with}}` node. See [`BranchNode`] for fields.
///
/// Unlike `if`, `with` sets dot to the pipeline result inside the body.
pub type WithNode = BranchNode;
/// Type alias for a `{{range}}` node. See [`BranchNode`] for fields.
///
/// The pipeline's [`decl`](PipeNode::decl) may contain one or two variable names
/// for the loop index and value (e.g., `$i, $v := range .Items` or
/// `$i, $v = range .Items` for assignment to existing variables).
pub type RangeNode = BranchNode;
/// A `{{template "name" pipeline}}` invocation node.
/// A `{{define "name"}}...{{end}}` template definition.
///
/// Collected by the parser and stored in the [`Template`](crate::Template)'s
/// definition map, keyed by [`name`](Self::name).