put names all in one place. some stub code for funcs!
This commit is contained in:
23
crates/generate/src/funcs.rs
Normal file
23
crates/generate/src/funcs.rs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
use crate::names::Names;
|
||||||
|
|
||||||
|
pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream {
|
||||||
|
let ident = names.func(&func.name);
|
||||||
|
let mut args = TokenStream::new();
|
||||||
|
|
||||||
|
for param in func.params.iter() {
|
||||||
|
let name = names.func_param(¶m.name);
|
||||||
|
let type_ = names.type_ref(¶m.tref);
|
||||||
|
args.extend(quote!(#name: #type_,));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut rets = TokenStream::new();
|
||||||
|
for result in func.results.iter() {
|
||||||
|
let type_ = names.type_ref(&result.tref);
|
||||||
|
rets.extend(quote!(#type_,));
|
||||||
|
}
|
||||||
|
|
||||||
|
quote!(pub fn #ident(#args) -> (#rets) { unimplemented!() })
|
||||||
|
}
|
||||||
@@ -1,33 +1,40 @@
|
|||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
mod funcs;
|
||||||
|
mod names;
|
||||||
mod parse;
|
mod parse;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
use heck::SnakeCase;
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::{format_ident, quote};
|
use quote::quote;
|
||||||
|
|
||||||
|
use funcs::define_func;
|
||||||
|
use names::Names;
|
||||||
use types::define_datatype;
|
use types::define_datatype;
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn from_witx(args: TokenStream) -> TokenStream {
|
pub fn from_witx(args: TokenStream) -> TokenStream {
|
||||||
let args = TokenStream2::from(args);
|
let args = TokenStream2::from(args);
|
||||||
let witx_paths = parse::witx_paths(args).expect("parsing macro arguments");
|
let witx_paths = parse::witx_paths(args).expect("parsing macro arguments");
|
||||||
|
|
||||||
|
let names = Names::new(); // TODO parse the names from the invocation of the macro, or from a file?
|
||||||
|
|
||||||
let doc = witx::load(&witx_paths).expect("loading witx");
|
let doc = witx::load(&witx_paths).expect("loading witx");
|
||||||
|
|
||||||
let mut types = TokenStream2::new();
|
let mut types = TokenStream2::new();
|
||||||
for namedtype in doc.typenames() {
|
for namedtype in doc.typenames() {
|
||||||
let def = define_datatype(&namedtype);
|
let def = define_datatype(&names, &namedtype);
|
||||||
types.extend(def);
|
types.extend(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut modules = TokenStream2::new();
|
let mut modules = TokenStream2::new();
|
||||||
for module in doc.modules() {
|
for module in doc.modules() {
|
||||||
let modname = format_ident!("{}", module.name.as_str().to_snake_case());
|
let modname = names.module(&module.name);
|
||||||
|
|
||||||
let mut fs = TokenStream2::new();
|
let mut fs = TokenStream2::new();
|
||||||
for func in module.funcs() {
|
for func in module.funcs() {
|
||||||
let ident = format_ident!("{}", func.name.as_str().to_snake_case());
|
fs.extend(define_func(&names, &func));
|
||||||
fs.extend(quote!(pub fn #ident() { unimplemented!() }));
|
|
||||||
}
|
}
|
||||||
modules.extend(quote!(mod #modname { use super::types::*; #fs }));
|
modules.extend(quote!(mod #modname { use super::types::*; #fs }));
|
||||||
}
|
}
|
||||||
|
|||||||
68
crates/generate/src/names.rs
Normal file
68
crates/generate/src/names.rs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
use heck::{CamelCase, SnakeCase};
|
||||||
|
use proc_macro2::{Ident, TokenStream};
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
use witx::{BuiltinType, Id, TypeRef};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Names {
|
||||||
|
// FIXME: overrides go in here, so we can map e.g. 2big => TooBig
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Names {
|
||||||
|
pub fn new() -> Names {
|
||||||
|
Names {}
|
||||||
|
}
|
||||||
|
pub fn type_(&self, id: &Id) -> Ident {
|
||||||
|
format_ident!("{}", id.as_str().to_camel_case())
|
||||||
|
}
|
||||||
|
pub fn builtin_type(&self, b: BuiltinType) -> TokenStream {
|
||||||
|
match b {
|
||||||
|
BuiltinType::String => quote!(String),
|
||||||
|
BuiltinType::U8 => quote!(u8),
|
||||||
|
BuiltinType::U16 => quote!(u16),
|
||||||
|
BuiltinType::U32 => quote!(u32),
|
||||||
|
BuiltinType::U64 => quote!(u64),
|
||||||
|
BuiltinType::S8 => quote!(i8),
|
||||||
|
BuiltinType::S16 => quote!(i16),
|
||||||
|
BuiltinType::S32 => quote!(i32),
|
||||||
|
BuiltinType::S64 => quote!(i64),
|
||||||
|
BuiltinType::F32 => quote!(f32),
|
||||||
|
BuiltinType::F64 => quote!(f64),
|
||||||
|
BuiltinType::Char8 => quote!(char),
|
||||||
|
BuiltinType::USize => quote!(usize),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn type_ref(&self, tref: &TypeRef) -> TokenStream {
|
||||||
|
match tref {
|
||||||
|
TypeRef::Name(nt) => {
|
||||||
|
let ident = self.type_(&nt.name);
|
||||||
|
quote!(#ident)
|
||||||
|
}
|
||||||
|
TypeRef::Value(ty) => match &**ty {
|
||||||
|
witx::Type::Builtin(builtin) => self.builtin_type(*builtin),
|
||||||
|
_ => unimplemented!("anonymous type ref"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enum_variant(&self, id: &Id) -> Ident {
|
||||||
|
// FIXME this is a hack - just a proof of concept.
|
||||||
|
if id.as_str().starts_with('2') {
|
||||||
|
format_ident!("TooBig")
|
||||||
|
} else {
|
||||||
|
format_ident!("{}", id.as_str().to_camel_case())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn module(&self, id: &Id) -> Ident {
|
||||||
|
format_ident!("{}", id.as_str().to_snake_case())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn func(&self, id: &Id) -> Ident {
|
||||||
|
format_ident!("{}", id.as_str().to_snake_case())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn func_param(&self, id: &Id) -> Ident {
|
||||||
|
format_ident!("{}", id.as_str().to_snake_case())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,19 @@
|
|||||||
use heck::{CamelCase, MixedCase};
|
use crate::names::Names;
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
|
|
||||||
pub fn define_datatype(namedtype: &witx::NamedType) -> TokenStream {
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
pub fn define_datatype(names: &Names, namedtype: &witx::NamedType) -> TokenStream {
|
||||||
match &namedtype.tref {
|
match &namedtype.tref {
|
||||||
witx::TypeRef::Name(alias_to) => define_alias(&namedtype.name, &alias_to),
|
witx::TypeRef::Name(alias_to) => define_alias(names, &namedtype.name, &alias_to),
|
||||||
witx::TypeRef::Value(v) => match &**v {
|
witx::TypeRef::Value(v) => match &**v {
|
||||||
witx::Type::Enum(e) => define_enum(&namedtype.name, &e),
|
witx::Type::Enum(e) => define_enum(names, &namedtype.name, &e),
|
||||||
witx::Type::Int(_) => unimplemented!("int types"),
|
witx::Type::Int(_) => unimplemented!("int types"),
|
||||||
witx::Type::Flags(_) => unimplemented!("flag types"),
|
witx::Type::Flags(_) => unimplemented!("flag types"),
|
||||||
witx::Type::Struct(_) => unimplemented!("struct types"),
|
witx::Type::Struct(_) => unimplemented!("struct types"),
|
||||||
witx::Type::Union(_) => unimplemented!("union types"),
|
witx::Type::Union(_) => unimplemented!("union types"),
|
||||||
witx::Type::Handle(_h) => unimplemented!("handle types"),
|
witx::Type::Handle(_h) => unimplemented!("handle types"),
|
||||||
witx::Type::Builtin(b) => define_builtin(&namedtype.name, &b),
|
witx::Type::Builtin(b) => define_builtin(names, &namedtype.name, *b),
|
||||||
witx::Type::Pointer { .. } => unimplemented!("pointer types"),
|
witx::Type::Pointer { .. } => unimplemented!("pointer types"),
|
||||||
witx::Type::ConstPointer { .. } => unimplemented!("constpointer types"),
|
witx::Type::ConstPointer { .. } => unimplemented!("constpointer types"),
|
||||||
witx::Type::Array { .. } => unimplemented!("array types"),
|
witx::Type::Array { .. } => unimplemented!("array types"),
|
||||||
@@ -20,15 +21,16 @@ pub fn define_datatype(namedtype: &witx::NamedType) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn define_alias(name: &witx::Id, to: &witx::NamedType) -> TokenStream {
|
fn define_alias(names: &Names, name: &witx::Id, to: &witx::NamedType) -> TokenStream {
|
||||||
let ident = format_ident!("{}", name.as_str().to_camel_case());
|
let ident = names.type_(name);
|
||||||
let to = format_ident!("{}", to.name.as_str().to_camel_case());
|
let to = names.type_(&to.name);
|
||||||
|
|
||||||
quote!(pub type #ident = #to;)
|
quote!(pub type #ident = #to;)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn define_enum(name: &witx::Id, e: &witx::EnumDatatype) -> TokenStream {
|
fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenStream {
|
||||||
let ident = format_ident!("{}", name.as_str().to_camel_case());
|
let ident = names.type_(&name);
|
||||||
|
|
||||||
let mut output = TokenStream::new();
|
let mut output = TokenStream::new();
|
||||||
let repr = int_repr_tokens(e.repr);
|
let repr = int_repr_tokens(e.repr);
|
||||||
output.extend(quote!(#[repr(#repr)]));
|
output.extend(quote!(#[repr(#repr)]));
|
||||||
@@ -36,13 +38,8 @@ fn define_enum(name: &witx::Id, e: &witx::EnumDatatype) -> TokenStream {
|
|||||||
|
|
||||||
let mut inner = TokenStream::new();
|
let mut inner = TokenStream::new();
|
||||||
for variant in &e.variants {
|
for variant in &e.variants {
|
||||||
let value_name = if name.as_str() == "errno" {
|
let variant_name = names.enum_variant(&variant.name);
|
||||||
// FIXME discussion point!
|
inner.extend(quote!(#variant_name,));
|
||||||
format_ident!("E{}", variant.name.as_str().to_mixed_case())
|
|
||||||
} else {
|
|
||||||
format_ident!("{}", variant.name.as_str().to_camel_case())
|
|
||||||
};
|
|
||||||
inner.extend(quote!(#value_name,));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output.extend(quote!(pub enum #ident {
|
output.extend(quote!(pub enum #ident {
|
||||||
@@ -52,24 +49,10 @@ fn define_enum(name: &witx::Id, e: &witx::EnumDatatype) -> TokenStream {
|
|||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
fn define_builtin(name: &witx::Id, builtin: &witx::BuiltinType) -> TokenStream {
|
fn define_builtin(names: &Names, name: &witx::Id, builtin: witx::BuiltinType) -> TokenStream {
|
||||||
let ident = format_ident!("{}", name.as_str().to_camel_case());
|
let ident = names.type_(name);
|
||||||
let prim = match builtin {
|
let built = names.builtin_type(builtin);
|
||||||
witx::BuiltinType::String => quote!(String),
|
quote!(pub type #ident = #built;)
|
||||||
witx::BuiltinType::U8 => quote!(u8),
|
|
||||||
witx::BuiltinType::U16 => quote!(u16),
|
|
||||||
witx::BuiltinType::U32 => quote!(u32),
|
|
||||||
witx::BuiltinType::U64 => quote!(u64),
|
|
||||||
witx::BuiltinType::S8 => quote!(i8),
|
|
||||||
witx::BuiltinType::S16 => quote!(i16),
|
|
||||||
witx::BuiltinType::S32 => quote!(i32),
|
|
||||||
witx::BuiltinType::S64 => quote!(i64),
|
|
||||||
witx::BuiltinType::F32 => quote!(f32),
|
|
||||||
witx::BuiltinType::F64 => quote!(f64),
|
|
||||||
witx::BuiltinType::Char8 => quote!(char),
|
|
||||||
witx::BuiltinType::USize => quote!(usize),
|
|
||||||
};
|
|
||||||
quote!(pub type #ident = #prim;)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn int_repr_tokens(int_repr: witx::IntRepr) -> TokenStream {
|
fn int_repr_tokens(int_repr: witx::IntRepr) -> TokenStream {
|
||||||
|
|||||||
Reference in New Issue
Block a user