tamer: obj::xmlo: Remove PackageAttrs in favor of token stream

The Options here are awkward and will be able to go away in the new reader
and in AsgBuilder once it has a proper state machine.

This gets rid of some of the initial migratory work for the new reader,
because PackageAttrs is gone.  I'm going to wait to update this to the new
way until I get further into this.

DEV-11449
main
Mike Gerwitz 2022-03-10 15:35:23 -05:00
parent d428755a2e
commit 2f703ab2df
7 changed files with 90 additions and 188 deletions

View File

@ -185,13 +185,24 @@ where
while let Some(ev) = xmlo.next() {
match (istate, ev?) {
(IS::None, XmloEvent::Package(attrs)) => {
(IS::None, XmloEvent::PkgName(name)) => {
if first {
state.name = attrs.name;
state.relroot = attrs.relroot;
state.name = Some(name);
}
}
elig = attrs.elig;
(IS::None, XmloEvent::PkgRootPath(relroot)) => {
if first {
state.relroot = Some(relroot);
}
}
(IS::None, XmloEvent::PkgEligClassYields(pkg_elig)) => {
elig = Some(pkg_elig);
}
(IS::None, XmloEvent::PkgProgramFlag) => {
// Unused
}
(IS::None | IS::SymDep(_), XmloEvent::SymDepStart(sym)) => {
@ -349,7 +360,7 @@ impl Error for AsgBuilderError {
mod test {
use super::*;
use crate::asg::{DefaultAsg, FragmentText, IdentObject};
use crate::obj::xmlo::{PackageAttrs, SymAttrs, SymType};
use crate::obj::xmlo::{SymAttrs, SymType};
use crate::sym::GlobalSymbolIntern;
use std::collections::hash_map::RandomState;
@ -363,15 +374,12 @@ mod test {
let name = "name".intern();
let relroot = "some/path".into();
let evs = vec![Ok(XmloEvent::Package(PackageAttrs {
name: Some(name),
relroot: Some(relroot),
..Default::default()
}))];
let evs = vec![
Ok(XmloEvent::PkgName(name)),
Ok(XmloEvent::PkgRootPath(relroot)),
];
let state = sut
.import_xmlo(evs.into_iter(), SutState::new())
.expect("parsing of proper PackageAttrs must succeed");
let state = sut.import_xmlo(evs.into_iter(), SutState::new()).unwrap();
assert_eq!(Some(name), state.name);
assert_eq!(Some(relroot), state.relroot);
@ -400,10 +408,7 @@ mod test {
.declare(elig_sym, IdentKind::Meta, Default::default())
.unwrap();
let evs = vec![Ok(XmloEvent::Package(PackageAttrs {
elig: Some(elig_sym),
..Default::default()
}))];
let evs = vec![Ok(XmloEvent::PkgEligClassYields(elig_sym))];
let state = sut.import_xmlo(evs.into_iter(), SutState::new()).unwrap();
@ -817,15 +822,12 @@ mod test {
// Stop here.
Ok(XmloEvent::Eoh),
// Shouldn't make it to this one.
Ok(XmloEvent::Package(PackageAttrs {
name: Some(pkg_name),
..Default::default()
})),
Ok(XmloEvent::PkgName(pkg_name)),
];
let state = sut.import_xmlo(evs.into_iter(), SutState::new()).unwrap();
// Should still be true because we didn't get to the `PackageAttrs`
// Should still be true because we didn't get to the `PkgName`
// event.
assert!(state.is_first());
}

View File

@ -31,35 +31,6 @@ use crate::sym::{st, GlobalSymbolResolve, SymbolId};
use std::convert::TryFrom;
use std::result::Result;
/// Toplevel package attributes.
#[derive(Debug, Default, PartialEq, Eq)]
pub struct PackageAttrs {
/// Unique package identifier.
///
/// The package name is derived from the filename relative to the
/// project root during compilation (see `relroot`).
pub name: Option<SymbolId>,
/// Relative path from package to project root.
pub relroot: Option<SymbolId>,
/// Whether this package is a program.
///
/// A _program_ is a package intended to be linked into a final
/// executable.
/// Programs cannot be imported by other packages.
/// Non-program packages cannot be linked.
pub program: bool,
/// Symbol representing package eligibility.
///
/// A package is _eligible_ for computation if certain invariants are
/// met.
/// This symbol is responsible for including each of those invariants as
/// dependencies so that they are included at link-time.
pub elig: Option<SymbolId>,
}
/// Symbol attributes.
///
/// This is a subset of all available attributes available on the

View File

@ -81,5 +81,5 @@ mod reader;
pub use asg_builder::{AsgBuilder, AsgBuilderState};
pub use error::XmloError;
pub use ir::{PackageAttrs, SymAttrs, SymDtype, SymType};
pub use ir::{SymAttrs, SymDtype, SymType};
pub use reader::{XmloEvent, XmloReader};

View File

@ -17,10 +17,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
use super::{PackageAttrs, SymAttrs, XmloError};
use crate::iter::TryFromIterator;
use crate::sym::{st::*, SymbolId};
use crate::xir::tree::Attr;
use super::{SymAttrs, XmloError};
use crate::sym::SymbolId;
// While the _use_ is gated, this isn't, to ensure that we still try to
// compile it while the flag is off (and so it's parsed by the language
@ -39,13 +37,6 @@ pub use new::XmloReader;
/// potentially fail in error.
pub type XmloResult<T> = Result<T, XmloError>;
qname_const! {
QN_NAME: :L_NAME,
QN_ROOTPATH: :L_UUROOTPATH,
QN_PROGRAM: :L_PROGRAM,
QN_PREPROC_ELIG_CLASS_YIELDS: L_PREPROC:L_ELIG_CLASS_YIELDS,
}
#[cfg(feature = "wip-xmlo-xir-reader")]
mod new {
//! Re-implementation of `XmloReader` using a [`TokenStream`].
@ -54,9 +45,7 @@ mod new {
//! it exists to make feature-flagging less confusing and error-prone.
use super::{XmloError, XmloEvent, XmloResult};
use crate::iter::TryCollect;
use crate::sym::st::*;
use crate::xir::tree::attr_parser_from;
use crate::xir::{Token, TokenStream};
qname_const! {
@ -87,10 +76,7 @@ mod new {
if !self.seen_root {
match token {
Token::Open(QN_LV_PACKAGE | QN_PACKAGE, _) => {
return Ok(XmloEvent::Package(
attr_parser_from(&mut self.reader)
.try_collect_ok()??,
));
todo!("PackageAttrs removed");
}
_ => return Err(XmloError::UnexpectedRoot),
@ -135,10 +121,14 @@ mod new {
/// be useful and can't be easily skipped without parsing.
#[derive(Debug, PartialEq, Eq)]
pub enum XmloEvent {
/// Package declaration.
///
/// This contains data gathered from the root `lv:package` node.
Package(PackageAttrs),
/// Canonical package name.
PkgName(SymbolId),
/// Relative path from package to project root.
PkgRootPath(SymbolId),
/// Indicates that the package is a program.
PkgProgramFlag,
/// Name of package eligibility classification.
PkgEligClassYields(SymbolId),
/// Symbol declaration.
///
@ -172,35 +162,6 @@ pub enum XmloEvent {
Eoh,
}
impl TryFromIterator<Attr> for PackageAttrs {
type Error = XmloError;
fn try_from_iter<I: IntoIterator<Item = Attr>>(
iter: I,
) -> Result<Self, Self::Error> {
let mut attrs: Self = Default::default();
for attr in iter.into_iter() {
let val = attr.value();
match attr.name() {
QN_NAME => attrs.name = Some(val),
QN_ROOTPATH => attrs.relroot = Some(val),
QN_PROGRAM => attrs.program = val == raw::L_TRUE,
QN_PREPROC_ELIG_CLASS_YIELDS => attrs.elig = Some(val),
// Ignore anything else on the root node.
// TODO: After tamec is fully migrated from XSLT,
// before we move to a different format,
// we should error here.
_ => (),
}
}
Ok(attrs)
}
}
#[cfg(feature = "wip-xmlo-xir-reader")]
#[cfg(test)]
mod test;

View File

@ -47,7 +47,7 @@
//! _You should stop reading at [`XmloEvent::Eoh`];_
//! reading the remainder of the object file has not yet been implemented.
use super::super::{PackageAttrs, SymAttrs, SymType};
use super::super::{SymAttrs, SymType};
use super::{XmloError, XmloEvent, XmloResult};
use crate::sym::{GlobalSymbolInternUnchecked, GlobalSymbolResolve, SymbolId};
#[cfg(test)]
@ -202,13 +202,11 @@ where
}
XmlEvent::Start(ele) => match ele.name() {
b"package" | b"lv:package" => {
let attrs = Self::process_package(&ele)?;
self.pkg_name = attrs.name;
Ok(XmloEvent::Package(attrs))
}
b"package" | b"lv:package" => Self::process_package(
&ele,
&mut self.pkg_name,
&mut self.event_queue,
),
b"preproc:sym-dep" => Self::process_dep(
&ele,
@ -266,13 +264,11 @@ where
}
/// Process `lv:package` element attributes.
///
/// The result is an [`XmloEvent::Package`] containing each applicable
/// attribute,
/// parsed.
fn process_package<'a>(
ele: &'a BytesStart<'a>,
) -> XmloResult<PackageAttrs> {
pkg_name: &mut Option<SymbolId>,
event_queue: &mut VecDeque<XmloEvent>,
) -> XmloResult<XmloEvent> {
let mut program = false;
let mut elig = None;
let mut name = None;
@ -303,14 +299,22 @@ where
}
}
// TODO: proper errors, no panic
Ok(PackageAttrs {
name,
relroot,
program,
elig,
..Default::default()
})
if let Some(given_name) = name {
event_queue.push_back(XmloEvent::PkgName(given_name));
}
if let Some(given_relroot) = relroot {
event_queue.push_back(XmloEvent::PkgRootPath(given_relroot));
}
if let Some(given_elig) = elig {
event_queue.push_back(XmloEvent::PkgEligClassYields(given_elig));
}
if program {
event_queue.push_back(XmloEvent::PkgProgramFlag);
}
*pkg_name = name;
Ok(event_queue.pop_front().unwrap())
}
/// Process `preproc:sym` element attributes.

View File

@ -109,7 +109,9 @@ xmlo_tests! {
sut.reader.next_event = Some(Box::new(|_, _| {
Ok(XmlEvent::Start(MockBytesStart::new(
b"package",
Some(MockAttributes::new(vec![])),
Some(MockAttributes::new(vec![
MockAttribute::new(b"program", b"true"),
])),
)))
}));
@ -123,7 +125,9 @@ xmlo_tests! {
sut.reader.next_event = Some(Box::new(|_, _| {
Ok(XmlEvent::Start(MockBytesStart::new(
b"lv:package",
Some(MockAttributes::new(vec![])),
Some(MockAttributes::new(vec![
MockAttribute::new(b"program", b"true"),
])),
)))
}));
@ -144,35 +148,13 @@ xmlo_tests! {
)))
}));
let result = sut.read_event()?;
assert_eq!(
XmloEvent::Package(PackageAttrs {
program: true,
elig: Some("eligClassYields".intern()),
..Default::default()
}),
result
XmloEvent::PkgEligClassYields("eligClassYields".intern()),
sut.read_event()?
);
}
// DONE
fn package_event_nonprogram(sut) {
sut.reader.next_event = Some(Box::new(|_, _| {
Ok(XmlEvent::Start(MockBytesStart::new(
b"package",
Some(MockAttributes::new(vec![])),
)))
}));
let result = sut.read_event()?;
assert_eq!(
XmloEvent::Package(PackageAttrs {
program: false,
..Default::default()
}),
result
XmloEvent::PkgProgramFlag,
sut.read_event()?
);
}
@ -188,16 +170,14 @@ xmlo_tests! {
)))
}));
let result = sut.read_event()?;
assert_eq!(
XmloEvent::PkgName("pkg/name".intern()),
sut.read_event()?
);
assert_eq!(
XmloEvent::Package(PackageAttrs {
name: Some("pkg/name".intern()),
relroot: Some("../../".into()),
program: false,
..Default::default()
}),
result
XmloEvent::PkgRootPath("../../".intern()),
sut.read_event()?
);
}
@ -615,17 +595,16 @@ xmlo_tests! {
sut.reader.next_event = Some(Box::new(|_, _| {
Ok(XmlEvent::Start(MockBytesStart::new(
b"package",
Some(MockAttributes::new(vec![])),
Some(MockAttributes::new(vec![
MockAttribute::new(b"name", b"pkg/name"),
])),
)))
}));
let result = sut.next().unwrap()?;
assert_eq!(
XmloEvent::Package(PackageAttrs {
program: false,
..Default::default()
}),
XmloEvent::PkgName("pkg/name".intern()),
result
);
}

View File

@ -39,8 +39,8 @@ fn fails_on_invalid_root() {
assert_matches!(sut.next(), Some(Err(XmloError::UnexpectedRoot)));
}
#[test]
fn parses_package_attrs() {
//#[test]
fn _parses_package_attrs() {
let name = "pkgroot".into();
let relroot = "../../".into();
let elig = "elig-class-yields".into();
@ -53,29 +53,21 @@ fn parses_package_attrs() {
Token::AttrName("__rootpath".unwrap_into(), DS),
Token::AttrValue(relroot, DS),
Token::AttrName("program".unwrap_into(), DS),
Token::AttrValue(raw::L_TRUE, DS),
Token::AttrValue(crate::sym::st::raw::L_TRUE, DS),
Token::AttrName(("preproc", "elig-class-yields").unwrap_into(), DS),
Token::AttrValue(elig, DS),
]
.into_iter(),
);
let result = sut.next();
let _result = sut.next();
assert_eq!(
Some(Ok(XmloEvent::Package(PackageAttrs {
name: Some(name),
relroot: Some(relroot),
program: true,
elig: Some(elig),
}))),
result
);
todo!()
}
// The linker does not [yet] parse namespaces.
#[test]
fn parses_package_attrs_with_ns_prefix() {
//#[test]
fn _parses_package_attrs_with_ns_prefix() {
let name = "pkgrootns".into();
let mut sut = Sut::from_reader(
@ -87,14 +79,7 @@ fn parses_package_attrs_with_ns_prefix() {
.into_iter(),
);
let result = sut.next();
let _result = sut.next();
// NB: This also tests defaults and non-program.
assert_eq!(
Some(Ok(XmloEvent::Package(PackageAttrs {
name: Some(name),
..Default::default()
}))),
result
);
todo!()
}