some progress on marshalling args
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
use crate::names::Names;
|
use crate::names::Names;
|
||||||
@@ -66,29 +66,20 @@ pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream {
|
|||||||
let marshal_args = func
|
let marshal_args = func
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|param| match param.tref.type_().passed_by() {
|
.map(|p| marshal_arg(names, p, func.results.get(0).map(|r| &r.tref)));
|
||||||
witx::TypePassedBy::Value(_atom) => {
|
|
||||||
// FIXME atom -> param.tref can be either an `as` conversion, or `try_from`
|
|
||||||
let name = names.func_param(¶m.name);
|
|
||||||
let interface_type = names.type_ref(¶m.tref);
|
|
||||||
quote!( let #name = #name as #interface_type; )
|
|
||||||
}
|
|
||||||
_ => unimplemented!(),
|
|
||||||
});
|
|
||||||
let trait_args = func
|
let trait_args = func
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|param| names.func_param(¶m.name));
|
.map(|param| names.func_param(¶m.name));
|
||||||
|
|
||||||
let trait_rets = func
|
let (trait_rets, trait_bindings) = if func.results.len() < 2 {
|
||||||
.results
|
|
||||||
.iter()
|
|
||||||
.skip(1)
|
|
||||||
.map(|result| names.func_param(&result.name))
|
|
||||||
.collect::<Vec<Ident>>();
|
|
||||||
let (trait_rets, trait_bindings) = if trait_rets.is_empty() {
|
|
||||||
(quote!({}), quote!(_))
|
(quote!({}), quote!(_))
|
||||||
} else {
|
} else {
|
||||||
|
let trait_rets = func
|
||||||
|
.results
|
||||||
|
.iter()
|
||||||
|
.skip(1)
|
||||||
|
.map(|result| names.func_param(&result.name));
|
||||||
let tuple = quote!((#(#trait_rets),*));
|
let tuple = quote!((#(#trait_rets),*));
|
||||||
(tuple.clone(), tuple)
|
(tuple.clone(), tuple)
|
||||||
};
|
};
|
||||||
@@ -110,3 +101,67 @@ pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream {
|
|||||||
#abi_ret::from(success)
|
#abi_ret::from(success)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn marshal_arg(
|
||||||
|
names: &Names,
|
||||||
|
param: &witx::InterfaceFuncParam,
|
||||||
|
error_type: Option<&witx::TypeRef>,
|
||||||
|
) -> TokenStream {
|
||||||
|
let tref = ¶m.tref;
|
||||||
|
let interface_typename = names.type_ref(&tref);
|
||||||
|
let name = names.func_param(¶m.name);
|
||||||
|
|
||||||
|
let value_error_handling = if let Some(tref) = error_type {
|
||||||
|
let abi_ret = match tref.type_().passed_by() {
|
||||||
|
witx::TypePassedBy::Value(atom) => names.atom_type(atom),
|
||||||
|
_ => unreachable!("err should always be passed by value"),
|
||||||
|
};
|
||||||
|
let err_typename = names.type_ref(&tref);
|
||||||
|
quote! {
|
||||||
|
let err: #err_typename = ::memory::GuestError::from_memory_error(e, ctx);
|
||||||
|
return #abi_ret::from(err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
panic!("memory error: {:?}", e)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let try_into_conversion = quote! {
|
||||||
|
use ::std::convert::TryInto;
|
||||||
|
let #name: #interface_typename = match #name.try_into() {
|
||||||
|
Ok(a) => a,
|
||||||
|
Err(e) => {
|
||||||
|
#value_error_handling
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
match &*tref.type_() {
|
||||||
|
witx::Type::Enum(_e) => try_into_conversion,
|
||||||
|
witx::Type::Builtin(b) => match b {
|
||||||
|
witx::BuiltinType::U8 | witx::BuiltinType::U16 | witx::BuiltinType::Char8 => {
|
||||||
|
try_into_conversion
|
||||||
|
}
|
||||||
|
witx::BuiltinType::S8 | witx::BuiltinType::S16 => quote! {
|
||||||
|
let #name: #interface_typename = match (#name as i32).try_into() {
|
||||||
|
Ok(a) => a,
|
||||||
|
Err(e) => {
|
||||||
|
#value_error_handling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
witx::BuiltinType::U32
|
||||||
|
| witx::BuiltinType::S32
|
||||||
|
| witx::BuiltinType::U64
|
||||||
|
| witx::BuiltinType::S64
|
||||||
|
| witx::BuiltinType::USize
|
||||||
|
| witx::BuiltinType::F32
|
||||||
|
| witx::BuiltinType::F64 => quote! {
|
||||||
|
let #name = #name as #interface_typename;
|
||||||
|
},
|
||||||
|
witx::BuiltinType::String => unimplemented!("string types unimplemented"),
|
||||||
|
},
|
||||||
|
_ => unimplemented!("only enums and builtins so far"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,13 +37,11 @@ fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenS
|
|||||||
let variant_names = e.variants.iter().map(|v| names.enum_variant(&v.name));
|
let variant_names = e.variants.iter().map(|v| names.enum_variant(&v.name));
|
||||||
let tryfrom_repr_cases = e.variants.iter().enumerate().map(|(n, v)| {
|
let tryfrom_repr_cases = e.variants.iter().enumerate().map(|(n, v)| {
|
||||||
let variant_name = names.enum_variant(&v.name);
|
let variant_name = names.enum_variant(&v.name);
|
||||||
let n = n as u32;
|
|
||||||
quote!(#n => Ok(#ident::#variant_name))
|
quote!(#n => Ok(#ident::#variant_name))
|
||||||
});
|
});
|
||||||
let to_repr_cases = e.variants.iter().enumerate().map(|(n, v)| {
|
let to_repr_cases = e.variants.iter().enumerate().map(|(n, v)| {
|
||||||
let variant_name = names.enum_variant(&v.name);
|
let variant_name = names.enum_variant(&v.name);
|
||||||
let n = n as u32;
|
quote!(#ident::#variant_name => #n as #repr)
|
||||||
quote!(#ident::#variant_name => #n)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
@@ -56,14 +54,14 @@ fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenS
|
|||||||
impl ::std::convert::TryFrom<#repr> for #ident {
|
impl ::std::convert::TryFrom<#repr> for #ident {
|
||||||
type Error = ::memory::GuestValueError;
|
type Error = ::memory::GuestValueError;
|
||||||
fn try_from(value: #repr) -> Result<#ident, ::memory::GuestValueError> {
|
fn try_from(value: #repr) -> Result<#ident, ::memory::GuestValueError> {
|
||||||
match value {
|
match value as usize {
|
||||||
#(#tryfrom_repr_cases),*,
|
#(#tryfrom_repr_cases),*,
|
||||||
_ => Err(::memory::GuestValueError::InvalidEnum(stringify!(#ident))),
|
_ => Err(::memory::GuestValueError::InvalidEnum(stringify!(#ident))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::convert::TryFrom<#signed_repr> for #ident {
|
impl ::std::convert::TryFrom<#signed_repr> for #ident { // XXX this one should always be from i32/i64 (abi size)
|
||||||
type Error = ::memory::GuestValueError;
|
type Error = ::memory::GuestValueError;
|
||||||
fn try_from(value: #signed_repr) -> Result<#ident, ::memory::GuestValueError> {
|
fn try_from(value: #signed_repr) -> Result<#ident, ::memory::GuestValueError> {
|
||||||
#ident::try_from(value as #repr)
|
#ident::try_from(value as #repr)
|
||||||
@@ -78,7 +76,7 @@ fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<#ident> for #signed_repr {
|
impl From<#ident> for #signed_repr { // XXX this should be to i32 or i64 (abi size)
|
||||||
fn from(e: #ident) -> #signed_repr {
|
fn from(e: #ident) -> #signed_repr {
|
||||||
#repr::from(e) as #signed_repr
|
#repr::from(e) as #signed_repr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ pub mod test {
|
|||||||
println!("BAR: {} {}", an_int, an_float);
|
println!("BAR: {} {}", an_int, an_float);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
fn baz(&mut self, excuse: types::Excuse) -> Result<(), types::Errno> {
|
||||||
|
println!("BAZ: {:?}", excuse);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Errno is used as a first return value in the functions above, therefore
|
// Errno is used as a first return value in the functions above, therefore
|
||||||
|
|||||||
@@ -8,9 +8,18 @@
|
|||||||
$physically_unable
|
$physically_unable
|
||||||
$picket_line))
|
$picket_line))
|
||||||
|
|
||||||
|
(typename $excuse
|
||||||
|
(enum u8
|
||||||
|
$dog_ate
|
||||||
|
$traffic
|
||||||
|
$sleeping))
|
||||||
|
|
||||||
(module $foo
|
(module $foo
|
||||||
(@interface func (export "bar")
|
(@interface func (export "bar")
|
||||||
(param $an_int u32)
|
(param $an_int u32)
|
||||||
(param $an_float f32)
|
(param $an_float f32)
|
||||||
(result $error $errno))
|
(result $error $errno))
|
||||||
|
(@interface func (export "baz")
|
||||||
|
(param $an_excuse $excuse)
|
||||||
|
(result $error $errno))
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user