1use itertools::Itertools;
2use num::{BigInt, BigUint, Signed, Zero};
3use spade_common::{
4 location_info::{Loc, WithLocation},
5 name::{Identifier, Path},
6 num_ext::InfallibleToBigInt,
7};
8use std::fmt::Display;
9pub mod testutil;
10
11#[derive(PartialEq, Debug, Clone)]
12pub enum TypeExpression {
13 TypeSpec(Box<Loc<TypeSpec>>),
14 Integer(BigInt),
15 ConstGeneric(Box<Loc<Expression>>),
16}
17impl WithLocation for TypeExpression {}
18
19impl std::fmt::Display for TypeExpression {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 match self {
22 TypeExpression::TypeSpec(inner) => write!(f, "{inner}"),
23 TypeExpression::Integer(inner) => write!(f, "{inner}"),
24 TypeExpression::ConstGeneric(_) => write!(f, "{{...}}"),
25 }
26 }
27}
28
29#[derive(PartialEq, Debug, Clone)]
30pub enum NamedTurbofish {
31 Short(Loc<Identifier>),
32 Full(Loc<Identifier>, Loc<TypeExpression>),
33}
34impl WithLocation for NamedTurbofish {}
35
36#[derive(PartialEq, Debug, Clone)]
37pub enum TurbofishInner {
38 Named(Vec<Loc<NamedTurbofish>>),
39 Positional(Vec<Loc<TypeExpression>>),
40}
41impl WithLocation for TurbofishInner {}
42
43#[derive(PartialEq, Debug, Clone)]
46pub enum TypeSpec {
47 Tuple(Vec<Loc<TypeExpression>>),
48 Array {
49 inner: Box<Loc<TypeExpression>>,
50 size: Box<Loc<TypeExpression>>,
51 },
52 Named(Loc<Path>, Option<Loc<Vec<Loc<TypeExpression>>>>),
53 Inverted(Box<Loc<TypeExpression>>),
59 Wire(Box<Loc<TypeExpression>>),
60 Wildcard,
61}
62impl WithLocation for TypeSpec {}
63
64impl std::fmt::Display for TypeSpec {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 match self {
67 TypeSpec::Tuple(inner) => {
68 write!(f, "({})", inner.iter().map(|i| format!("{i}")).join(", "))
69 }
70 TypeSpec::Array { inner, size } => write!(f, "[{inner}; {size}]"),
71 TypeSpec::Named(name, args) => {
72 let args = match args {
73 Some(a) => a.iter().map(|a| format!("{a}")).join(", "),
74 None => String::new(),
75 };
76 write!(f, "{name}{args}")
77 }
78 TypeSpec::Inverted(inner) => write!(f, "inv {inner}"),
79 TypeSpec::Wire(inner) => write!(f, "&{inner}"),
80 TypeSpec::Wildcard => write!(f, "_"),
81 }
82 }
83}
84
85#[derive(PartialEq, Debug, Clone)]
86pub enum ArgumentPattern {
87 Named(Vec<(Loc<Identifier>, Option<Loc<Pattern>>)>),
88 Positional(Vec<Loc<Pattern>>),
89}
90impl WithLocation for ArgumentPattern {}
91
92#[derive(PartialEq, Debug, Clone)]
93pub enum Pattern {
94 Integer(IntLiteral),
95 Bool(bool),
96 Path(Loc<Path>),
97 Tuple(Vec<Loc<Pattern>>),
98 Array(Vec<Loc<Pattern>>),
99 Type(Loc<Path>, Loc<ArgumentPattern>),
100}
101impl WithLocation for Pattern {}
102
103impl Pattern {
105 pub fn integer(val: i32) -> Self {
106 Pattern::Integer(IntLiteral::Unsized(val.to_bigint()))
107 }
108 pub fn name(name: &str) -> Loc<Self> {
109 Pattern::Path(Path(vec![Identifier(name.to_string()).nowhere()]).nowhere()).nowhere()
110 }
111}
112
113#[derive(PartialEq, Debug, Clone)]
114pub enum NamedArgument {
115 Full(Loc<Identifier>, Loc<Expression>),
116 Short(Loc<Identifier>),
118}
119impl WithLocation for NamedArgument {}
120
121#[derive(PartialEq, Debug, Clone)]
122pub enum ArgumentList {
123 Positional(Vec<Loc<Expression>>),
124 Named(Vec<NamedArgument>),
125}
126impl WithLocation for ArgumentList {}
127
128#[derive(PartialEq, Debug, Clone)]
129pub enum WhereClause {
130 GenericInt {
131 target: Loc<Path>,
132 expression: Loc<Expression>,
133 },
134 TraitBounds {
135 target: Loc<Path>,
136 traits: Vec<Loc<TraitSpec>>,
137 },
138}
139impl WhereClause {
140 pub fn target(&self) -> &Loc<Path> {
141 match self {
142 WhereClause::GenericInt {
143 target,
144 expression: _,
145 } => target,
146 WhereClause::TraitBounds { target, traits: _ } => target,
147 }
148 }
149}
150impl WithLocation for WhereClause {}
151
152#[derive(PartialEq, Debug, Clone)]
153pub enum BinaryOperator {
154 Add,
155 Sub,
156 Mul,
157 Div,
158 Mod,
159 Equals,
160 NotEquals,
161 Lt,
162 Gt,
163 Le,
164 Ge,
165 LogicalAnd,
166 LogicalOr,
167 LogicalXor,
168 LeftShift,
169 RightShift,
170 ArithmeticRightShift,
171 BitwiseAnd,
172 BitwiseOr,
173 BitwiseXor,
174}
175impl WithLocation for BinaryOperator {}
176
177impl std::fmt::Display for BinaryOperator {
178 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179 match self {
180 BinaryOperator::Add => write!(f, "+"),
181 BinaryOperator::Sub => write!(f, "-"),
182 BinaryOperator::Mul => write!(f, "*"),
183 BinaryOperator::Div => write!(f, "/"),
184 BinaryOperator::Mod => write!(f, "%"),
185 BinaryOperator::Equals => write!(f, "=="),
186 BinaryOperator::NotEquals => write!(f, "!="),
187 BinaryOperator::Lt => write!(f, "<"),
188 BinaryOperator::Gt => write!(f, ">"),
189 BinaryOperator::Le => write!(f, "<="),
190 BinaryOperator::Ge => write!(f, ">="),
191 BinaryOperator::LogicalAnd => write!(f, "&"),
192 BinaryOperator::LogicalOr => write!(f, "|"),
193 BinaryOperator::LogicalXor => write!(f, "^"),
194 BinaryOperator::LeftShift => write!(f, "<<"),
195 BinaryOperator::RightShift => write!(f, ">>"),
196 BinaryOperator::ArithmeticRightShift => write!(f, ">>>"),
197 BinaryOperator::BitwiseAnd => write!(f, "&&"),
198 BinaryOperator::BitwiseOr => write!(f, "||"),
199 BinaryOperator::BitwiseXor => write!(f, "^^"),
200 }
201 }
202}
203
204#[derive(PartialEq, Debug, Clone)]
205pub enum UnaryOperator {
206 Sub,
207 Not,
208 BitwiseNot,
209 Dereference,
210 Reference,
211}
212impl WithLocation for UnaryOperator {}
213
214impl std::fmt::Display for UnaryOperator {
215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216 match self {
217 UnaryOperator::Sub => write!(f, "-"),
218 UnaryOperator::Not => write!(f, "!"),
219 UnaryOperator::BitwiseNot => write!(f, "~"),
220 UnaryOperator::Dereference => write!(f, "*"),
221 UnaryOperator::Reference => write!(f, "&"),
222 }
223 }
224}
225
226#[derive(PartialEq, Debug, Clone)]
227pub enum PipelineStageReference {
228 Relative(Loc<TypeExpression>),
229 Absolute(Loc<Identifier>),
230}
231
232#[derive(PartialEq, Debug, Clone)]
233pub enum CallKind {
234 Function,
235 Entity(Loc<()>),
236 Pipeline(Loc<()>, Loc<TypeExpression>),
237}
238impl WithLocation for CallKind {}
239
240#[derive(PartialEq, Debug, Clone)]
241pub enum BitLiteral {
242 Low,
243 High,
244 HighImp,
245}
246impl WithLocation for BitLiteral {}
247
248#[derive(PartialEq, Debug, Clone)]
249pub enum Expression {
250 Identifier(Loc<Path>),
251 IntLiteral(IntLiteral),
252 BoolLiteral(bool),
253 BitLiteral(BitLiteral),
254 ArrayLiteral(Vec<Loc<Expression>>),
256 ArrayShorthandLiteral(Box<Loc<Expression>>, Box<Loc<Expression>>),
259 Index(Box<Loc<Expression>>, Box<Loc<Expression>>),
260 RangeIndex {
261 target: Box<Loc<Expression>>,
262 start: Box<Loc<Expression>>,
264 end: Box<Loc<Expression>>,
265 },
266 TupleLiteral(Vec<Loc<Expression>>),
267 TupleIndex(Box<Loc<Expression>>, Loc<u128>),
268 FieldAccess(Box<Loc<Expression>>, Loc<Identifier>),
269 CreatePorts,
270 Lambda {
271 unit_kind: Loc<UnitKind>,
272 args: Loc<Vec<Loc<Pattern>>>,
273 body: Box<Loc<Block>>,
274 },
275 Call {
276 kind: CallKind,
277 callee: Loc<Path>,
278 args: Loc<ArgumentList>,
279 turbofish: Option<Loc<TurbofishInner>>,
280 },
281 MethodCall {
282 target: Box<Loc<Expression>>,
283 name: Loc<Identifier>,
284 args: Loc<ArgumentList>,
285 kind: CallKind,
286 turbofish: Option<Loc<TurbofishInner>>,
287 },
288 If(
289 Box<Loc<Expression>>,
290 Box<Loc<Expression>>,
291 Box<Loc<Expression>>,
292 ),
293 TypeLevelIf(
294 Box<Loc<Expression>>,
295 Box<Loc<Expression>>,
296 Box<Loc<Expression>>,
297 ),
298 Match(
299 Box<Loc<Expression>>,
300 Loc<Vec<(Loc<Pattern>, Loc<Expression>)>>,
301 ),
302 UnaryOperator(Loc<UnaryOperator>, Box<Loc<Expression>>),
303 BinaryOperator(
304 Box<Loc<Expression>>,
305 Loc<BinaryOperator>,
306 Box<Loc<Expression>>,
307 ),
308 Block(Box<Block>),
309 PipelineReference {
311 stage_kw_and_reference_loc: Loc<()>,
316 stage: PipelineStageReference,
321 name: Loc<Identifier>,
326 },
327 StageValid,
328 StageReady,
329 StaticUnreachable(Loc<String>),
330}
331impl WithLocation for Expression {}
332
333impl Expression {
334 pub fn int_literal_signed(val: i32) -> Self {
335 Self::IntLiteral(IntLiteral::unsized_(val))
336 }
337
338 pub fn as_int_literal(self) -> Option<IntLiteral> {
339 match self {
340 Expression::IntLiteral(lit) => Some(lit),
341 _ => None,
342 }
343 }
344
345 pub fn assume_block(&self) -> &Block {
346 if let Expression::Block(inner) = self {
347 inner
348 } else {
349 panic!("Expected block")
350 }
351 }
352
353 pub fn variant_str(&self) -> &'static str {
354 match self {
355 Expression::Identifier(_) => "identifier",
356 Expression::IntLiteral(_) => "int literal",
357 Expression::BoolLiteral(_) => "bool literal",
358 Expression::BitLiteral(_) => "bit literal",
359 Expression::ArrayLiteral(_) => "array literal",
360 Expression::ArrayShorthandLiteral(_, _) => "array shorthand literal",
361 Expression::CreatePorts => "port",
362 Expression::Index(_, _) => "index",
363 Expression::RangeIndex { .. } => "range index",
364 Expression::TupleLiteral(_) => "tuple literal",
365 Expression::TupleIndex(_, _) => "tuple index",
366 Expression::FieldAccess(_, _) => "field access",
367 Expression::If(_, _, _) => "if",
368 Expression::TypeLevelIf(_, _, _) => "type level if",
369 Expression::Match(_, _) => "match",
370 Expression::Lambda { .. } => "lambda",
371 Expression::Call { .. } => "call",
372 Expression::MethodCall { .. } => "method call",
373 Expression::UnaryOperator(_, _) => "unary operator",
374 Expression::BinaryOperator(_, _, _) => "binary operator",
375 Expression::Block(_) => "block",
376 Expression::PipelineReference { .. } => "pipeline reference",
377 Expression::StageValid => "stage.valid",
378 Expression::StageReady => "stage.ready",
379 Expression::StaticUnreachable(_) => "static_unreachable",
380 }
381 }
382}
383
384#[derive(PartialEq, Debug, Clone)]
387pub enum IntLiteral {
388 Unsized(BigInt),
389 Signed { val: BigInt, size: BigUint },
390 Unsigned { val: BigUint, size: BigUint },
391}
392impl WithLocation for IntLiteral {}
393
394impl IntLiteral {
395 pub fn unsized_(val: i32) -> IntLiteral {
396 IntLiteral::Unsized(val.to_bigint())
397 }
398
399 pub fn as_signed(self) -> BigInt {
402 match self {
403 IntLiteral::Signed { val, size: _ } => val,
404 IntLiteral::Unsigned { val, size: _ } => val.to_bigint(),
405 IntLiteral::Unsized(val) => val,
406 }
407 }
408
409 pub fn as_unsigned(self) -> Option<BigUint> {
412 match self {
413 IntLiteral::Signed { val, size: _ } | IntLiteral::Unsized(val) => {
414 if val >= BigInt::zero() {
415 Some(val.to_biguint().unwrap())
416 } else {
417 None
418 }
419 }
420 IntLiteral::Unsigned { val, size: _ } => Some(val),
421 }
422 }
423
424 pub fn is_negative(&self) -> bool {
425 match self {
426 IntLiteral::Unsized(val) | IntLiteral::Signed { val, size: _ } => val.is_negative(),
427 IntLiteral::Unsigned { .. } => false,
428 }
429 }
430}
431
432impl Display for IntLiteral {
433 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
434 match self {
435 IntLiteral::Unsized(val) | IntLiteral::Signed { val, .. } => write!(f, "{}", val),
437 IntLiteral::Unsigned { val, .. } => write!(f, "{}", val),
438 }
439 }
440}
441
442#[derive(PartialEq, Debug, Clone)]
443pub struct Block {
444 pub statements: Vec<Loc<Statement>>,
445 pub result: Option<Loc<Expression>>,
446}
447impl WithLocation for Block {}
448
449#[derive(PartialEq, Debug, Clone)]
450pub struct Binding {
451 pub pattern: Loc<Pattern>,
452 pub ty: Option<Loc<TypeSpec>>,
453 pub value: Loc<Expression>,
454 pub attrs: AttributeList,
455}
456
457#[derive(PartialEq, Debug, Clone)]
458pub enum Statement {
459 Label(Loc<Identifier>),
460 Declaration(Vec<Loc<Identifier>>),
461 Binding(Binding),
462 Expression(Loc<Expression>),
463 PipelineRegMarker(Option<Loc<TypeExpression>>, Option<Loc<Expression>>),
464 Register(Loc<Register>),
465 Set {
468 target: Loc<Expression>,
469 value: Loc<Expression>,
470 },
471 Assert(Loc<Expression>),
472}
473impl WithLocation for Statement {}
474
475impl Statement {
476 pub fn binding(
478 pattern: Loc<Pattern>,
479 ty: Option<Loc<TypeSpec>>,
480 value: Loc<Expression>,
481 ) -> Self {
482 Self::Binding(Binding {
483 pattern,
484 ty,
485 value,
486 attrs: AttributeList::empty(),
487 })
488 }
489}
490
491#[derive(PartialEq, Debug, Clone)]
493pub enum TypeParam {
494 TypeName {
495 name: Loc<Identifier>,
496 traits: Vec<Loc<TraitSpec>>,
497 },
498 TypeWithMeta {
499 meta: Loc<Identifier>,
500 name: Loc<Identifier>,
501 },
502}
503impl WithLocation for TypeParam {}
504impl TypeParam {
505 pub fn name(&self) -> &Loc<Identifier> {
506 match self {
507 TypeParam::TypeName { name, traits: _ } => name,
508 TypeParam::TypeWithMeta { meta: _, name } => name,
509 }
510 }
511}
512
513#[derive(PartialEq, Debug, Clone)]
514pub enum GenericBound {
515 IntegerConstraint(Loc<Path>, Loc<Expression>),
516 TypeConstraint(Loc<Path>, Vec<Loc<Identifier>>),
517}
518
519impl WithLocation for GenericBound {}
520
521impl GenericBound {
522 pub fn path(&self) -> &Loc<Path> {
523 match self {
524 GenericBound::IntegerConstraint(path, _) => path,
525 GenericBound::TypeConstraint(path, _) => path,
526 }
527 }
528}
529
530#[derive(PartialEq, Debug, Clone)]
531pub enum Attribute {
532 Optimize {
533 passes: Vec<Loc<String>>,
534 },
535 NoMangle {
536 all: bool,
537 },
538 Fsm {
539 state: Option<Loc<Identifier>>,
540 },
541 WalTraceable {
542 suffix: Option<Loc<Identifier>>,
543 uses_clk: bool,
544 uses_rst: bool,
545 },
546 WalTrace {
547 clk: Option<Loc<Expression>>,
548 rst: Option<Loc<Expression>>,
549 },
550 WalSuffix {
552 suffix: Loc<Identifier>,
553 },
554 Documentation {
555 content: String,
556 },
557 SurferTranslator(String),
558}
559
560impl Attribute {
561 pub fn name(&self) -> &str {
562 match self {
563 Attribute::Optimize { passes: _ } => "optimize",
564 Attribute::NoMangle { .. } => "no_mangle",
565 Attribute::Fsm { state: _ } => "fsm",
566 Attribute::WalTraceable { .. } => "wal_traceable",
567 Attribute::WalTrace { .. } => "wal_trace",
568 Attribute::WalSuffix { .. } => "wal_suffix",
569 Attribute::Documentation { .. } => "doc",
570 Attribute::SurferTranslator(_) => "surfer_translator",
571 }
572 }
573}
574
575impl WithLocation for Attribute {}
576
577#[derive(PartialEq, Debug, Clone)]
578pub struct AttributeList(pub Vec<Loc<Attribute>>);
579impl AttributeList {
580 pub fn empty() -> Self {
581 Self(vec![])
582 }
583
584 pub fn from_vec(attrs: Vec<Loc<Attribute>>) -> Self {
585 Self(attrs)
586 }
587}
588
589#[derive(PartialEq, Debug, Clone)]
590pub struct ParameterList {
591 pub self_: Option<Loc<()>>,
592 pub args: Vec<(AttributeList, Loc<Identifier>, Loc<TypeSpec>)>,
593}
594impl WithLocation for ParameterList {}
595
596impl ParameterList {
597 pub fn without_self(args: Vec<(AttributeList, Loc<Identifier>, Loc<TypeSpec>)>) -> Self {
598 Self { self_: None, args }
599 }
600
601 pub fn with_self(self_: Loc<()>, args: Vec<(Loc<Identifier>, Loc<TypeSpec>)>) -> Self {
602 Self {
603 self_: Some(self_),
604 args: args
605 .into_iter()
606 .map(|(n, t)| (AttributeList::empty(), n, t))
607 .collect(),
608 }
609 }
610}
611
612#[derive(PartialEq, Debug, Clone)]
613pub enum UnitKind {
614 Function,
615 Entity,
616 Pipeline(Loc<TypeExpression>),
617}
618impl WithLocation for UnitKind {}
619
620impl UnitKind {
621 pub fn is_pipeline(&self) -> bool {
622 match self {
623 UnitKind::Function => false,
624 UnitKind::Entity => false,
625 UnitKind::Pipeline(_) => true,
626 }
627 }
628}
629
630impl std::fmt::Display for UnitKind {
631 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
632 match self {
633 UnitKind::Function => write!(f, "fn"),
634 UnitKind::Entity => write!(f, "entity"),
635 UnitKind::Pipeline(_) => write!(f, "pipeline"),
636 }
637 }
638}
639
640#[derive(PartialEq, Debug, Clone)]
641pub struct UnitHead {
642 pub extern_token: Option<Loc<()>>,
643 pub attributes: AttributeList,
644 pub unit_kind: Loc<UnitKind>,
645 pub name: Loc<Identifier>,
646 pub inputs: Loc<ParameterList>,
647 pub output_type: Option<(Loc<()>, Loc<TypeSpec>)>,
648 pub type_params: Option<Loc<Vec<Loc<TypeParam>>>>,
649 pub where_clauses: Vec<WhereClause>,
650}
651impl WithLocation for UnitHead {}
652
653#[derive(PartialEq, Debug, Clone)]
654pub struct Unit {
655 pub head: UnitHead,
656 pub body: Option<Loc<Expression>>,
659}
660impl WithLocation for Unit {}
661
662#[derive(PartialEq, Debug, Clone)]
663pub struct Register {
664 pub pattern: Loc<Pattern>,
665 pub clock: Loc<Expression>,
666 pub reset: Option<(Loc<Expression>, Loc<Expression>)>,
667 pub initial: Option<Loc<Expression>>,
668 pub value: Loc<Expression>,
669 pub value_type: Option<Loc<TypeSpec>>,
670 pub attributes: AttributeList,
671}
672impl WithLocation for Register {}
673
674#[derive(PartialEq, Debug, Clone)]
676pub struct TraitDef {
677 pub name: Loc<Identifier>,
678 pub type_params: Option<Loc<Vec<Loc<TypeParam>>>>,
679 pub where_clauses: Vec<WhereClause>,
680 pub methods: Vec<Loc<UnitHead>>,
681}
682impl WithLocation for TraitDef {}
683
684#[derive(PartialEq, Debug, Clone)]
686pub struct TraitSpec {
687 pub path: Loc<Path>,
688 pub type_params: Option<Loc<Vec<Loc<TypeExpression>>>>,
689}
690impl WithLocation for TraitSpec {}
691
692#[derive(PartialEq, Debug, Clone)]
693pub struct ImplBlock {
694 pub r#trait: Option<Loc<TraitSpec>>,
695 pub type_params: Option<Loc<Vec<Loc<TypeParam>>>>,
696 pub where_clauses: Vec<WhereClause>,
697 pub target: Loc<TypeSpec>,
698 pub units: Vec<Loc<Unit>>,
699}
700impl WithLocation for ImplBlock {}
701
702#[derive(PartialEq, Debug, Clone)]
704pub struct Enum {
705 pub attributes: AttributeList,
706 pub name: Loc<Identifier>,
707 pub variants: Vec<EnumVariant>,
708}
709impl WithLocation for Enum {}
710
711#[derive(PartialEq, Debug, Clone)]
712pub struct EnumVariant {
713 pub attributes: AttributeList,
714 pub name: Loc<Identifier>,
715 pub args: Option<Loc<ParameterList>>,
716}
717
718#[derive(PartialEq, Debug, Clone)]
719pub struct Struct {
720 pub attributes: AttributeList,
721 pub name: Loc<Identifier>,
722 pub members: Loc<ParameterList>,
723 pub port_keyword: Option<Loc<()>>,
724}
725impl WithLocation for Struct {}
726
727impl Struct {
728 pub fn is_port(&self) -> bool {
729 self.port_keyword.is_some()
730 }
731}
732
733#[derive(PartialEq, Debug, Clone)]
734pub enum TypeDeclKind {
735 Enum(Loc<Enum>),
736 Struct(Loc<Struct>),
737}
738
739#[derive(PartialEq, Debug, Clone)]
741pub struct TypeDeclaration {
742 pub name: Loc<Identifier>,
743 pub kind: TypeDeclKind,
744 pub generic_args: Option<Loc<Vec<Loc<TypeParam>>>>,
745}
746impl WithLocation for TypeDeclaration {}
747
748#[derive(PartialEq, Debug, Clone)]
749pub struct UseStatement {
750 pub path: Loc<Path>,
751 pub alias: Option<Loc<Identifier>>,
752}
753impl WithLocation for UseStatement {}
754
755#[derive(PartialEq, Debug, Clone)]
758pub enum Item {
759 Unit(Loc<Unit>),
760 TraitDef(Loc<TraitDef>),
761 Type(Loc<TypeDeclaration>),
762 ExternalMod(Loc<Identifier>),
763 Module(Loc<Module>),
764 Use(Loc<UseStatement>),
765 ImplBlock(Loc<ImplBlock>),
766}
767impl WithLocation for Item {}
768
769impl Item {
770 pub fn name(&self) -> Option<&Identifier> {
771 match self {
772 Item::Unit(u) => Some(&u.head.name.inner),
773 Item::TraitDef(t) => Some(&t.name.inner),
774 Item::Type(t) => Some(&t.name.inner),
775 Item::Module(m) => Some(&m.name.inner),
776 Item::ExternalMod(name) => Some(name),
777 Item::Use(u) => u.alias.as_ref().map(|name| &name.inner),
778 Item::ImplBlock(_) => None,
779 }
780 }
781
782 pub fn variant_str(&self) -> &'static str {
783 match self {
784 Item::Unit(_) => "unit",
785 Item::TraitDef(_) => "trait definition",
786 Item::Type(_) => "type",
787 Item::Module(_) => "module",
788 Item::ExternalMod(_) => "module",
789 Item::Use(_) => "use",
790 Item::ImplBlock(_) => "impl",
791 }
792 }
793}
794
795#[derive(PartialEq, Debug, Clone)]
796pub struct Module {
797 pub name: Loc<Identifier>,
798 pub body: Loc<ModuleBody>,
799}
800impl WithLocation for Module {}
801
802#[derive(PartialEq, Debug, Clone)]
803pub struct ModuleBody {
804 pub members: Vec<Item>,
805 pub documentation: Vec<String>,
806}
807impl WithLocation for ModuleBody {}