wasmi/derive/src/parser.rs

98 lines
3.4 KiB
Rust
Raw Normal View History

2019-01-25 15:46:42 +00:00
use crate::error::CompileError;
use syn::{spanned::Spanned, FnArg, Ident, ImplItem, ImplItemMethod, ReturnType};
2019-01-25 09:45:39 +00:00
2019-01-25 15:46:42 +00:00
/// A parameter. This doesn't used for modeling `&self` or `&mut self` parameters.
2019-01-25 09:45:39 +00:00
#[derive(Clone)]
pub struct Param {
/// A generated identifier used to name temporary variables
/// used for storing this parameter in generated code.
2019-01-25 10:02:03 +00:00
///
/// This ident is used primary used for its' span.
2019-01-25 09:45:39 +00:00
pub ident: syn::Ident,
}
2019-01-25 10:02:03 +00:00
/// A function definition parsed from an impl block.
pub struct FuncDef {
2019-01-25 09:45:39 +00:00
/// Assigned index of this function.
pub index: u32,
pub name: String,
2019-01-25 15:46:42 +00:00
/// The parameter of this function. This excludes the `&self` or `&mut self`.
2019-01-25 10:02:03 +00:00
pub params: Vec<Param>,
2019-01-25 09:45:39 +00:00
pub return_ty: Option<proc_macro2::Span>,
}
2019-01-25 10:02:03 +00:00
/// This is the core data structure which contains the list of all defined functions
/// and the data required for the code generator (e.g. for implementing a trait).
pub struct ImplBlockDef {
/// List of all defined external functions.
pub funcs: Vec<FuncDef>,
2019-01-25 09:45:39 +00:00
/// The generics required to implement a trait for this type.
pub generics: syn::Generics,
2019-01-25 10:02:03 +00:00
/// The type declaration to implement a trait, most typically
2019-01-25 09:45:39 +00:00
/// represented by a structure.
2019-01-25 10:02:03 +00:00
///
/// E.g.: `Foo<'a>`, `()`
2019-01-25 09:45:39 +00:00
pub ty: Box<syn::Type>,
}
2019-01-19 20:59:32 +00:00
/// Parse an incoming stream of tokens into externalities definition.
2019-01-25 15:46:42 +00:00
pub fn parse(input: proc_macro2::TokenStream) -> Result<ImplBlockDef, CompileError> {
2019-01-25 15:47:35 +00:00
let item_impl = syn::parse2::<syn::ItemImpl>(input)
.map_err(|_| CompileError::new("failed to parse".to_string()))?;
2019-01-19 00:31:47 +00:00
let mut funcs = vec![];
for item in item_impl.items {
match item {
2019-01-25 09:43:03 +00:00
ImplItem::Method(ImplItemMethod { sig, .. }) => {
2019-01-19 00:31:47 +00:00
let index = funcs.len() as u32;
2019-01-25 10:02:03 +00:00
let params = sig
2019-01-25 09:43:03 +00:00
.decl
.inputs
.iter()
.enumerate()
2019-01-25 15:46:42 +00:00
.filter_map(|(idx, input)| {
// The first parameter should be either &self or &mut self.
// This makes code generation simpler.
if idx == 0 {
match input {
FnArg::SelfRef(_) => return None,
2019-01-25 15:47:35 +00:00
_ => {
return Some(Err(err_span!(
input.span(),
"only &self and &mut self supported as first argument"
)));
}
2019-01-25 15:46:42 +00:00
}
}
2019-01-25 09:43:03 +00:00
let param_name = format!("arg{}", idx);
let ident = Ident::new(&param_name, input.span());
2019-01-25 15:46:42 +00:00
Some(Ok(Param { ident }))
2019-01-25 09:43:03 +00:00
})
2019-01-25 15:46:42 +00:00
.collect::<Result<Vec<Param>, CompileError>>()?;
2019-01-19 00:31:47 +00:00
let return_ty = match sig.decl.output {
ReturnType::Default => None,
ReturnType::Type(_, ty) => Some(ty.span()),
};
2019-01-25 10:02:03 +00:00
funcs.push(FuncDef {
2019-01-19 00:31:47 +00:00
index,
name: sig.ident.to_string(),
2019-01-25 10:02:03 +00:00
params,
2019-01-19 00:31:47 +00:00
return_ty,
});
2019-01-25 09:43:03 +00:00
}
_ => {}
2019-01-19 00:31:47 +00:00
}
}
2019-01-25 10:02:03 +00:00
Ok(ImplBlockDef {
2019-01-19 00:31:47 +00:00
funcs,
generics: item_impl.generics.clone(),
ty: item_impl.self_ty.clone(),
})
}