1use std::sync::{Arc, RwLock, RwLockReadGuard};
22
23use derive_more::{From, IsVariant, Unwrap};
24
25pub use crate::span::{Span, Spanned};
26
27pub use wgsl_types::syntax::*;
28
29#[cfg(feature = "tokrepr")]
30use tokrepr::TokRepr;
31
32#[cfg(feature = "serde")]
33use serde::{Deserialize, Serialize};
34
35#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
36#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
37#[derive(Default, Clone, Debug, PartialEq)]
38pub struct TranslationUnit {
39 #[cfg(feature = "imports")]
40 pub imports: Vec<ImportStatement>,
41 pub global_directives: Vec<GlobalDirective>,
42 pub global_declarations: Vec<GlobalDeclarationNode>,
43}
44
45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
52#[derive(Clone, Debug)]
53pub struct Ident(Arc<RwLock<String>>);
54
55impl Ident {
56 pub fn new(name: String) -> Ident {
58 Ident(Arc::new(RwLock::new(name)))
60 }
61 pub fn name(&self) -> RwLockReadGuard<'_, String> {
63 self.0.read().unwrap()
64 }
65 pub fn rename(&mut self, name: String) {
67 *self.0.write().unwrap() = name;
68 }
69 pub fn use_count(&self) -> usize {
71 Arc::<_>::strong_count(&self.0)
72 }
73}
74
75impl From<String> for Ident {
76 fn from(name: String) -> Self {
77 Ident::new(name)
78 }
79}
80
81impl PartialEq for Ident {
83 fn eq(&self, other: &Self) -> bool {
84 Arc::ptr_eq(&self.0, &other.0)
85 }
86}
87
88impl Eq for Ident {}
90
91impl std::hash::Hash for Ident {
93 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
94 std::ptr::hash(&*self.0, state)
95 }
96}
97
98#[cfg(feature = "imports")]
99#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
100#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
101#[derive(Clone, Debug, PartialEq)]
102pub struct ImportStatement {
103 #[cfg(feature = "attributes")]
104 pub attributes: Attributes,
105 pub path: Option<ModulePath>,
106 pub content: ImportContent,
107}
108
109#[cfg(feature = "imports")]
110#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
111#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
112#[derive(Clone, Debug, PartialEq, Eq, Hash, IsVariant)]
113pub enum PathOrigin {
114 Absolute,
116 Relative(usize),
118 Package(String),
120}
121
122#[cfg(feature = "imports")]
123#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
124#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
125#[derive(Clone, Debug, PartialEq, Eq, Hash)]
126pub struct ModulePath {
127 pub origin: PathOrigin,
128 pub components: Vec<String>,
129}
130
131#[cfg(feature = "imports")]
132#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
133#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
134#[derive(Clone, Debug, PartialEq)]
135pub struct Import {
136 pub path: Vec<String>,
137 pub content: ImportContent,
138}
139
140#[cfg(feature = "imports")]
141#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
142#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
143#[derive(Clone, Debug, PartialEq, IsVariant)]
144pub enum ImportContent {
145 Item(ImportItem),
146 Collection(Vec<Import>),
147}
148
149#[cfg(feature = "imports")]
150#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
151#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
152#[derive(Clone, Debug, PartialEq)]
153pub struct ImportItem {
154 pub ident: Ident,
155 pub rename: Option<Ident>,
156}
157
158#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
159#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
160#[derive(Clone, Debug, PartialEq, From, IsVariant, Unwrap)]
161pub enum GlobalDirective {
162 Diagnostic(DiagnosticDirective),
163 Enable(EnableDirective),
164 Requires(RequiresDirective),
165}
166
167#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
168#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
169#[derive(Clone, Debug, PartialEq)]
170pub struct DiagnosticDirective {
171 #[cfg(feature = "attributes")]
172 pub attributes: Attributes,
173 pub severity: DiagnosticSeverity,
174 pub rule_name: String,
175}
176
177#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
178#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
179#[derive(Clone, Debug, PartialEq)]
180pub struct EnableDirective {
181 #[cfg(feature = "attributes")]
182 pub attributes: Attributes,
183 pub extensions: Vec<String>,
184}
185
186#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
188#[derive(Clone, Debug, PartialEq)]
189pub struct RequiresDirective {
190 #[cfg(feature = "attributes")]
191 pub attributes: Attributes,
192 pub extensions: Vec<String>,
193}
194
195#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
196#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
197#[derive(Clone, Debug, PartialEq, From, IsVariant, Unwrap)]
198pub enum GlobalDeclaration {
199 Void,
200 Declaration(Declaration),
201 TypeAlias(TypeAlias),
202 Struct(Struct),
203 Function(Function),
204 ConstAssert(ConstAssert),
205}
206
207pub type GlobalDeclarationNode = Spanned<GlobalDeclaration>;
208
209#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
211#[derive(Clone, Debug, PartialEq)]
212pub struct Declaration {
213 pub attributes: Attributes,
214 pub kind: DeclarationKind,
215 pub ident: Ident,
216 pub ty: Option<TypeExpression>,
217 pub initializer: Option<ExpressionNode>,
218}
219
220#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
221#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
222#[derive(Clone, Copy, Debug, PartialEq, Eq, IsVariant)]
223pub enum DeclarationKind {
224 Const,
225 Override,
226 Let,
227 Var(Option<(AddressSpace, Option<AccessMode>)>), }
229
230#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
231#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
232#[derive(Clone, Debug, PartialEq)]
233pub struct TypeAlias {
234 #[cfg(feature = "attributes")]
235 pub attributes: Attributes,
236 pub ident: Ident,
237 pub ty: TypeExpression,
238}
239
240#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
241#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
242#[derive(Clone, Debug, PartialEq)]
243pub struct Struct {
244 #[cfg(feature = "attributes")]
245 pub attributes: Attributes,
246 pub ident: Ident,
247 pub members: Vec<StructMemberNode>,
248}
249
250#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
252#[derive(Clone, Debug, PartialEq)]
253pub struct StructMember {
254 pub attributes: Attributes,
255 pub ident: Ident,
256 pub ty: TypeExpression,
257}
258
259pub type StructMemberNode = Spanned<StructMember>;
260
261#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
262#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
263#[derive(Clone, Debug, PartialEq)]
264pub struct Function {
265 pub attributes: Attributes,
266 pub ident: Ident,
267 pub parameters: Vec<FormalParameter>,
268 pub return_attributes: Attributes,
269 pub return_type: Option<TypeExpression>,
270 pub body: CompoundStatement,
271}
272
273#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
275#[derive(Clone, Debug, PartialEq)]
276pub struct FormalParameter {
277 pub attributes: Attributes,
278 pub ident: Ident,
279 pub ty: TypeExpression,
280}
281
282#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
283#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
284#[derive(Clone, Debug, PartialEq)]
285pub struct ConstAssert {
286 #[cfg(feature = "attributes")]
287 pub attributes: Attributes,
288 pub expression: ExpressionNode,
289}
290
291#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
292#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
293#[derive(Clone, Debug, PartialEq)]
294pub struct DiagnosticAttribute {
295 pub severity: DiagnosticSeverity,
296 pub rule: String,
297}
298
299#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
300#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
301#[derive(Clone, Debug, PartialEq)]
302pub struct InterpolateAttribute {
303 pub ty: InterpolationType,
304 pub sampling: Option<InterpolationSampling>,
305}
306
307#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
308#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
309#[derive(Clone, Debug, PartialEq)]
310pub struct WorkgroupSizeAttribute {
311 pub x: ExpressionNode,
312 pub y: Option<ExpressionNode>,
313 pub z: Option<ExpressionNode>,
314}
315
316#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
317#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
318#[derive(Clone, Debug, PartialEq)]
319pub struct CustomAttribute {
320 pub name: String,
321 pub arguments: Option<Vec<ExpressionNode>>,
322}
323
324#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
325#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
326#[derive(Clone, Debug, PartialEq, From, IsVariant, Unwrap)]
327pub enum Attribute {
328 Align(ExpressionNode),
329 Binding(ExpressionNode),
330 BlendSrc(ExpressionNode),
331 #[from]
332 Builtin(BuiltinValue),
333 Const,
334 #[from]
335 Diagnostic(DiagnosticAttribute),
336 Group(ExpressionNode),
337 Id(ExpressionNode),
338 #[from]
339 Interpolate(InterpolateAttribute),
340 Invariant,
341 Location(ExpressionNode),
342 MustUse,
343 Size(ExpressionNode),
344 #[from]
345 WorkgroupSize(WorkgroupSizeAttribute),
346 Vertex,
347 Fragment,
348 Compute,
349 #[cfg(feature = "naga-ext")]
350 Task,
351 #[cfg(feature = "naga-ext")]
352 Payload(ExpressionNode),
353 #[cfg(feature = "naga-ext")]
354 Mesh(ExpressionNode),
355 #[cfg(feature = "imports")]
356 Publish,
357 #[cfg(feature = "condcomp")]
358 If(ExpressionNode),
359 #[cfg(feature = "condcomp")]
360 Elif(ExpressionNode),
361 #[cfg(feature = "condcomp")]
362 Else,
363 #[cfg(feature = "generics")]
364 #[from]
365 Type(TypeConstraint),
366 #[cfg(feature = "naga-ext")]
367 EarlyDepthTest(Option<ConservativeDepth>),
368 #[from]
369 Custom(CustomAttribute),
370}
371
372impl Attribute {
373 pub fn is_entry_point(&self) -> bool {
374 match self {
375 Attribute::Vertex | Attribute::Fragment | Attribute::Compute => true,
376 #[cfg(feature = "naga-ext")]
377 Attribute::Task | Attribute::Mesh(_) => true,
378 _ => false,
379 }
380 }
381}
382
383pub type AttributeNode = Spanned<Attribute>;
384
385#[cfg(feature = "generics")]
386#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
387#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
388#[derive(Clone, Debug, PartialEq, From)]
389pub struct TypeConstraint {
390 pub ident: Ident,
391 pub variants: Vec<TypeExpression>,
392}
393
394pub type Attributes = Vec<AttributeNode>;
395
396#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
397#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
398#[derive(Clone, Debug, PartialEq, From, IsVariant, Unwrap)]
399pub enum Expression {
400 Literal(LiteralExpression),
401 Parenthesized(ParenthesizedExpression),
402 NamedComponent(NamedComponentExpression),
403 Indexing(IndexingExpression),
404 Unary(UnaryExpression),
405 Binary(BinaryExpression),
406 FunctionCall(FunctionCallExpression),
407 TypeOrIdentifier(TypeExpression),
408}
409
410pub type ExpressionNode = Spanned<Expression>;
411
412#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
413#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
414#[derive(Clone, Copy, Debug, PartialEq, From, IsVariant, Unwrap)]
415pub enum LiteralExpression {
416 Bool(bool),
417 AbstractInt(i64),
418 AbstractFloat(f64),
419 I32(i32),
420 U32(u32),
421 F32(f32),
422 #[from(skip)]
423 F16(f32),
424 #[cfg(feature = "naga-ext")]
425 #[from(skip)]
426 I64(i64),
427 #[cfg(feature = "naga-ext")]
428 #[from(skip)]
429 U64(u64),
430 #[cfg(feature = "naga-ext")]
431 #[from(skip)]
432 F64(f64),
433}
434
435#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
436#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
437#[derive(Clone, Debug, PartialEq)]
438pub struct ParenthesizedExpression {
439 pub expression: ExpressionNode,
440}
441
442#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
443#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
444#[derive(Clone, Debug, PartialEq)]
445pub struct NamedComponentExpression {
446 pub base: ExpressionNode,
447 pub component: Ident,
448}
449
450#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
451#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
452#[derive(Clone, Debug, PartialEq)]
453pub struct IndexingExpression {
454 pub base: ExpressionNode,
455 pub index: ExpressionNode,
456}
457
458#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
459#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
460#[derive(Clone, Debug, PartialEq)]
461pub struct UnaryExpression {
462 pub operator: UnaryOperator,
463 pub operand: ExpressionNode,
464}
465
466#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
467#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
468#[derive(Clone, Debug, PartialEq)]
469pub struct BinaryExpression {
470 pub operator: BinaryOperator,
471 pub left: ExpressionNode,
472 pub right: ExpressionNode,
473}
474
475#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
476#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
477#[derive(Clone, Debug, PartialEq)]
478pub struct FunctionCall {
479 pub ty: TypeExpression,
480 pub arguments: Vec<ExpressionNode>,
481}
482
483pub type FunctionCallExpression = FunctionCall;
484
485#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
486#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
487#[derive(Clone, Debug, PartialEq)]
488pub struct TypeExpression {
489 #[cfg(feature = "imports")]
490 pub path: Option<ModulePath>,
491 pub ident: Ident,
492 pub template_args: TemplateArgs,
493}
494
495#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
496#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
497#[derive(Clone, Debug, PartialEq)]
498pub struct TemplateArg {
499 pub expression: ExpressionNode,
500}
501pub type TemplateArgs = Option<Vec<TemplateArg>>;
502
503#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
504#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
505#[derive(Clone, Debug, PartialEq, From, IsVariant, Unwrap)]
506pub enum Statement {
507 Void,
508 Compound(CompoundStatement),
509 Assignment(AssignmentStatement),
510 Increment(IncrementStatement),
511 Decrement(DecrementStatement),
512 If(IfStatement),
513 Switch(SwitchStatement),
514 Loop(LoopStatement),
515 For(ForStatement),
516 While(WhileStatement),
517 Break(BreakStatement),
518 Continue(ContinueStatement),
519 Return(ReturnStatement),
520 Discard(DiscardStatement),
521 FunctionCall(FunctionCallStatement),
522 ConstAssert(ConstAssertStatement),
523 Declaration(DeclarationStatement),
524}
525
526pub type StatementNode = Spanned<Statement>;
527
528#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
529#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
530#[derive(Clone, Debug, PartialEq, Default)]
531pub struct CompoundStatement {
532 pub attributes: Attributes,
533 pub statements: Vec<StatementNode>,
534}
535
536#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
537#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
538#[derive(Clone, Debug, PartialEq)]
539pub struct AssignmentStatement {
540 #[cfg(feature = "attributes")]
541 pub attributes: Attributes,
542 pub operator: AssignmentOperator,
543 pub lhs: ExpressionNode,
544 pub rhs: ExpressionNode,
545}
546
547#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
548#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
549#[derive(Clone, Debug, PartialEq)]
550pub struct IncrementStatement {
551 #[cfg(feature = "attributes")]
552 pub attributes: Attributes,
553 pub expression: ExpressionNode,
554}
555
556#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
557#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
558#[derive(Clone, Debug, PartialEq)]
559pub struct DecrementStatement {
560 #[cfg(feature = "attributes")]
561 pub attributes: Attributes,
562 pub expression: ExpressionNode,
563}
564
565#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
566#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
567#[derive(Clone, Debug, PartialEq)]
568pub struct IfStatement {
569 pub attributes: Attributes,
570 pub if_clause: IfClause,
571 pub else_if_clauses: Vec<ElseIfClause>,
572 pub else_clause: Option<ElseClause>,
573}
574
575#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
576#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
577#[derive(Clone, Debug, PartialEq)]
578pub struct IfClause {
579 pub expression: ExpressionNode,
580 pub body: CompoundStatement,
581}
582
583#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
584#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
585#[derive(Clone, Debug, PartialEq)]
586pub struct ElseIfClause {
587 #[cfg(feature = "attributes")]
588 pub attributes: Attributes,
589 pub expression: ExpressionNode,
590 pub body: CompoundStatement,
591}
592
593#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
594#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
595#[derive(Clone, Debug, PartialEq)]
596pub struct ElseClause {
597 #[cfg(feature = "attributes")]
598 pub attributes: Attributes,
599 pub body: CompoundStatement,
600}
601
602#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
603#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
604#[derive(Clone, Debug, PartialEq)]
605pub struct SwitchStatement {
606 pub attributes: Attributes,
607 pub expression: ExpressionNode,
608 pub body_attributes: Attributes,
609 pub clauses: Vec<SwitchClause>,
610}
611
612#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
613#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
614#[derive(Clone, Debug, PartialEq)]
615pub struct SwitchClause {
616 #[cfg(feature = "attributes")]
617 pub attributes: Attributes,
618 pub case_selectors: Vec<CaseSelector>,
619 pub body: CompoundStatement,
620}
621
622#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
623#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
624#[derive(Clone, Debug, PartialEq, From, IsVariant, Unwrap)]
625pub enum CaseSelector {
626 Default,
627 Expression(ExpressionNode),
628}
629
630#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
631#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
632#[derive(Clone, Debug, PartialEq)]
633pub struct LoopStatement {
634 pub attributes: Attributes,
635 pub body: CompoundStatement,
636 pub continuing: Option<ContinuingStatement>,
640}
641
642#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
643#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
644#[derive(Clone, Debug, PartialEq)]
645pub struct ContinuingStatement {
646 #[cfg(feature = "attributes")]
647 pub attributes: Attributes,
648 pub body: CompoundStatement,
649 pub break_if: Option<BreakIfStatement>,
653}
654
655#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
656#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
657#[derive(Clone, Debug, PartialEq)]
658pub struct BreakIfStatement {
659 #[cfg(feature = "attributes")]
660 pub attributes: Attributes,
661 pub expression: ExpressionNode,
662}
663
664#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
665#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
666#[derive(Clone, Debug, PartialEq)]
667pub struct ForStatement {
668 pub attributes: Attributes,
669 pub initializer: Option<StatementNode>,
670 pub condition: Option<ExpressionNode>,
671 pub update: Option<StatementNode>,
672 pub body: CompoundStatement,
673}
674
675#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
676#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
677#[derive(Clone, Debug, PartialEq)]
678pub struct WhileStatement {
679 pub attributes: Attributes,
680 pub condition: ExpressionNode,
681 pub body: CompoundStatement,
682}
683
684#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
685#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
686#[derive(Clone, Debug, PartialEq)]
687pub struct BreakStatement {
688 #[cfg(feature = "attributes")]
689 pub attributes: Attributes,
690}
691
692#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
693#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
694#[derive(Clone, Debug, PartialEq)]
695pub struct ContinueStatement {
696 #[cfg(feature = "attributes")]
697 pub attributes: Attributes,
698}
699
700#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
701#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
702#[derive(Clone, Debug, PartialEq)]
703pub struct ReturnStatement {
704 #[cfg(feature = "attributes")]
705 pub attributes: Attributes,
706 pub expression: Option<ExpressionNode>,
707}
708
709#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
710#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
711#[derive(Clone, Debug, PartialEq)]
712pub struct DiscardStatement {
713 #[cfg(feature = "attributes")]
714 pub attributes: Attributes,
715}
716
717#[cfg_attr(feature = "tokrepr", derive(TokRepr))]
718#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
719#[derive(Clone, Debug, PartialEq)]
720pub struct FunctionCallStatement {
721 #[cfg(feature = "attributes")]
722 pub attributes: Attributes,
723 pub call: FunctionCall,
724}
725
726pub type ConstAssertStatement = ConstAssert;
727
728pub type DeclarationStatement = Declaration;