1pub mod meta_types;
2
3use num::BigInt;
4use serde::{Deserialize, Serialize};
5use spade_common::{
6 location_info::WithLocation,
7 name::{Identifier, NameID},
8 num_ext::InfallibleToBigInt,
9};
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12pub enum PrimitiveType {
13 Int,
14 Uint,
15 Clock,
16 Bool,
17 Bit,
18 Memory,
19 InOut,
20}
21
22impl std::fmt::Display for PrimitiveType {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 let str = match self {
25 PrimitiveType::Int => "int",
26 PrimitiveType::Uint => "uint",
27 PrimitiveType::Clock => "clk",
28 PrimitiveType::Bool => "bool",
29 PrimitiveType::Bit => "bit",
30 PrimitiveType::Memory => "Memory",
31 PrimitiveType::InOut => "inout",
32 };
33 write!(f, "{str}")
34 }
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
38pub enum ConcreteType {
39 Tuple(Vec<ConcreteType>),
40 Struct {
41 name: NameID,
42 is_port: bool,
43 members: Vec<(Identifier, ConcreteType)>,
44 },
45 Array {
46 inner: Box<ConcreteType>,
47 size: BigInt,
48 },
49 Enum {
50 options: Vec<(NameID, Vec<(Identifier, ConcreteType)>)>,
51 },
52 Single {
53 base: PrimitiveType,
54 params: Vec<ConcreteType>,
55 },
56 Integer(BigInt),
57 Bool(bool),
58 Backward(Box<ConcreteType>),
59 Wire(Box<ConcreteType>),
60}
61
62impl ConcreteType {
63 pub fn assume_struct(&self) -> (&NameID, &Vec<(Identifier, ConcreteType)>) {
64 match self {
65 ConcreteType::Struct {
66 name,
67 is_port: _,
68 members,
69 } => (name, members),
70 t => unreachable!("Assumed {} was a struct", t),
71 }
72 }
73
74 pub fn is_port(&self) -> bool {
75 match self {
76 ConcreteType::Tuple(inner) => inner.iter().any(Self::is_port),
77 ConcreteType::Struct {
78 name: _,
79 is_port,
80 members: _,
81 } => *is_port,
82 ConcreteType::Array { inner, size: _ } => inner.is_port(),
83 ConcreteType::Enum { .. } => false,
85 ConcreteType::Single {
86 base: PrimitiveType::Memory,
87 ..
88 } => true,
89 ConcreteType::Single {
90 base: PrimitiveType::Clock,
91 ..
92 } => true,
93 ConcreteType::Single { .. } => false,
94 ConcreteType::Integer(_) | ConcreteType::Bool(_) => false,
95 ConcreteType::Backward(_) => true,
96 ConcreteType::Wire(_) => true,
97 }
98 }
99}
100
101impl std::fmt::Display for ConcreteType {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 let str = match self {
104 ConcreteType::Tuple(inner) => {
105 format!(
106 "({})",
107 inner
108 .iter()
109 .map(|p| format!("{}", p))
110 .collect::<Vec<_>>()
111 .join(", ")
112 )
113 }
114 ConcreteType::Struct {
115 name,
116 is_port,
117 members,
118 } => {
119 let port = if *is_port { "port " } else { "" };
120 format!(
121 "struct {port}{name} {{{}}}",
122 members
123 .iter()
124 .map(|(name, t)| format!("{}: {}", name, t))
125 .collect::<Vec<_>>()
126 .join(", ")
127 )
128 }
129 ConcreteType::Array { inner, size } => {
130 format!("[{}; {}]", inner, size)
131 }
132 ConcreteType::Enum { options } => {
133 let inner = options
134 .iter()
135 .map(|o| {
136 let param_list =
137 o.1.iter()
138 .map(|t| format!("{}", t.1))
139 .collect::<Vec<_>>()
140 .join(",");
141 format!("{} ( {} )", o.0 .0, param_list)
142 })
143 .collect::<Vec<_>>()
144 .join(",");
145 format!("enum {{{}}}", inner)
146 }
147 ConcreteType::Single { base, params } => {
148 let params_str = if params.is_empty() {
149 String::new()
150 } else {
151 params
152 .iter()
153 .map(|p| format!("{}", p))
154 .collect::<Vec<_>>()
155 .join(", ")
156 };
157
158 format!("{}{}", base, params_str)
159 }
160 ConcreteType::Integer(size) => {
161 format!("{}", size)
162 }
163 ConcreteType::Bool(val) => {
164 format!("{}", val)
165 }
166 ConcreteType::Backward(inner) => {
167 format!("inv &{}", inner)
168 }
169 ConcreteType::Wire(inner) => {
170 format!("&{}", inner)
171 }
172 };
173
174 write!(f, "{str}")
175 }
176}
177
178#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
179pub enum KnownType {
180 Named(NameID),
181 Integer(BigInt),
182 Bool(bool),
183 Tuple,
184 Array,
185 Wire,
186 Inverted,
187}
188
189impl WithLocation for KnownType {}
190
191impl KnownType {
192 pub fn integer(val: u64) -> Self {
193 Self::Integer(val.to_bigint())
194 }
195}