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 let import = self.imports.get(module_name)?;
102 import.module.type_def_by_name(&identifier.name)
103 } else {
104 self.local.type_def_by_name(&identifier.name)
106 }
107 }
108}