diff --git a/src/interpreter/program.rs b/src/interpreter/program.rs index 20e9f5d..3e51bba 100644 --- a/src/interpreter/program.rs +++ b/src/interpreter/program.rs @@ -2,8 +2,9 @@ use std::collections::HashMap; use elements::Module; use interpreter::Error; -use interpreter::store::{Store, ModuleId}; +use interpreter::store::{ModuleId, Store, ExternVal}; use interpreter::host::HostModule; +use interpreter::value::RuntimeValue; /// Program instance. Program is a set of instantiated modules. pub struct ProgramInstance { @@ -32,7 +33,13 @@ impl ProgramInstance { let module = self.modules[import_entry.module()]; let extern_val = module .resolve_export(&self.store, import_entry.field()) - .ok_or_else(|| Error::Function(format!("Module {} doesn't have export {}", import_entry.module(), import_entry.field())))?; + .ok_or_else(|| { + Error::Program(format!( + "Module {} doesn't have export {}", + import_entry.module(), + import_entry.field() + )) + })?; extern_vals.push(extern_val); } @@ -42,14 +49,62 @@ impl ProgramInstance { Ok(module_id) } - pub fn add_host_module(&mut self, name: &str, host_module: HostModule) -> Result { + pub fn add_host_module( + &mut self, + name: &str, + host_module: HostModule, + ) -> Result { let module_id = host_module.allocate(&mut self.store)?; self.modules.insert(name.to_owned(), module_id); Ok(module_id) } - /// Get one of the modules by name - pub fn module(&self, name: &str) -> Option { - self.modules.get(name).cloned() + pub fn invoke_export( + &mut self, + module_name: &str, + func_name: &str, + args: Vec, + state: &mut St, + ) -> Result, Error> { + let module_id = self.modules.get(module_name).ok_or_else(|| { + Error::Program(format!("Module {} not found", module_name)) + })?; + let extern_val = module_id + .resolve_export(&self.store, func_name) + .ok_or_else(|| { + Error::Program(format!( + "Module {} doesn't have export {}", + module_name, + func_name + )) + })?; + + let func_id = match extern_val { + ExternVal::Func(func_id) => func_id, + unexpected => { + return Err(Error::Program(format!( + "Export {} is not a function, but {:?}", + func_name, + unexpected + ))) + } + }; + + self.store.invoke(func_id, args, state) + } + + pub fn invoke_index( + &mut self, + module_name: &str, + func_idx: u32, + args: Vec, + state: &mut St, + ) -> Result, Error> { + let module_id = self.modules.get(module_name).ok_or_else(|| { + Error::Program(format!("Module {} not found", module_name)) + })?; + let func_id = module_id.resolve_func(&self.store, func_idx); + + self.store.invoke(func_id, args, state) } }