diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..53eaa21960d1b9c229de5e6ca9becd1a6089c021 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +**/*.rs.bk diff --git a/.vscode/tasks.json b/.vscode/tasks.json index b4a2198b3ee7c3048411270fafbef8de4deccb4d..34137207d1ac52d9ffdbaff1fc37816cb465fb4b 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -4,13 +4,16 @@ "version": "2.0.0", "tasks": [ { - "label": "cargo run --example main", + "label": "cargo expand --example trust > expanded.rs", "type": "shell", - "command": "cargo run --example main", + "command": "cargo expand --example trust > expanded.rs", "group": { "kind": "build", "isDefault": true - } + }, + "problemMatcher": [ + "$rustc" + ] }, { "label": "cargo run --example trust", diff --git a/examples/trust.rs b/examples/trust.rs index 245595acf0635998d8710ca44979d477fe07f417..048c4f399b0972b98b9ee65acdd10890d192282b 100644 --- a/examples/trust.rs +++ b/examples/trust.rs @@ -3,22 +3,32 @@ use proc_collect::*; #[trust] mod kalleanka { fn hello() { + println!("in trust hello"); ext_hello(); } #[entry] - fn entry() {} + #[inline(always)] + fn entry() { + hello(); + } #[interrupt] - fn interrupt() {} + fn i1() { + println!("i1"); + } + + #[interrupt] + fn i2() { + println!("i2"); + } #[exception] - fn exception() {} + fn exception() { + println!("exc"); + } } fn ext_hello() { - println!("hello"); -} -fn main() { - hello(); + println!("ext_hello"); } diff --git a/expanded.rs b/expanded.rs new file mode 100644 index 0000000000000000000000000000000000000000..8d0bdb6913b1c5483c6959f25961765ce360658c --- /dev/null +++ b/expanded.rs @@ -0,0 +1,68 @@ +#![feature(prelude_import)] +#[prelude_import] +use std::prelude::v1::*; +#[macro_use] +extern crate std; +use proc_collect::*; + +fn hello() { + { + ::std::io::_print(::core::fmt::Arguments::new_v1( + &["in trust hello\n"], + &match () { + () => [], + }, + )); + }; + ext_hello(); +} +#[inline(always)] +fn entry() { + hello(); +} +fn i1() { + { + ::std::io::_print(::core::fmt::Arguments::new_v1( + &["i1\n"], + &match () { + () => [], + }, + )); + }; +} +fn i2() { + { + ::std::io::_print(::core::fmt::Arguments::new_v1( + &["i2\n"], + &match () { + () => [], + }, + )); + }; +} +fn exception() { + { + ::std::io::_print(::core::fmt::Arguments::new_v1( + &["exc\n"], + &match () { + () => [], + }, + )); + }; +} +fn main() { + let _ = entry(); + let _ = i1(); + let _ = i2(); + let _ = exception(); +} +fn ext_hello() { + { + ::std::io::_print(::core::fmt::Arguments::new_v1( + &["ext_hello\n"], + &match () { + () => [], + }, + )); + }; +} diff --git a/src/lib.rs b/src/lib.rs index d5a74e826c07792c0edcdca6c9a0498a8e25e48b..e3c3c4f1d65b9b32222380049c9f4ee1649ac2f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,36 +6,75 @@ use std::fs::{File, OpenOptions}; use std::io::prelude::*; use std::iter::FromIterator; use syn::parse::{Parse, ParseStream}; -use syn::{parse_macro_input, Attribute, Ident, Item, ItemMod, Result, Token}; +use syn::{parse_macro_input, Attribute, Ident, Item, ItemFn, ItemMod, Result, Token}; // use syn::{parse_macro_input, Attribute, Ident, ItemMod, Result, Token}; - #[proc_macro_attribute] pub fn entry(_args: TokenStream, input: TokenStream) -> TokenStream { - let items = parse_macro_input!(input as FnItem).items; - (quote! { #(#items)* }).into() + let fn_item = parse_macro_input!(input as ItemFn); + (quote! { #fn_item }).into() } #[proc_macro_attribute] pub fn interrupt(_args: TokenStream, input: TokenStream) -> TokenStream { - input + let fn_item = parse_macro_input!(input as ItemFn); + (quote! { #fn_item }).into() } #[proc_macro_attribute] pub fn exception(_args: TokenStream, input: TokenStream) -> TokenStream { - input + let fn_item = parse_macro_input!(input as ItemFn); + (quote! { #fn_item }).into() } #[derive(Debug)] struct TrustMod { items: Vec<Item>, + entries: Vec<Entry>, +} + +#[derive(Debug)] +enum Entry { + Entry(Ident), + Interrupt(Ident), + Exception(Ident), } impl Parse for TrustMod { fn parse(input: ParseStream) -> Result<Self> { let module: ItemMod = input.parse()?; + match module.content { - Some((_, items)) => Ok(TrustMod { items }), + Some((_, items)) => { + let mut v = vec![]; + let mut e = vec![]; + for i in items { + match i { + Item::Fn(ref item_fn) => { + for a in &item_fn.attrs { + for s in &a.path.segments { + match s.ident.to_string().as_str() { + "entry" => e.push(Entry::Entry(item_fn.sig.ident.clone())), + "interrupt" => { + e.push(Entry::Interrupt(item_fn.sig.ident.clone())) + } + "exception" => { + e.push(Entry::Exception(item_fn.sig.ident.clone())) + } + _ => (), + } + } + } + } + _ => (), + } + v.push(i); + } + Ok(TrustMod { + items: v, + entries: e, + }) + } _ => panic!("illegal trust module"), } } @@ -43,6 +82,24 @@ impl Parse for TrustMod { #[proc_macro_attribute] pub fn trust(_args: TokenStream, input: TokenStream) -> TokenStream { - let items = parse_macro_input!(input as TrustMod).items; - (quote! { #(#items)* }).into() + let trust_mod = parse_macro_input!(input as TrustMod); + let items = trust_mod.items; + + let mut calls = vec![]; + for e in trust_mod.entries { + let id = match e { + Entry::Entry(id) => id, + Entry::Interrupt(id) => id, + Entry::Exception(id) => id, + }; + calls.push(quote! { let _ = #id(); }); + } + + (quote! { + #(#items)* + fn main() { + #(#calls)* + } + }) + .into() }