erg_compiler/module/
global.rs

1use erg_common::config::ErgConfig;
2use erg_common::pathutil::NormalizedPathBuf;
3use erg_common::shared::MappedRwLockReadGuard;
4use erg_common::spawn::safe_yield;
5
6use crate::context::{Context, ModuleContext};
7
8use super::cache::{ModuleEntry, SharedGeneralizationCache, SharedModuleCache};
9use super::errors::{SharedCompileErrors, SharedCompileWarnings};
10use super::graph::SharedModuleGraph;
11use super::impls::SharedTraitImpls;
12use super::index::SharedModuleIndex;
13use super::promise::SharedPromises;
14
15fn try_forever<T, F: FnMut() -> Result<T, ()>>(mut f: F) -> T {
16    loop {
17        if let Ok(res) = f() {
18            return res;
19        }
20        safe_yield();
21    }
22}
23
24#[derive(Debug, Clone, Default)]
25pub struct SharedCompilerResource {
26    pub mod_cache: SharedModuleCache,
27    pub py_mod_cache: SharedModuleCache,
28    pub index: SharedModuleIndex,
29    pub graph: SharedModuleGraph,
30    /// K: name of a trait, V: (type, monomorphised trait that the type implements)
31    /// K: トレイトの名前, V: (型, その型が実装する単相化トレイト)
32    /// e.g. { "Named": [(Type, Named), (Func, Named), ...], "Add": [(Nat, Add(Nat)), (Int, Add(Int)), ...], ... }
33    pub trait_impls: SharedTraitImpls,
34    pub promises: SharedPromises,
35    pub errors: SharedCompileErrors,
36    pub warns: SharedCompileWarnings,
37    pub gen_cache: SharedGeneralizationCache,
38}
39
40impl SharedCompilerResource {
41    /// Initialize the shared compiler resource.
42    /// This API is normally called only once throughout the compilation phase.
43    pub fn new(cfg: ErgConfig) -> Self {
44        let graph = SharedModuleGraph::new();
45        let self_ = Self {
46            mod_cache: SharedModuleCache::new(),
47            py_mod_cache: SharedModuleCache::new(),
48            index: SharedModuleIndex::new(),
49            graph: graph.clone(),
50            trait_impls: SharedTraitImpls::new(),
51            promises: SharedPromises::new(graph, NormalizedPathBuf::from(cfg.input.path())),
52            errors: SharedCompileErrors::new(),
53            warns: SharedCompileWarnings::new(),
54            gen_cache: SharedGeneralizationCache::new(),
55        };
56        Context::init_builtins(cfg, self_.clone());
57        self_
58    }
59
60    pub fn inherit<P: Into<NormalizedPathBuf>>(&self, path: P) -> Self {
61        let mut _self = self.clone();
62        _self.promises.root = path.into();
63        _self
64    }
65
66    /// Clear all but builtin modules
67    pub fn clear_all(&self) {
68        self.mod_cache.initialize();
69        self.py_mod_cache.initialize();
70        self.index.initialize();
71        self.graph.initialize();
72        self.trait_impls.initialize();
73        self.promises.initialize();
74        self.errors.clear();
75        self.warns.clear();
76    }
77
78    /// Clear all information about the module.
79    /// Graph information is not cleared (due to ELS).
80    pub fn clear(&self, path: &NormalizedPathBuf) -> Option<ModuleEntry> {
81        let mut old = None;
82        for child in self.graph.children(path) {
83            self.clear(&child);
84        }
85        try_forever(|| {
86            if let Some(ent) = self.mod_cache.try_remove(path)? {
87                old = Some(ent);
88            }
89            Ok(())
90        });
91        try_forever(|| {
92            if let Some(ent) = self.py_mod_cache.try_remove(path)? {
93                old = Some(ent);
94            }
95            Ok(())
96        });
97        self.index.remove_path(path);
98        // self.graph.remove(path);
99        self.trait_impls.remove_by_path(path);
100        self.promises.remove(path);
101        self.errors.remove(path);
102        self.warns.remove(path);
103        old
104    }
105
106    pub fn clear_path(&self, path: &NormalizedPathBuf) {
107        try_forever(|| self.mod_cache.try_remove(path));
108        try_forever(|| self.py_mod_cache.try_remove(path));
109        self.index.remove_path(path);
110        // self.graph.remove(path);
111        self.trait_impls.remove_by_path(path);
112        self.promises.remove(path);
113        self.errors.remove(path);
114        self.warns.remove(path);
115    }
116
117    pub fn rename_path(&self, old: &NormalizedPathBuf, new: NormalizedPathBuf) {
118        self.mod_cache.rename_path(old, new.clone());
119        self.py_mod_cache.rename_path(old, new.clone());
120        self.index.rename_path(old, new.clone());
121        self.trait_impls.rename_path(old, new.clone());
122        self.graph.rename_path(old, new.clone());
123        self.promises.rename(old, new);
124    }
125
126    pub fn insert_module(&self, path: NormalizedPathBuf, entry: ModuleEntry) {
127        if path.to_string_lossy().ends_with(".d.er") {
128            self.py_mod_cache.insert(path, entry);
129        } else {
130            self.mod_cache.insert(path, entry);
131        }
132    }
133
134    /// This is intended to be called from a language server, etc.,
135    /// this blocks until it gets a lock.
136    pub fn remove_module(&self, path: &std::path::Path) -> Option<ModuleEntry> {
137        if path.to_string_lossy().ends_with(".d.er") {
138            try_forever(|| self.py_mod_cache.try_remove(path))
139        } else {
140            try_forever(|| self.mod_cache.try_remove(path))
141        }
142    }
143
144    pub fn get_module(
145        &self,
146        path: &std::path::Path,
147    ) -> Option<MappedRwLockReadGuard<'_, ModuleEntry>> {
148        if path.to_string_lossy().ends_with(".d.er") {
149            self.py_mod_cache.get(path)
150        } else {
151            self.mod_cache.get(path)
152        }
153    }
154
155    pub fn raw_ref_ctx_with_timeout(
156        &self,
157        path: &std::path::Path,
158        timeout: std::time::Duration,
159    ) -> Option<&ModuleContext> {
160        if path.to_string_lossy().ends_with(".d.er") {
161            self.py_mod_cache.raw_ref_ctx_with_timeout(path, timeout)
162        } else {
163            self.mod_cache.raw_ref_ctx_with_timeout(path, timeout)
164        }
165    }
166
167    pub fn raw_ref_builtins_ctx(&self) -> Option<&ModuleContext> {
168        self.mod_cache.raw_ref_builtins_ctx()
169    }
170
171    pub fn raw_modules(&self) -> impl Iterator<Item = &ModuleEntry> {
172        self.mod_cache
173            .raw_values()
174            .chain(self.py_mod_cache.raw_values())
175    }
176
177    pub fn raw_path_and_modules(&self) -> impl Iterator<Item = (&NormalizedPathBuf, &ModuleEntry)> {
178        self.mod_cache
179            .raw_iter()
180            .chain(self.py_mod_cache.raw_iter())
181    }
182}