extern crate alloc;
#[allow(unused_extern_crates)]
extern crate proc_macro;
use alloc::str::FromStr;
use proc_macro::{Delimiter, TokenStream, TokenTree};
#[proc_macro_attribute]
pub fn entry(_args: TokenStream, item: TokenStream) -> TokenStream {
let mut input = item.into_iter().peekable();
let mut saw_pub = false;
if let Some(TokenTree::Ident(t)) = input.next() {
if t.to_string() == "pub" {
saw_pub = true;
} else if t.to_string() != "async" {
panic!("Expected \"async\"")
}
} else {
panic!("Expected \"async\"")
}
if saw_pub {
if let Some(TokenTree::Ident(t)) = input.next() {
if t.to_string() != "async" {
panic!("Expected \"async\"")
}
} else {
panic!("Expected \"async\"")
}
}
if let Some(TokenTree::Ident(t)) = input.next() {
if t.to_string() != "fn" {
panic!("Expected \"fn\"")
}
} else {
panic!("Expected \"fn\"")
}
let function_name = if let Some(TokenTree::Ident(t)) = input.next() {
t.to_string()
} else {
panic!("Expected function name")
};
let func_params = if let Some(TokenTree::Group(t)) = input.next() {
if t.delimiter() == Delimiter::Parenthesis {
t.stream().to_string()
} else {
panic!("Expected function paramters")
}
} else {
panic!("Expected function paramters")
};
let function_content = if let Some(TokenTree::Group(t)) = input.next() {
if t.delimiter() == Delimiter::Brace {
t.stream().to_string()
} else {
panic!("Expected function content")
}
} else {
panic!("Expected function content")
};
let func = &format!(
"fn {}({}) {{
executor::block_on(async move{{
{}
}})
}}",
function_name, func_params, function_content
);
TokenStream::from_str(func).unwrap()
}
#[proc_macro_attribute]
pub fn main(_args: TokenStream, item: TokenStream) -> TokenStream {
let mut input = item.into_iter().peekable();
let mut saw_pub = false;
if let Some(TokenTree::Ident(t)) = input.next() {
if t.to_string() == "pub" {
saw_pub = true;
} else if t.to_string() != "async" {
panic!("Expected \"pub\" or \"async\"")
}
} else {
panic!("Expected \"async\"")
}
if saw_pub {
if let Some(TokenTree::Ident(t)) = input.next() {
if t.to_string() != "async" {
panic!("Expected \"async\"")
}
} else {
panic!("Expected \"async\"")
}
}
if let Some(TokenTree::Ident(t)) = input.next() {
if t.to_string() != "fn" {
panic!("Expected \"fn\"")
}
} else {
panic!("Expected \"fn\"")
}
if let Some(TokenTree::Ident(t)) = input.next() {
let s = t.to_string();
if s != "main" {
panic!("Expected \"main\"")
}
} else {
panic!("Expected function name")
}
let func_params = if let Some(TokenTree::Group(t)) = input.next() {
if t.delimiter() == Delimiter::Parenthesis {
t.stream().to_string()
} else {
panic!("Expected function paramters")
}
} else {
panic!("Expected function paramters")
};
let function_content = if let Some(TokenTree::Group(t)) = input.next() {
if t.delimiter() == Delimiter::Brace {
t.stream().to_string()
} else {
panic!("Expected function content")
}
} else {
panic!("Expected function content")
};
let func = &format!(
"fn main({}) -> Result<(), Box<dyn std::error::Error>> {{
let complete = std::sync::Arc::new(core::sync::atomic::AtomicBool::new(false));
let ender = complete.clone();
std::thread::spawn(||{{
executor::block_on(async move {{
(async {{
{}
}}).await;
ender.store(true, core::sync::atomic::Ordering::Release);
}});
}});
while !complete.load(core::sync::atomic::Ordering::Acquire) {{}}
Ok(())
}}",
func_params, function_content
);
TokenStream::from_str(func).unwrap()
}