Select Git revision
check.rs 5.44 KiB
//! Syntax checking pass
use std::collections::HashMap;
use syn::{Ident, Path};
use error::*;
use {util, Resources, Statics, Crcs, Ips, Ops};
/// `$($Ident: { .. },)*`
pub type Tasks = HashMap<Ident, Task>;
/// `app! { .. }`
#[derive(Debug)]
pub struct App {
/// `device: $path`
pub device: Path,
/// `idle: { $Idle }`
pub idle: Idle,
/// `init: { $Init }`
pub init: Init,
/// `resources: $Statics`
pub resources: Statics,
/// `tasks: { $Tasks }`
pub tasks: Tasks,
_extensible: (),
}
/// `idle: { .. }`
#[derive(Debug)]
pub struct Idle {
/// `path: $Path`
pub path: Path,
/// `resources: $Resources`
pub resources: Resources,
_extensible: (),
}
/// `init: { .. }`
#[derive(Debug)]
pub struct Init {
/// `path: $Path`
pub path: Path,
_extensible: (),
}
/// `$Ident: { .. }`
#[derive(Debug)]
pub struct Task {
/// `enabled: $bool`
pub enabled: Option<bool>,
/// `path: $Path`
pub path: Option<Path>,
/// `priority: $u8`
pub priority: Option<u8>,
/// `resources: $Resources`
pub resources: Resources,
_extensible: (),
}
/// Checks the syntax of the parsed `app!` macro
pub fn app(app: ::App) -> Result<App> {
Ok(App {
_extensible: (),
device: app.device,
idle: ::check::idle(app.idle).chain_err(|| "checking `idle`")?,
init: ::check::init(app.init).chain_err(|| "checking `init`")?,
resources: ::check::statics("resources", app.resources).chain_err(
|| "checking `resources`",
)?,
tasks: ::check::tasks(app.tasks).chain_err(|| "checking `tasks`")?,
})
}
fn idle(idle: Option<::Idle>) -> Result<Idle> {
Ok(if let Some(idle) = idle {
ensure!(
idle.path.is_some() || idle.resources.is_some(),
"empty `idle` field. It should be removed."
);
Idle {
_extensible: (),
path: ::check::path("idle", idle.path).chain_err(
|| "checking `path`",
)?,
resources: ::check::resources("resources", idle.resources)?,
}
} else {
Idle {
_extensible: (),
path: util::mk_path("idle"),
resources: Resources::new(),
}
})
}
fn init(init: Option<::Init>) -> Result<Init> {
Ok(if let Some(init) = init {
if let Some(path) = init.path {
Init {
_extensible: (),
path: ::check::path("init", Some(path)).chain_err(
|| "checking `path`",
)?,
}
} else {
bail!("empty `init` field. It should be removed.");
}
} else {
Init {
_extensible: (),
path: util::mk_path("init"),
}
})
}
fn path(default: &str, path: Option<Path>) -> Result<Path> {
Ok(if let Some(path) = path {
ensure!(
path.segments.len() != 1 || path.segments[0].ident.as_ref() != default,
"this is the default value. It should be omitted."
);
path
} else {
util::mk_path(default)
})
}
fn resources(field: &str, idents: Option<Resources>) -> Result<Resources> {
Ok(if let Some(idents) = idents {
ensure!(
!idents.is_empty(),
"empty `{}` field. It should be removed.",
field
);
idents
} else {
Resources::new()
})
}
fn statics(field: &str, statics: Option<Statics>) -> Result<Statics> {
Ok(if let Some(statics) = statics {
ensure!(
!statics.is_empty(),
"empty `{}` field. It should be removed.",
field
);
statics
} else {
Statics::new()
})
}
fn tasks(tasks: Option<::Tasks>) -> Result<Tasks> {
Ok(if let Some(tasks) = tasks {
ensure!(
!tasks.is_empty(),
"empty `tasks` field. It should be removed"
);
tasks
.into_iter()
.map(|(name_, task)| {
let name = name_.clone();
(move || -> Result<_> {
Ok((
name,
Task {
_extensible: (),
enabled: task.enabled,
path: task.path,
priority: task.priority,
resources: ::check::resources("resources", task.resources)?,
},
))
})().chain_err(|| format!("checking task `{}`", name_))
})
.collect::<Result<_>>()?
} else {
Tasks::new()
})
}
/// `crc! { .. }`
#[derive(Debug)]
pub struct Cro {
/// `crcs: Crcs`
pub ips: ::Ips,
/// `crcs: Crcs`
pub ops: ::Ops,
}
/// Checks the syntax of the parsed `app!` macro
pub fn crc(cro: ::Cro) -> Result<Cro> {
Ok(Cro {
ips: ::check::ips(cro.ips).chain_err(|| "checking `ips`")?,
ops: ::check::ops(cro.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()
})
}