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