aboutsummaryrefslogtreecommitdiff
path: root/embassy-macros
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2020-10-19 21:15:24 +0200
committerDario Nieuwenhuis <[email protected]>2020-10-19 21:25:54 +0200
commitcd9ecaef57982b33376dcfea3a0406a3df4b09c5 (patch)
tree41567981cfe2ba9a65e84a6025daf83cb2204fa5 /embassy-macros
parent0e1adc58f48a65c6af1d2ededa8712426fb3ab6e (diff)
integrate static-executor, cleanup time module.
Diffstat (limited to 'embassy-macros')
-rw-r--r--embassy-macros/Cargo.toml13
-rw-r--r--embassy-macros/src/lib.rs114
2 files changed, 127 insertions, 0 deletions
diff --git a/embassy-macros/Cargo.toml b/embassy-macros/Cargo.toml
new file mode 100644
index 000000000..1f3e20aa8
--- /dev/null
+++ b/embassy-macros/Cargo.toml
@@ -0,0 +1,13 @@
1[package]
2name = "embassy-macros"
3version = "0.1.0"
4authors = ["Dario Nieuwenhuis <[email protected]>"]
5edition = "2018"
6
7[dependencies]
8syn = { version = "1.0.39", features = ["full", "extra-traits"] }
9quote = "1.0.7"
10darling = "0.10.2"
11
12[lib]
13proc-macro = true
diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs
new file mode 100644
index 000000000..1745311ba
--- /dev/null
+++ b/embassy-macros/src/lib.rs
@@ -0,0 +1,114 @@
1#![feature(proc_macro_diagnostic)]
2
3extern crate proc_macro;
4
5use darling::FromMeta;
6use proc_macro::{Diagnostic, Level, Span, TokenStream};
7use quote::{format_ident, quote};
8use syn::spanned::Spanned;
9
10#[derive(Debug, FromMeta)]
11struct MacroArgs {
12 #[darling(default)]
13 pool_size: Option<usize>,
14}
15
16#[proc_macro_attribute]
17pub fn task(args: TokenStream, item: TokenStream) -> TokenStream {
18 let args = syn::parse_macro_input!(args as syn::AttributeArgs);
19 let mut task_fn = syn::parse_macro_input!(item as syn::ItemFn);
20
21 let args = match MacroArgs::from_list(&args) {
22 Ok(v) => v,
23 Err(e) => {
24 return TokenStream::from(e.write_errors());
25 }
26 };
27
28 let pool_size: usize = args.pool_size.unwrap_or(1);
29
30 let mut fail = false;
31 if task_fn.sig.asyncness.is_none() {
32 task_fn
33 .sig
34 .span()
35 .unwrap()
36 .error("task functions must be async")
37 .emit();
38 fail = true;
39 }
40 if task_fn.sig.generics.params.len() != 0 {
41 task_fn
42 .sig
43 .span()
44 .unwrap()
45 .error("task functions must not be generic")
46 .emit();
47 fail = true;
48 }
49 if pool_size < 1 {
50 Span::call_site()
51 .error("pool_size must be 1 or greater")
52 .emit();
53 fail = true
54 }
55
56 let mut arg_names: syn::punctuated::Punctuated<syn::Ident, syn::Token![,]> =
57 syn::punctuated::Punctuated::new();
58 let args = &task_fn.sig.inputs;
59
60 for arg in args.iter() {
61 match arg {
62 syn::FnArg::Receiver(_) => {
63 arg.span()
64 .unwrap()
65 .error("task functions must not have receiver arguments")
66 .emit();
67 fail = true;
68 }
69 syn::FnArg::Typed(t) => match t.pat.as_ref() {
70 syn::Pat::Ident(i) => arg_names.push(i.ident.clone()),
71 _ => {
72 arg.span()
73 .unwrap()
74 .error("pattern matching in task arguments is not yet supporteds")
75 .emit();
76 fail = true;
77 }
78 },
79 }
80 }
81
82 if fail {
83 return TokenStream::new();
84 }
85
86 let name = task_fn.sig.ident.clone();
87
88 let type_name = format_ident!("__embassy_executor_type_{}", name);
89 let pool_name = format_ident!("__embassy_executor_pool_{}", name);
90 let task_fn_name = format_ident!("__embassy_executor_task_{}", name);
91 let create_fn_name = format_ident!("__embassy_executor_create_{}", name);
92
93 let visibility = &task_fn.vis;
94
95 task_fn.sig.ident = task_fn_name.clone();
96
97 let result = quote! {
98 #task_fn
99 #[allow(non_camel_case_types)]
100 type #type_name = impl ::core::future::Future + 'static;
101
102 fn #create_fn_name(#args) -> #type_name {
103 #task_fn_name(#arg_names)
104 }
105
106 #[allow(non_upper_case_globals)]
107 static #pool_name: [::embassy::executor::Task<#type_name>; #pool_size] = [::embassy::executor::Task::new(); #pool_size];
108
109 #visibility fn #name(#args) -> ::embassy::executor::SpawnToken {
110 unsafe { ::embassy::executor::Task::spawn(&#pool_name, || #create_fn_name(#arg_names)) }
111 }
112 };
113 result.into()
114}