Skip to main content

luau_syntax/ast/
mod.rs

1use crate::ast_names::AstName;
2use crate::lexer::QuoteStyle as LexerQuoteStyle;
3use crate::location::Location;
4use luau_common::{BStr, ByteSlice};
5use std::fmt;
6
7pub struct Local<'ast> {
8    pub name: AstName<'ast>,
9    pub location: Location,
10    pub shadow: Option<&'ast Local<'ast>>,
11    pub function_depth: usize,
12    pub loop_depth: usize,
13    pub annotation: Option<Type<'ast>>,
14    pub is_const: bool,
15    pub is_exported: bool,
16}
17
18#[derive(Debug, Clone, Copy)]
19pub struct LocalInit<'ast> {
20    pub name: AstName<'ast>,
21    pub location: Location,
22    pub shadow: Option<&'ast Local<'ast>>,
23    pub function_depth: usize,
24    pub loop_depth: usize,
25    pub annotation: Option<Type<'ast>>,
26    pub is_const: bool,
27    pub is_exported: bool,
28}
29
30impl fmt::Debug for Local<'_> {
31    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
32        formatter
33            .debug_struct("Local")
34            .field("name", &self.name)
35            .field("location", &self.location)
36            .field("shadow", &self.shadow)
37            .field("function_depth", &self.function_depth)
38            .field("loop_depth", &self.loop_depth)
39            .field("annotation", &self.annotation)
40            .field("is_const", &self.is_const)
41            .field("is_exported", &self.is_exported)
42            .finish()
43    }
44}
45
46impl PartialEq for Local<'_> {
47    fn eq(&self, other: &Self) -> bool {
48        self.name == other.name
49            && self.location == other.location
50            && self.shadow == other.shadow
51            && self.function_depth == other.function_depth
52            && self.loop_depth == other.loop_depth
53            && self.annotation == other.annotation
54            && self.is_const == other.is_const
55            && self.is_exported == other.is_exported
56    }
57}
58
59#[derive(Debug, PartialEq)]
60pub struct GenericType<'ast> {
61    pub location: Location,
62    pub name: AstName<'ast>,
63    pub default_value: Option<Type<'ast>>,
64}
65
66#[derive(Debug, PartialEq)]
67pub struct GenericTypePack<'ast> {
68    pub location: Location,
69    pub name: AstName<'ast>,
70    pub default_value: Option<TypePack<'ast>>,
71}
72
73#[derive(Debug, Clone, Copy, PartialEq)]
74pub struct ArgumentName<'ast> {
75    pub name: AstName<'ast>,
76    pub location: Location,
77}
78
79impl<'ast> Local<'ast> {
80    pub(crate) fn new(init: LocalInit<'ast>) -> Self {
81        Local {
82            name: init.name,
83            location: init.location,
84            shadow: init.shadow,
85            function_depth: init.function_depth,
86            loop_depth: init.loop_depth,
87            annotation: init.annotation,
88            is_const: init.is_const,
89            is_exported: init.is_exported,
90        }
91    }
92
93    pub fn visit<V: AstVisitor>(&self, visitor: &mut V) {
94        if let Some(annotation) = &self.annotation {
95            annotation.visit(visitor);
96        }
97    }
98}
99
100impl GenericType<'_> {
101    pub fn visit<V: AstVisitor>(&self, visitor: &mut V) {
102        if !visitor.visit_generic_type(self) {
103            return;
104        }
105
106        if let Some(default_value) = &self.default_value {
107            default_value.visit(visitor);
108        }
109    }
110}
111
112impl GenericTypePack<'_> {
113    pub fn visit<V: AstVisitor>(&self, visitor: &mut V) {
114        if !visitor.visit_generic_type_pack(self) {
115            return;
116        }
117
118        if let Some(default_value) = &self.default_value {
119            default_value.visit(visitor);
120        }
121    }
122}
123
124#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
125pub struct AstString<'ast> {
126    bytes: &'ast BStr,
127}
128
129impl<'ast> AstString<'ast> {
130    pub(crate) fn from_arena_bytes(bytes: &'ast [u8]) -> Self {
131        Self {
132            bytes: BStr::new(bytes),
133        }
134    }
135
136    pub fn as_bytes(&self) -> &[u8] {
137        self.bytes.as_bytes()
138    }
139
140    pub fn as_bstr(self) -> &'ast BStr {
141        self.bytes
142    }
143
144    pub fn into_bytes(self) -> &'ast [u8] {
145        self.bytes.as_bytes()
146    }
147}
148
149impl PartialEq<str> for AstString<'_> {
150    fn eq(&self, other: &str) -> bool {
151        self.as_bytes() == other.as_bytes()
152    }
153}
154
155pub trait AstVisitor {
156    fn visit_node(&mut self, _node: AstNodeRef<'_, '_>) -> bool {
157        true
158    }
159
160    fn visit_attribute(&mut self, attribute: &Attribute<'_>) -> bool {
161        self.visit_node(AstNodeRef::Attribute(attribute))
162    }
163
164    fn visit_generic_type(&mut self, generic: &GenericType<'_>) -> bool {
165        self.visit_node(AstNodeRef::GenericType(generic))
166    }
167
168    fn visit_generic_type_pack(&mut self, generic: &GenericTypePack<'_>) -> bool {
169        self.visit_node(AstNodeRef::GenericTypePack(generic))
170    }
171
172    fn visit_block(&mut self, block: Block<'_>) -> bool {
173        self.visit_statement(block.as_statement())
174    }
175
176    fn visit_statement(&mut self, statement: Statement<'_>) -> bool {
177        self.visit_node(AstNodeRef::Statement(statement))
178    }
179
180    fn visit_assign_statement(&mut self, statement: Statement<'_>) -> bool {
181        self.visit_statement(statement)
182    }
183
184    fn visit_compound_assign_statement(&mut self, statement: Statement<'_>) -> bool {
185        self.visit_statement(statement)
186    }
187
188    fn visit_break_statement(&mut self, statement: Statement<'_>) -> bool {
189        self.visit_statement(statement)
190    }
191
192    fn visit_continue_statement(&mut self, statement: Statement<'_>) -> bool {
193        self.visit_statement(statement)
194    }
195
196    fn visit_class_statement(&mut self, statement: Statement<'_>) -> bool {
197        self.visit_statement(statement)
198    }
199
200    fn visit_expression_statement(&mut self, statement: Statement<'_>) -> bool {
201        self.visit_statement(statement)
202    }
203
204    fn visit_numeric_for_statement(&mut self, statement: Statement<'_>) -> bool {
205        self.visit_statement(statement)
206    }
207
208    fn visit_generic_for_statement(&mut self, statement: Statement<'_>) -> bool {
209        self.visit_statement(statement)
210    }
211
212    fn visit_function_declaration_statement(&mut self, statement: Statement<'_>) -> bool {
213        self.visit_statement(statement)
214    }
215
216    fn visit_if_statement(&mut self, statement: Statement<'_>) -> bool {
217        self.visit_statement(statement)
218    }
219
220    fn visit_local_function_statement(&mut self, statement: Statement<'_>) -> bool {
221        self.visit_statement(statement)
222    }
223
224    fn visit_local_statement(&mut self, statement: Statement<'_>) -> bool {
225        self.visit_statement(statement)
226    }
227
228    fn visit_type_alias_statement(&mut self, statement: Statement<'_>) -> bool {
229        self.visit_statement(statement)
230    }
231
232    fn visit_type_function_statement(&mut self, statement: Statement<'_>) -> bool {
233        self.visit_statement(statement)
234    }
235
236    fn visit_declare_global_statement(&mut self, statement: Statement<'_>) -> bool {
237        self.visit_statement(statement)
238    }
239
240    fn visit_declare_function_statement(&mut self, statement: Statement<'_>) -> bool {
241        self.visit_statement(statement)
242    }
243
244    fn visit_declare_extern_type_statement(&mut self, statement: Statement<'_>) -> bool {
245        self.visit_statement(statement)
246    }
247
248    fn visit_repeat_statement(&mut self, statement: Statement<'_>) -> bool {
249        self.visit_statement(statement)
250    }
251
252    fn visit_return_statement(&mut self, statement: Statement<'_>) -> bool {
253        self.visit_statement(statement)
254    }
255
256    fn visit_while_statement(&mut self, statement: Statement<'_>) -> bool {
257        self.visit_statement(statement)
258    }
259
260    fn visit_error_statement(&mut self, statement: Statement<'_>) -> bool {
261        self.visit_statement(statement)
262    }
263
264    fn visit_expression(&mut self, expression: Expression<'_>) -> bool {
265        self.visit_node(AstNodeRef::Expression(expression))
266    }
267
268    fn visit_boolean_expression(&mut self, expression: Expression<'_>) -> bool {
269        self.visit_expression(expression)
270    }
271
272    fn visit_call_expression(&mut self, expression: Expression<'_>) -> bool {
273        self.visit_expression(expression)
274    }
275
276    fn visit_function_literal_expression(&mut self, expression: Expression<'_>) -> bool {
277        self.visit_expression(expression)
278    }
279
280    fn visit_grouped_expression(&mut self, expression: Expression<'_>) -> bool {
281        self.visit_expression(expression)
282    }
283
284    fn visit_integer_expression(&mut self, expression: Expression<'_>) -> bool {
285        self.visit_expression(expression)
286    }
287
288    fn visit_nil_expression(&mut self, expression: Expression<'_>) -> bool {
289        self.visit_expression(expression)
290    }
291
292    fn visit_number_expression(&mut self, expression: Expression<'_>) -> bool {
293        self.visit_expression(expression)
294    }
295
296    fn visit_string_expression(&mut self, expression: Expression<'_>) -> bool {
297        self.visit_expression(expression)
298    }
299
300    fn visit_interp_string_expression(&mut self, expression: Expression<'_>) -> bool {
301        self.visit_expression(expression)
302    }
303
304    fn visit_table_expression(&mut self, expression: Expression<'_>) -> bool {
305        self.visit_expression(expression)
306    }
307
308    fn visit_if_expression(&mut self, expression: Expression<'_>) -> bool {
309        self.visit_expression(expression)
310    }
311
312    fn visit_varargs_expression(&mut self, expression: Expression<'_>) -> bool {
313        self.visit_expression(expression)
314    }
315
316    fn visit_index_expression(&mut self, expression: Expression<'_>) -> bool {
317        self.visit_expression(expression)
318    }
319
320    fn visit_index_name_expression(&mut self, expression: Expression<'_>) -> bool {
321        self.visit_expression(expression)
322    }
323
324    fn visit_type_assertion_expression(&mut self, expression: Expression<'_>) -> bool {
325        self.visit_expression(expression)
326    }
327
328    fn visit_instantiate_expression(&mut self, expression: Expression<'_>) -> bool {
329        self.visit_expression(expression)
330    }
331
332    fn visit_unary_expression(&mut self, expression: Expression<'_>) -> bool {
333        self.visit_expression(expression)
334    }
335
336    fn visit_local_expression(&mut self, expression: Expression<'_>) -> bool {
337        self.visit_expression(expression)
338    }
339
340    fn visit_global_expression(&mut self, expression: Expression<'_>) -> bool {
341        self.visit_expression(expression)
342    }
343
344    fn visit_binary_expression(&mut self, expression: Expression<'_>) -> bool {
345        self.visit_expression(expression)
346    }
347
348    fn visit_error_expression(&mut self, expression: Expression<'_>) -> bool {
349        self.visit_expression(expression)
350    }
351
352    fn visit_type(&mut self, _annotation: Type<'_>) -> bool {
353        false
354    }
355
356    fn visit_reference_type(&mut self, annotation: Type<'_>) -> bool {
357        self.visit_type(annotation)
358    }
359
360    fn visit_table_type(&mut self, annotation: Type<'_>) -> bool {
361        self.visit_type(annotation)
362    }
363
364    fn visit_function_type(&mut self, annotation: Type<'_>) -> bool {
365        self.visit_type(annotation)
366    }
367
368    fn visit_typeof_type(&mut self, annotation: Type<'_>) -> bool {
369        self.visit_type(annotation)
370    }
371
372    fn visit_singleton_bool_type(&mut self, annotation: Type<'_>) -> bool {
373        self.visit_type(annotation)
374    }
375
376    fn visit_singleton_string_type(&mut self, annotation: Type<'_>) -> bool {
377        self.visit_type(annotation)
378    }
379
380    fn visit_group_type(&mut self, annotation: Type<'_>) -> bool {
381        self.visit_type(annotation)
382    }
383
384    fn visit_optional_type(&mut self, annotation: Type<'_>) -> bool {
385        self.visit_type(annotation)
386    }
387
388    fn visit_union_type(&mut self, annotation: Type<'_>) -> bool {
389        self.visit_type(annotation)
390    }
391
392    fn visit_intersection_type(&mut self, annotation: Type<'_>) -> bool {
393        self.visit_type(annotation)
394    }
395
396    fn visit_error_type(&mut self, annotation: Type<'_>) -> bool {
397        self.visit_type(annotation)
398    }
399
400    fn visit_type_pack(&mut self, _annotation: TypePack<'_>) -> bool {
401        false
402    }
403
404    fn visit_explicit_type_pack(&mut self, annotation: TypePack<'_>) -> bool {
405        self.visit_type_pack(annotation)
406    }
407
408    fn visit_variadic_type_pack(&mut self, annotation: TypePack<'_>) -> bool {
409        self.visit_type_pack(annotation)
410    }
411
412    fn visit_generic_type_pack_type(&mut self, annotation: TypePack<'_>) -> bool {
413        self.visit_type_pack(annotation)
414    }
415}
416
417#[derive(Debug, Clone, Copy, PartialEq)]
418pub enum AstNodeRef<'a, 'ast> {
419    Attribute(&'a Attribute<'ast>),
420    GenericType(&'a GenericType<'ast>),
421    GenericTypePack(&'a GenericTypePack<'ast>),
422    Statement(Statement<'ast>),
423    Expression(Expression<'ast>),
424    Type(Type<'ast>),
425    TypePack(TypePack<'ast>),
426}
427
428mod expression;
429mod statement;
430mod types;
431
432pub(crate) use self::statement::{BlockNode, StatementUnit};
433
434pub use self::{
435    expression::{
436        BinaryOp, ConstantNumberParseResult, Expression, ExpressionInit, ExpressionKind, Function,
437        IndexNameOp, StringQuoteStyle, TableItem, UnaryOp,
438    },
439    statement::{
440        Block, ClassMember, Statement, StatementAssign, StatementClass, StatementCompoundAssign,
441        StatementDeclareExternType, StatementDeclareFunction, StatementDeclareGlobal,
442        StatementError, StatementExpression, StatementFunctionDeclaration, StatementGenericFor,
443        StatementIf, StatementLocal, StatementLocalFunction, StatementNumericFor, StatementRepeat,
444        StatementReturn, StatementTag, StatementTypeAlias, StatementTypeFunction, StatementWhile,
445    },
446    types::{
447        Attribute, AttributeKind, DeclaredExternTypeProperty, DeprecatedInfo, TableAccess,
448        TableTypeIndexer, TableTypeProp, Type, TypeKind, TypeList, TypeOrPack, TypePack,
449        TypePackKind,
450    },
451};
452
453pub(super) fn find_attribute<'ast>(
454    attributes: &[&'ast Attribute<'ast>],
455    kind: AttributeKind,
456) -> Option<&'ast Attribute<'ast>> {
457    attributes
458        .iter()
459        .copied()
460        .find(|attribute| attribute.kind == kind)
461}
462
463pub(super) fn visit_statements<V: AstVisitor>(statements: &[Statement<'_>], visitor: &mut V) {
464    for &statement in statements {
465        statement.visit(visitor);
466    }
467}
468
469pub(super) fn visit_expressions<V: AstVisitor>(expressions: &[Expression<'_>], visitor: &mut V) {
470    for &expression in expressions {
471        expression.visit(visitor);
472    }
473}