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