1extern crate alloc;
2#[allow(unused_extern_crates)]
3extern crate proc_macro;
4use alloc::str::FromStr;
5use proc_macro::{Delimiter, TokenStream, TokenTree};
6
7#[proc_macro_attribute]
8pub fn entry(_args: TokenStream, item: TokenStream) -> TokenStream {
9 let mut input = item.into_iter().peekable();
10 let mut saw_pub = false;
11 if let Some(TokenTree::Ident(t)) = input.next() {
12 if t.to_string() == "pub" {
13 saw_pub = true;
14 } else if t.to_string() != "async" {
15 panic!("Expected \"async\"")
16 }
17 } else {
18 panic!("Expected \"async\"")
19 }
20
21 if saw_pub {
22 if let Some(TokenTree::Ident(t)) = input.next() {
23 if t.to_string() != "async" {
24 panic!("Expected \"async\"")
25 }
26 } else {
27 panic!("Expected \"async\"")
28 }
29 }
30
31 if let Some(TokenTree::Ident(t)) = input.next() {
32 if t.to_string() != "fn" {
33 panic!("Expected \"fn\"")
34 }
35 } else {
36 panic!("Expected \"fn\"")
37 }
38 let function_name = if let Some(TokenTree::Ident(t)) = input.next() {
39 t.to_string()
40 } else {
41 panic!("Expected function name")
42 };
43 let func_params = if let Some(TokenTree::Group(t)) = input.next() {
44 if t.delimiter() == Delimiter::Parenthesis {
45 t.stream().to_string()
46 } else {
47 panic!("Expected function paramters")
48 }
49 } else {
50 panic!("Expected function paramters")
51 };
52 let function_content = if let Some(TokenTree::Group(t)) = input.next() {
53 if t.delimiter() == Delimiter::Brace {
54 t.stream().to_string()
55 } else {
56 panic!("Expected function content")
57 }
58 } else {
59 panic!("Expected function content")
60 };
61 let func = &format!(
62 "fn {}({}) {{
63 executor::block_on(async move{{
64 {}
65 }})
66 }}",
67 function_name, func_params, function_content
68 );
69 TokenStream::from_str(func).unwrap()
70}
71
72#[proc_macro_attribute]
73pub fn main(_args: TokenStream, item: TokenStream) -> TokenStream {
74 let mut input = item.into_iter().peekable();
75 let mut saw_pub = false;
76 if let Some(TokenTree::Ident(t)) = input.next() {
77 if t.to_string() == "pub" {
78 saw_pub = true;
79 } else if t.to_string() != "async" {
80 panic!("Expected \"pub\" or \"async\"")
81 }
82 } else {
83 panic!("Expected \"async\"")
84 }
85
86 if saw_pub {
87 if let Some(TokenTree::Ident(t)) = input.next() {
88 if t.to_string() != "async" {
89 panic!("Expected \"async\"")
90 }
91 } else {
92 panic!("Expected \"async\"")
93 }
94 }
95 if let Some(TokenTree::Ident(t)) = input.next() {
96 if t.to_string() != "fn" {
97 panic!("Expected \"fn\"")
98 }
99 } else {
100 panic!("Expected \"fn\"")
101 }
102 if let Some(TokenTree::Ident(t)) = input.next() {
103 let s = t.to_string();
104 if s != "main" {
105 panic!("Expected \"main\"")
106 }
107 } else {
108 panic!("Expected function name")
109 }
110 let func_params = if let Some(TokenTree::Group(t)) = input.next() {
111 if t.delimiter() == Delimiter::Parenthesis {
112 t.stream().to_string()
113 } else {
114 panic!("Expected function paramters")
115 }
116 } else {
117 panic!("Expected function paramters")
118 };
119 let function_content = if let Some(TokenTree::Group(t)) = input.next() {
120 if t.delimiter() == Delimiter::Brace {
121 t.stream().to_string()
122 } else {
123 panic!("Expected function content")
124 }
125 } else {
126 panic!("Expected function content")
127 };
128 let func = &format!(
129 "fn main({}) -> Result<(), Box<dyn std::error::Error>> {{
130 let complete = std::sync::Arc::new(core::sync::atomic::AtomicBool::new(false));
131 let ender = complete.clone();
132 std::thread::spawn(||{{
133 executor::block_on(async move {{
134 (async {{
135 {}
136 }}).await;
137 ender.store(true, core::sync::atomic::Ordering::Release);
138 }});
139 }});
140 while !complete.load(core::sync::atomic::Ordering::Acquire) {{}}
141 Ok(())
142 }}",
143 func_params, function_content
144 );
145 TokenStream::from_str(func).unwrap()
146}