258 lines
6.2 KiB
Rust
Raw Normal View History

2017-12-13 13:25:24 +01:00
use std::rc::Rc;
2017-12-11 16:28:05 +01:00
use std::collections::HashMap;
2017-12-14 15:33:40 +01:00
use std::collections::hash_map::Entry;
2017-12-18 16:12:59 +03:00
use elements::{FunctionType, GlobalType, MemoryType, TableType, ValueType};
2017-12-13 18:31:40 +01:00
use interpreter::module::{ExternVal, ModuleInstance};
2017-12-13 18:28:34 +01:00
use interpreter::func::FuncInstance;
2017-12-13 18:19:42 +01:00
use interpreter::global::GlobalInstance;
2017-12-13 14:36:06 +01:00
use interpreter::memory::MemoryInstance;
use interpreter::table::TableInstance;
2017-12-18 15:18:53 +03:00
use interpreter::value::{RuntimeValue, TryInto};
2017-12-11 16:28:05 +01:00
use interpreter::Error;
2017-12-14 15:33:40 +01:00
use interpreter::ImportResolver;
2017-12-11 19:22:45 +01:00
2017-12-18 16:12:59 +03:00
pub type HostFunc<St> = Fn(&St, &[RuntimeValue])
-> Result<Option<RuntimeValue>, Error>;
2017-12-15 18:23:54 +03:00
2017-12-11 19:22:45 +01:00
pub struct HostModuleBuilder<St> {
2017-12-15 18:23:54 +03:00
exports: HashMap<String, ExternVal<St>>,
2017-12-11 16:28:05 +01:00
}
2017-12-15 18:23:54 +03:00
impl<St> HostModuleBuilder<St> {
2017-12-11 19:22:45 +01:00
pub fn new() -> Self {
2017-12-11 16:28:05 +01:00
HostModuleBuilder {
2017-12-14 15:33:40 +01:00
exports: HashMap::new(),
2017-12-11 16:28:05 +01:00
}
}
2017-12-16 18:19:35 +03:00
pub fn with_func0<
2017-12-18 15:18:53 +03:00
Cl: Fn(&St) -> Result<Ret, Error> + 'static,
Ret: IntoReturnVal + 'static,
2017-12-16 18:19:35 +03:00
N: Into<String>,
>(
&mut self,
name: N,
f: Cl,
) {
let func_type = FunctionType::new(vec![], Ret::value_type());
2017-12-18 16:12:59 +03:00
let host_func = Rc::new(
move |state: &St, _args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
let result = f(state)?.into_return_val();
Ok(result)
},
);
2017-12-16 18:19:35 +03:00
let func = FuncInstance::alloc_host(Rc::new(func_type), host_func);
self.insert_func(name, func);
}
pub fn with_func1<
2017-12-18 15:18:53 +03:00
Cl: Fn(&St, P1) -> Result<Ret, Error> + 'static,
Ret: IntoReturnVal + 'static,
2017-12-16 18:19:35 +03:00
P1: FromArg + 'static,
N: Into<String>,
>(
&mut self,
name: N,
f: Cl,
) {
let func_type = FunctionType::new(vec![P1::value_type()], Ret::value_type());
2017-12-18 16:12:59 +03:00
let host_func = Rc::new(
move |state: &St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
let arg0 = P1::from_arg(&args[0]);
let result = f(state, arg0)?.into_return_val();
Ok(result)
},
);
2017-12-16 18:19:35 +03:00
let func = FuncInstance::alloc_host(Rc::new(func_type), host_func);
self.insert_func(name, func);
}
2017-12-11 16:28:05 +01:00
2017-12-12 10:32:51 +01:00
pub fn with_func2<
2017-12-18 15:18:53 +03:00
Cl: Fn(&St, P1, P2) -> Result<Ret, Error> + 'static,
Ret: IntoReturnVal + 'static,
2017-12-12 10:32:51 +01:00
P1: FromArg + 'static,
P2: FromArg + 'static,
2017-12-12 15:18:35 +01:00
N: Into<String>,
2017-12-12 10:32:51 +01:00
>(
&mut self,
2017-12-12 15:18:35 +01:00
name: N,
2017-12-15 18:23:54 +03:00
f: Cl,
2017-12-12 10:32:51 +01:00
) {
2017-12-18 16:12:59 +03:00
let func_type =
FunctionType::new(vec![P1::value_type(), P2::value_type()], Ret::value_type());
let host_func = Rc::new(
move |state: &St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
let p1 = P1::from_arg(&args[0]);
let p2 = P2::from_arg(&args[1]);
let result = f(state, p1, p2)?.into_return_val();
Ok(result)
},
);
2017-12-15 18:23:54 +03:00
2017-12-14 15:33:40 +01:00
let func = FuncInstance::alloc_host(Rc::new(func_type), host_func);
self.insert_func(name, func);
}
2017-12-12 10:32:51 +01:00
2017-12-15 18:23:54 +03:00
pub fn insert_func<N: Into<String>>(&mut self, name: N, func: Rc<FuncInstance<St>>) {
2017-12-14 15:33:40 +01:00
self.insert(name, ExternVal::Func(func));
2017-12-12 10:32:51 +01:00
}
2017-12-14 15:33:40 +01:00
pub fn insert_global<N: Into<String>>(&mut self, name: N, global: Rc<GlobalInstance>) {
self.insert(name, ExternVal::Global(global));
2017-12-11 18:38:09 +01:00
}
2017-12-14 15:33:40 +01:00
pub fn insert_memory<N: Into<String>>(&mut self, name: N, memory: Rc<MemoryInstance>) {
self.insert(name, ExternVal::Memory(memory));
2017-12-11 18:38:09 +01:00
}
2017-12-15 18:23:54 +03:00
pub fn insert_table<N: Into<String>>(&mut self, name: N, table: Rc<TableInstance<St>>) {
2017-12-14 15:33:40 +01:00
self.insert(name, ExternVal::Table(table));
2017-12-11 19:22:45 +01:00
}
2017-12-14 15:33:40 +01:00
pub fn with_global<N: Into<String>>(mut self, name: N, global: Rc<GlobalInstance>) -> Self {
self.insert_global(name, global);
self
}
pub fn with_memory<N: Into<String>>(mut self, name: N, memory: Rc<MemoryInstance>) -> Self {
self.insert_memory(name, memory);
self
}
2017-12-15 18:23:54 +03:00
pub fn with_table<N: Into<String>>(mut self, name: N, table: Rc<TableInstance<St>>) -> Self {
2017-12-14 15:33:40 +01:00
self.insert_table(name, table);
self
}
2017-12-15 18:23:54 +03:00
fn insert<N: Into<String>>(&mut self, name: N, extern_val: ExternVal<St>) {
2017-12-14 15:33:40 +01:00
match self.exports.entry(name.into()) {
Entry::Vacant(v) => v.insert(extern_val),
Entry::Occupied(o) => panic!("Duplicate export name {}", o.key()),
};
2017-12-12 15:18:35 +01:00
}
2017-12-15 18:23:54 +03:00
pub fn build(self) -> HostModule<St> {
2017-12-14 15:33:40 +01:00
let internal_instance = Rc::new(ModuleInstance::with_exports(self.exports));
2017-12-18 16:12:59 +03:00
HostModule { internal_instance }
2017-12-11 18:38:09 +01:00
}
2017-12-11 19:22:45 +01:00
}
2017-12-15 18:23:54 +03:00
pub struct HostModule<St> {
internal_instance: Rc<ModuleInstance<St>>,
2017-12-11 19:22:45 +01:00
}
2017-12-15 18:23:54 +03:00
impl<St> HostModule<St> {
pub fn export_by_name(&self, name: &str) -> Option<ExternVal<St>> {
2017-12-14 15:33:40 +01:00
self.internal_instance.export_by_name(name)
}
}
2017-12-15 18:23:54 +03:00
impl<St> ImportResolver<St> for HostModule<St> {
2017-12-14 15:33:40 +01:00
fn resolve_func(
&self,
field_name: &str,
func_type: &FunctionType,
2017-12-15 18:23:54 +03:00
) -> Result<Rc<FuncInstance<St>>, Error> {
2017-12-14 15:33:40 +01:00
self.internal_instance.resolve_func(field_name, func_type)
}
fn resolve_global(
&self,
field_name: &str,
global_type: &GlobalType,
) -> Result<Rc<GlobalInstance>, Error> {
2017-12-18 16:12:59 +03:00
self.internal_instance
.resolve_global(field_name, global_type)
2017-12-14 15:33:40 +01:00
}
fn resolve_memory(
&self,
field_name: &str,
memory_type: &MemoryType,
) -> Result<Rc<MemoryInstance>, Error> {
2017-12-18 16:12:59 +03:00
self.internal_instance
.resolve_memory(field_name, memory_type)
2017-12-14 15:33:40 +01:00
}
2017-12-11 19:22:45 +01:00
2017-12-14 15:33:40 +01:00
fn resolve_table(
&self,
field_name: &str,
table_type: &TableType,
2017-12-15 18:23:54 +03:00
) -> Result<Rc<TableInstance<St>>, Error> {
2017-12-14 15:33:40 +01:00
self.internal_instance.resolve_table(field_name, table_type)
2017-12-11 16:28:05 +01:00
}
}
2017-12-18 16:12:59 +03:00
pub trait FromArg
where
Self: Sized,
{
2017-12-11 16:28:05 +01:00
fn from_arg(arg: &RuntimeValue) -> Self;
fn value_type() -> ValueType;
}
2017-12-18 15:18:53 +03:00
macro_rules! impl_from_arg {
($ty: ident, $val_ty: ident) => {
impl FromArg for $ty {
fn from_arg(arg: &RuntimeValue) -> Self {
arg
.try_into()
.expect(
concat!("Due to validation, arg expected to be ", stringify!($val_ty))
)
}
fn value_type() -> ValueType {
use self::ValueType::*;
$val_ty
}
2017-12-11 16:28:05 +01:00
}
}
}
2017-12-18 15:18:53 +03:00
impl_from_arg!(i32, I32);
impl_from_arg!(u32, I32);
impl_from_arg!(i64, I64);
impl_from_arg!(u64, I64);
impl_from_arg!(f32, F32);
impl_from_arg!(f64, F64);
pub trait IntoReturnVal {
fn into_return_val(self) -> Option<RuntimeValue>;
2017-12-11 16:28:05 +01:00
fn value_type() -> Option<ValueType>;
}
2017-12-18 15:18:53 +03:00
macro_rules! impl_into_return_val {
($ty: ident, $val_ty: ident) => {
impl IntoReturnVal for $ty {
fn into_return_val(self) -> Option<RuntimeValue> {
Some(self.into())
}
fn value_type() -> Option<ValueType> {
use self::ValueType::*;
Some($val_ty)
}
}
2017-12-11 16:28:05 +01:00
}
}
2017-12-18 15:18:53 +03:00
impl_into_return_val!(i32, I32);
impl_into_return_val!(u32, I32);
impl_into_return_val!(i64, I64);
impl_into_return_val!(u64, I64);
impl_into_return_val!(f32, F32);
impl_into_return_val!(f64, F64);
impl IntoReturnVal for () {
fn into_return_val(self) -> Option<RuntimeValue> {
2017-12-11 16:28:05 +01:00
None
}
fn value_type() -> Option<ValueType> {
None
}
}