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