Merge pull request #62 from fitzgen/to-tokens

Implement quote::ToTokens for AST types
This commit is contained in:
Alex Crichton 2018-03-07 17:05:13 -06:00 committed by GitHub
commit c3b6191112
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 503 additions and 484 deletions

View File

@ -10,7 +10,7 @@ pub struct Program {
pub exports: Vec<Export>,
pub imports: Vec<Import>,
pub enums: Vec<Enum>,
pub imported_types: Vec<(syn::Visibility, syn::Ident)>,
pub imported_types: Vec<ImportedType>,
pub structs: Vec<Struct>,
}
@ -53,6 +53,11 @@ pub struct Enum {
pub variants: Vec<(syn::Ident, u32)>
}
pub struct ImportedType {
pub vis: syn::Visibility,
pub name: syn::Ident,
}
pub enum Type {
// special
Vector(VectorType, bool),
@ -323,7 +328,10 @@ impl Program {
pub fn push_foreign_ty(&mut self,
f: syn::ForeignItemType,
_module_opts: &BindgenAttrs) {
self.imported_types.push((f.vis, f.ident));
self.imported_types.push(ImportedType {
vis: f.vis,
name: f.ident
});
}
pub fn wbg_literal(&self, dst: &mut Tokens) -> usize {

View File

@ -34,7 +34,7 @@ pub fn wasm_bindgen(attr: TokenStream, input: TokenStream) -> TokenStream {
let mut ret = Tokens::new();
let mut program = ast::Program::default();
program.push_item(item, Some(opts), &mut ret);
generate_wrappers(program, &mut ret);
program.to_tokens(&mut ret);
// println!("{}", ret);
@ -59,22 +59,23 @@ fn to_ident_name(s: &str) -> Cow<str> {
)
}
// Generate wrappers for all the items that we've found
fn generate_wrappers(program: ast::Program, tokens: &mut Tokens) {
for export in program.exports.iter() {
bindgen_export(export, tokens);
impl ToTokens for ast::Program {
// Generate wrappers for all the items that we've found
fn to_tokens(&self, tokens: &mut Tokens) {
for export in self.exports.iter() {
export.to_tokens(tokens);
}
for s in program.structs.iter() {
bindgen_struct(s, tokens);
for s in self.structs.iter() {
s.to_tokens(tokens);
}
for i in program.imports.iter() {
bindgen_import(i, tokens);
for i in self.imports.iter() {
i.to_tokens(tokens);
}
for e in program.enums.iter() {
bindgen_enum(e, tokens);
for e in self.enums.iter() {
e.to_tokens(tokens);
}
for &(ref vis, ref t) in program.imported_types.iter() {
bindgen_imported_type(vis, t, tokens);
for it in self.imported_types.iter() {
it.to_tokens(tokens);
}
// Generate a static which will eventually be what lives in a custom section
@ -95,7 +96,7 @@ fn generate_wrappers(program: ast::Program, tokens: &mut Tokens) {
let generated_static_name = syn::Ident::from(generated_static_name);
let mut generated_static_value = Tokens::new();
let generated_static_length = program.wbg_literal(&mut generated_static_value);
let generated_static_length = self.wbg_literal(&mut generated_static_value);
(my_quote! {
#[no_mangle]
@ -103,11 +104,13 @@ fn generate_wrappers(program: ast::Program, tokens: &mut Tokens) {
pub static #generated_static_name: [u32; #generated_static_length] =
[#generated_static_value];
}).to_tokens(tokens);
}
}
fn bindgen_struct(s: &ast::Struct, into: &mut Tokens) {
let name = &s.name;
let free_fn = syn::Ident::from(shared::free_function(s.name.as_ref()));
impl ToTokens for ast::Struct {
fn to_tokens(&self, tokens: &mut Tokens) {
let name = &self.name;
let free_fn = syn::Ident::from(shared::free_function(self.name.as_ref()));
let c = shared::name_to_descriptor(name.as_ref()) as u32;
(my_quote! {
impl ::wasm_bindgen::convert::WasmBoundary for #name {
@ -150,20 +153,22 @@ fn bindgen_struct(s: &ast::Struct, into: &mut Tokens) {
pub unsafe extern fn #free_fn(ptr: u32) {
<#name as ::wasm_bindgen::convert::WasmBoundary>::from_js(ptr);
}
}).to_tokens(into);
}).to_tokens(tokens);
}
}
fn bindgen_export(export: &ast::Export, into: &mut Tokens) {
let generated_name = export.rust_symbol();
let export_name = export.export_name();
impl ToTokens for ast::Export {
fn to_tokens(self: &ast::Export, into: &mut Tokens) {
let generated_name = self.rust_symbol();
let export_name = self.export_name();
let mut args = vec![];
let mut arg_conversions = vec![];
let mut converted_arguments = vec![];
let ret = syn::Ident::from("_ret");
let mut offset = 0;
if export.method {
let class = export.class.unwrap();
if self.method {
let class = self.class.unwrap();
args.push(my_quote! { me: *mut ::wasm_bindgen::__rt::WasmRefCell<#class> });
arg_conversions.push(my_quote! {
::wasm_bindgen::__rt::assert_not_null(me);
@ -172,7 +177,7 @@ fn bindgen_export(export: &ast::Export, into: &mut Tokens) {
offset = 1;
}
for (i, ty) in export.function.arguments.iter().enumerate() {
for (i, ty) in self.function.arguments.iter().enumerate() {
let i = i + offset;
let ident = syn::Ident::from(format!("arg{}", i));
match *ty {
@ -251,7 +256,7 @@ fn bindgen_export(export: &ast::Export, into: &mut Tokens) {
}
let ret_ty;
let convert_ret;
match export.function.ret {
match self.function.ret {
Some(ast::Type::Vector(ref ty, true)) => {
ret_ty = my_quote! { -> *mut #ty };
convert_ret = my_quote! { Box::into_raw(Box::new(#ret)) };
@ -275,10 +280,10 @@ fn bindgen_export(export: &ast::Export, into: &mut Tokens) {
}
}
let name = export.function.name;
let receiver = match export.class {
Some(_) if export.method => {
if export.mutable {
let name = self.function.name;
let receiver = match self.class {
Some(_) if self.method => {
if self.mutable {
my_quote! { me.borrow_mut().#name }
} else {
my_quote! { me.borrow().#name }
@ -299,11 +304,13 @@ fn bindgen_export(export: &ast::Export, into: &mut Tokens) {
}
};
tokens.to_tokens(into);
}
}
fn bindgen_imported_type(vis: &syn::Visibility,
name: &syn::Ident,
tokens: &mut Tokens) {
impl ToTokens for ast::ImportedType {
fn to_tokens(&self, tokens: &mut Tokens) {
let vis = &self.vis;
let name = &self.name;
(my_quote! {
#vis struct #name {
obj: ::wasm_bindgen::JsValue,
@ -330,14 +337,15 @@ fn bindgen_imported_type(vis: &syn::Visibility,
}
}
}).to_tokens(tokens);
}
}
fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
impl ToTokens for ast::Import {
fn to_tokens(&self, tokens: &mut Tokens) {
let mut class_ty = None;
let mut is_method = false;
let mut class_name = None;
match import.kind {
match self.kind {
ast::ImportKind::Method { ref ty, ref class } => {
is_method = true;
class_ty = Some(ty);
@ -352,18 +360,18 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
}
let import_name = shared::mangled_import_name(
class_name.map(|s| &**s),
import.function.name.as_ref(),
self.function.name.as_ref(),
);
let vis = &import.function.rust_vis;
let ret = &import.function.rust_decl.output;
let fn_token = &import.function.rust_decl.fn_token;
let vis = &self.function.rust_vis;
let ret = &self.function.rust_decl.output;
let fn_token = &self.function.rust_decl.fn_token;
let mut abi_argument_names = Vec::new();
let mut abi_arguments = Vec::new();
let mut arg_conversions = Vec::new();
let ret_ident = syn::Ident::from("_ret");
let names = import.function.rust_decl.inputs
let names = self.function.rust_decl.inputs
.iter()
.map(|arg| {
match *arg {
@ -385,7 +393,7 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
}
});
for (i, (ty, name)) in import.function.arguments.iter().zip(names).enumerate() {
for (i, (ty, name)) in self.function.arguments.iter().zip(names).enumerate() {
match *ty {
ast::Type::Vector(ref ty, owned) => {
let ptr = syn::Ident::from(format!("{}_ptr", name));
@ -440,7 +448,7 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
}
let abi_ret;
let mut convert_ret;
match import.function.ret {
match self.function.ret {
Some(ast::Type::ByValue(ref t)) => {
abi_ret = my_quote! {
<#t as ::wasm_bindgen::convert::WasmBoundary>::Js
@ -483,7 +491,7 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
}
let mut exceptional_ret = my_quote! {};
if import.function.opts.catch() {
if self.function.opts.catch() {
let exn_data = syn::Ident::from("exn_data");
let exn_data_ptr = syn::Ident::from("exn_data_ptr");
abi_argument_names.push(exn_data_ptr);
@ -501,11 +509,11 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
};
}
let name = import.function.name;
let name = self.function.name;
let import_name = syn::Ident::from(import_name);
let attrs = &import.function.rust_attrs;
let attrs = &self.function.rust_attrs;
let arguments = import.function.rust_decl.inputs
let arguments = self.function.rust_decl.inputs
.iter()
.skip(if is_method { 1 } else { 0 })
.collect::<Vec<_>>();
@ -541,14 +549,16 @@ fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
} else {
invocation.to_tokens(tokens);
}
}
}
fn bindgen_enum(e: &ast::Enum, into: &mut Tokens) {
let enum_name = &e.name;
impl ToTokens for ast::Enum {
fn to_tokens(&self, into: &mut Tokens) {
let enum_name = &self.name;
let c = shared::TYPE_ENUM as u32;
let incoming_u32 = quote! { n };
let enum_name_as_string = enum_name.to_string();
let cast_clauses = e.variants.iter().map(|variant| {
let cast_clauses = self.variants.iter().map(|variant| {
let &(variant_name, _) = variant;
quote! {
if #incoming_u32 == #enum_name::#variant_name as u32 {
@ -578,4 +588,5 @@ fn bindgen_enum(e: &ast::Enum, into: &mut Tokens) {
}
}
}).to_tokens(into);
}
}