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