1use crate::{
2 errors::{CResult, FErr, TErr, TResult},
3 FuncType, Type, TypeRelation, typ::{can_transform::{transformation_steps_dist, Transformation}, ABI},
4};
5
6pub type DeriverFunc = fn(&CompData, Type) -> Option<FuncCode>;
7pub type TypeLevelFunc = fn(Vec<Type>, &CompData) -> Type;
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
10pub struct DeriverInfo {
11 pub func_name: VarName,
12 pub is_static: bool,
13}
14
15impl<'a> TryFrom<FuncCodeQuery<'a>> for DeriverInfo {
16 type Error = ();
17
18 fn try_from(info: FuncCodeQuery) -> Result<Self, ()> {
19 let is_static = match info.relation {
20 TypeRelation::MethodOf(_) => false,
21 TypeRelation::Static(_) => true,
22 TypeRelation::Unrelated => return Err(()),
23 };
24
25 Ok(DeriverInfo {
26 func_name: info.name.clone(),
27 is_static,
28 })
29 }
30}
31
32impl CompData {
33 pub fn new() -> Self {
34 let mut out = Self::default();
35
36 out.insert_intrinsic(FuncCode {
37 name: VarName::from("intrinsic_alloc"),
38 args: vec![VarDecl {
39 name: VarName::None,
40 type_spec: TypeSpec::Int(64),
41 }],
42 ret_type: TypeSpec::UInt(8).get_ref(),
43 generic_count: 0,
44 is_external: true,
45 ..FuncCode::empty()
46 });
47
48 out.insert_intrinsic(FuncCode {
49 name: VarName::from("free"),
50 ret_type: TypeSpec::Void,
51 args: vec![VarDecl {
52 name: VarName::None,
53 type_spec: TypeSpec::GenParam(0).get_ref(),
54 }],
55 generic_count: 1,
56 is_external: true,
57 ..FuncCode::empty()
58 });
59
60 out.insert_intrinsic(FuncCode {
61 name: VarName::from("memmove"),
62 ret_type: TypeSpec::Void,
63 args: vec![
64 VarDecl {
65 name: VarName::None,
66 type_spec: TypeSpec::GenParam(0).get_ref(),
67 },
68 VarDecl {
69 name: VarName::None,
70 type_spec: TypeSpec::GenParam(0).get_ref(),
71 },
72 VarDecl {
73 name: VarName::None,
74 type_spec: TypeSpec::UInt(64),
75 },
76 ],
77 generic_count: 1,
78 is_external: true,
79 ..FuncCode::empty()
80 });
81
82 out.insert_intrinsic(FuncCode {
83 name: VarName::from("memcpy"),
84 ret_type: TypeSpec::Void,
85 args: vec![
86 VarDecl {
87 name: VarName::None,
88 type_spec: TypeSpec::GenParam(0).get_ref(),
89 },
90 VarDecl {
91 name: VarName::None,
92 type_spec: TypeSpec::GenParam(0).get_ref(),
93 },
94 VarDecl {
95 name: VarName::None,
96 type_spec: TypeSpec::UInt(64),
97 },
98 ],
99 generic_count: 1,
100 is_external: true,
101 ..FuncCode::empty()
102 });
103
104 out.insert_intrinsic(FuncCode {
105 name: VarName::from("size_of"),
106 ret_type: TypeSpec::UInt(64),
107 args: Vec::new(),
108 generic_count: 1,
109 is_external: true,
110 ..FuncCode::empty()
111 });
112
113 out.insert_intrinsic(FuncCode {
114 name: VarName::from("alignment_of"),
115 ret_type: TypeSpec::UInt(64),
116 args: Vec::new(),
117 generic_count: 1,
118 is_external: true,
119 ..FuncCode::empty()
120 });
121
122 out.insert_intrinsic(FuncCode {
123 name: VarName::from("cast"),
124 args: vec![VarDecl {
125 name: VarName::None,
126 type_spec: "T".into(),
127 }],
128 ret_type: "U".into(),
129 generic_count: 2,
130 is_external: true,
131 ..FuncCode::empty()
132 });
133
134 out.insert_intrinsic(FuncCode {
135 name: VarName::from("typeobj"),
136 args: vec![],
137 ret_type: "Type".into(),
138 generic_count: 1,
139 is_external: true,
140 ..FuncCode::empty()
141 });
142
143 out.typedefs.insert("Type".into(), TypeSpec::Int(64));
144
145 out
146 }
147
148 pub fn insert_code(&mut self, code: FuncCode, backend: Option<&mut Backend>) -> FuncCodeId {
149 for (code_id, old_code) in &self.func_code {
150 if old_code.name == code.name && old_code.relation == code.relation {
151 self.func_code.remove(code_id);
152
153 if let Some(backend) = backend &&
154 let Some(realizations) = self.realizations.remove(code_id) {
155 for realization in realizations {
156 backend.mark_to_recompile(realization);
157 }
158 }
159
160 break;
161 }
162 }
163
164 self.func_code.insert(code)
165 }
166
167 fn insert_intrinsic(&mut self, code: FuncCode) {
168 let decl_info = self.insert_code(code, None);
169 self.intrinsics.insert(decl_info);
170 }
171
172 pub fn name_is_intrinsic(&self, name: &VarName) -> bool {
173 self.intrinsics.iter().any(|id| {
174 &self.func_code[*id].name == name
175 })
176 }
177
178 pub fn query_for_code_with_transformation(
179 &self,
180 query: FuncCodeQuery
181 ) -> Option<(FuncCodeId, Option<Transformation>)> {
182 if let Some(looking_for_relation) = query.relation.inner_type() {
183 let mut closest_function: Option<(FuncCodeId, Option<Transformation>)> = None;
184 let mut closest_function_dist = u32::MAX;
185
186 for (id, code) in &self.func_code {
187 if &code.name != query.name {
188 continue;
189 }
190
191 let Some(looking_at_relation) = code.relation.inner_type() else { continue };
192
193 if let Some(result) =
194 looking_for_relation.can_transform_to(looking_at_relation.clone()) {
195 let result_dist = transformation_steps_dist(&result.steps);
196
197 if closest_function_dist > result_dist {
198 closest_function_dist = result_dist;
199 closest_function = Some((id, Some(result)));
200 }
201 }
202 }
203
204 return closest_function;
205 } else {
206 for (id, code) in &self.func_code {
207 if &code.name != query.name {
208 continue;
209 }
210
211 return Some((id, None));
212 }
213
214 None
215 }
216 }
217
218 pub fn query_for_code(
219 &self,
220 info: FuncCodeQuery,
221 ) -> Option<FuncCodeId> {
222 self.query_for_code_with_transformation(info).map(|f| f.0)
223 }
224
225 pub fn query_for_id(&self, query: &FuncQuery) -> Option<FuncId> {
226 if let Some((code_id, transformation)) =
227 self.query_for_code_with_transformation(query.code_query()) &&
228 let Some(realizations) = self.realizations.get(code_id) {
229
230 let generics = transformation.map(|t| t.generics).unwrap_or_default();
231
232 for realization in realizations {
233 let realization_info = &self.processed[*realization];
234 if realization_info.generics == generics {
235 return Some(*realization);
236 }
237 }
238 }
239
240 for (func_id, info) in &self.processed {
241 if info.name == query.name &&
242 info.relation == query.relation &&
243 info.generics == query.generics {
244 return Some(func_id);
245 }
246 }
247
248 return None;
249 }
250
251
252 pub fn get_func_type(&self, query: &FuncQuery) -> CResult<FuncType> {
253 if let Some(func_id) = self.query_for_id(query) {
254 return Ok(self.processed[func_id].typ.clone());
255 }
256
257 let (code, _) = self.get_code(query.code_query())?;
258
259 let ret_type = self.get_spec(&code.ret_type, &query.generics)?;
260
261 let arg_types = code
262 .args
263 .iter()
264 .map(|arg| self.get_spec(&arg.type_spec, &query.generics))
265 .collect::<TResult<Vec<_>>>()?;
266
267 Ok(FuncType {
268 ret: ret_type,
269 args: arg_types,
270 abi: ABI::C,
271 })
272 }
273
274 pub fn get_derived_code(&self, info: FuncCodeQuery) -> Option<FuncCode> {
275 if let Ok(deriver_info) = DeriverInfo::try_from(info.clone()) &&
276 info.relation.inner_type()?.is_known() {
277 let deriver = self.derivers.get(&deriver_info)?;
278 deriver(self, info.relation.inner_type().cloned()?)
279 } else {
280 None
281 }
282 }
283
284 pub fn get_code(&self, query: FuncCodeQuery) -> CResult<(Cow<FuncCode>, FuncQuery)> {
292 if let Some((decl_info, trans)) = self.query_for_code_with_transformation(query) {
293 return Ok((
294 Cow::Borrowed(&self.func_code[decl_info]),
295 FuncQuery {
296 name: query.name.clone(),
297 relation: query.relation.clone(),
298 generics: trans.map(|t| t.generics).unwrap_or_default(),
299 },
300 ));
301 };
302
303 self.get_derived_code(query)
304 .map(|code| (
305 Cow::Owned(code),
306 FuncQuery {
307 name: query.name.clone(),
308 relation: query.relation.clone(),
309 generics: Vec::new(),
310 },
311 ))
312 .ok_or(FErr::NotFound(query.name.clone(), query.relation.clone()).into())
313 }
314
315 pub fn add_method_deriver(&mut self, func_name: VarName, func: DeriverFunc) {
316 self.derivers.insert(
317 DeriverInfo {
318 func_name,
319 is_static: false,
320 },
321 func,
322 );
323 }
324
325 pub fn add_static_deriver(&mut self, func_name: VarName, func: DeriverFunc) {
326 self.derivers.insert(
327 DeriverInfo {
328 func_name,
329 is_static: true,
330 },
331 func,
332 );
333 }
334
335 pub fn add_type_spec(&mut self, name: TypeName, a: TypeSpec) {
336 self.typedefs.insert(name, a);
337 }
338
339 pub fn contains(&self, key: &TypeName) -> bool { self.typedefs.contains_key(key) }
340
341 pub fn get_by_name(&self, name: &TypeName) -> TResult<Type> {
342 let alias = self.get_typedef_of(name)?;
343 let realized_type = self.get_spec(alias, &())?;
344 Ok(realized_type.with_name(name.clone()).with_generics(&Vec::new()))
345 }
346
347 pub fn get_typedef_of(&self, name: &TypeName) -> TResult<&TypeSpec> {
348 self.typedefs.get(name).ok_or(TErr::Unknown(name.clone()))
349 }
350}
351
352use std::{hash::Hash, borrow::Cow};
353
354use super::*;
355
356#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, XcReflectMac)]
357#[repr(C)]
358pub struct FuncQuery {
359 pub name: VarName,
360 pub relation: TypeRelation,
361 pub generics: Vec<Type>,
362}
363
364impl From<&str> for FuncQuery {
365 fn from(name: &str) -> FuncQuery {
366 FuncQuery {
367 name: name.into(),
368 ..Default::default()
369 }
370 }
371}
372
373impl From<VarName> for FuncQuery {
374 fn from(name: VarName) -> FuncQuery {
375 FuncQuery {
376 name,
377 ..Default::default()
378 }
379 }
380}
381
382impl FuncQuery {
383 pub fn code_query<'a>(&'a self) -> FuncCodeQuery<'a> {
384 FuncCodeQuery {
385 name: &self.name,
386 relation: &self.relation,
387 }
388 }
389}
390
391#[derive(Copy, Debug, Clone, PartialEq, Eq, Hash)]
392#[repr(C)]
393pub struct FuncCodeQuery<'a> {
394 pub name: &'a VarName,
395 pub relation: &'a TypeRelation,
396}
397
398impl<'a> FuncCodeQuery<'a> {
399 pub fn to_owned_fcq(&self) -> OwnedFuncCodeQuery {
400 OwnedFuncCodeQuery {
401 name: self.name.clone(),
402 relation: self.relation.clone(),
403 }
404 }
405}
406
407#[derive(Debug, Clone, PartialEq, Eq, Hash)]
408#[repr(C)]
409pub struct OwnedFuncCodeQuery {
412 pub name: VarName,
413 pub relation: TypeRelation,
414}
415
416impl OwnedFuncCodeQuery {
417 pub fn to_borrowed_fcq<'a>(&'a self) -> FuncCodeQuery<'a> {
418 FuncCodeQuery {
419 name: &self.name,
420 relation: &self.relation,
421 }
422 }
423}