Skip to main content

mproto_codegen/
db.rs

1use std::collections::HashMap;
2
3use crate::ast::{QualifiedIdentifier, TypeDef, TypeDefId};
4
5pub struct Module {
6    type_defs: Vec<TypeDef>,
7    type_defs_by_name: HashMap<String, TypeDefId>,
8}
9
10impl Module {
11    pub fn new() -> Self {
12        Self {
13            type_defs: Vec::new(),
14            type_defs_by_name: HashMap::new(),
15        }
16    }
17
18    pub fn type_defs(&self) -> impl Iterator<Item = &TypeDef> {
19        self.type_defs.iter()
20    }
21
22    pub fn from_type_defs(type_defs: Vec<TypeDef>) -> Self {
23        let type_defs_by_name = type_defs
24            .iter()
25            .enumerate()
26            .map(|(i, type_def)| (type_def.name.clone(), TypeDefId(i)))
27            .collect();
28
29        Self {
30            type_defs,
31            type_defs_by_name,
32        }
33    }
34
35    pub fn new_type_def(&mut self, type_def: TypeDef) -> TypeDefId {
36        let id = TypeDefId(self.type_defs.len());
37
38        self.type_defs_by_name.insert(type_def.name.clone(), id);
39        self.type_defs.push(type_def);
40
41        id
42    }
43
44    pub fn type_def(&self, id: TypeDefId) -> &TypeDef {
45        &self.type_defs[id.0]
46    }
47
48    pub fn type_def_by_name<'a>(&'a self, name: &str) -> Option<&'a TypeDef> {
49        Some(self.type_def(*self.type_defs_by_name.get(name)?))
50    }
51}
52
53struct DatabaseImport {
54    lib_suffix: String,
55    module: Module,
56}
57
58pub struct Database {
59    imports: HashMap<String, DatabaseImport>,
60    local: Module,
61}
62
63impl Database {
64    pub fn new(local: Module) -> Self {
65        Self {
66            imports: HashMap::new(),
67            local,
68        }
69    }
70
71    pub fn local(&self) -> &Module {
72        &self.local
73    }
74
75    pub fn local_mut(&mut self) -> &mut Module {
76        &mut self.local
77    }
78
79    pub fn add_module(&mut self, name: String, lib_suffix: impl Into<String>, module: Module) {
80        self.imports.insert(
81            name,
82            DatabaseImport {
83                lib_suffix: lib_suffix.into(),
84                module,
85            },
86        );
87    }
88
89    pub fn imported_module_mut(&mut self, module_name: &str) -> Option<&mut Module> {
90        Some(&mut self.imports.get_mut(module_name)?.module)
91    }
92
93    pub fn lookup_module_lib_suffix<'a>(&'a self, module_name: &str) -> Option<&'a str> {
94        let import = self.imports.get(module_name)?;
95        Some(&import.lib_suffix)
96    }
97
98    pub fn lookup_type_def<'a>(&'a self, identifier: &QualifiedIdentifier) -> Option<&'a TypeDef> {
99        if let Some(ref module_name) = identifier.module {
100            // Importing from another module.
101            let import = self.imports.get(module_name)?;
102            import.module.type_def_by_name(&identifier.name)
103        } else {
104            // It's a local definition.
105            self.local.type_def_by_name(&identifier.name)
106        }
107    }
108}