uni_locy/compiler/
modules.rs1use std::collections::HashMap;
2
3use uni_cypher::locy_ast::{LocyProgram, UseDecl};
4
5use super::errors::LocyCompileError;
6
7#[derive(Debug, Clone, Default)]
9pub struct ModuleContext {
10 pub module_name: Option<String>,
12 pub imports: HashMap<String, String>,
14}
15
16pub fn resolve_modules(
18 program: &LocyProgram,
19 available_modules: &HashMap<String, Vec<String>>,
20) -> Result<ModuleContext, LocyCompileError> {
21 let mut ctx = ModuleContext::default();
22
23 if let Some(module_decl) = &program.module {
24 ctx.module_name = Some(module_decl.name.to_string());
25 }
26
27 for use_decl in &program.uses {
28 resolve_use(&mut ctx, use_decl, available_modules)?;
29 }
30
31 Ok(ctx)
32}
33
34fn resolve_use(
35 ctx: &mut ModuleContext,
36 use_decl: &UseDecl,
37 available_modules: &HashMap<String, Vec<String>>,
38) -> Result<(), LocyCompileError> {
39 let module_name = use_decl.name.to_string();
40 if let Some(rules) = available_modules.get(&module_name) {
41 match &use_decl.imports {
42 None => {
43 for rule in rules {
45 ctx.imports
46 .insert(rule.clone(), format!("{}.{}", module_name, rule));
47 }
48 }
49 Some(selected) => {
50 for name in selected {
52 if rules.contains(name) {
53 ctx.imports
54 .insert(name.clone(), format!("{}.{}", module_name, name));
55 } else {
56 return Err(LocyCompileError::ImportNotFound {
57 module: module_name,
58 rule: name.clone(),
59 });
60 }
61 }
62 }
63 }
64 Ok(())
65 } else {
66 Err(LocyCompileError::ModuleNotFound { name: module_name })
67 }
68}
69
70pub fn resolve_rule_name(ctx: &ModuleContext, name: &str) -> String {
73 if let Some(qualified) = ctx.imports.get(name) {
74 qualified.clone()
75 } else if let Some(module) = &ctx.module_name {
76 if !name.contains('.') {
78 format!("{}.{}", module, name)
79 } else {
80 name.to_string()
81 }
82 } else {
83 name.to_string()
84 }
85}