use core::errors::Result;
use core::{Flavor, RpDecl, RpFile, RpName, RpReg};
use linked_hash_map::LinkedHashMap;
use std::collections::{btree_map, BTreeMap, LinkedList};
use std::vec;
pub struct ForEachFile<'a, F: 'static>
where
F: Flavor,
{
iter: btree_map::Iter<'a, F::Package, RpFile<F>>,
}
impl<'a, F: 'static> Iterator for ForEachFile<'a, F>
where
F: Flavor,
{
type Item = (&'a F::Package, &'a RpFile<F>);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
pub struct ToplevelDeclIter<'a, F: 'static>
where
F: Flavor,
{
it: vec::IntoIter<&'a RpDecl<F>>,
}
impl<'a, F: 'static> Iterator for ToplevelDeclIter<'a, F>
where
F: Flavor,
{
type Item = &'a RpDecl<F>;
fn next(&mut self) -> Option<Self::Item> {
self.it.next()
}
}
pub struct DeclIter<'a, F: 'static>
where
F: Flavor,
{
queue: LinkedList<&'a RpDecl<F>>,
}
impl<'a, F: 'static> Iterator for DeclIter<'a, F>
where
F: Flavor,
{
type Item = &'a RpDecl<F>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(decl) = self.queue.pop_front() {
self.queue.extend(decl.decls());
Some(decl)
} else {
None
}
}
}
pub struct Translated<F: 'static>
where
F: Flavor,
{
decls: LinkedHashMap<RpName<F>, RpReg>,
files: BTreeMap<F::Package, RpFile<F>>,
}
impl<F: 'static> Translated<F>
where
F: Flavor,
{
pub fn new(
decls: LinkedHashMap<RpName<F>, RpReg>,
files: BTreeMap<F::Package, RpFile<F>>,
) -> Self {
Self { decls, files }
}
pub fn lookup<'a>(&'a self, name: &RpName<F>) -> Result<&'a RpReg> {
let key = name.clone().without_prefix();
if let Some(registered) = self.decls.get(&key) {
return Ok(registered);
}
return Err(format!("no such type: {}", name).into());
}
pub fn for_each_file(&self) -> ForEachFile<F> {
ForEachFile {
iter: self.files.iter(),
}
}
pub fn toplevel_decl_iter(&self) -> ToplevelDeclIter<F> {
let values = self.files
.values()
.flat_map(|f| f.decls.iter())
.collect::<Vec<_>>();
ToplevelDeclIter {
it: values.into_iter(),
}
}
pub fn decl_iter(&self) -> DeclIter<F> {
let mut queue = LinkedList::new();
queue.extend(self.files.values().flat_map(|f| f.decls.iter()));
DeclIter { queue: queue }
}
}