Skip to main content

qanglang_core/backend/
module_resolver.rs

1use std::collections::VecDeque;
2
3use rustc_hash::{FxBuildHasher, FxHashMap};
4
5use crate::{
6    FunctionHandle, HashMapHandle, QangRuntimeError, SourceLocation, StringHandle, Value,
7    backend::vm::RuntimeResult,
8};
9
10#[derive(Debug, Clone, Copy, PartialEq, Hash)]
11pub struct RuntimeModule {
12    function: FunctionHandle,
13    instance: Option<HashMapHandle>,
14}
15
16impl RuntimeModule {
17    pub fn new(function: FunctionHandle) -> Self {
18        Self {
19            function,
20            instance: None,
21        }
22    }
23}
24
25#[derive(Debug, Clone, PartialEq, Default)]
26pub struct ModuleResolver {
27    modules: FxHashMap<StringHandle, RuntimeModule>,
28    module_names: FxHashMap<HashMapHandle, StringHandle>,
29    count: usize,
30}
31
32impl ModuleResolver {
33    pub fn gather_roots(&self, roots: &mut VecDeque<Value>) {
34        for (_, module) in self.modules.iter() {
35            if let Some(handle) = module.instance {
36                roots.push_front(Value::module(handle));
37            }
38        }
39    }
40
41    pub fn get_instance_handle(&self, module_id: StringHandle) -> Option<HashMapHandle> {
42        self.modules.get(&module_id).and_then(|m| m.instance)
43    }
44
45    pub fn remove_instance(&mut self, module_id: StringHandle) {
46        if let Some(module) = self.modules.get_mut(&module_id) {
47            module.instance = None;
48            self.count -= 1;
49        }
50    }
51
52    pub fn get_module_handle(
53        &self,
54        module_id: StringHandle,
55        loc: SourceLocation,
56    ) -> RuntimeResult<FunctionHandle> {
57        self.modules
58            .get(&module_id)
59            .map(|m| m.function)
60            .ok_or(QangRuntimeError::new(
61                "Failed to resolve module.".to_string(),
62                loc,
63            ))
64    }
65
66    pub fn add_instance(&mut self, module_id: StringHandle, handle: HashMapHandle) {
67        if let Some(module) = self.modules.get_mut(&module_id) {
68            module.instance = Some(handle);
69            self.count += 1;
70            self.module_names.insert(handle, module_id);
71        }
72    }
73
74    pub fn get_module_id(&self, handle: HashMapHandle) -> StringHandle {
75        self.module_names[&handle]
76    }
77
78    pub fn count(&self) -> usize {
79        self.count
80    }
81}
82
83impl From<FxHashMap<StringHandle, RuntimeModule>> for ModuleResolver {
84    fn from(val: FxHashMap<StringHandle, RuntimeModule>) -> Self {
85        let capacity = val.capacity();
86        ModuleResolver {
87            modules: val,
88            count: 0,
89            module_names: FxHashMap::with_capacity_and_hasher(capacity, FxBuildHasher),
90        }
91    }
92}