1pub mod expression;
2pub mod impl_tab;
3pub mod param_util;
4pub mod pretty_debug;
5pub mod pretty_print;
6pub mod query;
7pub mod symbol_table;
8pub mod testutil;
9
10use std::collections::BTreeMap;
11use std::fmt::Formatter;
12
13pub use expression::{Argument, ArgumentKind, ArgumentList, ExprKind, Expression};
14use itertools::Itertools;
15use num::BigInt;
16use rustc_hash::FxHashMap as HashMap;
17use serde::{Deserialize, Serialize};
18use spade_common::id_tracker::{ExprID, ImplID};
19use spade_common::{
20 location_info::{Loc, WithLocation},
21 name::{Identifier, NameID, Path},
22 num_ext::InfallibleToBigInt,
23};
24use spade_diagnostics::Diagnostic;
25use spade_types::{meta_types::MetaType, PrimitiveType};
26
27use crate::impl_tab::ImplTab;
28
29#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
35pub struct Block {
36 pub statements: Vec<Loc<Statement>>,
37 pub result: Option<Loc<Expression>>,
38}
39
40#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
41pub struct PatternArgument {
42 pub target: Loc<Identifier>,
43 pub value: Loc<Pattern>,
44 pub kind: ArgumentKind,
45}
46
47#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
48pub enum PatternKind {
49 Integer(BigInt),
50 Bool(bool),
51 Name {
52 name: Loc<NameID>,
53 pre_declared: bool,
54 },
55 Tuple(Vec<Loc<Pattern>>),
56 Array(Vec<Loc<Pattern>>),
57 Type(Loc<NameID>, Vec<PatternArgument>),
61}
62impl PatternKind {
63 pub fn name(name: Loc<NameID>) -> Self {
64 PatternKind::Name {
65 name,
66 pre_declared: false,
67 }
68 }
69
70 pub fn integer(val: i32) -> Self {
71 Self::Integer(val.to_bigint())
72 }
73}
74impl PatternKind {
75 pub fn with_id(self, id: ExprID) -> Pattern {
76 Pattern { id, kind: self }
77 }
78
79 pub fn idless(self) -> Pattern {
80 Pattern {
81 id: ExprID(0),
82 kind: self,
83 }
84 }
85}
86impl std::fmt::Display for PatternKind {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 match self {
89 PatternKind::Integer(val) => write!(f, "{val}"),
90 PatternKind::Bool(val) => write!(f, "{val}"),
91 PatternKind::Name { name, .. } => write!(f, "{name}"),
92 PatternKind::Tuple(members) => {
93 write!(
94 f,
95 "({})",
96 members.iter().map(|m| format!("{}", m.kind)).join(", ")
97 )
98 }
99 PatternKind::Array(members) => {
100 write!(
101 f,
102 "[{}]",
103 members.iter().map(|m| format!("{}", m.kind)).join(", ")
104 )
105 }
106 PatternKind::Type(name, _) => write!(f, "{name}(..)"),
107 }
108 }
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct Pattern {
113 pub id: ExprID,
116 pub kind: PatternKind,
117}
118
119impl Pattern {
120 pub fn get_names(&self) -> Vec<Loc<NameID>> {
121 match &self.kind {
122 PatternKind::Integer(_) => vec![],
123 PatternKind::Bool(_) => vec![],
124 PatternKind::Name {
125 name,
126 pre_declared: _,
127 } => vec![name.clone()],
128 PatternKind::Tuple(inner) => inner.iter().flat_map(|i| i.get_names()).collect(),
129 PatternKind::Type(_, args) => {
130 args.iter().flat_map(|arg| arg.value.get_names()).collect()
131 }
132 PatternKind::Array(inner) => inner.iter().flat_map(|i| i.get_names()).collect(),
133 }
134 }
135}
136
137impl PartialEq for Pattern {
138 fn eq(&self, other: &Self) -> bool {
139 self.kind == other.kind
140 }
141}
142
143#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
144pub struct WalTrace {
145 pub clk: Option<Loc<Expression>>,
146 pub rst: Option<Loc<Expression>>,
147}
148#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
149pub struct Binding {
150 pub pattern: Loc<Pattern>,
151 pub ty: Option<Loc<TypeSpec>>,
152 pub value: Loc<Expression>,
153 pub wal_trace: Option<Loc<WalTrace>>,
156}
157
158#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
159pub enum PipelineRegMarkerExtra {
160 Condition(Loc<Expression>),
161 Count {
162 count: Loc<TypeExpression>,
163 count_typeexpr_id: ExprID,
164 },
165}
166
167#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
168pub enum Statement {
169 Error,
170 Binding(Binding),
171 Expression(Loc<Expression>),
172 Register(Register),
173 Declaration(Vec<Loc<NameID>>),
174 PipelineRegMarker(Option<PipelineRegMarkerExtra>),
175 Label(Loc<NameID>),
176 Assert(Loc<Expression>),
177 Set {
178 target: Loc<Expression>,
179 value: Loc<Expression>,
180 },
181 WalSuffixed {
182 suffix: Identifier,
183 target: Loc<NameID>,
184 },
185}
186
187impl Statement {
188 pub fn named_let(pattern_id: ExprID, name_id: Loc<NameID>, val: Expression) -> Self {
190 Self::Binding(Binding {
191 pattern: PatternKind::name(name_id).with_id(pattern_id).nowhere(),
192 ty: None,
193 value: val.nowhere(),
194 wal_trace: None,
195 })
196 }
197
198 pub fn binding(
199 pattern: Loc<Pattern>,
200 ty: Option<Loc<TypeSpec>>,
201 value: Loc<Expression>,
202 ) -> Statement {
203 Statement::Binding(Binding {
204 pattern,
205 ty,
206 value,
207 wal_trace: None,
208 })
209 }
210}
211
212#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
213pub struct Register {
214 pub pattern: Loc<Pattern>,
215 pub clock: Loc<Expression>,
216 pub reset: Option<(Loc<Expression>, Loc<Expression>)>,
217 pub initial: Option<Loc<Expression>>,
218 pub value: Loc<Expression>,
219 pub value_type: Option<Loc<TypeSpec>>,
220 pub attributes: AttributeList,
221}
222
223#[derive(PartialEq, Debug, Clone, PartialOrd, Eq, Ord, Serialize, Deserialize)]
224pub struct Module {
225 pub name: Loc<NameID>,
226 pub documentation: String,
227}
228
229#[derive(PartialEq, Debug, Clone, Hash, Eq, Serialize, Deserialize)]
233pub struct TypeParam {
234 pub ident: Loc<Identifier>,
235 pub name_id: NameID,
236 pub trait_bounds: Vec<Loc<TraitSpec>>,
237 pub meta: MetaType,
238}
239impl TypeParam {
240 pub fn name_id(&self) -> NameID {
241 self.name_id.clone()
242 }
243}
244
245#[derive(PartialEq, Debug, Clone, Serialize, Deserialize, Hash, Eq)]
246pub enum TypeExpression {
247 Integer(BigInt),
249 String(String),
251 TypeSpec(TypeSpec),
253 ConstGeneric(Loc<ConstGeneric>),
254}
255
256impl TypeExpression {
257 fn replace_in(self, from: &TypeSpec, to: &TypeSpec) -> Self {
258 match self {
259 TypeExpression::TypeSpec(type_spec) => {
260 TypeExpression::TypeSpec(type_spec.replace_in(from, to))
261 }
262 TypeExpression::Integer(_) => self,
263 TypeExpression::String(_) => self,
264 TypeExpression::ConstGeneric(_) => self,
265 }
266 }
267}
268
269impl std::fmt::Display for TypeExpression {
270 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
271 match self {
272 TypeExpression::Integer(val) => write!(f, "{val}"),
273 TypeExpression::String(val) => write!(f, "{val:?}"),
274 TypeExpression::TypeSpec(val) => write!(f, "{val}"),
275 TypeExpression::ConstGeneric(val) => write!(f, "{val}"),
276 }
277 }
278}
279
280#[derive(PartialEq, Debug, Clone, Serialize, Deserialize, Hash, Eq)]
283pub enum TypeSpec {
284 Declared(Loc<NameID>, Vec<Loc<TypeExpression>>),
286 Generic(Loc<NameID>),
288 Tuple(Vec<Loc<TypeSpec>>),
290 Array {
291 inner: Box<Loc<TypeSpec>>,
292 size: Box<Loc<TypeExpression>>,
293 },
294 Inverted(Box<Loc<TypeSpec>>),
295 Wire(Box<Loc<TypeSpec>>),
296 TraitSelf(Loc<()>),
300 Wildcard(Loc<()>),
303}
304
305impl TypeSpec {
307 pub fn unit() -> Self {
308 TypeSpec::Tuple(Vec::new())
309 }
310
311 pub fn type_params(&self) -> Vec<TypeExpression> {
312 match self {
313 TypeSpec::Declared(_, exprs) => exprs.clone().into_iter().map(|e| e.inner).collect(),
314 TypeSpec::Generic(_) => vec![],
315 TypeSpec::Tuple(_) => vec![],
316 TypeSpec::Array { inner, size } => {
317 vec![
318 TypeExpression::TypeSpec(inner.inner.clone()),
319 size.inner.clone(),
320 ]
321 }
322 TypeSpec::Inverted(inner) => vec![TypeExpression::TypeSpec(inner.inner.clone())],
323 TypeSpec::Wire(inner) => vec![TypeExpression::TypeSpec(inner.inner.clone())],
324 TypeSpec::TraitSelf(_) => vec![],
325 TypeSpec::Wildcard(_) => vec![],
326 }
327 }
328
329 pub fn replace_in(self, from: &TypeSpec, to: &TypeSpec) -> Self {
330 if &self == from {
331 to.clone()
332 } else {
333 match self {
334 TypeSpec::Declared(base, inner) => TypeSpec::Declared(
335 base.clone(),
336 inner
337 .into_iter()
338 .map(|expr| expr.map(|s| s.replace_in(from, to)))
339 .collect(),
340 ),
341 TypeSpec::Generic(_) => self.clone(),
342 TypeSpec::Tuple(inner) => TypeSpec::Tuple(
343 inner
344 .into_iter()
345 .map(|s| s.map(|s| s.replace_in(from, to)))
346 .collect(),
347 ),
348 TypeSpec::Array { inner, size } => TypeSpec::Array {
349 inner: Box::new(inner.map(|s| s.replace_in(from, to))),
350 size: Box::new(size.map(|s| s.replace_in(from, to))),
351 },
352 TypeSpec::Inverted(inner) => {
353 TypeSpec::Inverted(Box::new(inner.map(|s| s.replace_in(from, to))))
354 }
355 TypeSpec::Wire(inner) => {
356 TypeSpec::Wire(Box::new(inner.map(|s| s.replace_in(from, to))))
357 }
358 TypeSpec::TraitSelf(_) => self,
359 TypeSpec::Wildcard(_) => self,
360 }
361 }
362 }
363}
364
365impl std::fmt::Display for TypeSpec {
366 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
367 let str = match self {
368 TypeSpec::Declared(name, params) => {
369 let type_params = if params.is_empty() {
370 String::from("")
371 } else {
372 format!(
373 "<{}>",
374 params
375 .iter()
376 .map(|g| format!("{g}"))
377 .collect::<Vec<_>>()
378 .join(", ")
379 )
380 };
381 format!("{name}{type_params}")
382 }
383 TypeSpec::Generic(name) => format!("{name}"),
384 TypeSpec::Tuple(members) => {
385 format!(
386 "({})",
387 members
388 .iter()
389 .map(|m| format!("{m}"))
390 .collect::<Vec<_>>()
391 .join(", ")
392 )
393 }
394 TypeSpec::Array { inner, size } => format!("[{inner}; {size}]"),
395 TypeSpec::Inverted(inner) => format!("~{inner}"),
396 TypeSpec::Wire(inner) => format!("&{inner}"),
397 TypeSpec::TraitSelf(_) => "Self".into(),
398 TypeSpec::Wildcard(_) => "_".into(),
399 };
400 write!(f, "{str}")
401 }
402}
403
404#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Hash, Eq)]
406pub struct TraitSpec {
407 pub name: TraitName,
408 pub type_params: Option<Loc<Vec<Loc<TypeExpression>>>>,
409 pub paren_syntax: bool,
410}
411
412#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
414pub struct Enum {
415 pub options: Vec<(Loc<NameID>, Loc<ParameterList>)>,
416 pub documentation: String,
417}
418
419#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
420pub struct WalTraceable {
421 pub suffix: Path,
422 pub uses_clk: bool,
423 pub uses_rst: bool,
424}
425
426#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
427pub struct Struct {
428 pub members: Loc<ParameterList>,
429 pub is_port: bool,
430 pub attributes: AttributeList,
431 pub wal_traceable: Option<Loc<WalTraceable>>,
432 pub documentation: String,
433}
434
435#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
436pub enum TypeDeclKind {
437 Enum(Loc<Enum>),
438 Primitive(PrimitiveType),
439 Struct(Loc<Struct>),
440}
441impl TypeDeclKind {
442 pub fn name(&self) -> &str {
443 match self {
444 TypeDeclKind::Enum(_) => "enum",
445 TypeDeclKind::Primitive(_) => "primitive",
446 TypeDeclKind::Struct(_) => "struct",
447 }
448 }
449}
450
451#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
453pub struct TypeDeclaration {
454 pub name: Loc<NameID>,
455 pub kind: TypeDeclKind,
456 pub generic_args: Vec<Loc<TypeParam>>,
457}
458
459#[derive(PartialEq, Debug, Clone, Serialize, Deserialize, Hash, Eq)]
460pub enum ConstGeneric {
461 Name(Loc<NameID>),
462 Int(BigInt),
463 Str(String),
464 Add(Box<Loc<ConstGeneric>>, Box<Loc<ConstGeneric>>),
465 Sub(Box<Loc<ConstGeneric>>, Box<Loc<ConstGeneric>>),
466 Mul(Box<Loc<ConstGeneric>>, Box<Loc<ConstGeneric>>),
467 Div(Box<Loc<ConstGeneric>>, Box<Loc<ConstGeneric>>),
468 Mod(Box<Loc<ConstGeneric>>, Box<Loc<ConstGeneric>>),
469 UintBitsToFit(Box<Loc<ConstGeneric>>),
470 Eq(Box<Loc<ConstGeneric>>, Box<Loc<ConstGeneric>>),
471 NotEq(Box<Loc<ConstGeneric>>, Box<Loc<ConstGeneric>>),
472}
473
474impl ConstGeneric {
475 pub fn with_id(self, id: ExprID) -> ConstGenericWithId {
476 ConstGenericWithId { id, inner: self }
477 }
478}
479
480#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
481pub struct ConstGenericWithId {
482 pub id: ExprID,
483 pub inner: ConstGeneric,
484}
485
486impl std::fmt::Display for ConstGeneric {
487 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
488 match self {
489 ConstGeneric::Name(n) => write!(f, "{n}"),
490 ConstGeneric::Int(val) => write!(f, "{val}"),
491 ConstGeneric::Str(val) => write!(f, "{val:?}"),
492 ConstGeneric::Add(l, r) => write!(f, "({l} + {r})"),
493 ConstGeneric::Sub(l, r) => write!(f, "({l} - {r})"),
494 ConstGeneric::Mul(l, r) => write!(f, "({l} * {r})"),
495 ConstGeneric::Div(l, r) => write!(f, "({l} / {r})"),
496 ConstGeneric::Mod(l, r) => write!(f, "({l} % {r})"),
497 ConstGeneric::Eq(l, r) => write!(f, "({l} == {r})"),
498 ConstGeneric::NotEq(l, r) => write!(f, "({l} != {r})"),
499 ConstGeneric::UintBitsToFit(a) => write!(f, "uint_bits_to_fit({a})"),
500 }
501 }
502}
503
504#[derive(PartialEq, Debug, Clone, Serialize, Deserialize, Hash, Eq, Copy)]
505pub enum WhereClauseKind {
506 Eq,
507 Neq,
508 Lt,
509 Leq,
510 Gt,
511 Geq,
512}
513
514impl std::fmt::Display for WhereClauseKind {
515 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
516 match self {
517 WhereClauseKind::Eq => write!(f, "=="),
518 WhereClauseKind::Neq => write!(f, "!="),
519 WhereClauseKind::Lt => write!(f, "<"),
520 WhereClauseKind::Leq => write!(f, "<="),
521 WhereClauseKind::Gt => write!(f, ">"),
522 WhereClauseKind::Geq => write!(f, ">="),
523 }
524 }
525}
526
527#[derive(PartialEq, Debug, Clone, Serialize, Deserialize, Hash, Eq)]
528pub enum WhereClause {
529 Int {
530 target: Loc<NameID>,
531 kind: WhereClauseKind,
532 constraint: Loc<ConstGeneric>,
533 if_unsatisfied: Option<String>,
534 },
535 Type {
536 target: Loc<NameID>,
537 traits: Vec<Loc<TraitSpec>>,
538 },
539}
540
541impl std::fmt::Display for WhereClause {
542 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
543 let str = match self {
544 WhereClause::Int {
545 target,
546 kind,
547 constraint,
548 if_unsatisfied,
549 } => {
550 format!("{target} {kind} {constraint} else {if_unsatisfied:?}")
551 }
552 WhereClause::Type { target, traits } => {
553 format!(
554 "{target}: {}",
555 traits.iter().map(|trait_spec| &trait_spec.name).join(" + ")
556 )
557 }
558 };
559 write!(f, "{}", str)
560 }
561}
562
563#[derive(PartialEq, Debug, Clone, Serialize, Deserialize, Hash, Eq)]
564pub enum UnitName {
565 WithID(Loc<NameID>),
568 FullPath(Loc<NameID>),
571 Unmangled(String, Loc<NameID>),
574}
575
576impl UnitName {
577 pub fn name_id(&self) -> &Loc<NameID> {
578 match self {
579 UnitName::WithID(name) => name,
580 UnitName::FullPath(name) => name,
581 UnitName::Unmangled(_, name) => name,
582 }
583 }
584}
585
586impl std::fmt::Display for UnitName {
587 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
588 match self {
589 UnitName::WithID(name) | UnitName::FullPath(name) | UnitName::Unmangled(_, name) => {
590 write!(f, "{name}")
591 }
592 }
593 }
594}
595
596#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
597pub struct Unit {
598 pub name: UnitName,
599 pub head: UnitHead,
600 pub attributes: AttributeList,
601 pub inputs: Vec<(Loc<NameID>, Loc<TypeSpec>)>,
603 pub body: Loc<Expression>,
604}
605
606#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
607pub struct Parameter {
608 pub no_mangle: Option<Loc<()>>,
611 pub name: Loc<Identifier>,
612 pub ty: Loc<TypeSpec>,
613 pub field_translator: Option<String>,
614}
615
616#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
617pub struct ParameterList(pub Vec<Parameter>);
618
619impl ParameterList {
620 pub fn argument_num(&self) -> usize {
621 self.0.len()
622 }
623
624 pub fn arg_type(&self, name: &Identifier) -> &TypeSpec {
626 if let Some(result) = self.try_get_arg_type(name) {
627 result
628 } else {
629 panic!(
630 "Tried to get type of an argument which is not part of the parameter list. {}",
631 name
632 )
633 }
634 }
635
636 pub fn try_get_arg_type(&self, name: &Identifier) -> Option<&Loc<TypeSpec>> {
638 for Parameter {
639 name: arg,
640 ty,
641 no_mangle: _,
642 field_translator: _,
643 } in &self.0
644 {
645 if &arg.inner == name {
646 return Some(ty);
647 }
648 }
649 None
650 }
651
652 pub fn arg_index(&self, target: &Identifier) -> Option<usize> {
653 let indices = self
654 .0
655 .iter()
656 .enumerate()
657 .filter_map(
658 |(
659 i,
660 Parameter {
661 name,
662 ty: _,
663 no_mangle: _,
664 field_translator: _,
665 },
666 )| {
667 if &name.inner == target {
668 Some(i)
669 } else {
670 None
671 }
672 },
673 )
674 .collect::<Vec<_>>();
675
676 if indices.len() > 1 {
677 panic!("Duplicate arguments with the same name")
678 } else {
679 indices.first().cloned()
680 }
681 }
682}
683
684#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
685pub enum FunctionKind {
686 Fn,
687 Struct,
688 Enum,
689}
690
691#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
692pub enum UnitKind {
693 Function(FunctionKind),
694 Entity,
695 Pipeline {
696 depth: Loc<TypeExpression>,
697 depth_typeexpr_id: ExprID,
698 },
699}
700
701impl UnitKind {
702 pub fn name(&self) -> &'static str {
703 match self {
704 UnitKind::Function(FunctionKind::Fn) => "function",
705 UnitKind::Function(FunctionKind::Struct) => "struct",
706 UnitKind::Function(FunctionKind::Enum) => "enum variant",
707 UnitKind::Entity => "entity",
708 UnitKind::Pipeline { .. } => "pipeline",
709 }
710 }
711
712 pub fn is_function_like(&self) -> bool {
713 matches!(self, UnitKind::Function(_))
714 }
715
716 pub fn is_pipeline(&self) -> bool {
717 matches!(self, UnitKind::Pipeline { .. })
718 }
719}
720
721#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
722pub struct UnitHead {
723 pub name: Loc<Identifier>,
724 pub inputs: Loc<ParameterList>,
725 pub is_nonstatic_method: bool,
726 pub output_type: Option<Loc<TypeSpec>>,
728 pub unit_type_params: Vec<Loc<TypeParam>>,
729 pub scope_type_params: Vec<Loc<TypeParam>>,
730 pub unit_kind: Loc<UnitKind>,
731 pub where_clauses: Vec<Loc<WhereClause>>,
732 pub unsafe_marker: Option<Loc<()>>,
733 pub documentation: String,
734}
735
736impl UnitHead {
737 pub fn output_type(&self) -> Loc<TypeSpec> {
738 match &self.output_type {
739 Some(t) => t.clone(),
740 None => {
741 TypeSpec::unit().at_loc(&self.name.loc())
743 }
744 }
745 }
746 pub fn get_type_params(&self) -> Vec<Loc<TypeParam>> {
747 self.unit_type_params
748 .iter()
749 .chain(self.scope_type_params.iter())
750 .cloned()
751 .collect_vec()
752 }
753}
754
755#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
756pub enum Item {
757 Unit(Loc<Unit>),
758 ExternUnit(UnitName, Loc<UnitHead>),
759}
760
761impl Item {
762 pub fn assume_unit(&self) -> &Unit {
763 match self {
764 Item::Unit(u) => &u.inner,
765 Item::ExternUnit(_, _) => panic!("Expected unit, got extern unit"),
766 }
767 }
768}
769
770#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
773pub enum ExecutableItem {
774 EnumInstance { base_enum: NameID, variant: usize },
775 StructInstance,
776 Unit(Loc<Unit>),
777 ExternUnit(UnitName, Loc<UnitHead>),
778}
779
780pub type TypeList = HashMap<NameID, Loc<TypeDeclaration>>;
781
782#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)]
783pub enum TraitName {
784 Named(Loc<NameID>),
785 Anonymous(ImplID),
786}
787
788impl TraitName {
789 pub fn is_anonymous(&self) -> bool {
790 matches!(self, Self::Anonymous(_))
791 }
792
793 pub fn name_loc(&self) -> Option<Loc<NameID>> {
795 match self {
796 TraitName::Named(n) => Some(n.clone()),
797 TraitName::Anonymous(_) => None,
798 }
799 }
800}
801
802impl std::fmt::Display for TraitName {
803 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
804 match self {
805 TraitName::Named(n) => write!(f, "{n}"),
806 TraitName::Anonymous(id) => write!(f, "Anonymous({})", id.0),
807 }
808 }
809}
810
811#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
815pub enum Attribute {
816 VerilogAttrs {
817 entries: Vec<(Loc<Identifier>, Option<Loc<String>>)>,
818 },
819 Optimize {
820 passes: Vec<Loc<String>>,
821 },
822 Fsm {
823 state: NameID,
824 },
825 WalTraceable {
826 suffix: Identifier,
827 },
828}
829impl Attribute {
830 pub fn name(&self) -> &str {
831 match self {
832 Attribute::VerilogAttrs { entries: _ } => "verilog_attrs",
833 Attribute::Optimize { passes: _ } => "optimize",
834 Attribute::Fsm { state: _ } => "fsm",
835 Attribute::WalTraceable { suffix: _ } => "suffix",
836 }
837 }
838}
839
840#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
841pub struct AttributeList(pub Vec<Loc<Attribute>>);
842
843impl AttributeList {
844 pub fn empty() -> Self {
845 Self(vec![])
846 }
847}
848
849#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
850pub struct ImplBlock {
851 pub fns: HashMap<Identifier, (NameID, Loc<()>)>,
854 pub type_params: Vec<Loc<TypeParam>>,
855 pub target: Loc<TypeSpec>,
856 pub id: ImplID,
857}
858
859#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
860pub struct TraitDef {
861 pub type_params: Option<Loc<Vec<Loc<TypeParam>>>>,
862 pub fns: HashMap<Identifier, Loc<UnitHead>>,
863 pub paren_sugar: bool,
864 pub documentation: String,
865}
866
867#[derive(PartialEq, Hash, Eq, Debug, Clone, Serialize, Deserialize, PartialOrd, Ord)]
868pub enum ImplTarget {
869 Array,
870 Inverted,
871 Wire,
872 Named(NameID),
873}
874
875impl ImplTarget {
876 pub fn display(&self, args: &[TypeExpression]) -> String {
877 match self {
878 ImplTarget::Array => {
879 format!(
880 "[{}; {}]",
881 args.get(0)
882 .map(|a| format!("{}", a))
883 .unwrap_or_else(|| "<(bug) Missing param 0>".to_string()),
884 args.get(1)
885 .map(|a| format!("{}", a))
886 .unwrap_or_else(|| "<(bug) Missing param 1>".to_string())
887 )
888 }
889 ImplTarget::Wire => {
890 format!(
891 "&{}",
892 args.get(0)
893 .map(|a| format!("{}", a))
894 .unwrap_or_else(|| "<(bug) Missing param 0>".to_string()),
895 )
896 }
897 ImplTarget::Inverted => {
898 format!(
899 "inv {}",
900 args.get(0)
901 .map(|a| format!("{}", a))
902 .unwrap_or_else(|| "<(bug) Missing param 0>".to_string()),
903 )
904 }
905 ImplTarget::Named(name) => {
906 format!(
907 "{}{}",
908 name,
909 if args.is_empty() {
910 format!("")
911 } else {
912 format!("<{}>", args.iter().map(|arg| format!("{}", arg)).join(", "))
913 }
914 )
915 }
916 }
917 }
918}
919
920#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
928pub struct ItemList {
929 pub executables: BTreeMap<NameID, ExecutableItem>,
930 pub types: TypeList,
931 pub modules: BTreeMap<NameID, Module>,
933 pub traits: HashMap<TraitName, TraitDef>,
938 pub impls: ImplTab,
939}
940
941impl Default for ItemList {
942 fn default() -> Self {
943 Self::new()
944 }
945}
946
947impl ItemList {
948 pub fn new() -> Self {
949 Self {
950 executables: BTreeMap::new(),
951 types: TypeList::default(),
952 modules: BTreeMap::new(),
953 traits: HashMap::default(),
954 impls: ImplTab::new(),
955 }
956 }
957
958 pub fn add_executable(
959 &mut self,
960 name: Loc<NameID>,
961 item: ExecutableItem,
962 ) -> Result<(), Diagnostic> {
963 if let Some(_) = self.executables.get_key_value(&name) {
964 Err(
965 Diagnostic::error(&name, format!("Multiple definitions of thing {name}"))
966 .primary_label("New definition"),
967 )
968 } else {
969 self.executables.insert(name.inner, item);
970 Ok(())
971 }
972 }
973
974 pub fn add_trait(
975 &mut self,
976 name: TraitName,
977 type_params: Option<Loc<Vec<Loc<TypeParam>>>>,
978 members: Vec<(Identifier, Loc<UnitHead>)>,
979 paren_sugar: bool,
980 documentation: String,
981 ) -> Result<(), Diagnostic> {
982 if let Some((prev, _)) = self.traits.get_key_value(&name) {
983 Err(
984 Diagnostic::error(
987 name.name_loc().unwrap(),
988 format!("Multiple definitions of trait {name}"),
989 )
990 .primary_label("New definition")
991 .secondary_label(prev.name_loc().unwrap(), "Previous definition"),
992 )
993 } else {
994 self.traits.insert(
995 name,
996 TraitDef {
997 type_params,
998 fns: members.into_iter().collect(),
999 paren_sugar,
1000 documentation,
1001 },
1002 );
1003 Ok(())
1004 }
1005 }
1006
1007 pub fn get_trait(&self, name: &TraitName) -> Option<&TraitDef> {
1008 self.traits.get(name)
1009 }
1010
1011 pub fn traits(&self) -> &HashMap<TraitName, TraitDef> {
1012 &self.traits
1013 }
1014}