diff --git a/crates/generate/.gitignore b/crates/generate/.gitignore new file mode 100644 index 0000000000..eb5a316cbd --- /dev/null +++ b/crates/generate/.gitignore @@ -0,0 +1 @@ +target diff --git a/crates/generate/Cargo.toml b/crates/generate/Cargo.toml index 2403f089a8..cd720d549c 100644 --- a/crates/generate/Cargo.toml +++ b/crates/generate/Cargo.toml @@ -12,3 +12,4 @@ witx = { path = "../WASI/tools/witx" } quote = "1.0" proc-macro2 = "1.0" heck = "0.3" +anyhow = "1" diff --git a/crates/generate/src/imp.rs b/crates/generate/src/imp.rs index 24f9ee6c2f..bd980c139b 100644 --- a/crates/generate/src/imp.rs +++ b/crates/generate/src/imp.rs @@ -3,8 +3,6 @@ use proc_macro2::{Delimiter, Group, Literal, TokenStream, TokenTree}; use quote::{format_ident, quote}; use std::convert::TryFrom; -const WITX_PATH: &'static str = "crates/WASI/phases/snapshot/witx/wasi_snapshot_preview1.witx"; - #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Mode { Host, @@ -21,15 +19,8 @@ impl Mode { } } -pub fn gen() -> TokenStream { +pub fn gen(doc: witx::Document) -> TokenStream { let mut output = TokenStream::new(); - let doc = match witx::load(&[&WITX_PATH]) { - Ok(doc) => doc, - Err(e) => { - panic!("error opening file {}: {}", WITX_PATH, e); - } - }; - gen_datatypes(&mut output, &doc, Mode::Wasi); // gen_datatypes(&mut output, &doc, Mode::Wasi32); // gen_datatypes(&mut output, &doc, Mode::Host); diff --git a/crates/generate/src/lib.rs b/crates/generate/src/lib.rs index 8e214f3345..f3b9a93f5f 100644 --- a/crates/generate/src/lib.rs +++ b/crates/generate/src/lib.rs @@ -1,10 +1,16 @@ extern crate proc_macro; mod imp; +mod parse; use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; #[proc_macro] -pub fn from_witx(_args: TokenStream) -> TokenStream { - TokenStream::from(imp::gen()) +pub fn from_witx(args: TokenStream) -> TokenStream { + let args = TokenStream2::from(args); + let witx_paths = parse::witx_paths(args).expect("parsing macro arguments"); + let doc = witx::load(&witx_paths).expect("loading witx"); + let out = imp::gen(doc); + TokenStream::from(out) } diff --git a/crates/generate/src/parse.rs b/crates/generate/src/parse.rs new file mode 100644 index 0000000000..65c8a190cc --- /dev/null +++ b/crates/generate/src/parse.rs @@ -0,0 +1,33 @@ +use anyhow::{bail, Result}; +use proc_macro2::{Literal, TokenStream, TokenTree}; + +pub fn witx_paths(args: TokenStream) -> Result> { + let arg_strings = args + .into_iter() + .map(|arg| match arg { + TokenTree::Literal(lit) => string_literal(lit), + _ => bail!("expected string literal, got: {:?}", arg), + }) + .collect::>>()?; + + if arg_strings.is_empty() { + bail!("expected at least one argument"); + } + Ok(arg_strings) +} + +fn string_literal(literal: Literal) -> Result { + let s = literal.to_string(); + if !s.starts_with('"') || !s.ends_with('"') { + bail!("string literal must be enclosed in double quotes"); + } + + let trimmed = s[1..s.len() - 1].to_owned(); + if trimmed.contains('"') { + bail!("string literal must not contain quotes"); + } + if trimmed.contains('\\') { + bail!("string literal must not contain backslashes"); + } + Ok(trimmed) +} diff --git a/src/lib.rs b/src/lib.rs index 0136867e5c..4c58828ac7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,8 @@ -generate::from_witx!(); - +pub mod test { + generate::from_witx!("test.witx"); +} +/* +pub mod wasi { + generate::from_witx!("crates/WASI/phases/snapshot/witx/wasi_snapshot_preview1.witx"); +} +*/ diff --git a/test.witx b/test.witx new file mode 100644 index 0000000000..f1185b63fe --- /dev/null +++ b/test.witx @@ -0,0 +1,13 @@ + + +(typename $errno + (enum u32 + $dont_want_to + $physically_unable + $picket_line)) + +(module $foo + (@interface func (export "bar") + (param $name string) + (result $error $errno)) +)