1pub mod meta_types;
2
3use num::BigInt;
4use rustc_hash::FxHashMap as HashMap;
5use serde::{Deserialize, Serialize};
6use spade_common::{
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 Tri,
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 => "clock",
28 PrimitiveType::Bool => "bool",
29 PrimitiveType::Tri => "tri",
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 Error,
40 Tuple(Vec<ConcreteType>),
41 Struct {
42 name: NameID,
43 is_port: bool,
44 members: Vec<(Identifier, ConcreteType)>,
45 field_translators: HashMap<Identifier, String>,
46 },
47 Array {
48 inner: Box<ConcreteType>,
49 size: BigInt,
50 },
51 Enum {
52 options: Vec<(NameID, Vec<(Identifier, ConcreteType)>)>,
53 },
54 Single {
55 base: PrimitiveType,
56 params: Vec<ConcreteType>,
57 },
58 Integer(BigInt),
59 Bool(bool),
60 String(String),
61 Backward(Box<ConcreteType>),
62 Wire(Box<ConcreteType>),
63}
64
65impl ConcreteType {
66 pub fn assume_struct(&self) -> (&NameID, &Vec<(Identifier, ConcreteType)>) {
67 match self {
68 ConcreteType::Struct {
69 name,
70 is_port: _,
71 members,
72 field_translators: _,
73 } => (name, members),
74 t => unreachable!("Assumed {} was a struct", t),
75 }
76 }
77
78 pub fn is_error_recursively(&self) -> bool {
79 match self {
80 ConcreteType::Error => true,
81 ConcreteType::Tuple(inner) => inner.iter().any(|ty| ty.is_error_recursively()),
82 ConcreteType::Struct {
83 name: _,
84 is_port: _,
85 members,
86 field_translators: _,
87 } => members.iter().any(|(_, ty)| ty.is_error_recursively()),
88 ConcreteType::Array { inner, size: _ } => inner.is_error_recursively(),
89 ConcreteType::Enum { options } => options.iter().any(|option| {
90 option
91 .1
92 .iter()
93 .any(|(_, member)| member.is_error_recursively())
94 }),
95 ConcreteType::Single { base: _, params } => {
96 params.iter().any(|p| p.is_error_recursively())
97 }
98 ConcreteType::Integer(_) => false,
99 ConcreteType::Bool(_) => false,
100 ConcreteType::String(_) => false,
101 ConcreteType::Backward(inner) => inner.is_error_recursively(),
102 ConcreteType::Wire(inner) => inner.is_error_recursively(),
103 }
104 }
105
106 pub fn is_port(&self) -> bool {
107 match self {
108 ConcreteType::Error => false,
109 ConcreteType::Tuple(inner) => inner.iter().any(Self::is_port),
110 ConcreteType::Struct {
111 name: _,
112 is_port,
113 members: _,
114 field_translators: _,
115 } => *is_port,
116 ConcreteType::Array { inner, size: _ } => inner.is_port(),
117 ConcreteType::Enum { .. } => false,
119 ConcreteType::Single {
120 base: PrimitiveType::Memory,
121 ..
122 } => true,
123 ConcreteType::Single {
124 base: PrimitiveType::Clock,
125 ..
126 } => true,
127 ConcreteType::Single { .. } => false,
128 ConcreteType::Integer(_) | ConcreteType::Bool(_) | ConcreteType::String(_) => false,
129 ConcreteType::Backward(_) => true,
130 ConcreteType::Wire(_) => true,
131 }
132 }
133}
134
135impl std::fmt::Display for ConcreteType {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 let str = match self {
138 ConcreteType::Error => "{error}".to_string(),
139 ConcreteType::Tuple(inner) => {
140 format!(
141 "({})",
142 inner
143 .iter()
144 .map(|p| format!("{}", p))
145 .collect::<Vec<_>>()
146 .join(", ")
147 )
148 }
149 ConcreteType::Struct {
150 name,
151 is_port,
152 members,
153 field_translators: _,
154 } => {
155 let port = if *is_port { "port " } else { "" };
156 format!(
157 "struct {port}{name} {{{}}}",
158 members
159 .iter()
160 .map(|(name, t)| format!("{}: {}", name, t))
161 .collect::<Vec<_>>()
162 .join(", ")
163 )
164 }
165 ConcreteType::Array { inner, size } => {
166 format!("[{}; {}]", inner, size)
167 }
168 ConcreteType::Enum { options } => {
169 let inner = options
170 .iter()
171 .map(|o| {
172 let param_list =
173 o.1.iter()
174 .map(|t| format!("{}", t.1))
175 .collect::<Vec<_>>()
176 .join(",");
177 format!("{} ( {} )", o.0 .0, param_list)
178 })
179 .collect::<Vec<_>>()
180 .join(",");
181 format!("enum {{{}}}", inner)
182 }
183 ConcreteType::Single { base, params } => {
184 let params_str = if params.is_empty() {
185 String::new()
186 } else {
187 params
188 .iter()
189 .map(|p| format!("{}", p))
190 .collect::<Vec<_>>()
191 .join(", ")
192 };
193
194 format!("{}{}", base, params_str)
195 }
196 ConcreteType::Integer(size) => {
197 format!("{}", size)
198 }
199 ConcreteType::Bool(val) => {
200 format!("{}", val)
201 }
202 ConcreteType::String(val) => {
203 format!("{:?}", val)
204 }
205 ConcreteType::Backward(inner) => {
206 format!("inv &{}", inner)
207 }
208 ConcreteType::Wire(inner) => {
209 format!("&{}", inner)
210 }
211 };
212
213 write!(f, "{str}")
214 }
215}
216
217#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
218pub enum KnownType {
219 Named(NameID),
220 Integer(BigInt),
221 Bool(bool),
222 String(String),
223 Tuple,
224 Array,
225 Wire,
226 Inverted,
227 Error,
230}
231
232impl KnownType {
233 pub fn integer(val: u64) -> Self {
234 Self::Integer(val.to_bigint())
235 }
236}