luau_ast_rs/
ast.rs

1use crate::errors::ParseError;
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6/// Represents the status of a statement in the AST.
7/// A status is Some when it is parsed correctly, None when it is removed from the AST by the user,
8/// PreAllocated when it is allocated but not yet parsed, and Error when it is parsed incorrectly.
9#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10#[derive(Debug, Clone, PartialEq)]
11pub enum StmtStatus {
12    Some(Stmt, Vec<Comment>),
13    None,
14    PreAllocated,
15    Error(ParseError),
16}
17
18/// Represents a comment in the AST. We don't care much about the exact position of the comment, so we
19/// aggregate them with the statement they are attached to.
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21#[derive(Debug, Clone, PartialEq)]
22pub enum Comment {
23    /// Comment that is trailing the statement. e.g. `local x = 1 -- trailing comment`
24    /// Comments that are inside the statement also count as trailing comments.
25    /// e.g. `local x --[[ trailing comment ]] = 1`
26    Trailing(String),
27    /// Comment that is leading the statement.
28    /// e.g.
29    /// ```lua
30    /// -- leading comment
31    /// local x = 1
32    /// ```
33    Leading(String),
34}
35
36/// The Chunk struct represents the root of the AST. It contains the root of the program in the
37/// block field. All the statements in the AST are stored in the stmts vector. This struct
38/// acts as an arena for the statements in the AST.
39#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
40#[derive(Debug, Default, Clone, PartialEq)]
41pub struct Chunk {
42    pub(crate) block: Block,
43    // TODO: benchmark different data structures for this arena
44    /// This vector contains all the statements in the AST. These are referenced
45    /// by index as if they were pointers in a linked list. It is an option
46    /// in the case that the statement is removed from the AST or it is pre-allocated.
47    /// We want to keep the indices the same, so we just replace the statement with None.
48    pub(crate) stmts: Vec<StmtStatus>, // NOTE: pub(crate) for testing. use methods instead of accessing directly.
49}
50
51impl Iterator for Chunk {
52    type Item = StmtStatus;
53
54    fn next(&mut self) -> Option<Self::Item> {
55        self.stmts.pop()
56    }
57}
58
59pub trait ChunkInfo {
60    /// Returns the number of statements in the chunk.
61    fn len(&self) -> usize;
62
63    /// Returns true if the chunk is empty, has no statements.
64    #[must_use]
65    fn is_empty(&self) -> bool {
66        self.len() == 0
67    }
68}
69
70pub trait ChunkRetrievable {
71    /// Returns the statement at the given index.
72    ///
73    /// # Panics
74    /// Panics if the index is out of bounds.
75    fn get_stmt(&self, index: usize) -> &StmtStatus;
76
77    /// Returns the main block of the chunk.
78    fn block(&self) -> &Block;
79
80    /// Produces a new `ChunkSlice` from the given `Block`.
81    fn slice_from_block(&self, block: Block) -> ChunkSlice<'_>;
82}
83
84pub trait ChunkRef: ChunkInfo + ChunkRetrievable {}
85
86impl ChunkInfo for &Chunk {
87    fn len(&self) -> usize {
88        self.stmts.len()
89    }
90}
91
92impl ChunkRetrievable for &Chunk {
93    fn get_stmt(&self, index: usize) -> &StmtStatus {
94        &self.stmts[index]
95    }
96
97    fn block(&self) -> &Block {
98        &self.block
99    }
100
101    fn slice_from_block(&self, block: Block) -> ChunkSlice<'_> {
102        ChunkSlice { chunk: self, block }
103    }
104}
105
106impl ChunkRef for &Chunk {}
107
108impl Chunk {
109    /// Allocates and adds a statement to the chunk.
110    pub fn add_stmt(&mut self, stmt_status: StmtStatus) -> usize {
111        let i = self.alloc();
112        self.set_stmt(i, stmt_status);
113        i
114    }
115
116    /// Removes a statement from the chunk at the given index. This will not deallocate the
117    /// statement, but rather replace it with None.
118    ///
119    /// # Panics
120    /// Panics if the index is out of bounds.
121    pub fn remove_stmt(&mut self, index: usize) {
122        self.set_stmt(index, StmtStatus::None);
123    }
124
125    /// Adds a comment to the statement at the given index.
126    ///
127    /// # Panics
128    /// If the given index is out of bounds, or if the statement at the given index is not Some,
129    /// except if it is an Error, in which case it is ignored and the comment is not added.
130    pub fn add_comment(&mut self, index: usize, comment: Comment) {
131        match &mut self.stmts[index] {
132            StmtStatus::Some(_, comments) => {
133                comments.push(comment);
134            }
135            // ignore error case
136            StmtStatus::Error(_) => {}
137            StmtStatus::None => panic!(
138                "Cannot add comment to statement that is None (ptr: {})",
139                index
140            ),
141            StmtStatus::PreAllocated => panic!(
142                "Cannot add comment to statement that is PreAllocated (ptr: {})",
143                index
144            ),
145        }
146    }
147
148    /// Allocates space for a statement in the chunk, returning the pointer (as a index) to the space. The
149    /// cell pointed to is set to StmtStatus::PreAllocated.
150    pub fn alloc(&mut self) -> usize {
151        // find if there are any holes in the vector
152        let mut index = None;
153        for (i, stmt) in self.stmts.iter().enumerate() {
154            if let StmtStatus::None = stmt {
155                index = Some(i);
156                break;
157            }
158        }
159
160        // if there are no holes, push the statement to the end
161        // otherwise, replace the hole with the statement
162        match index {
163            Some(i) => i,
164            None => {
165                self.stmts.push(StmtStatus::PreAllocated);
166                self.stmts.len() - 1
167            }
168        }
169    }
170
171    /// Sets the statement at the given index to the given statement.
172    ///
173    /// # Panics
174    /// Panics if the index is out of bounds.
175    pub fn set_stmt(&mut self, index: usize, stmt_status: StmtStatus) {
176        self.stmts[index] = stmt_status;
177    }
178}
179
180/// A slice of a chunk, used to traverse subsets of the AST.
181/// TODO: mutable version of this
182#[derive(Debug, Clone, PartialEq)]
183pub struct ChunkSlice<'a> {
184    chunk: &'a Chunk,
185    block: Block,
186}
187
188impl<'a> ChunkRetrievable for ChunkSlice<'a> {
189    fn get_stmt(&self, index: usize) -> &StmtStatus {
190        self.chunk.get_stmt(index)
191    }
192
193    fn block(&self) -> &Block {
194        &self.block
195    }
196
197    fn slice_from_block(&self, block: Block) -> ChunkSlice<'_> {
198        ChunkSlice {
199            chunk: self.chunk,
200            block,
201        }
202    }
203}
204
205impl ChunkInfo for ChunkSlice<'_> {
206    fn len(&self) -> usize {
207        self.block.stmt_ptrs.len()
208    }
209}
210
211impl<'a> ChunkRef for ChunkSlice<'a> {}
212
213/// A block represents a list of statement. The statements here are pointers to the statements
214/// that live in the chunk.
215#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
216#[derive(Debug, Default, Clone, PartialEq)]
217pub struct Block {
218    pub stmt_ptrs: Vec<usize>,
219}
220
221/// Represents a bindings in the ast. e.g. the `a` in `local a = 1`, or the
222/// `b: number` in `local b: number = 2`.
223#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
224#[derive(Debug, Clone, PartialEq)]
225pub struct Binding {
226    pub name: String,
227    pub ty: Option<Type>,
228}
229
230/// Represents a local variable declaration.
231#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
232#[derive(Debug, Clone, PartialEq)]
233pub struct Local {
234    pub bindings: Vec<Binding>,
235    pub init: Vec<Expr>,
236}
237
238/// Represents an assignment statement.
239#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
240#[derive(Debug, Clone, PartialEq)]
241pub struct Assign {
242    pub vars: Vec<Var>,
243    pub exprs: Vec<Expr>,
244}
245
246/// Represents the body of a function.
247#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
248#[derive(Debug, Clone, PartialEq)]
249pub struct FunctionBody {
250    pub params: Vec<Binding>,
251    pub generics: Vec<GenericParam>,
252    /// The variadic argument, if any.
253    /// None: no variadic argument
254    /// Some(None): variadic argument with no type
255    /// Some(Some(ty)): variadic argument with type
256    pub vararg: Option<Option<Type>>,
257    pub ret_ty: Option<TypeOrPack>,
258    pub block: Block,
259}
260
261/// Represents a global function definition.
262#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
263#[derive(Debug, Clone, PartialEq)]
264pub struct FunctionDef {
265    /// The table, with possible subtables, that the function is defined
266    /// in. e.g. `a.b.c` is `vec!["a", "b", "c"]`.
267    pub table: Vec<String>,
268    /// Whether the function is a method. e.g. `function a:b() end` is a method.
269    pub is_method: bool,
270    /// The name of the function. e.g. `a` in `function a() end`.
271    pub name: String,
272    /// The body of the function.
273    pub body: FunctionBody,
274}
275
276/// Represents a local function definition.
277#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
278#[derive(Debug, Clone, PartialEq)]
279pub struct LocalFunctionDef {
280    pub name: String,
281    pub body: FunctionBody,
282}
283
284/// Represents call arguments.
285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
286#[derive(Debug, Clone, PartialEq)]
287pub enum CallArgs {
288    Exprs(Vec<Expr>),
289    Table(TableConstructor),
290    String(String),
291}
292
293/// Represents a function call.
294#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
295#[derive(Debug, Clone, PartialEq)]
296pub struct Call {
297    pub func: Expr,
298    pub args: CallArgs,
299    pub method: Option<String>,
300}
301
302/// Represents a binary operation. e.g. `a + b`, `a * b`, `a / b`, etc.
303#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
304#[derive(Debug, Clone, PartialEq)]
305pub struct BinOp {
306    pub lhs: Expr,
307    pub op: BinOpKind,
308    pub rhs: Expr,
309}
310
311/// Represents a unary operation. e.g. `-a`, `not a`, and `#` (length operator).
312#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
313#[derive(Debug, Clone, PartialEq)]
314pub struct UnOp {
315    pub op: UnOpKind,
316    pub expr: Expr,
317}
318
319/// Represents a compound operation. e.g. `a += b`, `a -= b`, `a *= b`, etc.
320#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
321#[derive(Debug, Clone, PartialEq)]
322pub struct CompOp {
323    pub lhs: Var,
324    pub op: CompOpKind,
325    pub rhs: Box<Expr>,
326}
327
328/// Represents a return statement.
329#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
330#[derive(Debug, Clone, PartialEq)]
331pub struct Return {
332    pub exprs: Vec<Expr>,
333}
334
335/// Represents a break statement.
336#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
337#[derive(Debug, Clone, PartialEq)]
338pub struct Break;
339
340/// Represents a continue statement.
341#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
342#[derive(Debug, Clone, PartialEq)]
343pub struct Continue;
344
345/// Represents a named type.
346#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
347#[derive(Debug, Clone, PartialEq)]
348pub struct NamedType {
349    pub table: Option<String>,
350    pub name: String,
351    pub params: Vec<TypeOrPack>,
352}
353
354/// Represents a bound type.
355#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
356#[derive(Debug, Clone, PartialEq)]
357pub struct BoundType {
358    pub name: String,
359    pub ty: Box<Type>,
360}
361
362/// Represents a function type
363#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
364#[derive(Debug, Clone, PartialEq)]
365pub struct FunctionType {
366    pub generics: Vec<GenericParam>,
367    pub params: TypeList,
368    pub ret_ty: TypeOrPack,
369}
370
371/// Represents a table type
372#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
373#[derive(Debug, Clone, PartialEq)]
374pub struct TableType {
375    pub props: Vec<TableProp>,
376}
377
378/// Represents a do statement.
379#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
380#[derive(Debug, Clone, PartialEq)]
381pub struct Do {
382    pub block: Block,
383}
384
385/// Represents a while statement.
386#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
387#[derive(Debug, Clone, PartialEq)]
388pub struct While {
389    pub cond: Expr,
390    pub block: Block,
391}
392
393/// Represents a repeat statement.
394#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
395#[derive(Debug, Clone, PartialEq)]
396pub struct Repeat {
397    pub block: Block,
398    pub cond: Expr,
399}
400
401/// Represents an if statement.
402#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
403#[derive(Debug, Clone, PartialEq)]
404pub struct If {
405    pub cond: Expr,
406    pub block: Block,
407    pub else_if_blocks: Vec<(Expr, Block)>,
408    pub else_block: Option<Block>,
409}
410
411/// Represents a for statement.
412#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
413#[derive(Debug, Clone, PartialEq)]
414pub struct For {
415    pub var: Binding,
416    pub start: Expr,
417    pub end: Expr,
418    pub step: Option<Expr>,
419    pub block: Block,
420}
421
422/// Represents a for in statement.
423#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
424#[derive(Debug, Clone, PartialEq)]
425pub struct ForIn {
426    pub vars: Vec<Binding>,
427    pub exprs: Vec<Expr>,
428    pub block: Block,
429}
430
431/// Represents a table constructor expression.
432#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
433#[derive(Debug, Clone, PartialEq)]
434pub struct TableConstructor {
435    pub fields: Vec<TableField>,
436}
437
438/// Represents a ifelse expression.
439#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
440#[derive(Debug, Clone, PartialEq)]
441pub struct IfElseExpr {
442    pub cond: Expr,
443    pub if_expr: Expr,
444    pub else_expr: Expr,
445    pub else_if_exprs: Vec<(Expr, Expr)>,
446}
447
448/// Represents a table access operation
449#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
450#[derive(Debug, Clone, PartialEq)]
451pub struct TableAccess {
452    pub expr: Expr,
453    pub index: Expr,
454}
455
456/// Represents a field access operation
457#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
458#[derive(Debug, Clone, PartialEq)]
459pub struct FieldAccess {
460    pub expr: Expr,
461    pub field: String,
462}
463
464/// Represents a string interpolation operation
465#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
466#[derive(Debug, Clone, PartialEq)]
467pub struct StringInterp {
468    pub parts: Vec<StringInterpPart>,
469}
470
471/// Represents a type assertion
472#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
473#[derive(Debug, Clone, PartialEq)]
474pub struct TypeAssertion {
475    pub expr: Expr,
476    pub ty: Type,
477}
478
479/// Represents a type list. e.g. `(a, b, c)`. or `(a, b, c, ...d)`
480#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
481#[derive(Debug, Clone, PartialEq, Default)]
482pub struct TypeList {
483    pub types: Vec<Type>,
484    pub vararg: Option<Type>,
485}
486
487/// Represents a type definition
488#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
489#[derive(Debug, Clone, PartialEq)]
490pub struct TypeDef {
491    pub name: String,
492    pub ty: Type,
493    pub generics: Vec<GenericDef>,
494    pub is_exported: bool,
495}
496
497/// Represents an union type
498#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
499#[derive(Debug, Clone, PartialEq)]
500pub struct UnionType {
501    pub left: Type,
502    pub right: Type,
503}
504
505/// Represents an intersection type
506#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
507#[derive(Debug, Clone, PartialEq)]
508pub struct IntersectionType {
509    pub left: Type,
510    pub right: Type,
511}
512
513/// Represents a generic definition. Used in type definitions.
514#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
515#[derive(Debug, Clone, PartialEq)]
516pub struct GenericDef {
517    pub param: GenericParam,
518    pub default: Option<TypeOrPack>,
519}
520
521/// Represents a statement node in the AST.
522#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
523#[derive(Debug, Clone, PartialEq)]
524pub enum Stmt {
525    CompOp(CompOp),
526    Call(Call),
527    Do(Do),
528    While(While),
529    Repeat(Repeat),
530    If(If),
531    For(For),
532    ForIn(ForIn),
533    FunctionDef(FunctionDef),
534    LocalFunctionDef(LocalFunctionDef),
535    Local(Local),
536    Assign(Assign),
537    TypeDef(TypeDef),
538    // \ These under are technically "last statements", but we don't care about that in AST form /
539    Return(Return),
540    Break(Break),
541    Continue(Continue),
542}
543
544/// Represents an expression node in the AST.
545#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
546#[derive(Debug, Clone, PartialEq)]
547pub enum Expr {
548    // \ simple expressions, essentially values /
549    Number(f64),
550    String(String),
551    Nil,
552    Bool(bool),
553    VarArg,
554    Var(Var),
555    // NOTE: boxed because Call uses Expr
556    Call(Box<Call>),
557    TableConstructor(TableConstructor),
558    // NOTE: boxed because FunctionBody uses Expr
559    Function(Box<FunctionBody>),
560    IfElseExpr(Box<IfElseExpr>),
561    StringInterp(StringInterp),
562    TypeAssertion(Box<TypeAssertion>),
563    BinOp(Box<BinOp>),
564    UnOp(Box<UnOp>),
565}
566
567/// The type of a binary operator.
568/// binop = '+' | '-' | '*' | '/' | '^' | '%' | '..' | '<' | '<=' | '>' | '>=' | '==' | '~=' | 'and' | 'or'
569#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
570#[derive(Debug, Clone, PartialEq)]
571pub enum BinOpKind {
572    Add,
573    Sub,
574    Mul,
575    Div,
576    Pow,
577    Mod,
578    Concat,
579    Lt,
580    Le,
581    Gt,
582    Ge,
583    Eq,
584    Ne,
585    And,
586    Or,
587}
588
589/// The type of a unary operator.
590/// unop = '-' | 'not' | '#'
591#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
592#[derive(Debug, Clone, PartialEq)]
593pub enum UnOpKind {
594    Neg,
595    Not,
596    Len,
597}
598
599/// The type of a compound operator.
600/// compoundop :: '+=' | '-=' | '*=' | '/=' | '%=' | '^=' | '..='
601#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
602#[derive(Debug, Clone, PartialEq)]
603pub enum CompOpKind {
604    Add,
605    Sub,
606    Mul,
607    Div,
608    Mod,
609    Pow,
610    Concat,
611}
612
613/// Represents a type node in the AST.
614#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
615#[derive(Debug, Clone, PartialEq)]
616pub enum Type {
617    // \ special nodes, should be their own node but we don't care /
618    /// T...
619    /// This can typically only occur at the last parameter of a function.
620    Pack(Box<Type>),
621    // \ simple types /
622    /// `typeof(exp)`
623    TypeOf(Expr),
624    /// `T` or `T<PARAM1, PARAM2>` or `tbl.T`
625    Named(NamedType),
626    /// `id : T`
627    /// This is used in function type parameters.
628    Bound(BoundType),
629    /// `{ [T] : U }` or `{ x : T }`
630    Table(TableType),
631    /// `( T ) -> U` or `<T, U...>( T ) -> U`
632    Function(Box<FunctionType>),
633    /// `T?`
634    Optional(Box<Type>),
635    /// `T | U`
636    Union(Box<UnionType>),
637    /// `T & U`
638    Intersection(Box<IntersectionType>),
639    // \ literals (singleton) /
640    /// `nil`
641    Nil,
642    /// `"string"`
643    String(String),
644    /// `false` or `true`
645    Bool(bool),
646}
647
648/// Represents a type that is either a Type or TypePack
649#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
650#[derive(Debug, Clone, PartialEq)]
651pub enum TypeOrPack {
652    Type(Type),
653    Pack(TypePack),
654}
655
656/// Represents a type pack
657#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
658#[derive(Debug, Clone, PartialEq)]
659pub enum TypePack {
660    /// `( T, U )` or `( T, U, ...V )`
661    Listed(TypeList),
662    /// `...T`
663    Variadic(Type),
664    /// `T...`
665    Generic(Type),
666}
667
668/// Represents a table property or indexer.
669#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
670#[derive(Debug, Clone, PartialEq)]
671pub enum TableProp {
672    /// `[T] : U`
673    Indexer { key: Type, value: Type },
674    /// `x : T`
675    Prop { key: String, value: Type },
676    /// `T`
677    /// NOTE: when this prop appears, it will be the only prop in the table
678    Array(Type),
679}
680
681/// Represents a generic type parameter.
682#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
683#[derive(Debug, Clone, PartialEq)]
684pub enum GenericParam {
685    /// A type parameter with a name. e.g. `T` in `function foo<T>() end`.
686    Name(String),
687    /// A pack type parameter. e.g. `function foo<T...>() end`.
688    Pack(String),
689}
690
691/// Represents a variable node in the AST.
692#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
693#[derive(Debug, Clone, PartialEq)]
694pub enum Var {
695    Name(String),
696    TableAccess(Box<TableAccess>),
697    FieldAccess(Box<FieldAccess>),
698}
699
700/// Represents a table field.
701#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
702#[derive(Debug, Clone, PartialEq)]
703pub enum TableField {
704    /// Represents a field with an explicit key. e.g. `a = 1` in `{a = 1}`.
705    ExplicitKey { key: String, value: Expr },
706    /// Represents a field with an implicit key. e.g. `1` in `{1}`.
707    ImplicitKey(Expr),
708    /// Represents a field with an array-like key. e.g. `a` in `{[a] = 1}`.
709    ArrayKey { key: Expr, value: Expr },
710}
711
712/// Represents a part of a string interpolation.
713#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
714#[derive(Debug, Clone, PartialEq)]
715pub enum StringInterpPart {
716    /// A string literal.
717    String(String),
718    /// An expression.
719    Expr(Expr),
720}