tamer: ir::asg::section: Provide iterators for major section groups

These groups happen to correspond with the sections of the xmle file, which
suggests again that this lives in the wrong place.  But I should really have
my focus elsewhere right now, so I don't know if I'll go any further right
now.  I guess we'll see as the writer is reimplemented.
main
Mike Gerwitz 2021-09-01 11:21:44 -04:00
parent 1fa9614698
commit ab093046e9
3 changed files with 73 additions and 28 deletions

View File

@ -205,7 +205,7 @@ pub use object::{
FragmentText, IdentObject, IdentObjectData, IdentObjectState, Source,
TransitionError, TransitionResult, UnresolvedError,
};
pub use section::{Section, SectionIter, Sections};
pub use section::{Section, SectionIter, Sections, SectionsIter};
/// Default concrete ASG implementation.
pub type DefaultAsg<O, Ix> = base::BaseAsg<O, Ix>;

View File

@ -107,6 +107,7 @@ impl<'a, T> Iterator for SectionIter<'a, T> {
///
/// These sections may not necessarily correspond directly to sections of an
/// [object file](crate::obj).
// TODO: Remove pub
#[derive(Debug, Default, PartialEq)]
pub struct Sections<'a, T> {
pub map: Section<'a, T>,
@ -147,7 +148,7 @@ impl<'a, T> Sections<'a, T> {
/// they are chained in the same order in which they are defined
/// on the [`Sections`] struct.
pub fn iter_all(&self) -> SectionsIter<T> {
SectionsIter(
SectionsIter(SectionsIterType::All(
self.map
.iter()
.chain(self.retmap.iter())
@ -158,7 +159,44 @@ impl<'a, T> Sections<'a, T> {
.chain(self.funcs.iter())
.chain(self.consts.iter())
.chain(self.rater.iter()),
)
))
}
/// Construct an iterator over the static sections in arbitrary order.
///
/// These sections contain fragments that do not depend on any external
/// inputs and can therefore be executed a single time when the
/// program is loaded into memory.
///
/// Each individual section is ordered as stated in [`Section::iter`],
/// but you should not rely on the order that the sections themselves
/// appear in;
/// they may change or be combined in the future.
pub fn iter_static(&self) -> SectionsIter<T> {
SectionsIter(SectionsIterType::Static(
self.meta
.iter()
.chain(self.worksheet.iter())
.chain(self.params.iter())
.chain(self.types.iter())
.chain(self.funcs.iter())
.chain(self.consts.iter()),
))
}
/// Construct an iterator over the map section.
pub fn iter_map(&self) -> SectionsIter<T> {
SectionsIter(SectionsIterType::Single(self.map.iter()))
}
/// Construct an iterator over the return map section.
pub fn iter_retmap(&self) -> SectionsIter<T> {
SectionsIter(SectionsIterType::Single(self.retmap.iter()))
}
/// Construct an iterator over the executable `rater` section.
pub fn iter_exec(&self) -> SectionsIter<T> {
SectionsIter(SectionsIterType::Single(self.rater.iter()))
}
}
@ -170,20 +208,33 @@ type CSIter1<'a, T, L> = Chain<L, SIter<'a, T>>;
type CSIter2<'a, T, L> = CSIter1<'a, T, CSIter1<'a, T, L>>;
type CSIter4<'a, T, L> = CSIter2<'a, T, CSIter2<'a, T, L>>;
type CSIter8<'a, T, L> = CSIter4<'a, T, CSIter4<'a, T, L>>;
type SIter6<'a, T> = CSIter4<'a, T, CSIter1<'a, T, SIter<'a, T>>>;
type SIter9<'a, T> = CSIter8<'a, T, SIter<'a, T>>;
/// Types of iterators encapsulated by [`SectionsIter`].
enum SectionsIterType<'a, T> {
All(SIter9<'a, T>),
Static(SIter6<'a, T>),
Single(SIter<'a, T>),
}
/// Iterator over each of the sections.
///
/// This iterator should be created with [`Sections::iter_all`].
///
/// This hides the complex iterator type from callers.
pub struct SectionsIter<'a, T>(SIter9<'a, T>);
pub struct SectionsIter<'a, T>(SectionsIterType<'a, T>);
impl<'a, T> Iterator for SectionsIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
match &mut self.0 {
SectionsIterType::All(inner) => inner.next(),
SectionsIterType::Static(inner) => inner.next(),
SectionsIterType::Single(inner) => inner.next(),
}
}
}

View File

@ -20,7 +20,7 @@
use super::writer::{Result, WriterError};
use crate::global;
use crate::ir::asg::{
IdentKind, IdentObject, IdentObjectData, SectionIter, Sections,
IdentKind, IdentObject, IdentObjectData, Sections, SectionsIter,
};
use crate::sym::{GlobalSymbolResolve, ProgSymbolId, SymbolId};
use fxhash::FxHashSet;
@ -108,22 +108,16 @@ impl<W: Write> XmleWriter<W> {
writer.write_froms(&sections)
})?
.write_element(b"l:map-exec", |writer| {
writer.write_section(sections.map.iter())
writer.write_section(sections.iter_map())
})?
.write_element(b"l:retmap-exec", |writer| {
writer.write_section(sections.retmap.iter())
writer.write_section(sections.iter_retmap())
})?
.write_element(b"l:static", |writer| {
writer
.write_section(sections.meta.iter())?
.write_section(sections.worksheet.iter())?
.write_section(sections.params.iter())?
.write_section(sections.types.iter())?
.write_section(sections.funcs.iter())?
.write_section(sections.consts.iter())
writer.write_section(sections.iter_static())
})?
.write_element(b"l:exec", |writer| {
writer.write_section(sections.rater.iter())
writer.write_section(sections.iter_exec())
})?
.write_end_tag(b"package")?;
@ -313,7 +307,7 @@ impl<W: Write> XmleWriter<W> {
) -> Result<&mut XmleWriter<W>> {
let mut map_froms: FxHashSet<ProgSymbolId> = Default::default();
let map_iter = sections.map.iter();
let map_iter = sections.iter_map();
for map_ident in map_iter {
let src = map_ident.src().expect("internal error: missing map src");
@ -343,7 +337,7 @@ impl<W: Write> XmleWriter<W> {
/// `writer`'s 'write_event`.
fn write_section<T: IdentObjectData<Ix>>(
&mut self,
idents: SectionIter<T>,
idents: SectionsIter<T>,
) -> Result<&mut XmleWriter<W>> {
for obj in idents {
let ident = obj
@ -420,7 +414,7 @@ mod mock {
#[cfg(test)]
mod test {
use super::*;
use crate::ir::asg::{Dim, FragmentText, Section, Source};
use crate::ir::asg::{Dim, FragmentText, Source};
use crate::ir::legacyir::SymAttrs;
use crate::sym::GlobalSymbolIntern;
use std::str;
@ -517,9 +511,9 @@ mod test {
FragmentText::from(""),
);
let mut section = Section::new();
section.push_body(&obj);
sut.write_section(section.iter())?;
let mut sections = Sections::new();
sections.rater.push_body(&obj);
sut.write_section(sections.iter_all())?;
Ok(())
}
@ -537,9 +531,9 @@ mod test {
Source::default(),
);
let mut section = Section::new();
section.push_body(&obj);
sut.write_section(section.iter())?;
let mut sections = Sections::new();
sections.rater.push_body(&obj);
sut.write_section(sections.iter_all())?;
Ok(())
}
@ -553,9 +547,9 @@ mod test {
let obj = IdentObject::Missing("missing".intern());
let mut section = Section::new();
section.push_body(&obj);
let result = sut.write_section(section.iter());
let mut sections = Sections::new();
sections.rater.push_body(&obj);
let result = sut.write_section(sections.iter_all());
match result {
Err(WriterError::ExpectedFragment(_)) => {}