shape_vm/
configuration.rs1use std::collections::{HashMap, HashSet};
7use std::sync::Arc;
8use std::sync::atomic::AtomicU8;
9
10pub struct BytecodeExecutor {
15 pub(crate) extensions: Vec<shape_runtime::module_exports::ModuleExports>,
17 pub(crate) virtual_modules: HashMap<String, String>,
19 pub(crate) compiled_module_paths: HashSet<String>,
21 pub(crate) interrupt: Arc<AtomicU8>,
23 pub(crate) bytecode_cache: Option<crate::bytecode_cache::BytecodeCache>,
25 pub(crate) dependency_paths: HashMap<String, std::path::PathBuf>,
27 pub(crate) module_loader: Option<shape_runtime::module_loader::ModuleLoader>,
30}
31
32impl Default for BytecodeExecutor {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl BytecodeExecutor {
39 pub fn new() -> Self {
41 let mut executor = Self {
42 extensions: Vec::new(),
43 virtual_modules: HashMap::new(),
44 compiled_module_paths: HashSet::new(),
45 interrupt: Arc::new(AtomicU8::new(0)),
46 bytecode_cache: None,
47 dependency_paths: HashMap::new(),
48 module_loader: None,
49 };
50 executor.register_stdlib_extensions();
51
52 let mut loader = shape_runtime::module_loader::ModuleLoader::new();
55 executor.register_extension_artifacts_in_loader(&mut loader);
56 executor.module_loader = Some(loader);
57
58 executor
59 }
60
61 fn register_stdlib_extensions(&mut self) {
64 self.extensions
65 .push(shape_runtime::stdlib::regex::create_regex_module());
66 self.extensions
67 .push(shape_runtime::stdlib::http::create_http_module());
68 self.extensions
69 .push(shape_runtime::stdlib::crypto::create_crypto_module());
70 self.extensions
71 .push(shape_runtime::stdlib::env::create_env_module());
72 self.extensions
73 .push(shape_runtime::stdlib::log::create_log_module());
74 self.extensions
75 .push(shape_runtime::stdlib::json::create_json_module());
76 self.extensions
77 .push(shape_runtime::stdlib::toml_module::create_toml_module());
78 self.extensions
79 .push(shape_runtime::stdlib::yaml::create_yaml_module());
80 self.extensions
81 .push(shape_runtime::stdlib::xml::create_xml_module());
82 self.extensions
83 .push(shape_runtime::stdlib::compress::create_compress_module());
84 self.extensions
85 .push(shape_runtime::stdlib::archive::create_archive_module());
86 self.extensions
87 .push(shape_runtime::stdlib::unicode::create_unicode_module());
88 }
89
90 pub fn register_extension(&mut self, module: shape_runtime::module_exports::ModuleExports) {
93 let module_name = module.name.clone();
97 for artifact in &module.module_artifacts {
98 let Some(source) = artifact.source.as_ref() else {
99 continue;
100 };
101 let module_path = artifact.module_path.clone();
102 self.virtual_modules
103 .entry(module_path)
104 .or_insert_with(|| source.clone());
105 }
106
107 let mut registered_primary_path = false;
109 for (filename, source) in &module.shape_sources {
110 let legacy_path = format!("std::loaders::{}", module_name);
112 self.virtual_modules
113 .entry(legacy_path)
114 .or_insert_with(|| source.clone());
115
116 if !registered_primary_path {
118 self.virtual_modules
119 .entry(module_name.clone())
120 .or_insert_with(|| source.clone());
121 registered_primary_path = true;
122 } else if let Some(stem) = std::path::Path::new(filename)
123 .file_stem()
124 .and_then(|s| s.to_str())
125 {
126 let extra_path = format!("{}::{}", module_name, stem);
127 self.virtual_modules
128 .entry(extra_path)
129 .or_insert_with(|| source.clone());
130 }
131
132 }
133 self.extensions.push(module);
134 }
135
136 pub fn module_schemas(&self) -> Vec<shape_runtime::extensions::ParsedModuleSchema> {
138 self.extensions
139 .iter()
140 .map(|module| {
141 let mut functions = Vec::with_capacity(module.schemas.len());
142 for (name, schema) in &module.schemas {
143 if !module.is_export_public_surface(name, false) {
144 continue;
145 }
146 functions.push(shape_runtime::extensions::ParsedModuleFunction {
147 name: name.clone(),
148 description: schema.description.clone(),
149 params: schema.params.iter().map(|p| p.type_name.clone()).collect(),
150 return_type: schema.return_type.clone(),
151 });
152 }
153 let artifacts = module
154 .module_artifacts
155 .iter()
156 .map(|artifact| shape_runtime::extensions::ParsedModuleArtifact {
157 module_path: artifact.module_path.clone(),
158 source: artifact.source.clone(),
159 compiled: artifact.compiled.clone(),
160 })
161 .collect();
162 shape_runtime::extensions::ParsedModuleSchema {
163 module_name: module.name.clone(),
164 functions,
165 artifacts,
166 }
167 })
168 .collect()
169 }
170
171 pub fn enable_bytecode_cache(&mut self) -> bool {
175 match crate::bytecode_cache::BytecodeCache::new() {
176 Some(cache) => {
177 self.bytecode_cache = Some(cache);
178 true
179 }
180 None => false,
181 }
182 }
183
184 pub fn set_interrupt(&mut self, flag: Arc<AtomicU8>) {
186 self.interrupt = flag;
187 }
188
189 pub fn set_dependency_paths(&mut self, paths: HashMap<String, std::path::PathBuf>) {
194 self.dependency_paths = paths.clone();
195 if let Some(loader) = self.module_loader.as_mut() {
196 loader.set_dependency_paths(paths);
197 }
198 }
199
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205
206 #[test]
207 fn test_new_executor_has_module_loader() {
208 let executor = BytecodeExecutor::new();
209 assert!(
210 executor.module_loader.is_some(),
211 "new() should initialize module_loader"
212 );
213 }
214}