352 lines
7.8 KiB
Rust
Raw Normal View History

2017-12-11 16:28:05 +01:00
use std::any::Any;
2017-12-11 18:38:09 +01:00
use std::sync::Arc;
2017-12-11 16:28:05 +01:00
use std::marker::PhantomData;
use std::collections::HashMap;
2017-12-11 18:38:09 +01:00
use elements::{FunctionType, ValueType, GlobalType, MemoryType, TableType};
2017-12-11 19:22:45 +01:00
use interpreter::store::{Store, ExternVal, ModuleId, ModuleInstance};
2017-12-11 16:28:05 +01:00
use interpreter::value::RuntimeValue;
use interpreter::Error;
2017-12-11 19:22:45 +01:00
enum HostItem {
Func {
name: String,
func_type: FunctionType,
host_func: Arc<AnyFunc>,
},
Global {
name: String,
global_type: GlobalType,
init_val: RuntimeValue,
},
Memory {
name: String,
memory_type: MemoryType,
},
Table {
name: String,
table_type: TableType,
}
}
pub struct HostModuleBuilder<St> {
items: Vec<HostItem>,
2017-12-11 16:28:05 +01:00
_marker: PhantomData<St>,
}
2017-12-11 19:22:45 +01:00
impl<St: 'static> HostModuleBuilder<St> {
pub fn new() -> Self {
2017-12-11 16:28:05 +01:00
HostModuleBuilder {
2017-12-11 19:22:45 +01:00
items: Vec::new(),
2017-12-11 16:28:05 +01:00
_marker: PhantomData,
}
}
2017-12-12 10:32:51 +01:00
pub fn with_func0<
Cl: Fn(&mut St) -> Result<Option<Ret>, Error> + 'static,
Ret: AsReturnVal + 'static,
F: Into<Func0<Cl, St, Ret>>,
>(
&mut self,
name: &str,
f: F,
) {
let func_type = Func0::<Cl, St, Ret>::derive_func_type();
let host_func = Arc::new(f.into()) as Arc<AnyFunc>;
self.items.push(HostItem::Func {
name: name.to_owned(),
func_type,
host_func,
});
}
2017-12-11 18:38:09 +01:00
pub fn with_func1<
2017-12-11 16:28:05 +01:00
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error> + 'static,
2017-12-11 19:22:45 +01:00
Ret: AsReturnVal + 'static,
2017-12-11 16:28:05 +01:00
P1: FromArg + 'static,
F: Into<Func1<Cl, St, Ret, P1>>,
>(
&mut self,
name: &str,
f: F,
) {
let func_type = Func1::<Cl, St, Ret, P1>::derive_func_type();
2017-12-11 19:22:45 +01:00
let host_func = Arc::new(f.into()) as Arc<AnyFunc>;
2017-12-11 16:28:05 +01:00
2017-12-11 19:22:45 +01:00
self.items.push(HostItem::Func {
name: name.to_owned(),
func_type,
host_func,
});
}
2017-12-11 16:28:05 +01:00
2017-12-12 10:32:51 +01:00
pub fn with_func2<
Cl: Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error> + 'static,
Ret: AsReturnVal + 'static,
P1: FromArg + 'static,
P2: FromArg + 'static,
F: Into<Func2<Cl, St, Ret, P1, P2>>,
>(
&mut self,
name: &str,
f: F,
) {
let func_type = Func2::<Cl, St, Ret, P1, P2>::derive_func_type();
let host_func = Arc::new(f.into()) as Arc<AnyFunc>;
self.items.push(HostItem::Func {
name: name.to_owned(),
func_type,
host_func,
});
}
2017-12-11 19:22:45 +01:00
pub fn with_global(&mut self, name: &str, global_type: GlobalType, init_val: RuntimeValue) {
self.items.push(HostItem::Global {
name: name.to_owned(),
global_type,
init_val,
});
2017-12-11 18:38:09 +01:00
}
2017-12-11 19:22:45 +01:00
pub fn with_memory(&mut self, name: &str, memory_type: MemoryType) {
self.items.push(HostItem::Memory {
name: name.to_owned(),
memory_type,
});
2017-12-11 18:38:09 +01:00
}
2017-12-11 19:22:45 +01:00
pub fn with_table(&mut self, name: &str, table_type: TableType) {
self.items.push(HostItem::Table {
name: name.to_owned(),
table_type,
});
}
pub fn build(self) -> HostModule {
HostModule {
items: self.items
}
2017-12-11 18:38:09 +01:00
}
2017-12-11 19:22:45 +01:00
}
pub struct HostModule {
items: Vec<HostItem>,
}
impl HostModule {
pub(crate) fn allocate(self, store: &mut Store) -> Result<ModuleId, Error> {
let mut exports = HashMap::new();
for item in self.items {
match item {
HostItem::Func { name, func_type, host_func } => {
let type_id = store.alloc_func_type(func_type);
let func_id = store.alloc_host_func(type_id, host_func);
exports.insert(name, ExternVal::Func(func_id));
},
HostItem::Global { name, global_type, init_val } => {
let global_id = store.alloc_global(global_type, init_val);
exports.insert(name, ExternVal::Global(global_id));
},
HostItem::Memory { name, memory_type } => {
let memory_id = store.alloc_memory(&memory_type)?;
exports.insert(name, ExternVal::Memory(memory_id));
},
HostItem::Table { name, table_type } => {
let table_id = store.alloc_table(&table_type)?;
exports.insert(name, ExternVal::Table(table_id));
}
}
}
let host_module_instance = ModuleInstance::with_exports(exports);
let module_id = store.add_module_instance(host_module_instance);
2017-12-11 16:28:05 +01:00
2017-12-11 19:22:45 +01:00
Ok(module_id)
2017-12-11 16:28:05 +01:00
}
}
pub trait AnyFunc {
fn call_as_any(
&self,
state: &mut Any,
args: &[RuntimeValue],
) -> Result<Option<RuntimeValue>, Error>;
}
pub trait FromArg {
fn from_arg(arg: &RuntimeValue) -> Self;
fn value_type() -> ValueType;
}
impl FromArg for i32 {
fn from_arg(arg: &RuntimeValue) -> Self {
match arg {
&RuntimeValue::I32(v) => v,
2017-12-11 18:39:25 +01:00
unexpected => panic!("Expected I32, got {:?}", unexpected),
2017-12-11 16:28:05 +01:00
}
}
fn value_type() -> ValueType {
ValueType::I32
}
}
2017-12-11 19:22:45 +01:00
pub trait AsReturnVal {
2017-12-11 16:28:05 +01:00
fn as_return_val(self) -> Option<RuntimeValue>;
fn value_type() -> Option<ValueType>;
}
2017-12-11 19:22:45 +01:00
impl AsReturnVal for i32 {
2017-12-11 16:28:05 +01:00
fn as_return_val(self) -> Option<RuntimeValue> {
Some(self.into())
}
fn value_type() -> Option<ValueType> {
Some(ValueType::I32)
}
}
2017-12-11 19:22:45 +01:00
impl AsReturnVal for () {
2017-12-11 16:28:05 +01:00
fn as_return_val(self) -> Option<RuntimeValue> {
None
}
fn value_type() -> Option<ValueType> {
None
}
}
2017-12-12 10:32:51 +01:00
pub struct Func0<Cl: Fn(&mut St) -> Result<Option<Ret>, Error>, St, Ret: AsReturnVal> {
closure: Cl,
_marker: PhantomData<(St, Ret)>,
}
impl<
St: 'static,
Ret: AsReturnVal,
Cl: Fn(&mut St) -> Result<Option<Ret>, Error>,
> AnyFunc for Func0<Cl, St, Ret> {
fn call_as_any(
&self,
state: &mut Any,
args: &[RuntimeValue],
) -> Result<Option<RuntimeValue>, Error> {
let state = state.downcast_mut::<St>().unwrap();
let result = (self.closure)(state);
result.map(|r| r.and_then(|r| r.as_return_val()))
}
}
impl<St: 'static, Ret: AsReturnVal, Cl: Fn(&mut St) -> Result<Option<Ret>, Error>> From<Cl>
for Func0<Cl, St, Ret> {
fn from(cl: Cl) -> Self {
Func0 {
closure: cl,
_marker: PhantomData,
}
}
}
impl<
St: 'static,
Ret: AsReturnVal,
Cl: Fn(&mut St) -> Result<Option<Ret>, Error>,
> Func0<Cl, St, Ret> {
fn derive_func_type() -> FunctionType {
FunctionType::new(vec![], Ret::value_type())
}
}
2017-12-11 19:22:45 +01:00
pub struct Func1<Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>, St, Ret: AsReturnVal, P1: FromArg> {
2017-12-11 16:28:05 +01:00
closure: Cl,
_marker: PhantomData<(St, Ret, P1)>,
}
impl<
St: 'static,
2017-12-11 19:22:45 +01:00
Ret: AsReturnVal,
2017-12-11 16:28:05 +01:00
P1: FromArg,
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>,
> AnyFunc for Func1<Cl, St, Ret, P1> {
fn call_as_any(
&self,
state: &mut Any,
args: &[RuntimeValue],
) -> Result<Option<RuntimeValue>, Error> {
let state = state.downcast_mut::<St>().unwrap();
let p1 = P1::from_arg(&args[0]);
let result = (self.closure)(state, p1);
result.map(|r| r.and_then(|r| r.as_return_val()))
}
}
2017-12-11 19:22:45 +01:00
impl<St: 'static, Ret: AsReturnVal, P1: FromArg, Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>> From<Cl>
2017-12-11 16:28:05 +01:00
for Func1<Cl, St, Ret, P1> {
fn from(cl: Cl) -> Self {
Func1 {
closure: cl,
_marker: PhantomData,
}
}
}
impl<
St: 'static,
2017-12-11 19:22:45 +01:00
Ret: AsReturnVal,
2017-12-11 16:28:05 +01:00
P1: FromArg,
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>,
> Func1<Cl, St, Ret, P1> {
fn derive_func_type() -> FunctionType {
FunctionType::new(vec![P1::value_type()], Ret::value_type())
}
}
2017-12-12 10:32:51 +01:00
pub struct Func2<Cl: Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error>, St, Ret: AsReturnVal, P1: FromArg, P2: FromArg> {
closure: Cl,
_marker: PhantomData<(St, Ret, P1, P2)>,
}
impl<
St: 'static,
Ret: AsReturnVal,
P1: FromArg,
P2: FromArg,
Cl: Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error>,
> AnyFunc for Func2<Cl, St, Ret, P1, P2> {
fn call_as_any(
&self,
state: &mut Any,
args: &[RuntimeValue],
) -> Result<Option<RuntimeValue>, Error> {
let state = state.downcast_mut::<St>().unwrap();
let p1 = P1::from_arg(&args[0]);
let p2 = P2::from_arg(&args[1]);
let result = (self.closure)(state, p1, p2);
result.map(|r| r.and_then(|r| r.as_return_val()))
}
}
impl<St: 'static, Ret: AsReturnVal, P1: FromArg, P2: FromArg, Cl: Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error>> From<Cl>
for Func2<Cl, St, Ret, P1, P2> {
fn from(cl: Cl) -> Self {
Func2 {
closure: cl,
_marker: PhantomData,
}
}
}
impl<
St: 'static,
Ret: AsReturnVal,
P1: FromArg,
P2: FromArg,
Cl: Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error>,
> Func2<Cl, St, Ret, P1, P2> {
fn derive_func_type() -> FunctionType {
FunctionType::new(vec![P1::value_type(), P2::value_type()], Ret::value_type())
}
}