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