1use crate::{ImportAsset, ModuleDeclarationError};
2use arora_registry::local::ROOT_ID;
3use arora_registry::{get_primitive, Module, ModuleFrozen, ReadableRegistry, RegistryError};
4use arora_types::module::low::Header;
5use arora_types::module::{
6 high::{
7 ExportSymbol as HighExportSymbol, ImportSymbol as HighImportSymbol,
8 ModuleDefinition as HighModuleDefinition, Parameter as HighParameter,
9 TypeRef as HighTypeRef,
10 },
11 low::{
12 ExportSymbol as LowExportSymbol, ImportSymbol as LowImportSymbol,
13 Parameter as LowParameter, TypeRef as LowTypeRef,
14 },
15};
16use arora_types::record::Selector;
17use arora_types::record::{
18 module::unfrozen::{Export, Function, Parameter},
19 ty::{UnfrozenArray, UnfrozenScalar, UnfrozenTy},
20};
21use arora_types::record::{Freeze, Resolver, UnfrozenReference, VersionReq};
22use std::collections::HashSet;
23use std::{collections::HashMap, str::FromStr};
24use uuid::Uuid;
25
26pub async fn resolve_type_id(
27 name: &str,
28 registry: &mut dyn ReadableRegistry,
29) -> Result<Uuid, ModuleDeclarationError> {
30 Ok(match Uuid::parse_str(name) {
31 Ok(id) => id,
32 Err(_) => registry
33 .resolve_path(name)
34 .await
35 .map_err(ModuleDeclarationError::RegistryError)?,
36 })
37}
38
39pub async fn resolve_module_id(
40 name: &str,
41 registry: &mut dyn ReadableRegistry,
42) -> Result<Uuid, ModuleDeclarationError> {
43 Ok(match Uuid::parse_str(name) {
44 Ok(id) => id,
45 Err(_) => registry
46 .resolve_path(name)
47 .await
48 .map_err(ModuleDeclarationError::RegistryError)?,
49 })
50}
51
52pub async fn resolve_high_type_ref(
53 type_ref: &HighTypeRef,
54 registry: &mut dyn ReadableRegistry,
55) -> Result<UnfrozenTy, ModuleDeclarationError> {
56 match type_ref {
57 HighTypeRef::Scalar { id } => {
58 let selector = Selector::from_str(id).map_err(ModuleDeclarationError::Generic)?;
59 if let Some(primitive) = get_primitive(&selector) {
60 Ok(UnfrozenTy::Primitive(primitive.into()))
61 } else {
62 Ok(UnfrozenTy::UnfrozenScalar(UnfrozenScalar {
63 reference: unfrozen_reference_from_name(id, registry).await?,
64 }))
65 }
66 }
67 HighTypeRef::Array { id } => {
68 let selector = Selector::from_str(id).map_err(ModuleDeclarationError::Generic)?;
69 if let Some(primitive) = get_primitive(&selector) {
70 Ok(UnfrozenTy::Primitive(primitive.into()))
71 } else {
72 Ok(UnfrozenTy::UnfrozenArray(UnfrozenArray {
73 reference: unfrozen_reference_from_name(id, registry).await?,
74 }))
75 }
76 }
77 _ => Err(ModuleDeclarationError::Generic(format!(
78 "Unsupported type ref: {:?}",
79 type_ref
80 ))),
81 }
82}
83
84pub async fn resolve_low_type_ref(
85 type_ref: &LowTypeRef,
86) -> Result<UnfrozenTy, ModuleDeclarationError> {
87 match type_ref {
88 LowTypeRef::Scalar { id } => {
89 let selector = Selector::Id(id.to_owned());
90 if let Some(primitive) = get_primitive(&selector) {
91 Ok(UnfrozenTy::Primitive(primitive.into()))
92 } else {
93 Ok(UnfrozenTy::UnfrozenScalar(UnfrozenScalar {
94 reference: unfrozen_reference_from_id(id).await?,
95 }))
96 }
97 }
98 LowTypeRef::Array { id } => {
99 let selector = Selector::Id(id.to_owned());
100 if let Some(primitive) = get_primitive(&selector) {
101 Ok(UnfrozenTy::Primitive(primitive.into()))
102 } else {
103 Ok(UnfrozenTy::UnfrozenArray(UnfrozenArray {
104 reference: unfrozen_reference_from_id(id).await?,
105 }))
106 }
107 }
108 _ => Err(ModuleDeclarationError::Generic(format!(
109 "Unsupported type ref: {:?}",
110 type_ref
111 ))),
112 }
113}
114
115async fn unfrozen_reference_from_name(
116 name_or_id: &str,
117 registry: &mut dyn ReadableRegistry,
118) -> Result<UnfrozenReference, ModuleDeclarationError> {
119 Ok(UnfrozenReference {
120 id: resolve_type_id(name_or_id, registry).await?,
121 version_req: VersionReq::parse("*").unwrap(),
122 })
123}
124
125async fn unfrozen_reference_from_id(
126 id: &Uuid,
127) -> Result<UnfrozenReference, ModuleDeclarationError> {
128 Ok(UnfrozenReference {
129 id: id.to_owned(),
130 version_req: VersionReq::parse("*").unwrap(),
131 })
132}
133
134pub async fn resolve_high_parameter(
135 parameter: HighParameter,
136 registry: &mut dyn ReadableRegistry,
137) -> Result<Parameter, ModuleDeclarationError> {
138 Ok(Parameter {
139 name: parameter.name,
140 ty: resolve_high_type_ref(¶meter.ty, registry).await?,
141 mutable: parameter.mutable,
142 })
143}
144
145pub async fn resolve_low_parameter(
146 parameter: LowParameter,
147) -> Result<Parameter, ModuleDeclarationError> {
148 Ok(Parameter {
149 name: parameter.name,
150 ty: resolve_low_type_ref(¶meter.ty).await?,
151 mutable: parameter.mutable,
152 })
153}
154
155pub async fn resolve_high_import(
156 symbol: HighImportSymbol,
157 registry: &mut dyn ReadableRegistry,
158) -> Result<Export, ModuleDeclarationError> {
159 Ok(match symbol {
160 HighImportSymbol::Function(function) => {
161 let mut parameters = HashMap::new();
162 let mut parameter_ordering = Vec::new();
163 for parameter in function.parameters {
164 let parameter_id = parameter.id.to_owned();
165 let resolved_parameter = resolve_high_parameter(parameter, registry).await?;
166 parameters.insert(parameter_id.to_owned(), resolved_parameter);
167 parameter_ordering.push(parameter_id);
168 }
169 Export {
170 name: function.name,
171 kind: arora_types::record::module::unfrozen::ExportKind::Function(Function {
172 parameters,
173 return_ty: resolve_high_type_ref(&function.ret, registry).await?,
174 parameter_ordering,
175 }),
176 }
177 }
178 })
179}
180
181pub async fn resolve_low_import(symbol: LowImportSymbol) -> Result<Export, ModuleDeclarationError> {
182 Ok(match symbol {
183 LowImportSymbol::Function(function) => {
184 let mut parameters = HashMap::new();
185 let mut parameter_ordering = Vec::new();
186 for parameter in function.parameters {
187 let parameter_id = parameter.id.to_owned();
188 let resolved_parameter = resolve_low_parameter(parameter).await?;
189 parameters.insert(parameter_id.to_owned(), resolved_parameter);
190 parameter_ordering.push(parameter_id);
191 }
192 Export {
193 name: function.name,
194 kind: arora_types::record::module::unfrozen::ExportKind::Function(Function {
195 parameters,
196 return_ty: resolve_low_type_ref(&function.ret).await?,
197 parameter_ordering,
198 }),
199 }
200 }
201 })
202}
203
204pub async fn resolve_high_export(
205 symbol: HighExportSymbol,
206 registry: &mut dyn ReadableRegistry,
207) -> Result<Export, ModuleDeclarationError> {
208 Ok(match symbol {
209 HighExportSymbol::Function(function) => {
210 let mut parameters = HashMap::new();
211 let mut parameter_ordering = Vec::new();
212 for parameter in function.parameters {
213 let parameter_id = parameter.id.to_owned();
214 let resolved_parameter = resolve_high_parameter(parameter, registry).await?;
215 parameters.insert(parameter_id.to_owned(), resolved_parameter);
216 parameter_ordering.push(parameter_id);
217 }
218 Export {
219 name: function.name,
220 kind: arora_types::record::module::unfrozen::ExportKind::Function(Function {
221 parameters,
222 return_ty: resolve_high_type_ref(&function.ret, registry).await?,
223 parameter_ordering,
224 }),
225 }
226 }
227 })
228}
229
230pub async fn resolve_low_export(symbol: LowExportSymbol) -> Result<Export, ModuleDeclarationError> {
231 Ok(match symbol {
232 LowExportSymbol::Function(function) => {
233 let mut parameters = HashMap::new();
234 let mut parameter_ordering = Vec::new();
235 for parameter in function.parameters {
236 let parameter_id = parameter.id.to_owned();
237 let resolved_parameter = resolve_low_parameter(parameter).await?;
238 parameters.insert(parameter_id.to_owned(), resolved_parameter);
239 parameter_ordering.push(parameter_id);
240 }
241 Export {
242 name: function.name,
243 kind: arora_types::record::module::unfrozen::ExportKind::Function(Function {
244 parameters,
245 return_ty: resolve_low_type_ref(&function.ret).await?,
246 parameter_ordering,
247 }),
248 }
249 }
250 })
251}
252
253pub async fn resolve_high_module<R: ReadableRegistry + Resolver>(
254 module_definition: HighModuleDefinition,
255 registry: &mut R,
256) -> Result<ModuleAndImports, ModuleDeclarationError> {
257 let mut dependencies = HashSet::new();
258
259 let mut imports = Vec::new();
260 for import in module_definition.imports {
261 let HighImportSymbol::Function(import_function) = import.clone();
262 let import_module_id = resolve_module_id(import_function.module.as_str(), registry).await?;
263 let import_module_selector = Selector::Id(import_module_id);
264 let import_module_version = registry
265 .resolve_tag(&import_module_selector, &semver::VersionReq::STAR)
266 .await
267 .map_err(ModuleDeclarationError::RegistryError)?;
268 let import_module = registry
269 .get_module(&import_module_selector, &semver::VersionReq::STAR)
270 .await
271 .map_err(ModuleDeclarationError::RegistryError)?;
272 dependencies.insert(UnfrozenReference {
273 id: import_module_id,
274 version_req: VersionReq::parse("*").unwrap(),
275 });
276 let import_id = import_function.id.to_owned();
277 let resolved_import = resolve_high_import(import, registry).await?;
278 let mut import_deps = HashSet::new();
279 resolved_import.dependencies(&mut import_deps);
280 dependencies.extend(import_deps.into_iter().cloned());
281 imports.push(ImportAsset {
282 module_id: import_module_id,
283 tag: import_module_version,
284 module_name: import_module.name.clone(),
285 id: import_id,
286 import: resolved_import.freeze(registry).await.map_err(|e| {
287 ModuleDeclarationError::RegistryError(RegistryError::Generic {
288 message: format!("error freezing import {}: {}", import_id, e),
289 })
290 })?,
291 });
292 }
293
294 let mut exports = HashMap::new();
295 for export in module_definition.exports {
296 let HighExportSymbol::Function(export_function) = export.clone();
297 let resolved_export = resolve_high_export(export, registry).await?;
298 let mut export_deps = HashSet::new();
299 resolved_export.dependencies(&mut export_deps);
300 dependencies.extend(export_deps.into_iter().cloned());
301 exports.insert(export_function.id, resolved_export);
302 }
303
304 let module = Module {
305 parent: ROOT_ID.to_owned(),
306 name: module_definition.name,
307 executable: None,
308 exports,
309 dependencies: dependencies.into_iter().collect(),
310 };
311 Ok(ModuleAndImports {
312 module: module.freeze(registry).await.map_err(|e| {
313 ModuleDeclarationError::RegistryError(RegistryError::Generic {
314 message: format!("error freezing module {}: {}", module_definition.id, e),
315 })
316 })?,
317 imports,
318 })
319}
320
321pub async fn resolve_low_module<R: ReadableRegistry + Resolver>(
322 module_header: Header,
323 registry: &mut R,
324) -> Result<ModuleAndImports, ModuleDeclarationError> {
325 let mut dependencies = HashSet::new();
326
327 let mut imports = Vec::new();
328 for import in module_header.imports {
329 let LowImportSymbol::Function(import_function) = import.clone();
330 let import_module_id = import_function.module;
331 let import_module_selector = Selector::Id(import_module_id);
332 let import_module_version = registry
333 .resolve_tag(&import_module_selector, &semver::VersionReq::STAR)
334 .await
335 .map_err(ModuleDeclarationError::RegistryError)?;
336 let import_module = registry
337 .get_module(&Selector::Id(import_module_id), &semver::VersionReq::STAR)
338 .await
339 .map_err(ModuleDeclarationError::RegistryError)?;
340 dependencies.insert(UnfrozenReference {
341 id: import_module_id,
342 version_req: VersionReq::parse("*").unwrap(),
343 });
344 let import_id = import_function.id.to_owned();
345 let resolved_import = resolve_low_import(import).await?;
346 let mut import_deps = HashSet::new();
347 resolved_import.dependencies(&mut import_deps);
348 dependencies.extend(import_deps.into_iter().cloned());
349 imports.push(ImportAsset {
350 module_id: import_module_id,
351 tag: import_module_version,
352 module_name: import_module.name.clone(),
353 id: import_id.to_owned(),
354 import: resolved_import.freeze(registry).await.map_err(|e| {
355 ModuleDeclarationError::RegistryError(RegistryError::Generic {
356 message: format!("error freezing import {}: {}", import_id, e),
357 })
358 })?,
359 });
360 }
361
362 let mut exports = HashMap::new();
363 for export in module_header.exports {
364 let LowExportSymbol::Function(export_function) = export.clone();
365 let resolved_export = resolve_low_export(export).await?;
366 let mut export_deps = HashSet::new();
367 resolved_export.dependencies(&mut export_deps);
368 dependencies.extend(export_deps.into_iter().cloned());
369 exports.insert(export_function.id, resolved_export);
370 }
371 let module = Module {
372 parent: ROOT_ID.to_owned(),
373 name: module_header.name,
374 executable: None,
375 exports,
376 dependencies: dependencies.into_iter().collect(),
377 };
378 Ok(ModuleAndImports {
379 module: module.freeze(registry).await.map_err(|e| {
380 ModuleDeclarationError::RegistryError(RegistryError::Generic {
381 message: format!("error freezing module {}: {}", module_header.id, e),
382 })
383 })?,
384 imports,
385 })
386}
387
388pub struct ModuleAndImports {
389 pub module: ModuleFrozen,
390 pub imports: Vec<ImportAsset>,
391}