rtfm!: remove init.resources and make idle.local optional

This commit is contained in:
Jorge Aparicio 2017-07-06 17:51:34 -05:00
parent 86a360a396
commit 4b0c3bff87
3 changed files with 56 additions and 43 deletions

View file

@ -17,7 +17,6 @@ pub struct App {
#[derive(Debug)] #[derive(Debug)]
pub struct Init { pub struct Init {
pub path: Tokens, pub path: Tokens,
pub resources: HashSet<Ident>,
} }
#[derive(Debug)] #[derive(Debug)]

View file

@ -1,7 +1,6 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use syn::{self, DelimToken, Ident, IntTy, Lit, Token, TokenTree}; use syn::{self, DelimToken, Ident, IntTy, Lit, Token, TokenTree};
use quote::Tokens;
use syntax::{App, Idle, Init, Kind, Resource, Resources, Task, Tasks}; use syntax::{App, Idle, Init, Kind, Resource, Resources, Task, Tasks};
@ -136,10 +135,7 @@ pub fn app(input: &str) -> App {
} }
} }
fn idle_init( pub fn idle(tts: Vec<TokenTree>) -> Idle {
tts: Vec<TokenTree>,
allows_locals: bool,
) -> (Option<Resources>, Tokens, HashSet<Ident>) {
let mut tts = tts.into_iter(); let mut tts = tts.into_iter();
let mut local = None; let mut local = None;
@ -161,7 +157,7 @@ fn idle_init(
); );
match id.as_ref() { match id.as_ref() {
"local" if allows_locals => { "local" => {
assert!(local.is_none(), "duplicated local field"); assert!(local.is_none(), "duplicated local field");
let tt = tts.next(); let tt = tts.next();
@ -183,7 +179,8 @@ fn idle_init(
let mut pieces = vec![]; let mut pieces = vec![];
loop { loop {
let tt = tts.next().expect("expected comma, found EOM"); let tt = tts.next()
.expect("expected comma, found end of macro");
if tt == TokenTree::Token(Token::Comma) { if tt == TokenTree::Token(Token::Comma) {
path = Some(quote!(#(#pieces)*)); path = Some(quote!(#(#pieces)*));
@ -225,27 +222,52 @@ fn idle_init(
); );
} }
(
local,
path.expect("path field is missing"),
resources.unwrap_or(HashSet::new()),
)
}
pub fn idle(tts: Vec<TokenTree>) -> Idle {
let (locals, path, resources) = idle_init(tts, true);
Idle { Idle {
local: locals.expect("local field is missing"), local: local.unwrap_or(HashMap::new()),
path, path: path.expect("path field is missing"),
resources, resources: resources.unwrap_or(HashSet::new()),
} }
} }
pub fn init(tts: Vec<TokenTree>) -> Init { pub fn init(tts: Vec<TokenTree>) -> Init {
let (_, path, resources) = idle_init(tts, false); let mut tts = tts.into_iter();
Init { path, resources } let mut path = None;
while let Some(tt) = tts.next() {
let id = if let TokenTree::Token(Token::Ident(id)) = tt {
id
} else {
panic!("expected ident, found {:?}", tt);
};
let tt = tts.next();
assert_eq!(
tt,
Some(TokenTree::Token(Token::Colon)),
"expected colon, found {:?}",
tt
);
match id.as_ref() {
"path" => {
let mut pieces = vec![];
loop {
let tt = tts.next()
.expect("expected comma, found end of macro");
if tt == TokenTree::Token(Token::Comma) {
path = Some(quote!(#(#pieces)*));
break;
} else {
pieces.push(tt);
}
}
}
id => panic!("unexpected field {}", id),
}
}
Init { path: path.expect("path field is missing") }
} }
fn idents(tts: Vec<TokenTree>) -> HashSet<Ident> { fn idents(tts: Vec<TokenTree>) -> HashSet<Ident> {

View file

@ -33,10 +33,9 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
let mut fields = vec![]; let mut fields = vec![];
let mut exprs = vec![]; let mut exprs = vec![];
let mut lifetime = None; let mut lifetime = None;
for name in &app.init.resources { for (name, resource) in &app.resources {
lifetime = Some(quote!('a)); lifetime = Some(quote!('a));
if let Some(resource) = app.resources.get(name) {
let ty = &resource.ty; let ty = &resource.ty;
fields.push(quote! { fields.push(quote! {
@ -46,19 +45,12 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
exprs.push(quote! { exprs.push(quote! {
#name: &mut *super::#name.get(), #name: &mut *super::#name.get(),
}); });
} else {
fields.push(quote! {
pub #name: &'a mut ::#device::#name,
});
exprs.push(quote! {
#name: &mut *::#device::#name.get(),
});
}
} }
root.push(quote! { root.push(quote! {
mod init { mod init {
pub use ::#device::Peripherals;
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub struct Resources<#lifetime> { pub struct Resources<#lifetime> {
#(#fields)* #(#fields)*
@ -122,10 +114,10 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
let init = &app.init.path; let init = &app.init.path;
main.push(quote! { main.push(quote! {
// type check // type check
let init: fn(init::Resources) = #init; let init: fn(init::Peripherals, init::Resources) = #init;
#krate::atomic(|cs| unsafe { #krate::atomic(|cs| unsafe {
init(init::Resources::new()); init(init::Peripherals::all(), init::Resources::new());
#(#exceptions)* #(#exceptions)*
#(#interrupts)* #(#interrupts)*