factor the docs out as well

This commit is contained in:
Pat Hickey
2020-06-22 19:27:31 -07:00
parent 6adbae3007
commit cde32070fc
3 changed files with 102 additions and 36 deletions

View File

@@ -9,7 +9,16 @@ pub use wasi_common::{WasiCtx, WasiCtxBuilder};
wasmtime_wiggle::define_struct_for_wiggle!({ wasmtime_wiggle::define_struct_for_wiggle!({
witx: ["../wasi-common/WASI/phases/snapshot/witx/wasi_snapshot_preview1.witx"], witx: ["../wasi-common/WASI/phases/snapshot/witx/wasi_snapshot_preview1.witx"],
ctx: WasiCtx, ctx: WasiCtx,
instance: Wasi, instance: {
name: Wasi,
docs: "An instantiated instance of the wasi exports.
This represents a wasi module which can be used to instantiate other
wasm modules. This structure exports all that various fields of the
wasi instance as fields which can be used to implement your own
instantiation logic, if necessary. Additionally [`Wasi::get_export`]
can be used to do name-based resolution."
}
}); });
pub fn is_wasi_module(name: &str) -> bool { pub fn is_wasi_module(name: &str) -> bool {

View File

@@ -13,14 +13,14 @@ use {
pub struct Config { pub struct Config {
pub witx: WitxConf, pub witx: WitxConf,
pub ctx: CtxConf, pub ctx: CtxConf,
pub instance_typename: InstanceTypenameConf, pub instance: InstanceConf,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ConfigField { pub enum ConfigField {
Witx(WitxConf), Witx(WitxConf),
Ctx(CtxConf), Ctx(CtxConf),
InstanceTypename(InstanceTypenameConf), Instance(InstanceConf),
} }
mod kw { mod kw {
@@ -28,6 +28,8 @@ mod kw {
syn::custom_keyword!(witx_literal); syn::custom_keyword!(witx_literal);
syn::custom_keyword!(ctx); syn::custom_keyword!(ctx);
syn::custom_keyword!(instance); syn::custom_keyword!(instance);
syn::custom_keyword!(name);
syn::custom_keyword!(docs);
} }
impl Parse for ConfigField { impl Parse for ConfigField {
@@ -48,7 +50,7 @@ impl Parse for ConfigField {
} else if lookahead.peek(kw::instance) { } else if lookahead.peek(kw::instance) {
input.parse::<kw::instance>()?; input.parse::<kw::instance>()?;
input.parse::<Token![:]>()?; input.parse::<Token![:]>()?;
Ok(ConfigField::InstanceTypename(input.parse()?)) Ok(ConfigField::Instance(input.parse()?))
} else { } else {
Err(lookahead.error()) Err(lookahead.error())
} }
@@ -59,7 +61,7 @@ impl Config {
pub fn build(fields: impl Iterator<Item = ConfigField>, err_loc: Span) -> Result<Self> { pub fn build(fields: impl Iterator<Item = ConfigField>, err_loc: Span) -> Result<Self> {
let mut witx = None; let mut witx = None;
let mut ctx = None; let mut ctx = None;
let mut instance_typename = None; let mut instance = None;
for f in fields { for f in fields {
match f { match f {
ConfigField::Witx(c) => { ConfigField::Witx(c) => {
@@ -74,11 +76,11 @@ impl Config {
} }
ctx = Some(c); ctx = Some(c);
} }
ConfigField::InstanceTypename(c) => { ConfigField::Instance(c) => {
if instance_typename.is_some() { if instance.is_some() {
return Err(Error::new(err_loc, "duplicate `instance` field")); return Err(Error::new(err_loc, "duplicate `instance` field"));
} }
instance_typename = Some(c); instance = Some(c);
} }
} }
} }
@@ -89,7 +91,7 @@ impl Config {
ctx: ctx ctx: ctx
.take() .take()
.ok_or_else(|| Error::new(err_loc, "`ctx` field required"))?, .ok_or_else(|| Error::new(err_loc, "`ctx` field required"))?,
instance_typename: instance_typename instance: instance
.take() .take()
.ok_or_else(|| Error::new(err_loc, "`instance` field required"))?, .ok_or_else(|| Error::new(err_loc, "`instance` field required"))?,
}) })
@@ -115,15 +117,70 @@ impl Parse for Config {
} }
} }
#[derive(Debug, Clone)] enum InstanceConfField {
pub struct InstanceTypenameConf { Name(Ident),
pub name: Ident, Docs(String),
} }
impl Parse for InstanceTypenameConf { impl Parse for InstanceConfField {
fn parse(input: ParseStream) -> Result<Self> { fn parse(input: ParseStream) -> Result<Self> {
Ok(InstanceTypenameConf { let lookahead = input.lookahead1();
name: input.parse()?, if lookahead.peek(kw::name) {
input.parse::<kw::name>()?;
input.parse::<Token![:]>()?;
Ok(InstanceConfField::Name(input.parse()?))
} else if lookahead.peek(kw::docs) {
input.parse::<kw::docs>()?;
input.parse::<Token![:]>()?;
let docs: syn::LitStr = input.parse()?;
Ok(InstanceConfField::Docs(docs.value()))
} else {
Err(lookahead.error())
}
}
}
#[derive(Debug, Clone)]
pub struct InstanceConf {
pub name: Ident,
pub docs: Option<String>,
}
impl InstanceConf {
fn build(fields: impl Iterator<Item = InstanceConfField>, err_loc: Span) -> Result<Self> {
let mut name = None;
let mut docs = None;
for f in fields {
match f {
InstanceConfField::Name(c) => {
if name.is_some() {
return Err(Error::new(err_loc, "duplicate `name` field"));
}
name = Some(c);
}
InstanceConfField::Docs(c) => {
if docs.is_some() {
return Err(Error::new(err_loc, "duplicate `docs` field"));
}
docs = Some(c);
}
}
}
Ok(InstanceConf {
name: name
.take()
.ok_or_else(|| Error::new(err_loc, "`name` field required"))?,
docs,
}) })
} }
} }
impl Parse for InstanceConf {
fn parse(input: ParseStream) -> Result<Self> {
let contents;
let _lbrace = braced!(contents in input);
let fields: Punctuated<InstanceConfField, Token![,]> =
contents.parse_terminated(InstanceConfField::parse)?;
Ok(InstanceConf::build(fields.into_iter(), input.span())?)
}
}

View File

@@ -6,7 +6,7 @@ use wiggle_generate::Names;
mod config; mod config;
use config::InstanceTypenameConf; use config::InstanceConf;
#[proc_macro] #[proc_macro]
pub fn define_struct_for_wiggle(args: TokenStream) -> TokenStream { pub fn define_struct_for_wiggle(args: TokenStream) -> TokenStream {
@@ -17,7 +17,7 @@ pub fn define_struct_for_wiggle(args: TokenStream) -> TokenStream {
let doc = config.load_document(); let doc = config.load_document();
let names = Names::new(&config.ctx.name, quote!(wasmtime_wiggle)); let names = Names::new(&config.ctx.name, quote!(wasmtime_wiggle));
generate(&doc, &names, &config.instance_typename).into() generate(&doc, &names, &config.instance).into()
} }
enum Abi { enum Abi {
@@ -27,11 +27,7 @@ enum Abi {
F64, F64,
} }
fn generate( fn generate(doc: &witx::Document, names: &Names, instance_conf: &InstanceConf) -> TokenStream2 {
doc: &witx::Document,
names: &Names,
instance_typename: &InstanceTypenameConf,
) -> TokenStream2 {
let mut fields = Vec::new(); let mut fields = Vec::new();
let mut get_exports = Vec::new(); let mut get_exports = Vec::new();
let mut ctor_externs = Vec::new(); let mut ctor_externs = Vec::new();
@@ -239,27 +235,31 @@ fn generate(
} }
} }
let inst_type = instance_typename.name.clone(); let inst_type = instance_conf.name.clone();
let inst_docs = if let Some(ref docs) = instance_conf.docs {
quote!( #[doc = #docs] )
} else {
quote!()
};
let constructor_docs = format!(
"Creates a new [`{}`] instance.
External values are allocated into the `store` provided and
configuration of the wasi instance itself should be all
contained in the `cx` parameter.",
instance_conf.name.to_string()
);
let ctx_type = names.ctx_type(); let ctx_type = names.ctx_type();
quote! { quote! {
/// An instantiated instance of the wasi exports. #inst_docs
///
/// This represents a wasi module which can be used to instantiate other
/// wasm modules. This structure exports all that various fields of the
/// wasi instance as fields which can be used to implement your own
/// instantiation logic, if necessary. Additionally [`#inst_type::get_export`]
/// can be used to do name-based resolution.
pub struct #inst_type { pub struct #inst_type {
#(#fields,)* #(#fields,)*
} }
impl #inst_type { impl #inst_type {
/// Creates a new [`#inst_type`] instance. #[doc = #constructor_docs]
///
/// External values are allocated into the `store` provided and
/// configuration of the wasi instance itself should be all
/// contained in the `cx` parameter.
pub fn new(store: &wasmtime::Store, cx: #ctx_type) -> Self { pub fn new(store: &wasmtime::Store, cx: #ctx_type) -> Self {
let cx = std::rc::Rc::new(std::cell::RefCell::new(cx)); let cx = std::rc::Rc::new(std::cell::RefCell::new(cx));
#(#ctor_externs)* #(#ctor_externs)*
@@ -281,7 +281,7 @@ fn generate(
} }
} }
/// Adds all wasi items to the specified `Linker`. /// Adds all instance items to the specified `Linker`.
pub fn add_to_linker(&self, linker: &mut wasmtime::Linker) -> anyhow::Result<()> { pub fn add_to_linker(&self, linker: &mut wasmtime::Linker) -> anyhow::Result<()> {
#(#linker_add)* #(#linker_add)*
Ok(()) Ok(())