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

prepare for code synthesis

parent 5afe78bf
Branches
No related tags found
No related merge requests found
......@@ -5,7 +5,7 @@ use std::collections::HashMap;
use syn::{Ident, Path};
use error::*;
use {util, Resources, Statics, Crcs};
use {util, Resources, Statics, Crcs, Ips, Ops};
/// `$($Ident: { .. },)*`
pub type Tasks = HashMap<Ident, Task>;
......@@ -194,9 +194,41 @@ fn tasks(tasks: Option<::Tasks>) -> Result<Tasks> {
pub struct Crc {
/// `crcs: Crcs`
pub crcs: Option<Crcs>,
/// `crcs: Crcs`
pub ips: ::Ips,
/// `crcs: Crcs`
pub ops: ::Ops,
}
/// Checks the syntax of the parsed `app!` macro
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 {
/// `$($Ident: $Ty > $Path,)*`
pub type Ips = HashMap<Ident, (Ty, Path)>;
/// `$($Ident: $Ty < $Path,)*`
pub type Ops = HashMap<Ident, (Ty, Path)>;
/// `crc! { .. }`
#[derive(Debug)]
pub struct Crc {
/// Inner Crcs (can be None)
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>,
/// Output ports (should not be None, given we treat peripherals as Crcs)
pub ops: Option<Ops>,
}
impl Crc {
......
......@@ -7,7 +7,8 @@ use syn::{self, DelimToken, Ident, IntTy, Lit, Path, Token, BinOpToken,
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 }`
pub fn app(input: &str) -> Result<App> {
......@@ -445,6 +446,7 @@ pub fn crc(input: &str) -> Result<Crc> {
let mut crcs = None;
let mut ips = None;
let mut ops = None;
fields(&tts, |key, tts| {
match key.as_ref() {
......@@ -456,7 +458,13 @@ pub fn crc(input: &str) -> Result<Crc> {
"ips" => {
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),
......@@ -466,7 +474,7 @@ pub fn crc(input: &str) -> Result<Crc> {
Ok(())
})?;
Ok(Crc { crcs, ips })
Ok(Crc { crcs, ips, ops })
}
......@@ -505,7 +513,7 @@ fn crcs(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Crcs> {
}
/// 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| {
let mut ips = HashMap::new();
let mut tts = tts.iter().peekable();
......@@ -528,9 +536,9 @@ fn ip(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ips> {
bail!("expected Colon, found {:?}", tt);
}
let ty = ::parse::ty(&mut tts).chain_err(|| {
format!("parsing `type` for {:?}", ident)
})?;
let ty =
::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`")?;
tts.next();
......@@ -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 `
fn ty(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ty> {
fn ty(token: &TokenTree, tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ty> {
let mut fragments = vec![];
loop {
if let Some(tt) = tts.next() {
// if tt == &TokenTree::Token(Token::BinOp(BinOpToken::Minus)) {
if tt == &TokenTree::Token(Token::Gt) {
if tt == token {
break;
} else {
fragments.push(tt);
}
} 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