funcs get abi type definitions
This commit is contained in:
@@ -3,21 +3,53 @@ use quote::quote;
|
|||||||
|
|
||||||
use crate::names::Names;
|
use crate::names::Names;
|
||||||
|
|
||||||
|
// FIXME need to template what arguments are required to an import function - some context
|
||||||
|
// struct (e.g. WasiCtx) should be provided at the invocation of the `gen` proc macro.
|
||||||
|
// Rather than pass in memory as a `&mut [u8]` as today, require a `GuestMemory<'a>` be
|
||||||
|
// passed in.
|
||||||
pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream {
|
pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream {
|
||||||
let ident = names.func(&func.name);
|
let ident = names.func(&func.name);
|
||||||
let mut args = TokenStream::new();
|
let mut args = quote!(wasi_ctx: &mut WasiCtx, memory: GuestMemory,);
|
||||||
|
|
||||||
|
let arg_signature = |param: &witx::InterfaceFuncParam| -> TokenStream {
|
||||||
|
let name = names.func_param(¶m.name);
|
||||||
|
match param.tref.type_().passed_by() {
|
||||||
|
witx::TypePassedBy::Value(atom) => {
|
||||||
|
let atom = names.atom_type(atom);
|
||||||
|
quote!(#name: #atom,)
|
||||||
|
}
|
||||||
|
witx::TypePassedBy::Pointer => {
|
||||||
|
let atom = names.atom_type(witx::AtomType::I32);
|
||||||
|
quote!(#name: #atom,)
|
||||||
|
}
|
||||||
|
witx::TypePassedBy::PointerLengthPair => {
|
||||||
|
let atom = names.atom_type(witx::AtomType::I32);
|
||||||
|
let len_name = names.func_len_param(¶m.name);
|
||||||
|
quote!(#name: #atom, #len_name, #atom,)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
for param in func.params.iter() {
|
for param in func.params.iter() {
|
||||||
let name = names.func_param(¶m.name);
|
args.extend(arg_signature(param));
|
||||||
let type_ = names.type_ref(¶m.tref);
|
|
||||||
args.extend(quote!(#name: #type_,));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rets = TokenStream::new();
|
if let Some(arg_results) = func.results.get(1..) {
|
||||||
for result in func.results.iter() {
|
for result in arg_results {
|
||||||
let type_ = names.type_ref(&result.tref);
|
args.extend(arg_signature(result))
|
||||||
rets.extend(quote!(#type_,));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quote!(pub fn #ident(#args) -> (#rets) { unimplemented!() })
|
let ret = if let Some(first_result) = func.results.get(0) {
|
||||||
|
match first_result.tref.type_().passed_by() {
|
||||||
|
witx::TypePassedBy::Value(atom) => names.atom_type(atom),
|
||||||
|
_ => unreachable!("first result should always be passed by value"),
|
||||||
|
}
|
||||||
|
} else if func.noreturn {
|
||||||
|
quote!(!)
|
||||||
|
} else {
|
||||||
|
quote!(())
|
||||||
|
};
|
||||||
|
|
||||||
|
quote!(pub fn #ident(#args) -> #ret { unimplemented!() })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,14 @@ pub fn from_witx(args: TokenStream) -> TokenStream {
|
|||||||
for func in module.funcs() {
|
for func in module.funcs() {
|
||||||
fs.extend(define_func(&names, &func));
|
fs.extend(define_func(&names, &func));
|
||||||
}
|
}
|
||||||
modules.extend(quote!(mod #modname { use super::types::*; #fs }));
|
modules.extend(quote!(
|
||||||
|
mod #modname {
|
||||||
|
use super::*;
|
||||||
|
use super::types::*;
|
||||||
|
use memory::*;
|
||||||
|
#fs
|
||||||
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenStream::from(quote!(mod types { #types } #modules))
|
TokenStream::from(quote!(mod types { #types } #modules))
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use heck::{CamelCase, SnakeCase};
|
use heck::{CamelCase, SnakeCase};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use witx::{BuiltinType, Id, TypeRef};
|
use witx::{AtomType, BuiltinType, Id, TypeRef};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Names {
|
pub struct Names {
|
||||||
@@ -32,6 +32,15 @@ impl Names {
|
|||||||
BuiltinType::USize => quote!(usize),
|
BuiltinType::USize => quote!(usize),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn atom_type(&self, atom: AtomType) -> TokenStream {
|
||||||
|
match atom {
|
||||||
|
AtomType::I32 => quote!(i32),
|
||||||
|
AtomType::I64 => quote!(i64),
|
||||||
|
AtomType::F32 => quote!(f32),
|
||||||
|
AtomType::F64 => quote!(f64),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn type_ref(&self, tref: &TypeRef) -> TokenStream {
|
pub fn type_ref(&self, tref: &TypeRef) -> TokenStream {
|
||||||
match tref {
|
match tref {
|
||||||
TypeRef::Name(nt) => {
|
TypeRef::Name(nt) => {
|
||||||
@@ -65,4 +74,9 @@ impl Names {
|
|||||||
pub fn func_param(&self, id: &Id) -> Ident {
|
pub fn func_param(&self, id: &Id) -> Ident {
|
||||||
format_ident!("{}", id.as_str().to_snake_case())
|
format_ident!("{}", id.as_str().to_snake_case())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For when you need a {name}_len parameter for passing an array:
|
||||||
|
pub fn func_len_param(&self, id: &Id) -> Ident {
|
||||||
|
format_ident!("{}_len", id.as_str().to_snake_case())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod test {
|
pub mod test {
|
||||||
|
pub struct WasiCtx {} // FIXME: parameterize macro on what ctx type is used here
|
||||||
generate::from_witx!("test.witx");
|
generate::from_witx!("test.witx");
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user