rukalang/elab/
instantiate_functions.rs1use super::prelude::*;
2
3struct InstantiateRuntimeFunctionPass<'a> {
14 elaborator: &'a mut Elaborator,
15 callee_name: &'a str,
16 template: &'a RuntimeFunctionTemplate,
17 type_bindings: &'a BTreeMap<String, Ty>,
18 meta_bindings: &'a BTreeMap<String, TemplateMetaBinding>,
19 specialization_key: &'a SpecializationKey,
20 variadic_pack_tys: &'a [Ty],
21}
22
23impl<'a> Pass for InstantiateRuntimeFunctionPass<'a> {
24 type In = ();
25 type Out = String;
26 type Error = ElabError;
27
28 const NAME: &'static str = "elab.instantiate_runtime_function";
29
30 fn run(&mut self, _input: Self::In, _cx: &mut PassContext) -> Result<Self::Out, Self::Error> {
31 if let Some(existing) = self.elaborator.specializations.get(self.specialization_key) {
32 return Ok(existing.clone());
33 }
34 if !self
35 .elaborator
36 .instantiating_functions
37 .insert(self.specialization_key.clone())
38 {
39 return self
40 .elaborator
41 .specializations
42 .get(self.specialization_key)
43 .cloned()
44 .ok_or_else(|| ElabError::ConflictingSpecialization {
45 name: self.callee_name.to_owned(),
46 });
47 }
48
49 let concrete_name = self.elaborator.next_instance_name(self.callee_name);
50 if self.elaborator.signatures.contains_key(&concrete_name) {
51 return Ok(concrete_name);
52 }
53
54 let mut function = self.template.function.clone();
55 function.name = concrete_name.clone();
56 self.elaborator
57 .specialize_function_params(&mut function, self.variadic_pack_tys)?;
58 self.elaborator.apply_type_bindings_to_function(
59 &mut function,
60 self.type_bindings,
61 &self.template.type_params,
62 )?;
63 self.elaborator
64 .apply_meta_bindings_to_function(&mut function, self.meta_bindings)?;
65 function = expand_function_template_instance(
66 &self.elaborator.program,
67 &function,
68 self.meta_bindings,
69 )?;
70
71 let signature = self.elaborator.resolve_function_signature(
72 &function,
73 &self.template.type_params,
74 self.type_bindings,
75 )?;
76 self.elaborator
77 .signatures
78 .insert(concrete_name.clone(), signature);
79 self.elaborator.elaborate_function_body(&mut function)?;
80 self.elaborator.program.functions.push(function);
81 self.elaborator
82 .specializations
83 .insert(self.specialization_key.clone(), concrete_name.clone());
84 let _ = self
85 .elaborator
86 .instantiating_functions
87 .remove(self.specialization_key);
88 Ok(concrete_name)
89 }
90}
91
92impl Elaborator {
93 pub(super) fn instantiate_runtime_function(
95 &mut self,
96 callee_name: &str,
97 template: &RuntimeFunctionTemplate,
98 type_bindings: &BTreeMap<String, Ty>,
99 meta_bindings: &BTreeMap<String, TemplateMetaBinding>,
100 specialization_key: &SpecializationKey,
101 variadic_pack_tys: &[Ty],
102 ) -> Result<String, ElabError> {
103 let mut pass = InstantiateRuntimeFunctionPass {
104 elaborator: self,
105 callee_name,
106 template,
107 type_bindings,
108 meta_bindings,
109 specialization_key,
110 variadic_pack_tys,
111 };
112 let (output, timings) = Elaborator::run_subpass(&mut pass, ())?;
113 self.record_subpass_timings(&timings);
114 Ok(output)
115 }
116}