diff --git a/src/builder/module.rs b/src/builder/module.rs index 7a74c87..39cc198 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -282,6 +282,12 @@ impl ModuleBuilder where F: Invoke { SignaturesBuilder::with_callback(self) } + /// With inserted export entry + pub fn with_export(mut self, entry: elements::ExportEntry) -> Self { + self.module.export.entries_mut().push(entry); + self + } + /// With inserted import entry pub fn with_import(mut self, entry: elements::ImportEntry) -> Self { self.module.import.entries_mut().push(entry); diff --git a/src/elements/export_entry.rs b/src/elements/export_entry.rs index 535ae26..4f09c67 100644 --- a/src/elements/export_entry.rs +++ b/src/elements/export_entry.rs @@ -54,6 +54,13 @@ pub struct ExportEntry { } impl ExportEntry { + /// Create new export entry + pub fn new(field: String, internal: Internal) -> Self { + Self { + field_str: field, + internal: internal, + } + } /// Public name pub fn field(&self) -> &str { &self.field_str } /// Public name (mutable) diff --git a/src/interpreter/module.rs b/src/interpreter/module.rs index 46ae3f7..65bb1ee 100644 --- a/src/interpreter/module.rs +++ b/src/interpreter/module.rs @@ -178,7 +178,8 @@ impl ModuleInstance { match self.imports.parse_function_index(index) { ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"), ItemIndex::Internal(index) => self.call_internal_function(outer, index, None), - ItemIndex::External(index) => self.module.import_section() + ItemIndex::External(index) => + self.module.import_section() .ok_or(Error::Function(format!("trying to access external function with index {} in module without import section", index))) .and_then(|s| s.entries().get(index as usize) .ok_or(Error::Function(format!("trying to access external function with index {} in module with {}-entries import section", index, s.entries().len())))) diff --git a/src/interpreter/tests/import.rs b/src/interpreter/tests/import.rs new file mode 100644 index 0000000..070d3b7 --- /dev/null +++ b/src/interpreter/tests/import.rs @@ -0,0 +1,38 @@ +use builder::module; +use elements::{ExportEntry, Internal, ImportEntry, External, Opcodes, Opcode}; +use interpreter::program::ProgramInstance; +use interpreter::value::RuntimeValue; + +#[test] +fn import_function() { + let module1 = module() + .with_export(ExportEntry::new("external_func".into(), Internal::Function(0))) + .function() + .signature().return_type().i32().build() + .body().with_opcodes(Opcodes::new(vec![ + Opcode::I32Const(3), + Opcode::End, + ])).build() + .build() + .build(); + + let module2 = module() + .with_import(ImportEntry::new("external_module".into(), "external_func".into(), External::Function(0))) + .function() + .signature().return_type().i32().build() + .body().with_opcodes(Opcodes::new(vec![ + Opcode::Call(0), + Opcode::I32Const(7), + Opcode::I32Add, + Opcode::End, + ])).build() + .build() + .build(); + + let program = ProgramInstance::new(); + let external_module = program.add_module("external_module", module1).unwrap(); + let main_module = program.add_module("main", module2).unwrap(); + + assert_eq!(external_module.execute(0, vec![]).unwrap().unwrap(), RuntimeValue::I32(3)); + assert_eq!(main_module.execute(1, vec![]).unwrap().unwrap(), RuntimeValue::I32(10)); +} diff --git a/src/interpreter/tests/mod.rs b/src/interpreter/tests/mod.rs index e79767c..fd2c28a 100644 --- a/src/interpreter/tests/mod.rs +++ b/src/interpreter/tests/mod.rs @@ -1 +1,2 @@ +mod import; mod wabt; \ No newline at end of file diff --git a/src/interpreter/tests/wabt.rs b/src/interpreter/tests/wabt.rs index 083daca..d2bb362 100644 --- a/src/interpreter/tests/wabt.rs +++ b/src/interpreter/tests/wabt.rs @@ -1,7 +1,5 @@ ///! Tests from https://github.com/WebAssembly/wabt/tree/8e1f6031e9889ba770c7be4a9b084da5f14456a0/test/interp -// TODO: https://github.com/WebAssembly/wabt/blob/8e1f6031e9889ba770c7be4a9b084da5f14456a0/test/interp/import.txt - use std::sync::Weak; use builder::module; use elements::{Module, ValueType, Opcodes, Opcode, BlockType, FunctionType};