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