Skip to content
Snippets Groups Projects
Commit bee96a0e authored by pln's avatar pln
Browse files

prepare for code synthesis

parent 5afe78bf
Branches
Tags
No related merge requests found
...@@ -5,7 +5,7 @@ use std::collections::HashMap; ...@@ -5,7 +5,7 @@ use std::collections::HashMap;
use syn::{Ident, Path}; use syn::{Ident, Path};
use error::*; use error::*;
use {util, Resources, Statics, Crcs}; use {util, Resources, Statics, Crcs, Ips, Ops};
/// `$($Ident: { .. },)*` /// `$($Ident: { .. },)*`
pub type Tasks = HashMap<Ident, Task>; pub type Tasks = HashMap<Ident, Task>;
...@@ -194,9 +194,41 @@ fn tasks(tasks: Option<::Tasks>) -> Result<Tasks> { ...@@ -194,9 +194,41 @@ fn tasks(tasks: Option<::Tasks>) -> Result<Tasks> {
pub struct Crc { pub struct Crc {
/// `crcs: Crcs` /// `crcs: Crcs`
pub crcs: Option<Crcs>, pub crcs: Option<Crcs>,
/// `crcs: Crcs`
pub ips: ::Ips,
/// `crcs: Crcs`
pub ops: ::Ops,
} }
/// Checks the syntax of the parsed `app!` macro /// Checks the syntax of the parsed `app!` macro
pub fn crc(crc: ::Crc) -> Result<Crc> { pub fn crc(crc: ::Crc) -> Result<Crc> {
Ok(Crc { crcs: crc.crcs }) Ok(Crc {
crcs: crc.crcs,
ips: ::check::ips(crc.ips).chain_err(|| "checking `ips`")?,
ops: ::check::ops(crc.ops).chain_err(|| "checking `ops`")?,
})
}
///
pub fn ips(ips: Option<::Ips>) -> Result<::Ips> {
Ok(if let Some(ips) = ips {
ensure!(
!ips.is_empty(),
"empty `ips` field. Each Crc must have at least one input port"
);
ips
} else {
bail!("missing input ports ")
})
}
///
pub fn ops(ops: Option<::Ops>) -> Result<::Ops> {
Ok(if let Some(ops) = ops {
ops
} else {
bail!("missing input ports ")
//Ops::new()
})
} }
...@@ -117,13 +117,18 @@ pub enum IpTo { ...@@ -117,13 +117,18 @@ pub enum IpTo {
/// `$($Ident: $Ty > $Path,)*` /// `$($Ident: $Ty > $Path,)*`
pub type Ips = HashMap<Ident, (Ty, Path)>; pub type Ips = HashMap<Ident, (Ty, Path)>;
/// `$($Ident: $Ty < $Path,)*`
pub type Ops = HashMap<Ident, (Ty, Path)>;
/// `crc! { .. }` /// `crc! { .. }`
#[derive(Debug)] #[derive(Debug)]
pub struct Crc { pub struct Crc {
/// Inner Crcs (can be None) /// Inner Crcs (can be None)
pub crcs: Option<Crcs>, pub crcs: Option<Crcs>,
/// Input ports (should not be None) /// Input ports (should not be None, given we have interrupts at top level)
pub ips: Option<Ips>, pub ips: Option<Ips>,
/// Output ports (should not be None, given we treat peripherals as Crcs)
pub ops: Option<Ops>,
} }
impl Crc { impl Crc {
......
...@@ -7,7 +7,8 @@ use syn::{self, DelimToken, Ident, IntTy, Lit, Path, Token, BinOpToken, ...@@ -7,7 +7,8 @@ use syn::{self, DelimToken, Ident, IntTy, Lit, Path, Token, BinOpToken,
use error::*; use error::*;
use {Crc, Crcs, Ips, App, Idle, Init, Resources, Static, Statics, Task, Tasks}; use {Crc, Crcs, Ips, Ops, App, Idle, Init, Resources, Static, Statics, Task,
Tasks};
/// Parses the contents of `app! { $App }` /// Parses the contents of `app! { $App }`
pub fn app(input: &str) -> Result<App> { pub fn app(input: &str) -> Result<App> {
...@@ -445,6 +446,7 @@ pub fn crc(input: &str) -> Result<Crc> { ...@@ -445,6 +446,7 @@ pub fn crc(input: &str) -> Result<Crc> {
let mut crcs = None; let mut crcs = None;
let mut ips = None; let mut ips = None;
let mut ops = None;
fields(&tts, |key, tts| { fields(&tts, |key, tts| {
match key.as_ref() { match key.as_ref() {
...@@ -456,7 +458,13 @@ pub fn crc(input: &str) -> Result<Crc> { ...@@ -456,7 +458,13 @@ pub fn crc(input: &str) -> Result<Crc> {
"ips" => { "ips" => {
ensure!(ips.is_none(), "duplicated `ips` field"); ensure!(ips.is_none(), "duplicated `ips` field");
ips = Some(::parse::ip(tts).chain_err(|| "parsing `ips`")?); ips = Some(::parse::ips(tts).chain_err(|| "parsing `ips`")?);
}
"ops" => {
ensure!(ops.is_none(), "duplicated `ops` field");
ops = Some(::parse::ops(tts).chain_err(|| "parsing `ops`")?);
} }
_ => bail!("unknown field: `{}`", key), _ => bail!("unknown field: `{}`", key),
...@@ -466,7 +474,7 @@ pub fn crc(input: &str) -> Result<Crc> { ...@@ -466,7 +474,7 @@ pub fn crc(input: &str) -> Result<Crc> {
Ok(()) Ok(())
})?; })?;
Ok(Crc { crcs, ips }) Ok(Crc { crcs, ips, ops })
} }
...@@ -505,7 +513,7 @@ fn crcs(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Crcs> { ...@@ -505,7 +513,7 @@ fn crcs(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Crcs> {
} }
/// Parses `$($Ident: $Ty > $Path,)*` /// Parses `$($Ident: $Ty > $Path,)*`
fn ip(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ips> { fn ips(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ips> {
::parse::delimited(tts, DelimToken::Brace, |tts| { ::parse::delimited(tts, DelimToken::Brace, |tts| {
let mut ips = HashMap::new(); let mut ips = HashMap::new();
let mut tts = tts.iter().peekable(); let mut tts = tts.iter().peekable();
...@@ -528,9 +536,9 @@ fn ip(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ips> { ...@@ -528,9 +536,9 @@ fn ip(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ips> {
bail!("expected Colon, found {:?}", tt); bail!("expected Colon, found {:?}", tt);
} }
let ty = ::parse::ty(&mut tts).chain_err(|| { let ty =
format!("parsing `type` for {:?}", ident) ::parse::ty(&TokenTree::Token(Token::Gt), &mut tts)
})?; .chain_err(|| format!("parsing `type` for {:?}", ident))?;
let path = ::parse::path(&mut tts).chain_err(|| "parsing `path`")?; let path = ::parse::path(&mut tts).chain_err(|| "parsing `path`")?;
tts.next(); tts.next();
...@@ -542,19 +550,56 @@ fn ip(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ips> { ...@@ -542,19 +550,56 @@ fn ip(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ips> {
}) })
} }
/// Parses `$($Ident: $Ty < $Path,)*`
fn ops(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ops> {
::parse::delimited(tts, DelimToken::Brace, |tts| {
let mut ops = HashMap::new();
let mut tts = tts.iter().peekable();
while let Some(tt) = tts.next() {
let ident = if let &TokenTree::Token(Token::Ident(ref id)) = tt {
id
} else {
bail!("expected Ident, found {:?}", tt);
};
ensure!(
!ops.contains_key(ident),
"op {} listed more than once",
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::Lt), &mut tts)
.chain_err(|| format!("parsing `type` for {:?}", ident))?;
let path = ::parse::path(&mut tts).chain_err(|| "parsing `path`")?;
tts.next();
ops.insert(ident.clone(), (ty, path));
}
Ok(ops)
})
}
/// Parses `$Ty ` /// Parses `$Ty `
fn ty(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ty> { fn ty(token: &TokenTree, tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ty> {
let mut fragments = vec![]; let mut fragments = vec![];
loop { loop {
if let Some(tt) = tts.next() { if let Some(tt) = tts.next() {
// if tt == &TokenTree::Token(Token::BinOp(BinOpToken::Minus)) { if tt == token {
if tt == &TokenTree::Token(Token::Gt) {
break; break;
} else { } else {
fragments.push(tt); fragments.push(tt);
} }
} else { } else {
bail!("expected `>`, found end of macro"); bail!("expected `{:?}`, found end of macro", token);
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment