use std::sync::Arc; use std::collections::HashMap; use parking_lot::RwLock; use elements::Module; use interpreter::Error; use interpreter::env::{self, env_module}; use interpreter::module::{ModuleInstance, ModuleInstanceInterface}; /// Program instance. Program is a set of instantiated modules. pub struct ProgramInstance { /// Shared data reference. essence: Arc, } /// Program instance essence. pub struct ProgramInstanceEssence { /// Loaded modules. modules: RwLock>>, } impl ProgramInstance { /// Create new program instance. pub fn new() -> Result { ProgramInstance::with_env_params(env::EnvParams::default()) } /// Create new program instance with custom env module params (mostly memory) pub fn with_env_params(params: env::EnvParams) -> Result { Ok(ProgramInstance { essence: Arc::new(ProgramInstanceEssence::with_env_params(params)?), }) } /// Instantiate module with validation. pub fn add_module(&self, name: &str, module: Module) -> Result, Error> { let module_instance = Arc::new(ModuleInstance::new(Arc::downgrade(&self.essence), module)?); // replace existing module with the same name with new one self.essence.modules.write().insert(name.into(), module_instance.clone()); Ok(module_instance) } /// Instantiate module without validation. pub fn add_module_without_validation(&self, name: &str, module: Module) -> Result, Error> { let module_instance = Arc::new(ModuleInstance::new_with_validation_flag(Arc::downgrade(&self.essence), module, false)?); // replace existing module with the same name with new one self.essence.modules.write().insert(name.into(), module_instance.clone()); Ok(module_instance) } /// Get one of the modules by name pub fn module(&self, name: &str) -> Option> { self.essence.module(name) } } impl ProgramInstanceEssence { /// Create new program essence. pub fn new() -> Result { ProgramInstanceEssence::with_env_params(env::EnvParams::default()) } pub fn with_env_params(env_params: env::EnvParams) -> Result { let mut modules = HashMap::new(); let env_module: Arc = Arc::new(env_module(env_params)?); modules.insert("env".into(), env_module); Ok(ProgramInstanceEssence { modules: RwLock::new(modules), }) } /// Get module reference. pub fn module(&self, name: &str) -> Option> { self.modules.read().get(name).cloned() } }