1use slang_derive::{IterableEnum, NamedEnum, NumericEnum};
2
3pub const TYPE_NAME_I32: &str = PrimitiveType::I32.name();
5pub const TYPE_NAME_I64: &str = PrimitiveType::I64.name();
6pub const TYPE_NAME_U32: &str = PrimitiveType::U32.name();
7pub const TYPE_NAME_U64: &str = PrimitiveType::U64.name();
8pub const TYPE_NAME_F32: &str = PrimitiveType::F32.name();
9pub const TYPE_NAME_F64: &str = PrimitiveType::F64.name();
10pub const TYPE_NAME_BOOL: &str = PrimitiveType::Bool.name();
11pub const TYPE_NAME_STRING: &str = PrimitiveType::String.name();
12pub const TYPE_NAME_INT: &str = PrimitiveType::UnspecifiedInt.name();
13pub const TYPE_NAME_FLOAT: &str = PrimitiveType::UnspecifiedFloat.name();
14pub const TYPE_NAME_UNIT: &str = PrimitiveType::Unit.name();
15pub const TYPE_NAME_UNKNOWN: &str = PrimitiveType::Unknown.name();
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, NamedEnum, IterableEnum, NumericEnum)]
19pub enum PrimitiveType {
20 I32,
22 I64,
24 U32,
26 U64,
28 F32,
30 F64,
32 Bool,
34 String,
36 #[name = "int"]
38 UnspecifiedInt,
39 #[name = "float"]
41 UnspecifiedFloat,
42 #[name = "()"]
44 Unit,
45 Unknown,
47}
48
49impl PrimitiveType {
50 pub fn is_numeric(&self) -> bool {
52 self.is_integer() || self.is_float()
53 }
54
55 pub fn is_integer(&self) -> bool {
57 matches!(
58 self,
59 PrimitiveType::I32
60 | PrimitiveType::I64
61 | PrimitiveType::U32
62 | PrimitiveType::U64
63 | PrimitiveType::UnspecifiedInt
64 )
65 }
66
67 pub fn is_float(&self) -> bool {
69 matches!(
70 self,
71 PrimitiveType::F32 | PrimitiveType::F64 | PrimitiveType::UnspecifiedFloat
72 )
73 }
74
75 pub fn is_signed_integer(&self) -> bool {
77 matches!(
78 self,
79 PrimitiveType::I32 | PrimitiveType::I64 | PrimitiveType::UnspecifiedInt
80 )
81 }
82
83 pub fn is_unsigned_integer(&self) -> bool {
85 matches!(self, PrimitiveType::U32 | PrimitiveType::U64)
86 }
87
88 pub fn bit_width(&self) -> u8 {
90 match self {
91 PrimitiveType::I32 | PrimitiveType::U32 | PrimitiveType::F32 => 32,
92 PrimitiveType::I64 | PrimitiveType::U64 | PrimitiveType::F64 => 64,
93 PrimitiveType::Bool => 1,
94 PrimitiveType::Unit => 0,
95 _ => 0,
96 }
97 }
98
99 pub fn to_type_kind(&self) -> TypeKind {
104 match self {
105 PrimitiveType::I32 => TypeKind::Integer(IntegerType {
106 signed: true,
107 bits: 32,
108 is_unspecified: false,
109 }),
110 PrimitiveType::I64 => TypeKind::Integer(IntegerType {
111 signed: true,
112 bits: 64,
113 is_unspecified: false,
114 }),
115 PrimitiveType::U32 => TypeKind::Integer(IntegerType {
116 signed: false,
117 bits: 32,
118 is_unspecified: false,
119 }),
120 PrimitiveType::U64 => TypeKind::Integer(IntegerType {
121 signed: false,
122 bits: 64,
123 is_unspecified: false,
124 }),
125 PrimitiveType::UnspecifiedInt => TypeKind::Integer(IntegerType {
126 signed: true,
127 bits: 0,
128 is_unspecified: true,
129 }),
130 PrimitiveType::F32 => TypeKind::Float(FloatType {
131 bits: 32,
132 is_unspecified: false,
133 }),
134 PrimitiveType::F64 => TypeKind::Float(FloatType {
135 bits: 64,
136 is_unspecified: false,
137 }),
138 PrimitiveType::UnspecifiedFloat => TypeKind::Float(FloatType {
139 bits: 0,
140 is_unspecified: true,
141 }),
142 PrimitiveType::String => TypeKind::String,
143 PrimitiveType::Bool => TypeKind::Boolean,
144 PrimitiveType::Unit => TypeKind::Unit,
145 PrimitiveType::Unknown => TypeKind::Unknown,
146 }
147 }
148}
149
150impl From<PrimitiveType> for usize {
151 fn from(primitive: PrimitiveType) -> usize {
152 primitive as usize
153 }
154}
155
156impl From<PrimitiveType> for TypeId {
157 fn from(primitive: PrimitiveType) -> Self {
158 TypeId::from_primitive(primitive)
159 }
160}
161
162#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
164pub struct TypeId(pub usize);
165
166impl Default for TypeId {
167 fn default() -> Self {
168 TypeId::unknown()
169 }
170}
171
172impl TypeId {
173 pub fn new() -> Self {
175 static NEXT_ID: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(1000); TypeId(NEXT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed))
177 }
178
179 pub fn from_primitive(primitive: PrimitiveType) -> Self {
190 use std::collections::HashMap;
191 use std::sync::LazyLock;
192
193 static PRIMITIVE_IDS: LazyLock<HashMap<PrimitiveType, TypeId>> = LazyLock::new(|| {
194 let mut map = HashMap::new();
195
196 for primitive in PrimitiveType::iter() {
197 map.insert(primitive, TypeId(primitive as usize));
198 }
199 map
200 });
201
202 PRIMITIVE_IDS
203 .get(&primitive)
204 .cloned()
205 .unwrap_or_else(|| panic!("Unknown primitive type: {:?}", primitive))
206 }
207
208 #[inline]
210 pub fn bool() -> Self {
211 Self::from_primitive(PrimitiveType::Bool)
212 }
213
214 #[inline]
216 pub fn i32() -> Self {
217 Self::from_primitive(PrimitiveType::I32)
218 }
219
220 #[inline]
222 pub fn i64() -> Self {
223 Self::from_primitive(PrimitiveType::I64)
224 }
225
226 #[inline]
228 pub fn u32() -> Self {
229 Self::from_primitive(PrimitiveType::U32)
230 }
231
232 #[inline]
234 pub fn u64() -> Self {
235 Self::from_primitive(PrimitiveType::U64)
236 }
237
238 #[inline]
240 pub fn f32() -> Self {
241 Self::from_primitive(PrimitiveType::F32)
242 }
243
244 #[inline]
246 pub fn f64() -> Self {
247 Self::from_primitive(PrimitiveType::F64)
248 }
249
250 #[inline]
252 pub fn string() -> Self {
253 Self::from_primitive(PrimitiveType::String)
254 }
255
256 #[inline]
258 pub fn unit() -> Self {
259 Self::from_primitive(PrimitiveType::Unit)
260 }
261
262 #[inline]
264 pub fn unspecified_int() -> Self {
265 Self::from_primitive(PrimitiveType::UnspecifiedInt)
266 }
267
268 #[inline]
270 pub fn unspecified_float() -> Self {
271 Self::from_primitive(PrimitiveType::UnspecifiedFloat)
272 }
273
274 #[inline]
276 pub fn unknown() -> Self {
277 Self::from_primitive(PrimitiveType::Unknown)
278 }
279}
280
281#[derive(Debug, Clone, PartialEq, Eq, Hash)]
283pub enum TypeKind {
284 Integer(IntegerType),
286 Float(FloatType),
288 String,
290 Boolean,
292 Unit,
294 Struct(StructType),
296 Function(FunctionType),
298 Unknown,
300}
301
302impl TypeKind {
303 pub fn as_function(&self) -> Option<&FunctionType> {
305 match self {
306 TypeKind::Function(func_type) => Some(func_type),
307 _ => None,
308 }
309 }
310}
311
312#[derive(Debug, Clone, PartialEq, Eq, Hash)]
314pub struct IntegerType {
315 pub signed: bool,
317 pub bits: u8,
319 pub is_unspecified: bool,
321}
322
323#[derive(Debug, Clone, PartialEq, Eq, Hash)]
325pub struct FloatType {
326 pub bits: u8,
328 pub is_unspecified: bool,
330}
331
332#[derive(Debug, Clone, PartialEq, Eq, Hash)]
334pub struct StructType {
335 pub name: String,
337 pub fields: Vec<(String, TypeId)>,
339}
340
341impl StructType {
342 pub fn new(name: String, fields: Vec<(String, TypeId)>) -> Self {
344 StructType { name, fields }
345 }
346}
347
348#[derive(Debug, Clone, PartialEq, Eq, Hash)]
350pub struct FunctionType {
351 pub param_types: Vec<TypeId>,
353 pub return_type: TypeId,
355}
356
357impl FunctionType {
358 pub fn new(param_types: Vec<TypeId>, return_type: TypeId) -> Self {
360 FunctionType {
361 param_types,
362 return_type,
363 }
364 }
365}
366
367#[derive(Debug)]
369pub struct TypeInfo {
370 pub id: TypeId,
372 pub name: String,
374 pub kind: TypeKind,
376}