1use crate::llvm::global::Global;
2use crate::llvm::types::LLVMType;
3#[derive(Clone, Debug, PartialEq, Eq, Hash)]
4pub enum Type {
5 Int8,
6 Int16,
7 Int32,
8 Int64,
9 Float,
10 Double,
11 String,
12 Bool,
13 Pointer(Box<Type>),
14 Ref(Box<Type>),
16 Generic(Box<Type>, Vec<Type>),
18 GenericInstance {
19 template: Box<Type>,
20 instance: Box<Type>,
21 },
22 Alias(String),
23 Struct(Option<String>, Vec<(String, Type)>),
24 Enum(Option<String>, Vec<(String, Option<Type>)>),
27 Function(Box<Type>, Vec<(String, Type)>, bool),
28 Array(Box<Type>),
29 Map(Box<Type>, Box<Type>),
30 Closure {
31 name: Option<String>,
32 ptr: (Box<Type>, Vec<(String, Type)>),
33 env: Vec<(String, Type)>,
34 },
35 Any,
36 Unit,
37 ArrayVarArg(Box<Type>),
38 VarArg,
39 Module,
40}
41impl From<&str> for Type {
42 fn from(s: &str) -> Self {
43 match s {
44 "Unit" => Type::Unit,
45 "Int8" => Type::Int8,
46 "Int16" => Type::Int16,
47 "Int32" => Type::Int32,
48 "Int64" => Type::Int64,
49 "Float" => Type::Float,
50 "Double" => Type::Double,
51 "String" => Type::String,
52 "Bool" => Type::Bool,
53 "Any" => Type::Any,
54 "Pointer" => Type::Pointer(Box::new(Type::Any)),
55 "Ref" => Type::Ref(Box::new(Type::Any)),
56 _ => panic!("Unknown type: {}", s),
58 }
59 }
60}
61
62impl From<LLVMType> for Type {
63 fn from(value: LLVMType) -> Self {
64 match value {
65 LLVMType::Int1(_) => Type::Bool,
66 LLVMType::Int8(_) => Type::Int8,
67 LLVMType::Int16(_) => Type::Int16,
68 LLVMType::Int32(_) => Type::Int32,
69 LLVMType::Int64(_) => Type::Int64,
70 LLVMType::Float(_) => Type::Float,
71 LLVMType::Double(_) => Type::Double,
72 LLVMType::Pointer(e, _) => Type::Pointer(Box::new((*e).into())),
73 LLVMType::Unit(_) => Type::Any,
74 t => panic!("{t:?}"),
75 }
76 }
77}
78impl From<String> for Type {
79 fn from(s: String) -> Self {
80 match s.as_str() {
81 "Unit" => Type::Unit,
82 "Int16" => Type::Int16,
83 "Int8" => Type::Int8,
84 "Int32" => Type::Int32,
85 "Int64" => Type::Int64,
86 "Float" => Type::Float,
87 "Double" => Type::Double,
88 "String" => Type::String,
89 "Bool" => Type::Bool,
90 "Any" => Type::Any,
91 s if s.starts_with("*") => {
92 let s = s.strip_prefix("*").unwrap();
93 let t = s.into();
94 Type::Pointer(Box::new(t))
95 }
96
97 s if s.starts_with("[]") => {
98 let s = s.strip_prefix("[]").unwrap();
99 let t = s.into();
100 Type::Array(Box::new(t))
101 }
102 s if s.starts_with("..") => {
103 let s = s.strip_prefix("..").unwrap();
104 let t = s.into();
105 Type::ArrayVarArg(Box::new(t))
106 }
107 t => Type::Alias(t.into()),
108 }
109 }
110}
111impl Type {
112 pub fn get_struct_name(&self) -> Option<&str> {
113 match self {
114 Type::Struct(name, _) => name.as_deref(),
115 Type::Array(_) => Some("Array"),
116 _ => None,
117 }
118 }
119 pub fn get_composite_type_name(&self) -> Option<&str> {
120 match self {
121 Type::Struct(name, _) => name.as_deref(),
122 Type::Array(_) => Some("Array"),
123 Type::Enum(name, _) => name.as_deref(),
124 Type::GenericInstance { instance, .. } => instance.get_composite_type_name(),
125 Type::Ref(t) => t.get_composite_type_name(),
126 _ => None,
127 }
128 }
129 pub fn get_generic_wrapper(&self) -> Option<&Type> {
130 match self {
131 Type::Generic(wrapper, _) => Some(wrapper),
132 _ => None,
133 }
134 }
135 pub fn unwrap_ref(&self) -> Type {
136 match self {
137 Type::Ref(t) => *t.clone(),
138 _ => panic!("Not a ref type"),
139 }
140 }
141 pub fn has_name(&self) -> bool {
142 match self {
143 Type::Struct(name, _) => name.is_some(),
144 Type::Enum(name, _) => name.is_some(),
145 _ => false,
146 }
147 }
148 pub fn set_name(&mut self, name: String) {
149 match self {
150 Type::Struct(n, _) => *n = Some(name),
151 Type::Enum(n, _) => *n = Some(name),
152 _ => panic!("Not a composite type"),
153 }
154 }
155 pub fn is_generic_instance(&self) -> bool {
156 matches!(self, Type::GenericInstance { .. })
157 }
158 pub fn set_composite_type_name(&mut self, name: Option<String>) {
159 match self {
160 Type::Struct(n, _) => *n = name,
161 Type::Array(_) => panic!("Array type cannot be set name"),
162 Type::Enum(n, _) => *n = name,
163 _ => panic!("Not a composite type"),
164 }
165 }
166 pub fn is_integer(&self) -> bool {
167 matches!(self, Type::Int8 | Type::Int16 | Type::Int32 | Type::Int64)
168 }
169 pub fn get_enum_variant_type(&self, name: &str) -> Option<Type> {
170 match self {
171 Type::Enum(_, variants) => {
172 for (name0, t) in variants {
173 if name0 == name {
174 return t.clone();
175 }
176 }
177 None
178 }
179 Type::Ref(t) => t.get_enum_variant_type(name),
180 Type::GenericInstance { instance, .. } => instance.get_enum_variant_type(name),
181 _ => None,
182 }
183 }
184 pub fn is_float(&self) -> bool {
185 matches!(self, Type::Float)
186 }
187 pub fn is_double(&self) -> bool {
188 matches!(self, Type::Double)
189 }
190 pub fn is_generic(&self) -> bool {
191 matches!(self, Type::Generic(_, _))
192 }
193 pub fn id(&self) -> i32 {
194 match self {
195 Type::Unit => 0,
196 Type::Int8 => 1,
197 Type::Pointer(t) if t.is_i8() => 2,
198 Type::Int16 => 3,
199 Type::Pointer(t) if t.is_i16() => 4,
200 Type::Int32 => 5,
201 Type::Pointer(t) if t.is_i32() => 6,
202 Type::Int64 => 7,
203 Type::Pointer(t) | Type::Ref(t) if t.is_i64() => 8,
204 Type::Float => 9,
205 Type::Pointer(t) if t.is_float() => 10,
206 Type::Double => 11,
207 Type::Pointer(t) if t.is_double() => 12,
208 Type::String => 13,
209 Type::Bool => 15,
210 t => panic!("{t:?}"),
212 }
213 }
214 pub fn is_primitive(&self) -> bool {
215 matches!(
216 self,
217 Type::Int32 | Type::Int64 | Type::Float | Type::Double | Type::String | Type::Bool
218 )
219 }
220
221 pub fn as_struct(&self) -> Option<&Vec<(String, Type)>> {
222 match self {
223 Type::Struct(_, m) => Some(m),
224 _ => None,
225 }
226 }
227 pub fn get_generic_template(&self) -> Option<&Type> {
228 match self {
229 Type::GenericInstance { template, .. } => Some(template),
230 _ => None,
231 }
232 }
233 pub fn is_function(&self) -> bool {
234 matches!(self, Type::Function(_, _, _))
235 }
236 pub fn is_module(&self) -> bool {
237 matches!(self, Type::Module)
238 }
239 pub fn is_pointer(&self) -> bool {
240 matches!(self, Type::Pointer(_))
241 }
242 pub fn is_array_vararg(&self) -> bool {
243 matches!(self, Type::ArrayVarArg(_))
244 }
245 pub fn with_return_type(&self, return_type: Type) -> Type {
246 match self {
247 Type::Function(_, args, is_vararg) => {
248 Type::Function(Box::new(return_type), args.clone(), *is_vararg)
249 }
250 _ => panic!("Not a function type"),
251 }
252 }
253 pub fn is_ref(&self) -> bool {
254 matches!(self, Type::Ref(_))
255 }
256 pub fn get_struct_field(&self, name: impl AsRef<str>) -> Option<(usize, Type)> {
257 match self {
258 Type::Struct(_, m) => {
259 for (i, (field_name, t)) in m.iter().enumerate() {
260 if field_name == name.as_ref() {
261 return Some((i, t.clone()));
262 }
263 }
264 None
265 }
266 Type::Ref(t) => t.get_struct_field(name),
267 Type::Pointer(t) => t.get_struct_field(name),
268 Type::GenericInstance { instance, .. } => instance.get_struct_field(name),
269 _ => None,
270 }
271 }
272 pub fn get_function_arg_count(&self) -> usize {
273 match self {
274 Type::Function(_, args, _) => args.len(),
275 Type::Ref(t) => t.get_function_arg_count(),
276 Type::Closure { ptr, .. } => ptr.1.len(),
277 Type::Pointer(t) => t.get_function_arg_count(),
278 Type::GenericInstance { instance, .. } => instance.get_function_arg_count(),
279 _ => panic!("{self:?} Not a function type"),
280 }
281 }
282 pub fn get_closure_fn_name(&self) -> Option<String> {
283 match self {
284 Type::Closure { name, .. } => name.clone(),
285 Type::Ref(t) => t.get_closure_fn_name(),
286 _ => None,
287 }
288 }
289 pub fn get_function_arg_type(&self, index: usize) -> Option<Type> {
290 match self {
291 Type::Function(_, args, _) => args.get(index).cloned().map(|(_, t)| t),
292 _ => None,
293 }
294 }
295 pub fn is_i8(&self) -> bool {
296 matches!(self, Type::Int8)
297 }
298 pub fn is_any(&self) -> bool {
299 matches!(self, Type::Any)
300 }
301 pub fn is_string(&self) -> bool {
302 matches!(self, Type::String)
303 }
304 pub fn is_i16(&self) -> bool {
305 matches!(self, Type::Int16)
306 }
307 pub fn is_i32(&self) -> bool {
308 matches!(self, Type::Int32)
309 }
310 pub fn is_i64(&self) -> bool {
311 matches!(self, Type::Int64)
312 }
313 pub fn is_struct(&self) -> bool {
314 matches!(self, Type::Struct(_, _))
315 }
316 pub fn is_array(&self) -> bool {
317 matches!(self, Type::Array(_))
318 }
319
320 pub fn as_llvm_type(&self) -> LLVMType {
321 match self {
322 Type::Int8 => Global::i8_type(),
323 Type::Int16 => Global::i16_type(),
324 Type::Int32 => Global::i32_type(),
325 Type::Int64 => Global::i64_type(),
326 Type::Float => Global::float_type(),
327 Type::Double => Global::double_type(),
328 Type::Bool => Global::i8_type(),
329 Type::String => Global::string_type(),
330 Type::Pointer(t) => Global::pointer_type(t.as_llvm_type()),
331 Type::Array(t) => Global::pointer_type(t.as_llvm_type()),
332 Type::Struct(_, _) => Global::pointer_type(Global::i8_type()),
333 Type::Enum(_, _) => {
334 let fields = vec![
340 ("id".into(), Global::i32_type()),
342 ("data".into(), Global::i64_type()),
344 ];
345
346 Global::struct_type("Enum".into(), fields)
347 }
348 Type::Function(ret, args, is_vararg) => {
349 let mut v = vec![];
350 for (name, t) in args.iter() {
351 v.push((name.clone(), t.as_llvm_type()));
352 }
353 if *is_vararg {
354 return Global::function_type_with_var_arg(ret.as_llvm_type(), v);
355 }
356 Global::function_type(ret.as_llvm_type(), v)
357 }
358 Type::ArrayVarArg(t) => Global::pointer_type(t.as_llvm_type()),
359 Type::Ref(t) => Global::pointer_type(t.as_llvm_type()),
360 Type::Any => Global::struct_type(
361 "Any".into(),
362 vec![
363 ("id".into(), Global::i32_type()),
364 ("data".into(), Global::pointer_type(Global::i8_type())),
365 ],
366 ),
367 Type::Unit => Global::unit_type(),
368 _ => panic!("Unknown type: {:?}", self),
369 }
370 }
371 pub fn get_alias_name(&self) -> Option<String> {
372 match self {
373 Type::Alias(s) => Some(s.clone()),
374 _ => None,
375 }
376 }
377 pub fn get_struct_fields(&self) -> Option<&Vec<(String, Type)>> {
378 match self {
379 Type::Struct(_, s) => Some(s),
380 _ => None,
381 }
382 }
383 pub fn is_closure(&self) -> bool {
384 matches!(self, Type::Closure { .. })
385 }
386 pub fn is_alias(&self) -> bool {
387 matches!(self, Type::Alias(_))
388 }
389 pub fn get_function_return_type(&self) -> Option<Type> {
390 match self {
391 Type::Pointer(f) => f.get_function_return_type(),
392 Type::Function(r, _, _) => Some(*r.clone()),
393 Type::Ref(t) => t.get_function_return_type(),
394 Type::Closure { ptr, .. } => Some(*ptr.0.clone()),
395 _ => None,
396 }
397 }
398 pub fn get_element_type(&self) -> Option<&Type> {
399 match self {
400 Type::Array(t) => Some(t),
401 Type::Pointer(t) => Some(t),
402 Type::ArrayVarArg(t) => Some(t),
403 Type::Ref(t) => Some(t),
404 _ => None,
405 }
406 }
407 pub fn get_env_type(&self) -> Option<Type> {
408 match self {
409 Type::Closure {
410 name: _,
411 ptr: _,
412 env,
413 } => Some(Type::Pointer(Box::new(Type::Struct(None, env.clone())))),
414 _ => None,
415 }
416 }
417 pub fn get_closure_name(&self) -> Option<String> {
418 match self {
419 Type::Closure {
420 name,
421 ptr: _,
422 env: _,
423 } => name.clone(),
424 _ => None,
425 }
426 }
427 pub fn get_closure_fn_gen_type(&self) -> Option<Type> {
428 match self {
429 Type::Closure { name: _, ptr, env } => {
430 let mut gen_fn_params_type = ptr.1.clone();
431 gen_fn_params_type.push((
432 "env".into(),
433 Type::Pointer(Box::new(Type::Struct(None, env.clone()))),
434 ));
435 Some(Type::Function(ptr.0.clone(), gen_fn_params_type, false))
436 }
437 _ => None,
438 }
439 }
440 pub fn set_enum_name(&mut self, name: String) {
491 match self {
492 Type::Enum(n, _) => *n = Some(name),
493 _ => panic!("Not an enum type"),
494 }
495 }
496 pub fn has_alias(&self) -> bool {
497 match self {
499 Type::Alias(_) => true,
500 Type::Struct(_, s) => {
501 for (_, t) in s.iter() {
502 if t.has_alias() {
503 return true;
504 }
505 }
506 false
507 }
508 Type::Function(_, args, _) => {
509 for (_, t) in args.iter() {
510 if t.has_alias() {
511 return true;
512 }
513 }
514 false
515 }
516 Type::Array(t) => {
517 if t.has_alias() {
518 return true;
519 }
520 false
521 }
522 Type::Pointer(t) => {
523 if t.has_alias() {
524 return true;
525 }
526 false
527 }
528 Type::ArrayVarArg(t) => {
529 if t.has_alias() {
530 return true;
531 }
532 false
533 }
534 Type::Closure { ptr, env, .. } => {
535 if ptr.0.has_alias()
536 || ptr.1.iter().any(|(_, t)| t.has_alias())
537 || env.iter().any(|(_, t)| t.has_alias())
538 {
539 return true;
540 }
541 false
542 }
543 Type::Generic(t, _) => {
544 if t.has_alias() {
545 return true;
546 }
547 false
548 }
549 Type::Map(k, v) => {
550 if k.has_alias() || v.has_alias() {
551 return true;
552 }
553 false
554 }
555 Type::Enum(_, variants) => {
556 for (_, t) in variants.iter() {
557 if let Some(ty) = t {
558 if ty.has_alias() {
559 return true;
560 }
561 }
562 }
563 false
564 }
565 _ => false,
566 }
567 }
568 pub fn as_str(&self) -> String {
569 match self {
570 Type::Alias(s) => s.clone(),
571 Type::Struct(_, s) => {
572 let mut v = vec![];
573 for (_, t) in s.iter() {
574 v.push(t.as_str());
575 }
576 v.join(".")
577 }
578 Type::Function(_, args, _) => {
579 let mut v = vec![];
580 for (name, t) in args.iter() {
581 v.push(format!("{}:{}", name, t.as_str()));
582 }
583 v.join(",")
584 }
585
586 Type::Array(t) => {
587 format!("[]{}", t.as_str())
588 }
589 Type::Pointer(t) => {
590 format!("*{}", t.as_str())
591 }
592 Type::Ref(t) => {
593 format!("&{}", t.as_str())
594 }
595 Type::ArrayVarArg(t) => {
596 format!("..{}", t.as_str())
597 }
598 Type::Closure {
599 name,
600 ptr: _,
601 env: _,
602 } => name.as_deref().unwrap_or("").to_string(),
603 Type::VarArg => "..".to_string(),
604 Type::Generic(t, _) => t.as_str().to_string(),
605
606 Type::Map(k, v) => {
607 format!("Map<{},{}>", k.as_str(), v.as_str())
608 }
609 Type::Enum(name, variants) => {
610 let mut result = String::new();
611 if let Some(name) = name {
612 result.push_str(name);
613 } else {
614 result.push_str("Enum");
615 }
616
617 if !variants.is_empty() {
618 result.push('<');
619 for (i, (variant_name, variant_type)) in variants.iter().enumerate() {
620 if i > 0 {
621 result.push(',');
622 }
623 result.push_str(variant_name);
624 if let Some(ty) = variant_type {
625 result.push_str(&format!("({})", ty.as_str()));
626 }
627 }
628 result.push('>');
629 }
630 result
631 }
632 Type::Module => "Module".to_string(),
633 Type::Int8 => "Int8".to_string(),
634 Type::Int16 => "Int16".to_string(),
635 Type::Int32 => "Int32".to_string(),
636 Type::Int64 => "Int64".to_string(),
637 Type::Float => "Float".to_string(),
638 Type::Double => "Double".to_string(),
639 Type::String => "String".to_string(),
640 Type::Bool => "Bool".to_string(),
641 Type::Any => "Any".to_string(),
642 Type::Unit => "Unit".to_string(),
643 _ => panic!("Unknown type: {:?}", self),
644 }
645 }
646 pub fn is_enum(&self) -> bool {
647 matches!(self, Type::Enum(_, _))
648 }
649
650 pub fn get_enum_name(&self) -> Option<&str> {
651 match self {
652 Type::Enum(name, _) => name.as_ref().map(|s| s.as_str()),
653 _ => None,
654 }
655 }
656
657 pub fn get_enum_variants(&self) -> Option<&Vec<(String, Option<Type>)>> {
658 match self {
659 Type::Enum(_, variants) => Some(variants),
660 _ => None,
661 }
662 }
663 pub fn is_vararg_function(&self) -> bool {
664 matches!(self, Type::Function(_, _, true))
665 }
666}