1use super::GaiaType;
7use std::collections::HashMap;
8
9#[derive(Debug, Default)]
11pub struct TypeMappingContext {
12 type_cache: HashMap<String, GaiaType>,
14 generic_bounds: HashMap<String, Vec<GaiaType>>,
16 type_erasure_map: HashMap<String, String>,
18}
19
20impl TypeMappingContext {
21 pub fn new() -> Self {
23 Self::default()
24 }
25
26 pub fn add_generic_bound(&mut self, type_param: &str, bound: GaiaType) {
28 self.generic_bounds.entry(type_param.to_string())
29 .or_default()
30 .push(bound);
31 }
32
33 pub fn add_type_erasure(&mut self, generic_type: &str, erased_type: &str) {
35 self.type_erasure_map.insert(generic_type.to_string(), erased_type.to_string());
36 }
37
38 pub fn get_erased_type(&self, generic_type: &str) -> Option<&String> {
40 self.type_erasure_map.get(generic_type)
41 }
42}
43
44pub fn parse_type_name(type_name: &str, ctx: &mut TypeMappingContext) -> GaiaType {
48 if let Some(gaia_type) = ctx.type_cache.get(type_name) {
49 return gaia_type.clone();
50 }
51
52 let gaia_type = match type_name {
53 "bool" => GaiaType::Bool,
54 "byte" | "i8" => GaiaType::I8,
55 "short" | "i16" => GaiaType::I16,
56 "int" | "i32" => GaiaType::I32,
57 "long" | "i64" => GaiaType::I64,
58 "float" | "f32" => GaiaType::F32,
59 "double" | "f64" => GaiaType::F64,
60 "char" => GaiaType::U16,
61 "void" => GaiaType::Void,
62
63 "String" => GaiaType::String,
64 "Object" => GaiaType::Object,
65
66 s if s.starts_with('[') => {
67 let element_type = &s[1..];
68 let gaia_element_type = parse_type_name(element_type, ctx);
69 GaiaType::Array(Box::new(gaia_element_type), 0)
70 }
71
72 s if s.contains('<') && s.contains('>') => {
73 let (base_type, _type_params) = parse_generic_type(s);
74
75 if let Some(erased_type) = ctx.get_erased_type(base_type) {
76 GaiaType::Class(erased_type.clone())
77 } else {
78 GaiaType::Class(base_type.to_string())
79 }
80 }
81
82 s => GaiaType::Class(s.to_string()),
83 };
84
85 ctx.type_cache.insert(type_name.to_string(), gaia_type.clone());
86 gaia_type
87}
88
89pub fn map_uir_type_to_gaia_type(uir_type: &str, ctx: &mut TypeMappingContext) -> GaiaType {
91 parse_type_name(uir_type, ctx)
92}
93
94fn parse_generic_type(generic_type: &str) -> (&str, Vec<&str>) {
96 if let Some(idx) = generic_type.find('<') {
97 let base_type = &generic_type[..idx];
98 let params_str = &generic_type[idx+1..generic_type.len()-1];
99 let type_params = params_str.split(',').map(|p| p.trim()).collect();
100 (base_type, type_params)
101 } else {
102 (generic_type, Vec::new())
103 }
104}
105
106pub fn map_gaia_type_to_jvm_descriptor(ty: &GaiaType) -> String {
108 match ty {
109 GaiaType::Void => "V".to_string(),
110 GaiaType::Bool => "Z".to_string(),
111 GaiaType::I8 => "B".to_string(),
112 GaiaType::U8 => "B".to_string(),
113 GaiaType::I16 => "S".to_string(),
114 GaiaType::U16 => "S".to_string(),
115 GaiaType::I32 => "I".to_string(),
116 GaiaType::U32 => "I".to_string(),
117 GaiaType::I64 => "J".to_string(),
118 GaiaType::U64 => "J".to_string(),
119 GaiaType::F32 => "F".to_string(),
120 GaiaType::F64 => "D".to_string(),
121 GaiaType::String => "Ljava/lang/String;".to_string(),
122 GaiaType::Class(name) => format!("L{};", name.replace('.', "/")),
123 GaiaType::Array(inner, _) => format!("[{}", map_gaia_type_to_jvm_descriptor(inner)),
124 GaiaType::Object => "Ljava/lang/Object;".to_string(),
125 GaiaType::Interface(name) => format!("L{};", name.replace('.', "/")),
126 _ => "Ljava/lang/Object;".to_string(),
127 }
128}
129
130pub fn are_types_compatible(from: &GaiaType, to: &GaiaType) -> bool {
132 match (from, to) {
133 (f, t) if f == t => true,
134
135 (GaiaType::I8, GaiaType::I16) => true,
136 (GaiaType::I8, GaiaType::I32) => true,
137 (GaiaType::I8, GaiaType::I64) => true,
138 (GaiaType::I8, GaiaType::F32) => true,
139 (GaiaType::I8, GaiaType::F64) => true,
140 (GaiaType::U8, GaiaType::I16) => true,
141 (GaiaType::U8, GaiaType::I32) => true,
142 (GaiaType::U8, GaiaType::I64) => true,
143 (GaiaType::U8, GaiaType::F32) => true,
144 (GaiaType::U8, GaiaType::F64) => true,
145 (GaiaType::I16, GaiaType::I32) => true,
146 (GaiaType::I16, GaiaType::I64) => true,
147 (GaiaType::I16, GaiaType::F32) => true,
148 (GaiaType::I16, GaiaType::F64) => true,
149 (GaiaType::U16, GaiaType::I32) => true,
150 (GaiaType::U16, GaiaType::I64) => true,
151 (GaiaType::U16, GaiaType::F32) => true,
152 (GaiaType::U16, GaiaType::F64) => true,
153 (GaiaType::I32, GaiaType::I64) => true,
154 (GaiaType::I32, GaiaType::F32) => true,
155 (GaiaType::I32, GaiaType::F64) => true,
156 (GaiaType::U32, GaiaType::I64) => true,
157 (GaiaType::U32, GaiaType::F32) => true,
158 (GaiaType::U32, GaiaType::F64) => true,
159 (GaiaType::I64, GaiaType::F64) => true,
160 (GaiaType::U64, GaiaType::F64) => true,
161 (GaiaType::F32, GaiaType::F64) => true,
162
163 (GaiaType::String, GaiaType::Object) => true,
164 (GaiaType::Class(_), GaiaType::Object) => true,
165 (GaiaType::Interface(_), GaiaType::Object) => true,
166 (GaiaType::Array(_, _), GaiaType::Object) => true,
167
168 (GaiaType::Bool, GaiaType::Object) => true,
169 (GaiaType::I8, GaiaType::Object) => true,
170 (GaiaType::U8, GaiaType::Object) => true,
171 (GaiaType::I16, GaiaType::Object) => true,
172 (GaiaType::U16, GaiaType::Object) => true,
173 (GaiaType::I32, GaiaType::Object) => true,
174 (GaiaType::U32, GaiaType::Object) => true,
175 (GaiaType::I64, GaiaType::Object) => true,
176 (GaiaType::U64, GaiaType::Object) => true,
177 (GaiaType::F32, GaiaType::Object) => true,
178 (GaiaType::F64, GaiaType::Object) => true,
179
180 (GaiaType::Array(f_inner, _), GaiaType::Array(t_inner, _)) => {
181 are_types_compatible(f_inner, t_inner)
182 },
183
184 (GaiaType::Any, GaiaType::Object) => true,
185
186 _ => false,
187 }
188}
189
190pub fn get_common_super_type(a: &GaiaType, b: &GaiaType) -> Option<GaiaType> {
192 if are_types_compatible(a, b) {
193 return Some(b.clone());
194 }
195 if are_types_compatible(b, a) {
196 return Some(a.clone());
197 }
198
199 match (a, b) {
200 (GaiaType::String, _) | (_, GaiaType::String) => Some(GaiaType::Object),
201 (GaiaType::Class(_), _) | (_, GaiaType::Class(_)) => Some(GaiaType::Object),
202 (GaiaType::Interface(_), _) | (_, GaiaType::Interface(_)) => Some(GaiaType::Object),
203 (GaiaType::Array(_, _), _) | (_, GaiaType::Array(_, _)) => Some(GaiaType::Object),
204 _ => None,
205 }
206}