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 Call {
271 kind: CallKind,
272 callee: Loc<Path>,
273 args: Loc<ArgumentList>,
274 turbofish: Option<Loc<TurbofishInner>>,
275 },
276 MethodCall {
277 target: Box<Loc<Expression>>,
278 name: Loc<Identifier>,
279 args: Loc<ArgumentList>,
280 kind: CallKind,
281 turbofish: Option<Loc<TurbofishInner>>,
282 },
283 If(
284 Box<Loc<Expression>>,
285 Box<Loc<Expression>>,
286 Box<Loc<Expression>>,
287 ),
288 TypeLevelIf(
289 Box<Loc<Expression>>,
290 Box<Loc<Expression>>,
291 Box<Loc<Expression>>,
292 ),
293 Match(
294 Box<Loc<Expression>>,
295 Loc<Vec<(Loc<Pattern>, Loc<Expression>)>>,
296 ),
297 UnaryOperator(Loc<UnaryOperator>, Box<Loc<Expression>>),
298 BinaryOperator(
299 Box<Loc<Expression>>,
300 Loc<BinaryOperator>,
301 Box<Loc<Expression>>,
302 ),
303 Block(Box<Block>),
304 PipelineReference {
306 stage_kw_and_reference_loc: Loc<()>,
311 stage: PipelineStageReference,
316 name: Loc<Identifier>,
321 },
322 StageValid,
323 StageReady,
324}
325impl WithLocation for Expression {}
326
327impl Expression {
328 pub fn int_literal_signed(val: i32) -> Self {
329 Self::IntLiteral(IntLiteral::unsized_(val))
330 }
331
332 pub fn as_int_literal(self) -> Option<IntLiteral> {
333 match self {
334 Expression::IntLiteral(lit) => Some(lit),
335 _ => None,
336 }
337 }
338
339 pub fn assume_block(&self) -> &Block {
340 if let Expression::Block(inner) = self {
341 inner
342 } else {
343 panic!("Expected block")
344 }
345 }
346
347 pub fn variant_str(&self) -> &'static str {
348 match self {
349 Expression::Identifier(_) => "identifier",
350 Expression::IntLiteral(_) => "int literal",
351 Expression::BoolLiteral(_) => "bool literal",
352 Expression::BitLiteral(_) => "bit literal",
353 Expression::ArrayLiteral(_) => "array literal",
354 Expression::ArrayShorthandLiteral(_, _) => "array shorthand literal",
355 Expression::CreatePorts => "port",
356 Expression::Index(_, _) => "index",
357 Expression::RangeIndex { .. } => "range index",
358 Expression::TupleLiteral(_) => "tuple literal",
359 Expression::TupleIndex(_, _) => "tuple index",
360 Expression::FieldAccess(_, _) => "field access",
361 Expression::If(_, _, _) => "if",
362 Expression::TypeLevelIf(_, _, _) => "type level if",
363 Expression::Match(_, _) => "match",
364 Expression::Call { .. } => "call",
365 Expression::MethodCall { .. } => "method call",
366 Expression::UnaryOperator(_, _) => "unary operator",
367 Expression::BinaryOperator(_, _, _) => "binary operator",
368 Expression::Block(_) => "block",
369 Expression::PipelineReference { .. } => "pipeline reference",
370 Expression::StageValid => "stage.valid",
371 Expression::StageReady => "stage.ready",
372 }
373 }
374}
375
376#[derive(PartialEq, Debug, Clone)]
379pub enum IntLiteral {
380 Unsized(BigInt),
381 Signed { val: BigInt, size: BigUint },
382 Unsigned { val: BigUint, size: BigUint },
383}
384impl WithLocation for IntLiteral {}
385
386impl IntLiteral {
387 pub fn unsized_(val: i32) -> IntLiteral {
388 IntLiteral::Unsized(val.to_bigint())
389 }
390
391 pub fn as_signed(self) -> BigInt {
394 match self {
395 IntLiteral::Signed { val, size: _ } => val,
396 IntLiteral::Unsigned { val, size: _ } => val.to_bigint(),
397 IntLiteral::Unsized(val) => val,
398 }
399 }
400
401 pub fn as_unsigned(self) -> Option<BigUint> {
404 match self {
405 IntLiteral::Signed { val, size: _ } | IntLiteral::Unsized(val) => {
406 if val >= BigInt::zero() {
407 Some(val.to_biguint().unwrap())
408 } else {
409 None
410 }
411 }
412 IntLiteral::Unsigned { val, size: _ } => Some(val),
413 }
414 }
415
416 pub fn is_negative(&self) -> bool {
417 match self {
418 IntLiteral::Unsized(val) | IntLiteral::Signed { val, size: _ } => val.is_negative(),
419 IntLiteral::Unsigned { .. } => false,
420 }
421 }
422}
423
424impl Display for IntLiteral {
425 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
426 match self {
427 IntLiteral::Unsized(val) | IntLiteral::Signed { val, .. } => write!(f, "{}", val),
429 IntLiteral::Unsigned { val, .. } => write!(f, "{}", val),
430 }
431 }
432}
433
434#[derive(PartialEq, Debug, Clone)]
435pub struct Block {
436 pub statements: Vec<Loc<Statement>>,
437 pub result: Option<Loc<Expression>>,
438}
439impl WithLocation for Block {}
440
441#[derive(PartialEq, Debug, Clone)]
442pub struct Binding {
443 pub pattern: Loc<Pattern>,
444 pub ty: Option<Loc<TypeSpec>>,
445 pub value: Loc<Expression>,
446 pub attrs: AttributeList,
447}
448
449#[derive(PartialEq, Debug, Clone)]
450pub enum Statement {
451 Label(Loc<Identifier>),
452 Declaration(Vec<Loc<Identifier>>),
453 Binding(Binding),
454 Expression(Loc<Expression>),
455 PipelineRegMarker(Option<Loc<TypeExpression>>, Option<Loc<Expression>>),
456 Register(Loc<Register>),
457 Set {
460 target: Loc<Expression>,
461 value: Loc<Expression>,
462 },
463 Assert(Loc<Expression>),
464}
465impl WithLocation for Statement {}
466
467impl Statement {
468 pub fn binding(
470 pattern: Loc<Pattern>,
471 ty: Option<Loc<TypeSpec>>,
472 value: Loc<Expression>,
473 ) -> Self {
474 Self::Binding(Binding {
475 pattern,
476 ty,
477 value,
478 attrs: AttributeList::empty(),
479 })
480 }
481}
482
483#[derive(PartialEq, Debug, Clone)]
485pub enum TypeParam {
486 TypeName {
487 name: Loc<Identifier>,
488 traits: Vec<Loc<TraitSpec>>,
489 },
490 TypeWithMeta {
491 meta: Loc<Identifier>,
492 name: Loc<Identifier>,
493 },
494}
495impl WithLocation for TypeParam {}
496impl TypeParam {
497 pub fn name(&self) -> &Loc<Identifier> {
498 match self {
499 TypeParam::TypeName { name, traits: _ } => name,
500 TypeParam::TypeWithMeta { meta: _, name } => name,
501 }
502 }
503}
504
505#[derive(PartialEq, Debug, Clone)]
506pub enum GenericBound {
507 IntegerConstraint(Loc<Path>, Loc<Expression>),
508 TypeConstraint(Loc<Path>, Vec<Loc<Identifier>>),
509}
510
511impl WithLocation for GenericBound {}
512
513impl GenericBound {
514 pub fn path(&self) -> &Loc<Path> {
515 match self {
516 GenericBound::IntegerConstraint(path, _) => path,
517 GenericBound::TypeConstraint(path, _) => path,
518 }
519 }
520}
521
522#[derive(PartialEq, Debug, Clone)]
523pub enum Attribute {
524 Optimize {
525 passes: Vec<Loc<String>>,
526 },
527 NoMangle {
528 all: bool,
529 },
530 Fsm {
531 state: Option<Loc<Identifier>>,
532 },
533 WalTraceable {
534 suffix: Option<Loc<Identifier>>,
535 uses_clk: bool,
536 uses_rst: bool,
537 },
538 WalTrace {
539 clk: Option<Loc<Expression>>,
540 rst: Option<Loc<Expression>>,
541 },
542 WalSuffix {
544 suffix: Loc<Identifier>,
545 },
546 Documentation {
547 content: String,
548 },
549}
550
551impl Attribute {
552 pub fn name(&self) -> &str {
553 match self {
554 Attribute::Optimize { passes: _ } => "optimize",
555 Attribute::NoMangle { .. } => "no_mangle",
556 Attribute::Fsm { state: _ } => "fsm",
557 Attribute::WalTraceable { .. } => "wal_traceable",
558 Attribute::WalTrace { .. } => "wal_trace",
559 Attribute::WalSuffix { .. } => "wal_suffix",
560 Attribute::Documentation { .. } => "doc",
561 }
562 }
563}
564
565impl WithLocation for Attribute {}
566
567#[derive(PartialEq, Debug, Clone)]
568pub struct AttributeList(pub Vec<Loc<Attribute>>);
569impl AttributeList {
570 pub fn empty() -> Self {
571 Self(vec![])
572 }
573
574 pub fn from_vec(attrs: Vec<Loc<Attribute>>) -> Self {
575 Self(attrs)
576 }
577}
578
579#[derive(PartialEq, Debug, Clone)]
580pub struct ParameterList {
581 pub self_: Option<Loc<()>>,
582 pub args: Vec<(AttributeList, Loc<Identifier>, Loc<TypeSpec>)>,
583}
584impl WithLocation for ParameterList {}
585
586impl ParameterList {
587 pub fn without_self(args: Vec<(Loc<Identifier>, Loc<TypeSpec>)>) -> Self {
588 Self {
589 self_: None,
590 args: args
591 .into_iter()
592 .map(|(n, t)| (AttributeList::empty(), n, t))
593 .collect(),
594 }
595 }
596
597 pub fn with_self(self_: Loc<()>, args: Vec<(Loc<Identifier>, Loc<TypeSpec>)>) -> Self {
598 Self {
599 self_: Some(self_),
600 args: args
601 .into_iter()
602 .map(|(n, t)| (AttributeList::empty(), n, t))
603 .collect(),
604 }
605 }
606}
607
608#[derive(PartialEq, Debug, Clone)]
609pub enum UnitKind {
610 Function,
611 Entity,
612 Pipeline(Loc<TypeExpression>),
613}
614impl WithLocation for UnitKind {}
615
616impl UnitKind {
617 pub fn is_pipeline(&self) -> bool {
618 match self {
619 UnitKind::Function => false,
620 UnitKind::Entity => false,
621 UnitKind::Pipeline(_) => true,
622 }
623 }
624}
625
626impl std::fmt::Display for UnitKind {
627 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
628 match self {
629 UnitKind::Function => write!(f, "fn"),
630 UnitKind::Entity => write!(f, "entity"),
631 UnitKind::Pipeline(_) => write!(f, "pipeline"),
632 }
633 }
634}
635
636#[derive(PartialEq, Debug, Clone)]
637pub struct UnitHead {
638 pub extern_token: Option<Loc<()>>,
639 pub attributes: AttributeList,
640 pub unit_kind: Loc<UnitKind>,
641 pub name: Loc<Identifier>,
642 pub inputs: Loc<ParameterList>,
643 pub output_type: Option<(Loc<()>, Loc<TypeSpec>)>,
644 pub type_params: Option<Loc<Vec<Loc<TypeParam>>>>,
645 pub where_clauses: Vec<WhereClause>,
646}
647impl WithLocation for UnitHead {}
648
649#[derive(PartialEq, Debug, Clone)]
650pub struct Unit {
651 pub head: UnitHead,
652 pub body: Option<Loc<Expression>>,
655}
656impl WithLocation for Unit {}
657
658#[derive(PartialEq, Debug, Clone)]
659pub struct Register {
660 pub pattern: Loc<Pattern>,
661 pub clock: Loc<Expression>,
662 pub reset: Option<(Loc<Expression>, Loc<Expression>)>,
663 pub initial: Option<Loc<Expression>>,
664 pub value: Loc<Expression>,
665 pub value_type: Option<Loc<TypeSpec>>,
666 pub attributes: AttributeList,
667}
668impl WithLocation for Register {}
669
670#[derive(PartialEq, Debug, Clone)]
672pub struct TraitDef {
673 pub name: Loc<Identifier>,
674 pub type_params: Option<Loc<Vec<Loc<TypeParam>>>>,
675 pub where_clauses: Vec<WhereClause>,
676 pub methods: Vec<Loc<UnitHead>>,
677}
678impl WithLocation for TraitDef {}
679
680#[derive(PartialEq, Debug, Clone)]
682pub struct TraitSpec {
683 pub path: Loc<Path>,
684 pub type_params: Option<Loc<Vec<Loc<TypeExpression>>>>,
685}
686impl WithLocation for TraitSpec {}
687
688#[derive(PartialEq, Debug, Clone)]
689pub struct ImplBlock {
690 pub r#trait: Option<Loc<TraitSpec>>,
691 pub type_params: Option<Loc<Vec<Loc<TypeParam>>>>,
692 pub where_clauses: Vec<WhereClause>,
693 pub target: Loc<TypeSpec>,
694 pub units: Vec<Loc<Unit>>,
695}
696impl WithLocation for ImplBlock {}
697
698#[derive(PartialEq, Debug, Clone)]
700pub struct Enum {
701 pub attributes: AttributeList,
702 pub name: Loc<Identifier>,
703 pub variants: Vec<EnumVariant>,
704}
705impl WithLocation for Enum {}
706
707#[derive(PartialEq, Debug, Clone)]
708pub struct EnumVariant {
709 pub attributes: AttributeList,
710 pub name: Loc<Identifier>,
711 pub args: Option<Loc<ParameterList>>,
712}
713
714#[derive(PartialEq, Debug, Clone)]
715pub struct Struct {
716 pub attributes: AttributeList,
717 pub name: Loc<Identifier>,
718 pub members: Loc<ParameterList>,
719 pub port_keyword: Option<Loc<()>>,
720}
721impl WithLocation for Struct {}
722
723impl Struct {
724 pub fn is_port(&self) -> bool {
725 self.port_keyword.is_some()
726 }
727}
728
729#[derive(PartialEq, Debug, Clone)]
730pub enum TypeDeclKind {
731 Enum(Loc<Enum>),
732 Struct(Loc<Struct>),
733}
734
735#[derive(PartialEq, Debug, Clone)]
737pub struct TypeDeclaration {
738 pub name: Loc<Identifier>,
739 pub kind: TypeDeclKind,
740 pub generic_args: Option<Loc<Vec<Loc<TypeParam>>>>,
741}
742impl WithLocation for TypeDeclaration {}
743
744#[derive(PartialEq, Debug, Clone)]
745pub struct UseStatement {
746 pub path: Loc<Path>,
747 pub alias: Option<Loc<Identifier>>,
748}
749impl WithLocation for UseStatement {}
750
751#[derive(PartialEq, Debug, Clone)]
754pub enum Item {
755 Unit(Loc<Unit>),
756 TraitDef(Loc<TraitDef>),
757 Type(Loc<TypeDeclaration>),
758 ExternalMod(Loc<Identifier>),
759 Module(Loc<Module>),
760 Use(Loc<UseStatement>),
761 ImplBlock(Loc<ImplBlock>),
762}
763impl WithLocation for Item {}
764
765impl Item {
766 pub fn name(&self) -> Option<&Identifier> {
767 match self {
768 Item::Unit(u) => Some(&u.head.name.inner),
769 Item::TraitDef(t) => Some(&t.name.inner),
770 Item::Type(t) => Some(&t.name.inner),
771 Item::Module(m) => Some(&m.name.inner),
772 Item::ExternalMod(name) => Some(name),
773 Item::Use(u) => u.alias.as_ref().map(|name| &name.inner),
774 Item::ImplBlock(_) => None,
775 }
776 }
777
778 pub fn variant_str(&self) -> &'static str {
779 match self {
780 Item::Unit(_) => "unit",
781 Item::TraitDef(_) => "trait definition",
782 Item::Type(_) => "type",
783 Item::Module(_) => "module",
784 Item::ExternalMod(_) => "module",
785 Item::Use(_) => "use",
786 Item::ImplBlock(_) => "impl",
787 }
788 }
789}
790
791#[derive(PartialEq, Debug, Clone)]
792pub struct Module {
793 pub name: Loc<Identifier>,
794 pub body: Loc<ModuleBody>,
795}
796impl WithLocation for Module {}
797
798#[derive(PartialEq, Debug, Clone)]
799pub struct ModuleBody {
800 pub members: Vec<Item>,
801 pub documentation: Vec<String>,
802}
803impl WithLocation for ModuleBody {}