static variants of passed functions

This commit is contained in:
NikVolf 2017-06-14 17:07:22 +03:00
parent 9c2061c63c
commit f2ee624cea
2 changed files with 74 additions and 20 deletions

View File

@ -1,5 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use std::collections::HashMap; use std::collections::HashMap;
use std::borrow::Cow;
use parking_lot::RwLock; use parking_lot::RwLock;
use elements::{FunctionType, Internal, ValueType}; use elements::{FunctionType, Internal, ValueType};
use interpreter::Error; use interpreter::Error;
@ -22,20 +23,62 @@ pub trait UserFunctionExecutor {
fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>; fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
} }
#[derive(Clone)]
pub enum UserFunctionDescriptor {
Static(&'static str, &'static [ValueType]),
Heap(String, Vec<ValueType>),
}
/// User function type. /// User function type.
#[derive(Clone)]
pub struct UserFunction { pub struct UserFunction {
/// User function name. pub desc: UserFunctionDescriptor,
pub name: String,
/// User function parameters (for signature matching).
pub params: Vec<ValueType>,
/// User function return type (for signature matching).
pub result: Option<ValueType>, pub result: Option<ValueType>,
} }
impl UserFunction {
/// New function with statically known params
pub fn statik(name: &'static str, params: &'static [ValueType], result: Option<ValueType>) -> Self {
UserFunction {
desc: UserFunctionDescriptor::Static(name, params),
result: result,
}
}
/// New function with statically unknown params
pub fn heap(name: String, params: Vec<ValueType>, result: Option<ValueType>) -> Self {
UserFunction {
desc: UserFunctionDescriptor::Heap(name, params),
result: result,
}
}
/// Name of the function
pub fn name(&self) -> &str {
match self.desc {
UserFunctionDescriptor::Static(name, _) => name,
UserFunctionDescriptor::Heap(ref name, _) => name,
}
}
/// Arguments of the function
pub fn params(&self) -> &[ValueType] {
match self.desc {
UserFunctionDescriptor::Static(_, params) => params,
UserFunctionDescriptor::Heap(_, ref params) => params,
}
}
/// Return type of the function
pub fn result(&self) -> Option<ValueType> {
self.result
}
}
/// Set of user-defined functions /// Set of user-defined functions
pub struct UserFunctions<'a> { pub struct UserFunctions<'a> {
/// Functions list. /// Functions list.
pub functions: Vec<UserFunction>, pub functions: Cow<'static, [UserFunction]>,
/// Functions executor. /// Functions executor.
pub executor: &'a mut UserFunctionExecutor, pub executor: &'a mut UserFunctionExecutor,
} }
@ -49,7 +92,7 @@ pub struct NativeModuleInstance<'a> {
/// By-name functions index. /// By-name functions index.
by_name: HashMap<String, u32>, by_name: HashMap<String, u32>,
/// User functions list. /// User functions list.
functions: Vec<UserFunction>, functions: Cow<'static, [UserFunction]>,
} }
impl<'a> NativeModuleInstance<'a> { impl<'a> NativeModuleInstance<'a> {
@ -58,7 +101,7 @@ impl<'a> NativeModuleInstance<'a> {
Ok(NativeModuleInstance { Ok(NativeModuleInstance {
env: env, env: env,
executor: RwLock::new(functions.executor), executor: RwLock::new(functions.executor),
by_name: functions.functions.iter().enumerate().map(|(i, f)| (f.name.clone(), i as u32)).collect(), by_name: functions.functions.iter().enumerate().map(|(i, f)| (f.name().to_owned(), i as u32)).collect(),
functions: functions.functions, functions: functions.functions,
}) })
} }
@ -98,7 +141,7 @@ impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
self.functions self.functions
.get((index - NATIVE_INDEX_FUNC_MIN) as usize) .get((index - NATIVE_INDEX_FUNC_MIN) as usize)
.ok_or(Error::Native(format!("missing native env function with index {}", index))) .ok_or(Error::Native(format!("missing native env function with index {}", index)))
.map(|f| FunctionType::new(f.params.clone(), f.result.clone())) .map(|f| FunctionType::new(f.params().to_vec(), f.result().clone()))
} }
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> { fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
@ -130,7 +173,7 @@ impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
self.functions self.functions
.get((index - NATIVE_INDEX_FUNC_MIN) as usize) .get((index - NATIVE_INDEX_FUNC_MIN) as usize)
.ok_or(Error::Native(format!("trying to call native function with index {}", index))) .ok_or(Error::Native(format!("trying to call native function with index {}", index)))
.and_then(|f| self.executor.write().execute(&f.name, outer)) .and_then(|f| self.executor.write().execute(&f.name(), outer))
} }
} }

View File

@ -5,7 +5,7 @@ use builder::module;
use elements::{ExportEntry, Internal, ImportEntry, External, GlobalEntry, GlobalType, use elements::{ExportEntry, Internal, ImportEntry, External, GlobalEntry, GlobalType,
InitExpr, ValueType, BlockType, Opcodes, Opcode, FunctionType}; InitExpr, ValueType, BlockType, Opcodes, Opcode, FunctionType};
use interpreter::Error; use interpreter::Error;
use interpreter::env_native::{env_native_module, UserFunction, UserFunctions, UserFunctionExecutor}; use interpreter::env_native::{env_native_module, UserFunction, UserFunctions, UserFunctionExecutor, UserFunctionDescriptor};
use interpreter::imports::ModuleImports; use interpreter::imports::ModuleImports;
use interpreter::memory::MemoryInstance; use interpreter::memory::MemoryInstance;
use interpreter::module::{ModuleInstanceInterface, CallerContext, ItemIndex, ExecutionParams}; use interpreter::module::{ModuleInstanceInterface, CallerContext, ItemIndex, ExecutionParams};
@ -123,6 +123,25 @@ fn global_get_set() {
assert_eq!(module.execute_index(2, vec![].into()).unwrap_err(), Error::Variable("trying to update variable of type I32 with value of type Some(I64)".into())); assert_eq!(module.execute_index(2, vec![].into()).unwrap_err(), Error::Variable("trying to update variable of type I32 with value of type Some(I64)".into()));
} }
const SIGNATURE_I32: &'static [ValueType] = &[ValueType::I32];
const SIGNATURES: &'static [UserFunction] = &[
UserFunction {
desc: UserFunctionDescriptor::Static(
"add",
SIGNATURE_I32,
),
result: Some(ValueType::I32),
},
UserFunction {
desc: UserFunctionDescriptor::Static(
"sub",
SIGNATURE_I32,
),
result: Some(ValueType::I32),
},
];
#[test] #[test]
fn single_program_different_modules() { fn single_program_different_modules() {
// user function executor // user function executor
@ -170,15 +189,7 @@ fn single_program_different_modules() {
{ {
let functions: UserFunctions = UserFunctions { let functions: UserFunctions = UserFunctions {
executor: &mut executor, executor: &mut executor,
functions: vec![UserFunction { functions: ::std::borrow::Cow::from(SIGNATURES),
name: "add".into(),
params: vec![ValueType::I32],
result: Some(ValueType::I32),
}, UserFunction {
name: "sub".into(),
params: vec![ValueType::I32],
result: Some(ValueType::I32),
}],
}; };
let native_env_instance = Arc::new(env_native_module(env_instance, functions).unwrap()); let native_env_instance = Arc::new(env_native_module(env_instance, functions).unwrap());
let params = ExecutionParams::with_external("env".into(), native_env_instance); let params = ExecutionParams::with_external("env".into(), native_env_instance);