1use super::*;
2use crate::allocator::AstArena;
3use crate::location::Position;
4use std::fmt;
5use std::marker::PhantomData;
6use std::ptr::NonNull;
7
8#[repr(u8)]
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum StatementTag {
11 Block,
12 Assign,
13 CompoundAssign,
14 Break,
15 Continue,
16 Class,
17 Expression,
18 NumericFor,
19 GenericFor,
20 FunctionDeclaration,
21 If,
22 LocalFunction,
23 Local,
24 TypeAlias,
25 TypeFunction,
26 DeclareGlobal,
27 DeclareFunction,
28 DeclareExternType,
29 Repeat,
30 Return,
31 While,
32 Error,
33}
34
35#[repr(C)]
36#[derive(Debug, PartialEq)]
37pub struct StatementHeader<'ast> {
38 pub tag: StatementTag,
39 pub location: Location,
40 pub has_semicolon: bool,
41 _marker: PhantomData<&'ast ()>,
42}
43
44#[derive(Clone, Copy)]
45pub struct Statement<'ast> {
46 ptr: NonNull<StatementHeader<'ast>>,
47 _marker: PhantomData<&'ast StatementHeader<'ast>>,
48}
49
50impl<'ast> std::ops::Deref for Statement<'ast> {
51 type Target = StatementHeader<'ast>;
52
53 fn deref(&self) -> &Self::Target {
54 self.header()
55 }
56}
57
58impl fmt::Debug for Statement<'_> {
59 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
60 match self.tag {
61 StatementTag::Block => fmt::Debug::fmt(&self.as_block_unchecked(), formatter),
62 StatementTag::Assign => fmt::Debug::fmt(self.as_assign_unchecked(), formatter),
63 StatementTag::CompoundAssign => {
64 fmt::Debug::fmt(self.as_compound_assign_unchecked(), formatter)
65 }
66 StatementTag::Break | StatementTag::Continue => formatter
67 .debug_struct("StatementUnit")
68 .field("tag", &self.tag)
69 .field("location", &self.location)
70 .field("has_semicolon", &self.has_semicolon)
71 .finish(),
72 StatementTag::Class => fmt::Debug::fmt(self.as_class_unchecked(), formatter),
73 StatementTag::Expression => fmt::Debug::fmt(self.as_expression_unchecked(), formatter),
74 StatementTag::NumericFor => fmt::Debug::fmt(self.as_numeric_for_unchecked(), formatter),
75 StatementTag::GenericFor => fmt::Debug::fmt(self.as_generic_for_unchecked(), formatter),
76 StatementTag::FunctionDeclaration => {
77 fmt::Debug::fmt(self.as_function_declaration_unchecked(), formatter)
78 }
79 StatementTag::If => fmt::Debug::fmt(self.as_if_unchecked(), formatter),
80 StatementTag::LocalFunction => {
81 fmt::Debug::fmt(self.as_local_function_unchecked(), formatter)
82 }
83 StatementTag::Local => fmt::Debug::fmt(self.as_local_unchecked(), formatter),
84 StatementTag::TypeAlias => fmt::Debug::fmt(self.as_type_alias_unchecked(), formatter),
85 StatementTag::TypeFunction => {
86 fmt::Debug::fmt(self.as_type_function_unchecked(), formatter)
87 }
88 StatementTag::DeclareGlobal => {
89 fmt::Debug::fmt(self.as_declare_global_unchecked(), formatter)
90 }
91 StatementTag::DeclareFunction => {
92 fmt::Debug::fmt(self.as_declare_function_unchecked(), formatter)
93 }
94 StatementTag::DeclareExternType => {
95 fmt::Debug::fmt(self.as_declare_extern_type_unchecked(), formatter)
96 }
97 StatementTag::Repeat => fmt::Debug::fmt(self.as_repeat_unchecked(), formatter),
98 StatementTag::Return => fmt::Debug::fmt(self.as_return_unchecked(), formatter),
99 StatementTag::While => fmt::Debug::fmt(self.as_while_unchecked(), formatter),
100 StatementTag::Error => fmt::Debug::fmt(self.as_error_unchecked(), formatter),
101 }
102 }
103}
104
105impl PartialEq for Statement<'_> {
106 fn eq(&self, other: &Self) -> bool {
107 match (self.tag, other.tag) {
108 (StatementTag::Block, StatementTag::Block) => self.as_block() == other.as_block(),
109 (StatementTag::Assign, StatementTag::Assign) => self.as_assign() == other.as_assign(),
110 (StatementTag::CompoundAssign, StatementTag::CompoundAssign) => {
111 self.as_compound_assign() == other.as_compound_assign()
112 }
113 (StatementTag::Break, StatementTag::Break)
114 | (StatementTag::Continue, StatementTag::Continue) => {
115 self.location == other.location && self.has_semicolon == other.has_semicolon
116 }
117 (StatementTag::Class, StatementTag::Class) => self.as_class() == other.as_class(),
118 (StatementTag::Expression, StatementTag::Expression) => {
119 self.as_expression() == other.as_expression()
120 }
121 (StatementTag::NumericFor, StatementTag::NumericFor) => {
122 self.as_numeric_for() == other.as_numeric_for()
123 }
124 (StatementTag::GenericFor, StatementTag::GenericFor) => {
125 self.as_generic_for() == other.as_generic_for()
126 }
127 (StatementTag::FunctionDeclaration, StatementTag::FunctionDeclaration) => {
128 self.as_function_declaration() == other.as_function_declaration()
129 }
130 (StatementTag::If, StatementTag::If) => self.as_if() == other.as_if(),
131 (StatementTag::LocalFunction, StatementTag::LocalFunction) => {
132 self.as_local_function() == other.as_local_function()
133 }
134 (StatementTag::Local, StatementTag::Local) => self.as_local() == other.as_local(),
135 (StatementTag::TypeAlias, StatementTag::TypeAlias) => {
136 self.as_type_alias() == other.as_type_alias()
137 }
138 (StatementTag::TypeFunction, StatementTag::TypeFunction) => {
139 self.as_type_function() == other.as_type_function()
140 }
141 (StatementTag::DeclareGlobal, StatementTag::DeclareGlobal) => {
142 self.as_declare_global() == other.as_declare_global()
143 }
144 (StatementTag::DeclareFunction, StatementTag::DeclareFunction) => {
145 self.as_declare_function() == other.as_declare_function()
146 }
147 (StatementTag::DeclareExternType, StatementTag::DeclareExternType) => {
148 self.as_declare_extern_type() == other.as_declare_extern_type()
149 }
150 (StatementTag::Repeat, StatementTag::Repeat) => self.as_repeat() == other.as_repeat(),
151 (StatementTag::Return, StatementTag::Return) => self.as_return() == other.as_return(),
152 (StatementTag::While, StatementTag::While) => self.as_while() == other.as_while(),
153 (StatementTag::Error, StatementTag::Error) => self.as_error() == other.as_error(),
154 _ => false,
155 }
156 }
157}
158
159#[repr(C)]
160pub(crate) struct BlockNode<'ast> {
161 pub base: StatementHeader<'ast>,
162 pub statements: &'ast [Statement<'ast>],
163 pub has_end: bool,
164}
165
166#[derive(Clone, Copy)]
167pub struct Block<'ast> {
168 ptr: NonNull<BlockNode<'ast>>,
169 _marker: PhantomData<&'ast BlockNode<'ast>>,
170}
171
172impl fmt::Debug for Block<'_> {
173 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
174 formatter
175 .debug_struct("Block")
176 .field("location", &self.location())
177 .field("has_semicolon", &self.has_semicolon())
178 .field("has_end", &self.has_end())
179 .field("statements", &self.as_slice())
180 .finish()
181 }
182}
183
184impl PartialEq for Block<'_> {
185 fn eq(&self, other: &Self) -> bool {
186 self.location() == other.location()
187 && self.has_semicolon() == other.has_semicolon()
188 && self.has_end() == other.has_end()
189 && self.as_slice() == other.as_slice()
190 }
191}
192
193impl<'ast> Block<'ast> {
194 pub(crate) fn from_node(node: &'ast mut BlockNode<'ast>) -> Self {
195 Self {
196 ptr: NonNull::from(node),
197 _marker: PhantomData,
198 }
199 }
200
201 #[inline(always)]
202 fn node(&self) -> &BlockNode<'ast> {
203 unsafe { self.ptr.as_ref() }
204 }
205
206 pub fn as_statement(self) -> Statement<'ast> {
207 Statement {
208 ptr: self.ptr.cast(),
209 _marker: PhantomData,
210 }
211 }
212
213 pub fn location(self) -> Location {
214 self.node().base.location
215 }
216
217 pub fn has_semicolon(self) -> bool {
218 self.node().base.has_semicolon
219 }
220
221 pub fn has_end(self) -> bool {
222 self.node().has_end
223 }
224
225 pub fn as_slice(self) -> &'ast [Statement<'ast>] {
226 self.node().statements
227 }
228
229 pub fn len(self) -> usize {
230 self.as_slice().len()
231 }
232
233 pub fn is_empty(self) -> bool {
234 self.as_slice().is_empty()
235 }
236
237 pub fn first(self) -> Option<Statement<'ast>> {
238 self.as_slice().first().copied()
239 }
240
241 pub fn visit<V: AstVisitor>(self, visitor: &mut V) {
242 if !visitor.visit_block(self) {
243 return;
244 }
245
246 visit_statements(self.as_slice(), visitor);
247 }
248}
249
250impl<'ast> BlockNode<'ast> {
251 pub(crate) fn new(
252 statements: &'ast [Statement<'ast>],
253 has_end: bool,
254 location: Location,
255 ) -> Self {
256 Self {
257 base: Statement::new_header(StatementTag::Block, location, false),
258 statements,
259 has_end,
260 }
261 }
262}
263
264impl<'ast> std::ops::Index<usize> for Block<'ast> {
265 type Output = Statement<'ast>;
266
267 fn index(&self, index: usize) -> &Self::Output {
268 &self.node().statements[index]
269 }
270}
271
272impl<'a, 'ast> IntoIterator for &'a Block<'ast> {
273 type Item = Statement<'ast>;
274 type IntoIter = std::iter::Copied<std::slice::Iter<'a, Statement<'ast>>>;
275
276 fn into_iter(self) -> Self::IntoIter {
277 self.as_slice().iter().copied()
278 }
279}
280
281macro_rules! stmt_node {
282 ($name:ident { $($field:ident : $ty:ty),* $(,)? }, $tag:ident) => {
283 #[repr(C)]
284 pub struct $name<'ast> {
285 pub base: StatementHeader<'ast>,
286 $(pub $field: $ty),*
287 }
288
289 impl fmt::Debug for $name<'_> {
290 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
291 let mut debug = formatter.debug_struct(stringify!($name));
292 debug
293 .field("location", &self.location())
294 .field("has_semicolon", &self.has_semicolon());
295 $(debug.field(stringify!($field), &self.$field);)*
296 debug.finish()
297 }
298 }
299
300 impl PartialEq for $name<'_> {
301 fn eq(&self, other: &Self) -> bool {
302 self.location() == other.location()
303 && self.has_semicolon() == other.has_semicolon()
304 $(&& self.$field == other.$field)*
305 }
306 }
307
308 impl<'ast> $name<'ast> {
309 #[allow(clippy::too_many_arguments)]
312 pub fn new(location: Location, has_semicolon: bool, $($field: $ty),*) -> Self {
313 Self {
314 base: Statement::new_header(StatementTag::$tag, location, has_semicolon),
315 $($field),*
316 }
317 }
318
319 pub fn location(&self) -> Location {
320 self.base.location
321 }
322
323 pub fn has_semicolon(&self) -> bool {
324 self.base.has_semicolon
325 }
326 }
327 };
328}
329
330#[repr(C)]
331pub struct StatementUnit<'ast> {
332 pub base: StatementHeader<'ast>,
333}
334
335impl<'ast> StatementUnit<'ast> {
336 pub fn new(tag: StatementTag, location: Location, has_semicolon: bool) -> Self {
337 Self {
338 base: Statement::new_header(tag, location, has_semicolon),
339 }
340 }
341}
342
343impl fmt::Debug for StatementUnit<'_> {
344 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
345 formatter
346 .debug_struct("StatementUnit")
347 .field("tag", &self.base.tag)
348 .field("location", &self.base.location)
349 .field("has_semicolon", &self.base.has_semicolon)
350 .finish()
351 }
352}
353
354impl PartialEq for StatementUnit<'_> {
355 fn eq(&self, other: &Self) -> bool {
356 self.base.tag == other.base.tag
357 && self.base.location == other.base.location
358 && self.base.has_semicolon == other.base.has_semicolon
359 }
360}
361
362stmt_node!(StatementAssign {
363 vars: &'ast [Expression<'ast>],
364 values: &'ast [Expression<'ast>]
365}, Assign);
366stmt_node!(StatementCompoundAssign {
367 var: Expression<'ast>,
368 op: BinaryOp,
369 value: Expression<'ast>
370}, CompoundAssign);
371stmt_node!(StatementClass {
372 name: &'ast Local<'ast>,
373 super_class: Option<Expression<'ast>>,
374 members: &'ast [ClassMember<'ast>],
375 exported: bool
376}, Class);
377stmt_node!(StatementExpression {
378 expr: Expression<'ast>
379}, Expression);
380stmt_node!(StatementNumericFor {
381 name: &'ast Local<'ast>,
382 start: Expression<'ast>,
383 limit: Expression<'ast>,
384 step: Option<Expression<'ast>>,
385 body: Block<'ast>,
386 has_do: bool,
387 do_location: Location
388}, NumericFor);
389stmt_node!(StatementGenericFor {
390 names: &'ast [&'ast Local<'ast>],
391 values: &'ast [Expression<'ast>],
392 body: Block<'ast>,
393 has_in: bool,
394 in_location: Location,
395 has_do: bool,
396 do_location: Location
397}, GenericFor);
398stmt_node!(StatementFunctionDeclaration {
399 name: Expression<'ast>,
400 function: &'ast Function<'ast>
401}, FunctionDeclaration);
402stmt_node!(StatementIf {
403 condition: Expression<'ast>,
404 then_body: Block<'ast>,
405 else_body: Option<Statement<'ast>>,
406 then_location: Option<Location>,
407 else_location: Option<Location>
408}, If);
409stmt_node!(StatementLocalFunction {
410 name: &'ast Local<'ast>,
411 function: &'ast Function<'ast>,
412 is_const: bool,
413 const_keyword_begin: Position
414}, LocalFunction);
415stmt_node!(StatementLocal {
416 bindings: &'ast [&'ast Local<'ast>],
417 values: &'ast [Expression<'ast>],
418 keyword_location: Option<Location>,
419 equals_sign_location: Option<Location>,
420 is_const: bool,
421 is_exported: bool
422}, Local);
423stmt_node!(StatementTypeAlias {
424 name: AstName<'ast>,
425 name_location: Location,
426 generics: &'ast [&'ast GenericType<'ast>],
427 generic_packs: &'ast [&'ast GenericTypePack<'ast>],
428 exported: bool,
429 ty: Type<'ast>
430}, TypeAlias);
431stmt_node!(StatementTypeFunction {
432 name: AstName<'ast>,
433 name_location: Location,
434 exported: bool,
435 body: &'ast Function<'ast>,
436 has_errors: bool
437}, TypeFunction);
438stmt_node!(StatementDeclareGlobal {
439 name: AstName<'ast>,
440 name_location: Location,
441 ty: Type<'ast>
442}, DeclareGlobal);
443stmt_node!(StatementDeclareFunction {
444 name: AstName<'ast>,
445 name_location: Location,
446 params: TypeList<'ast>,
447 param_names: &'ast [ArgumentName<'ast>],
448 variadic: bool,
449 vararg_location: Location,
450 generics: &'ast [&'ast GenericType<'ast>],
451 generic_packs: &'ast [&'ast GenericTypePack<'ast>],
452 return_types: TypePack<'ast>,
453 attributes: &'ast [&'ast Attribute<'ast>]
454}, DeclareFunction);
455stmt_node!(StatementDeclareExternType {
456 name: AstName<'ast>,
457 super_name: Option<AstName<'ast>>,
458 props: &'ast [DeclaredExternTypeProperty<'ast>],
459 indexer: Option<&'ast TableTypeIndexer<'ast>>
460}, DeclareExternType);
461stmt_node!(StatementRepeat {
462 body: Block<'ast>,
463 condition: Expression<'ast>
464}, Repeat);
465stmt_node!(StatementReturn {
466 expressions: &'ast [Expression<'ast>]
467}, Return);
468stmt_node!(StatementWhile {
469 condition: Expression<'ast>,
470 body: Block<'ast>,
471 has_do: bool,
472 do_location: Location
473}, While);
474stmt_node!(StatementError {
475 expressions: &'ast [Expression<'ast>],
476 statements: &'ast [Statement<'ast>],
477 message_index: usize
478}, Error);
479
480impl<'ast> Statement<'ast> {
481 pub const fn new_header(
482 tag: StatementTag,
483 location: Location,
484 has_semicolon: bool,
485 ) -> StatementHeader<'ast> {
486 StatementHeader {
487 tag,
488 location,
489 has_semicolon,
490 _marker: PhantomData,
491 }
492 }
493
494 pub(crate) fn from_node<T>(node: &'ast mut T) -> Self {
495 Self {
496 ptr: NonNull::from(node).cast(),
497 _marker: PhantomData,
498 }
499 }
500
501 pub fn as_ptr(self) -> *const () {
502 self.ptr.as_ptr().cast()
503 }
504
505 #[inline(always)]
506 fn header(&self) -> &StatementHeader<'ast> {
507 unsafe { self.ptr.as_ref() }
508 }
509
510 #[inline(always)]
511 fn header_mut(&mut self) -> &mut StatementHeader<'ast> {
512 unsafe { self.ptr.as_mut() }
513 }
514
515 #[inline(always)]
516 pub fn location(self) -> Location {
517 self.header().location
518 }
519
520 #[inline(always)]
521 pub fn has_semicolon(self) -> bool {
522 self.header().has_semicolon
523 }
524
525 pub fn is_checked_declare_function(&self) -> bool {
526 self.has_declare_function_attribute(AttributeKind::Checked)
527 }
528
529 pub fn has_declare_function_attribute(&self, kind: AttributeKind) -> bool {
530 self.get_declare_function_attribute(kind).is_some()
531 }
532
533 pub fn get_declare_function_attribute(&self, kind: AttributeKind) -> Option<&Attribute<'ast>> {
534 self.as_declare_function()
535 .and_then(|statement| find_attribute(statement.attributes, kind))
536 }
537
538 pub fn as_block(self) -> Option<Block<'ast>> {
539 (self.tag == StatementTag::Block).then(|| Block {
540 ptr: self.ptr.cast(),
541 _marker: PhantomData,
542 })
543 }
544
545 #[inline(always)]
546 pub(crate) fn as_block_unchecked(self) -> Block<'ast> {
547 debug_assert_eq!(self.tag, StatementTag::Block);
548 Block {
549 ptr: self.ptr.cast(),
550 _marker: PhantomData,
551 }
552 }
553
554 pub(crate) fn set_semicolon(mut self, location: Location) {
555 let header = self.header_mut();
556 header.has_semicolon = true;
557 header.location.end = location.end;
558 }
559
560 pub fn visit<V: AstVisitor>(self, visitor: &mut V) {
561 match self.tag {
562 StatementTag::Block => self.as_block_unchecked().visit(visitor),
563 StatementTag::Assign => {
564 let node = self.as_assign_unchecked();
565 if !visitor.visit_assign_statement(self) {
566 return;
567 }
568 visit_expressions(node.vars, visitor);
569 visit_expressions(node.values, visitor);
570 }
571 StatementTag::CompoundAssign => {
572 let node = self.as_compound_assign_unchecked();
573 if !visitor.visit_compound_assign_statement(self) {
574 return;
575 }
576 node.var.visit(visitor);
577 node.value.visit(visitor);
578 }
579 StatementTag::Break => {
580 let _ = visitor.visit_break_statement(self);
581 }
582 StatementTag::Continue => {
583 let _ = visitor.visit_continue_statement(self);
584 }
585 StatementTag::Class => {
586 let node = self.as_class_unchecked();
587 if !visitor.visit_class_statement(self) {
588 return;
589 }
590 if let Some(super_class) = node.super_class {
591 super_class.visit(visitor);
592 }
593 for member in node.members {
594 member.visit(visitor);
595 }
596 }
597 StatementTag::Expression => {
598 let node = self.as_expression_unchecked();
599 if !visitor.visit_expression_statement(self) {
600 return;
601 }
602 node.expr.visit(visitor);
603 }
604 StatementTag::NumericFor => {
605 let node = self.as_numeric_for_unchecked();
606 if !visitor.visit_numeric_for_statement(self) {
607 return;
608 }
609 node.name.visit(visitor);
610 node.start.visit(visitor);
611 node.limit.visit(visitor);
612 if let Some(step) = node.step {
613 step.visit(visitor);
614 }
615 node.body.visit(visitor);
616 }
617 StatementTag::GenericFor => {
618 let node = self.as_generic_for_unchecked();
619 if !visitor.visit_generic_for_statement(self) {
620 return;
621 }
622 for name in node.names {
623 name.visit(visitor);
624 }
625 visit_expressions(node.values, visitor);
626 node.body.visit(visitor);
627 }
628 StatementTag::FunctionDeclaration => {
629 let node = self.as_function_declaration_unchecked();
630 if !visitor.visit_function_declaration_statement(self) {
631 return;
632 }
633 node.name.visit(visitor);
634 node.function.visit(visitor);
635 }
636 StatementTag::If => {
637 let node = self.as_if_unchecked();
638 if !visitor.visit_if_statement(self) {
639 return;
640 }
641 node.condition.visit(visitor);
642 node.then_body.visit(visitor);
643 if let Some(else_body) = node.else_body {
644 else_body.visit(visitor);
645 }
646 }
647 StatementTag::LocalFunction => {
648 let node = self.as_local_function_unchecked();
649 if !visitor.visit_local_function_statement(self) {
650 return;
651 }
652 node.function.visit(visitor);
653 }
654 StatementTag::TypeFunction => {
655 let node = self.as_type_function_unchecked();
656 if !visitor.visit_type_function_statement(self) {
657 return;
658 }
659 node.body.visit(visitor);
660 }
661 StatementTag::Local => {
662 let node = self.as_local_unchecked();
663 if !visitor.visit_local_statement(self) {
664 return;
665 }
666 for binding in node.bindings {
667 binding.visit(visitor);
668 }
669 visit_expressions(node.values, visitor);
670 }
671 StatementTag::TypeAlias => {
672 let node = self.as_type_alias_unchecked();
673 if !visitor.visit_type_alias_statement(self) {
674 return;
675 }
676 for generic in node.generics {
677 generic.visit(visitor);
678 }
679 for generic_pack in node.generic_packs {
680 generic_pack.visit(visitor);
681 }
682 node.ty.visit(visitor);
683 }
684 StatementTag::DeclareGlobal => {
685 let node = self.as_declare_global_unchecked();
686 if !visitor.visit_declare_global_statement(self) {
687 return;
688 }
689 node.ty.visit(visitor);
690 }
691 StatementTag::DeclareFunction => {
692 let node = self.as_declare_function_unchecked();
693 if !visitor.visit_declare_function_statement(self) {
694 return;
695 }
696 node.params.visit(visitor);
697 node.return_types.visit(visitor);
698 }
699 StatementTag::DeclareExternType => {
700 let node = self.as_declare_extern_type_unchecked();
701 if !visitor.visit_declare_extern_type_statement(self) {
702 return;
703 }
704 for prop in node.props {
705 prop.ty.visit(visitor);
706 }
707 if let Some(indexer) = node.indexer {
708 indexer.index_type.visit(visitor);
709 indexer.result_type.visit(visitor);
710 }
711 }
712 StatementTag::Repeat => {
713 let node = self.as_repeat_unchecked();
714 if !visitor.visit_repeat_statement(self) {
715 return;
716 }
717 node.body.visit(visitor);
718 node.condition.visit(visitor);
719 }
720 StatementTag::Return => {
721 let node = self.as_return_unchecked();
722 if !visitor.visit_return_statement(self) {
723 return;
724 }
725 visit_expressions(node.expressions, visitor);
726 }
727 StatementTag::While => {
728 let node = self.as_while_unchecked();
729 if !visitor.visit_while_statement(self) {
730 return;
731 }
732 node.condition.visit(visitor);
733 node.body.visit(visitor);
734 }
735 StatementTag::Error => {
736 let node = self.as_error_unchecked();
737 if !visitor.visit_error_statement(self) {
738 return;
739 }
740 visit_expressions(node.expressions, visitor);
741 visit_statements(node.statements, visitor);
742 }
743 }
744 }
745
746 #[inline(always)]
747 fn cast_ref<T>(self) -> &'ast T {
748 unsafe { self.ptr.cast::<T>().as_ref() }
749 }
750
751 #[inline(always)]
752 fn cast_if_tag<T>(self, tag: StatementTag) -> Option<&'ast T> {
753 (self.tag == tag).then(|| self.cast_ref())
754 }
755
756 #[inline(always)]
757 fn cast_unchecked<T>(self, tag: StatementTag) -> &'ast T {
758 debug_assert_eq!(self.tag, tag);
759 self.cast_ref()
760 }
761
762 #[inline(always)]
763 pub fn as_assign(self) -> Option<&'ast StatementAssign<'ast>> {
764 self.cast_if_tag(StatementTag::Assign)
765 }
766
767 #[inline(always)]
768 pub(crate) fn as_assign_unchecked(self) -> &'ast StatementAssign<'ast> {
769 self.cast_unchecked(StatementTag::Assign)
770 }
771
772 #[inline(always)]
773 pub fn as_compound_assign(self) -> Option<&'ast StatementCompoundAssign<'ast>> {
774 self.cast_if_tag(StatementTag::CompoundAssign)
775 }
776
777 #[inline(always)]
778 pub(crate) fn as_compound_assign_unchecked(self) -> &'ast StatementCompoundAssign<'ast> {
779 self.cast_unchecked(StatementTag::CompoundAssign)
780 }
781
782 #[inline(always)]
783 pub fn as_class(self) -> Option<&'ast StatementClass<'ast>> {
784 self.cast_if_tag(StatementTag::Class)
785 }
786
787 #[inline(always)]
788 pub(crate) fn as_class_unchecked(self) -> &'ast StatementClass<'ast> {
789 self.cast_unchecked(StatementTag::Class)
790 }
791
792 #[inline(always)]
793 pub fn as_expression(self) -> Option<&'ast StatementExpression<'ast>> {
794 self.cast_if_tag(StatementTag::Expression)
795 }
796
797 #[inline(always)]
798 pub(crate) fn as_expression_unchecked(self) -> &'ast StatementExpression<'ast> {
799 self.cast_unchecked(StatementTag::Expression)
800 }
801
802 #[inline(always)]
803 pub fn as_numeric_for(self) -> Option<&'ast StatementNumericFor<'ast>> {
804 self.cast_if_tag(StatementTag::NumericFor)
805 }
806
807 #[inline(always)]
808 pub(crate) fn as_numeric_for_unchecked(self) -> &'ast StatementNumericFor<'ast> {
809 self.cast_unchecked(StatementTag::NumericFor)
810 }
811
812 #[inline(always)]
813 pub fn as_generic_for(self) -> Option<&'ast StatementGenericFor<'ast>> {
814 self.cast_if_tag(StatementTag::GenericFor)
815 }
816
817 #[inline(always)]
818 pub(crate) fn as_generic_for_unchecked(self) -> &'ast StatementGenericFor<'ast> {
819 self.cast_unchecked(StatementTag::GenericFor)
820 }
821
822 #[inline(always)]
823 pub fn as_function_declaration(self) -> Option<&'ast StatementFunctionDeclaration<'ast>> {
824 self.cast_if_tag(StatementTag::FunctionDeclaration)
825 }
826
827 #[inline(always)]
828 pub(crate) fn as_function_declaration_unchecked(
829 self,
830 ) -> &'ast StatementFunctionDeclaration<'ast> {
831 self.cast_unchecked(StatementTag::FunctionDeclaration)
832 }
833
834 #[inline(always)]
835 pub fn as_if(self) -> Option<&'ast StatementIf<'ast>> {
836 self.cast_if_tag(StatementTag::If)
837 }
838
839 #[inline(always)]
840 pub(crate) fn as_if_unchecked(self) -> &'ast StatementIf<'ast> {
841 self.cast_unchecked(StatementTag::If)
842 }
843
844 #[inline(always)]
845 pub fn as_local_function(self) -> Option<&'ast StatementLocalFunction<'ast>> {
846 self.cast_if_tag(StatementTag::LocalFunction)
847 }
848
849 #[inline(always)]
850 pub(crate) fn as_local_function_unchecked(self) -> &'ast StatementLocalFunction<'ast> {
851 self.cast_unchecked(StatementTag::LocalFunction)
852 }
853
854 #[inline(always)]
855 pub fn as_local(self) -> Option<&'ast StatementLocal<'ast>> {
856 self.cast_if_tag(StatementTag::Local)
857 }
858
859 #[inline(always)]
860 pub(crate) fn as_local_unchecked(self) -> &'ast StatementLocal<'ast> {
861 self.cast_unchecked(StatementTag::Local)
862 }
863
864 #[inline(always)]
865 pub fn as_type_alias(self) -> Option<&'ast StatementTypeAlias<'ast>> {
866 self.cast_if_tag(StatementTag::TypeAlias)
867 }
868
869 #[inline(always)]
870 pub(crate) fn as_type_alias_unchecked(self) -> &'ast StatementTypeAlias<'ast> {
871 self.cast_unchecked(StatementTag::TypeAlias)
872 }
873
874 #[inline(always)]
875 pub fn as_type_function(self) -> Option<&'ast StatementTypeFunction<'ast>> {
876 self.cast_if_tag(StatementTag::TypeFunction)
877 }
878
879 #[inline(always)]
880 pub(crate) fn as_type_function_unchecked(self) -> &'ast StatementTypeFunction<'ast> {
881 self.cast_unchecked(StatementTag::TypeFunction)
882 }
883
884 #[inline(always)]
885 pub fn as_declare_global(self) -> Option<&'ast StatementDeclareGlobal<'ast>> {
886 self.cast_if_tag(StatementTag::DeclareGlobal)
887 }
888
889 #[inline(always)]
890 pub(crate) fn as_declare_global_unchecked(self) -> &'ast StatementDeclareGlobal<'ast> {
891 self.cast_unchecked(StatementTag::DeclareGlobal)
892 }
893
894 #[inline(always)]
895 pub fn as_declare_function(self) -> Option<&'ast StatementDeclareFunction<'ast>> {
896 self.cast_if_tag(StatementTag::DeclareFunction)
897 }
898
899 #[inline(always)]
900 pub(crate) fn as_declare_function_unchecked(self) -> &'ast StatementDeclareFunction<'ast> {
901 self.cast_unchecked(StatementTag::DeclareFunction)
902 }
903
904 #[inline(always)]
905 pub fn as_declare_extern_type(self) -> Option<&'ast StatementDeclareExternType<'ast>> {
906 self.cast_if_tag(StatementTag::DeclareExternType)
907 }
908
909 #[inline(always)]
910 pub(crate) fn as_declare_extern_type_unchecked(self) -> &'ast StatementDeclareExternType<'ast> {
911 self.cast_unchecked(StatementTag::DeclareExternType)
912 }
913
914 #[inline(always)]
915 pub fn as_repeat(self) -> Option<&'ast StatementRepeat<'ast>> {
916 self.cast_if_tag(StatementTag::Repeat)
917 }
918
919 #[inline(always)]
920 pub(crate) fn as_repeat_unchecked(self) -> &'ast StatementRepeat<'ast> {
921 self.cast_unchecked(StatementTag::Repeat)
922 }
923
924 #[inline(always)]
925 pub fn as_return(self) -> Option<&'ast StatementReturn<'ast>> {
926 self.cast_if_tag(StatementTag::Return)
927 }
928
929 #[inline(always)]
930 pub(crate) fn as_return_unchecked(self) -> &'ast StatementReturn<'ast> {
931 self.cast_unchecked(StatementTag::Return)
932 }
933
934 #[inline(always)]
935 pub fn as_while(self) -> Option<&'ast StatementWhile<'ast>> {
936 self.cast_if_tag(StatementTag::While)
937 }
938
939 #[inline(always)]
940 pub(crate) fn as_while_unchecked(self) -> &'ast StatementWhile<'ast> {
941 self.cast_unchecked(StatementTag::While)
942 }
943
944 #[inline(always)]
945 pub fn as_error(self) -> Option<&'ast StatementError<'ast>> {
946 self.cast_if_tag(StatementTag::Error)
947 }
948
949 #[inline(always)]
950 pub(crate) fn as_error_unchecked(self) -> &'ast StatementError<'ast> {
951 self.cast_unchecked(StatementTag::Error)
952 }
953}
954
955#[derive(Debug, Clone, Copy, PartialEq)]
956pub enum ClassMember<'ast> {
957 Property {
958 qualifier_location: Location,
959 name: AstName<'ast>,
960 name_location: Location,
961 type_colon_location: Option<Location>,
962 ty: Option<Type<'ast>>,
963 },
964 Method {
965 qualifier_location: Option<Location>,
966 keyword_location: Location,
967 function_name: AstName<'ast>,
968 name_location: Location,
969 function: &'ast Function<'ast>,
970 },
971}
972
973impl ClassMember<'_> {
974 pub fn name(&self) -> AstName<'_> {
975 match self {
976 Self::Property { name, .. } => *name,
977 Self::Method { function_name, .. } => *function_name,
978 }
979 }
980
981 pub fn visit<V: AstVisitor>(&self, visitor: &mut V) {
982 match self {
983 Self::Property { ty, .. } => {
984 if let Some(annotation) = ty {
985 annotation.visit(visitor);
986 }
987 }
988 Self::Method { function, .. } => function.visit(visitor),
989 }
990 }
991}
992
993impl AstArena {
994 pub(crate) fn alloc_block_node<'ast>(&'ast self, node: BlockNode<'ast>) -> Block<'ast> {
995 Block::from_node(self.alloc(node))
996 }
997
998 pub(crate) fn alloc_statement_node<'ast, T: 'ast>(&'ast self, node: T) -> Statement<'ast> {
999 Statement::from_node(self.alloc(node))
1000 }
1001}