abletk/abletk-macros/src/lib.rs

82 lines
2.6 KiB
Rust
Executable File

/*
* Copyright (C) 2022 Umut İnan Erdoğan <umutinanerdogan@pm.me>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
//! # abletk-macros
//!
//! This crate implements procedural macros to be used with AbleTK. You
//! shouldn't depend on this directly.
#[macro_use] extern crate quote;
use proc_macro::TokenStream;
use syn::{ItemFn, ReturnType, Type};
use syn::spanned::Spanned;
#[proc_macro_attribute]
pub fn launch(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut func: ItemFn = syn::parse(item).expect("parsing failed");
assert_ne!(func.sig.ident, "main", "Function cannot be named main");
assert_eq!(func.sig.inputs.len(), 0, "Function cannot take any arguments");
let asyncness = func.sig.asyncness.is_some();
let ident = func.sig.ident.clone();
// could be simplified if we could deref inside nested patterns
match &mut func.sig.output {
ReturnType::Type(_, ty) => {
if let Type::Infer(_) = **ty {
let span = ty.span();
*ty = syn::parse2(
quote_spanned!(span=> ::abletk::application::Application)
).unwrap();
}
}
ReturnType::Default => {
let span = func.sig.span();
let new = if asyncness {
quote_spanned! { span =>
async fn #ident() -> ::abletk::application::Application
}
} else {
quote_spanned! { span =>
fn #ident() -> ::abletk::application::Application
}
};
func.sig = syn::parse2(new).unwrap();
}
}
let out = if asyncness {
quote! {
fn main() {
let rt = ::tokio::runtime::Builder::new_multi_thread()
// todo: make this the application name
.thread_name("abletk-tokio-runtime-worker")
.enable_time()
.build().unwrap();
rt.block_on(#ident()).launch(rt);
}
#func
}
} else {
quote! {
fn main() {
let rt = ::tokio::runtime::Builder::new_multi_thread()
// todo: make this the application name
.thread_name("abletk-tokio-runtime-worker")
.enable_time()
.build().unwrap();
#ident().launch(rt);
}
#func
}
};
out.into()
}