diff --git a/src/lib.rs b/src/lib.rs index 1667fcaaf1f01ac2533477e0678ed21b04c3b64e..266450dc0bc752c7e720448cc5534af689908723 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,8 +114,8 @@ pub enum IpTo { Method(Ident), } -/// `$($Ident: $Ty > $Path,)*` -pub type Ips = HashMap<Ident, (Ty, Path)>; +/// `$($Ident: Ident ($Ty) -> $Ty )*` +pub type Ips = HashMap<Ident, (Ident, Ty, Ty)>; /// `$($Ident: $Ty = $Expr < $Path,)*` pub type Ops = HashMap<Ident, (Ty, Expr, Path)>; diff --git a/src/parse.rs b/src/parse.rs index 7dff7806d479301a14151e78b95a8174f41b033d..b1bce2381a4d9c4c3b0979b402df8d1d204c759d 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -2,11 +2,13 @@ use std::collections::{HashMap, HashSet}; use std::iter::Peekable; use std::slice::Iter; -use syn::{self, DelimToken, Ident, IntTy, Lit, Path, Token, BinOpToken, TokenTree, Ty}; +use syn::{self, DelimToken, Ident, IntTy, Lit, Path, Token, BinOpToken, + TokenTree, Ty}; use error::*; -use {Cro, Ips, Ops, App, Idle, Init, Resources, Static, Statics, Task, Tasks, Expr}; +use {Cro, Ips, Ops, App, Idle, Init, Resources, Static, Statics, Task, Tasks, + Expr}; /// Parses the contents of `app! { $App }` pub fn app(input: &str) -> Result<App> { @@ -23,7 +25,8 @@ pub fn app(input: &str) -> Result<App> { "device" => { ensure!(device.is_none(), "duplicated `device` field"); - device = Some(::parse::path(tts).chain_err(|| "parsing `device`")?); + device = + Some(::parse::path(tts).chain_err(|| "parsing `device`")?); } "idle" => { ensure!(idle.is_none(), "duplicated `idle` field"); @@ -38,12 +41,15 @@ pub fn app(input: &str) -> Result<App> { "resources" => { ensure!(resources.is_none(), "duplicated `resources` field"); - resources = Some(::parse::statics(tts).chain_err(|| "parsing `resources`")?); + resources = Some(::parse::statics(tts).chain_err( + || "parsing `resources`", + )?); } "tasks" => { ensure!(tasks.is_none(), "duplicated `tasks` field"); - tasks = Some(::parse::tasks(tts).chain_err(|| "parsing `tasks`")?); + tasks = + Some(::parse::tasks(tts).chain_err(|| "parsing `tasks`")?); } _ => bail!("unknown field: `{}`", key), } @@ -71,7 +77,11 @@ fn bool(tt: Option<&TokenTree>) -> Result<bool> { } /// Parses a delimited token tree -fn delimited<R, F>(tts: &mut Peekable<Iter<TokenTree>>, delimiter: DelimToken, f: F) -> Result<R> +fn delimited<R, F>( + tts: &mut Peekable<Iter<TokenTree>>, + delimiter: DelimToken, + f: F, +) -> Result<R> where F: FnOnce(&[TokenTree]) -> Result<R>, { @@ -137,9 +147,14 @@ fn idle(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Idle> { path = Some(::parse::path(tts)?); } "resources" => { - ensure!(resources.is_none(), "duplicated `resources` field"); + ensure!( + resources.is_none(), + "duplicated `resources` field" + ); - resources = Some(::parse::resources(tts).chain_err(|| "parsing `resources`")?); + resources = Some(::parse::resources(tts).chain_err( + || "parsing `resources`", + )?); } _ => bail!("unknown field: `{}`", key), } @@ -188,7 +203,10 @@ fn resources(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Resources> { let mut tts = tts.iter().peekable(); while let Some(tt) = tts.next() { if let &TokenTree::Token(Token::Ident(ref ident)) = tt { - ensure!(!idents.contains(ident), "ident {} listed more than once"); + ensure!( + !idents.contains(ident), + "ident {} listed more than once" + ); idents.insert(ident.clone()); @@ -262,18 +280,20 @@ fn statics(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Statics> { let mut tts = tts.iter(); while let Some(tt) = tts.next() { match tt { - &TokenTree::Token(Token::Ident(ref id)) if id.as_ref() == "static" => {} + &TokenTree::Token(Token::Ident(ref id)) + if id.as_ref() == "static" => {} _ => { bail!("expected keyword `static`, found {:?}", tt); } } let tt = tts.next(); - let ident = if let Some(&TokenTree::Token(Token::Ident(ref id))) = tt { - id - } else { - bail!("expected Ident, found {:?}", tt); - }; + let ident = + if let Some(&TokenTree::Token(Token::Ident(ref id))) = tt { + id + } else { + bail!("expected Ident, found {:?}", tt); + }; ensure!( !statics.contains_key(ident), @@ -334,22 +354,33 @@ fn task(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Task> { "enabled" => { ensure!(enabled.is_none(), "duplicated `enabled` field"); - enabled = Some(::parse::bool(tts.next()).chain_err(|| "parsing `enabled`")?); + enabled = Some(::parse::bool(tts.next()).chain_err( + || "parsing `enabled`", + )?); } "path" => { ensure!(path.is_none(), "duplicated `path` field"); - path = Some(::parse::path(tts).chain_err(|| "parsing `path`")?); + path = Some( + ::parse::path(tts).chain_err(|| "parsing `path`")?, + ); } "priority" => { ensure!(priority.is_none(), "duplicated `priority` field"); - priority = Some(::parse::u8(tts.next()).chain_err(|| "parsing `priority`")?); + priority = Some(::parse::u8(tts.next()).chain_err( + || "parsing `priority`", + )?); } "resources" => { - ensure!(resources.is_none(), "duplicated `resources` field"); + ensure!( + resources.is_none(), + "duplicated `resources` field" + ); - resources = Some(::parse::resources(tts).chain_err(|| "parsing `resources`")?); + resources = Some(::parse::resources(tts).chain_err( + || "parsing `resources`", + )?); } _ => bail!("unknown field: `{}`", key), } @@ -490,19 +521,48 @@ fn ips(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ips> { ident ); + let tt = tts.next(); if let Some(&TokenTree::Token(Token::Colon)) = tt { } else { bail!("expected Colon, found {:?}", tt); } - let ty = ::parse::ty(&TokenTree::Token(Token::Gt), &mut tts) - .chain_err(|| format!("parsing `type` for {:?}", ident))?; + let tt = tts.next(); + let meth = + if let Some(&TokenTree::Token(Token::Ident(ref id))) = tt { + id + } else { + bail!("expected Ident, found {:?}", tt); + }; - let path = ::parse::path(&mut tts).chain_err(|| "parsing `path`")?; - tts.next(); + //let ty_param: Result<Ty> = + let ty_param = + ::parse::delimited(&mut tts, DelimToken::Paren, |tts| { + Ok(syn::parse_type(&format!("{}", quote!(#(#tts)*)))?) + })?; + + + let tt = tts.next(); + // let ty_return: Result<Ty> = Ok(syn::parse_type(&"()")?); + let ty_return: Result<Ty> = match tt { + Some(&TokenTree::Token(Token::Comma)) => { + tts.next(); + Ok(syn::parse_type(&"()")?) + } + Some(&TokenTree::Token(Token::RArrow)) => { + ::parse::ty(&TokenTree::Token(Token::Comma), &mut tts) + } + _ => bail!("expected `-> Type,' or `,` found {:?}", tt), + }; + + //let tt = tts.next(); + // if let Some(&TokenTree::Token(Token::Comma)) = tt { + // } else { + // bail!("expected Comma, found {:?}", tt); + // }; - ips.insert(ident.clone(), (ty, path)); + ips.insert(ident.clone(), (meth.clone(), ty_param, ty_return?)); } Ok(ips) @@ -533,12 +593,14 @@ fn ops(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ops> { bail!("expected Colon, found {:?}", tt); } - let ty = ::parse::ty(&TokenTree::Token(Token::Eq), &mut tts) - .chain_err(|| format!("parsing `type` for {:?}", ident))?; + let ty = + ::parse::ty(&TokenTree::Token(Token::Eq), &mut tts) + .chain_err(|| format!("parsing `type` for {:?}", ident))?; - let expr = ::parse::expr(&TokenTree::Token(Token::Lt), &mut tts) - .chain_err(|| format!("parsing `type` for {:?}", ident))?; + let expr = + ::parse::expr(&TokenTree::Token(Token::Lt), &mut tts) + .chain_err(|| format!("parsing `type` for {:?}", ident))?; @@ -573,7 +635,10 @@ fn ty(token: &TokenTree, tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ty> { } /// Parses `$Expr ` -fn expr(token: &TokenTree, tts: &mut Peekable<Iter<TokenTree>>) -> Result<::Expr> { +fn expr( + token: &TokenTree, + tts: &mut Peekable<Iter<TokenTree>>, +) -> Result<::Expr> { let mut fragments = vec![]; loop { if let Some(tt) = tts.next() {