tamer: tamec: Extract package parsing into pipeline module

The previous commit extracted xmlo loading, because that will be a common
operation between `tamec` and `tameld`.  This extracts parsing, which will
only used by `tamec` for now, though components of the pipeline are similar
to xmlo loading.

Not only does it need to be removed from `tamec` and better abstracted, but
the intent now is to get all of these things into one place so that the
patterns are obviated and a better abstraction can be created to remove all
of this boilerplate and type complexity.

Furthermore, xmlo loading needs to use reporting and recovery, so having
`parse_package_xml` here will help show how to make that happen easily.  I'm
pleased that it ended up being trivial to extract error reporting from the
lowering pipeline as a simple (mutable) callback.  I'm not pleased about
the side-effects, but, this works well for now given how the system works
today.

DEV-13162
Mike Gerwitz 2023-05-26 11:45:27 -04:00
parent 57a805b495
commit 61753d77aa
2 changed files with 70 additions and 56 deletions

View File

@ -39,26 +39,21 @@ use std::{
path::Path,
};
use tamer::{
asg::{
air::{Air, AirAggregate, AirAggregateCtx},
AsgError, DefaultAsg,
},
asg::{air::Air, AsgError, DefaultAsg},
diagnose::{
AnnotatedSpan, Diagnostic, FsSpanResolver, Reporter, VisualReporter,
},
nir::{
InterpError, InterpolateNir, Nir, NirToAir, NirToAirError,
TplShortDesugar, XirfToNir, XirfToNirError,
},
nir::{InterpError, Nir, NirToAirError, XirfToNirError},
parse::{
lowerable, FinalizeError, Lower, ParseError, ParsedObject, Token,
UnknownToken,
},
pipeline::parse_package_xml,
xir::{
self,
flat::{RefinedText, XirToXirf, XirToXirfError, XirfToken},
flat::{RefinedText, XirToXirfError, XirfToken},
reader::XmlXirReader,
DefaultEscaper, Error as XirError, Token as XirToken,
DefaultEscaper, Token as XirToken,
},
};
@ -127,18 +122,14 @@ fn compile<R: Reporter>(
let mut ebuf = String::new();
fn report_err<R: Reporter>(
e: &RecoverableError,
reporter: &mut R,
ebuf: &mut String,
) -> Result<(), UnrecoverableError> {
let report_err = |e: &RecoverableError| {
// See below note about buffering.
ebuf.clear();
writeln!(ebuf, "{}", reporter.render(e))?;
println!("{ebuf}");
Ok(())
}
Ok::<_, UnrecoverableError>(())
};
// TODO: We're just echoing back out XIR,
// which will be the same sans some formatting.
@ -151,40 +142,15 @@ fn compile<R: Reporter>(
{
|_| ()
}
}))
.map(|result| result.map_err(RecoverableError::from));
}));
// TODO: Determine a good default capacity once we have this populated
// and can come up with some heuristics.
let air_ctx: AirAggregateCtx = DefaultAsg::with_capacity(1024, 2048).into();
let (_, air_ctx) = Lower::<
ParsedObject<UnknownToken, XirToken, XirError>,
XirToXirf<64, RefinedText>,
_,
>::lower::<_, UnrecoverableError>(src, |toks| {
Lower::<XirToXirf<64, RefinedText>, XirfToNir, _>::lower(toks, |nir| {
Lower::<XirfToNir, TplShortDesugar, _>::lower(nir, |nir| {
Lower::<TplShortDesugar, InterpolateNir, _>::lower(nir, |nir| {
Lower::<InterpolateNir, NirToAir, _>::lower(nir, |air| {
Lower::<NirToAir, AirAggregate, _>::lower_with_context(
air,
air_ctx,
|end| {
end.fold(Ok(()), |x, result| match result {
Ok(_) => x,
Err(e) => {
report_err(&e, reporter, &mut ebuf)?;
x
}
})
},
)
})
})
})
})
})?;
let air_ctx = parse_package_xml(
src,
DefaultAsg::with_capacity(1024, 2048).into(),
report_err,
)?;
match reporter.has_errors() {
false => {

View File

@ -43,13 +43,14 @@
use crate::{
asg::air::{AirAggregate, AirAggregateCtx},
diagnose::Diagnostic,
nir::{InterpolateNir, NirToAir, TplShortDesugar, XirfToNir},
obj::xmlo::{XmloAirContext, XmloReader, XmloToAir, XmloToken},
parse::{
FinalizeError, FromParseError, Lower, LowerSource, ParseError, Parsed,
ParsedObject, UnknownToken,
},
xir::{
flat::{PartialXirToXirf, Text},
flat::{PartialXirToXirf, RefinedText, Text, XirToXirf},
Error as XirError, Token as XirToken,
},
};
@ -63,13 +64,13 @@ use crate::{
/// TODO: To re-use this in `tamec` we want to be able to ignore fragments.
///
/// TODO: More documentation once this has been further cleaned up.
pub fn load_xmlo<EO: Diagnostic + PartialEq>(
pub fn load_xmlo<EU: Diagnostic + PartialEq>(
src: impl LowerSource<UnknownToken, XirToken, XirError>,
air_ctx: AirAggregateCtx,
xmlo_ctx: XmloAirContext,
) -> Result<(AirAggregateCtx, XmloAirContext), EO>
) -> Result<(AirAggregateCtx, XmloAirContext), EU>
where
EO: From<ParseError<UnknownToken, XirError>>
EU: From<ParseError<UnknownToken, XirError>>
+ FromParseError<PartialXirToXirf<4, Text>>
+ FromParseError<XmloReader>
+ FromParseError<XmloToAir>
@ -81,8 +82,8 @@ where
Lower::<
ParsedObject<UnknownToken, XirToken, XirError>,
PartialXirToXirf<4, Text>,
EO,
>::lower(&mut src.map(|result| result.map_err(EO::from)), |toks| {
EU,
>::lower(&mut src.map(|result| result.map_err(EU::from)), |toks| {
Lower::<PartialXirToXirf<4, Text>, XmloReader, _>::lower(toks, |xmlo| {
let mut iter = xmlo.scan(false, |st, rtok| match st {
true => None,
@ -106,13 +107,60 @@ where
let _ = result?;
}
Ok::<_, EO>(())
Ok::<_, EU>(())
},
)?;
Ok::<_, EO>(air_ctx)
Ok::<_, EU>(air_ctx)
},
)
})
})
}
/// Parse a source package into the [ASG](crate::asg) using TAME's XML
/// source language.
///
/// TODO: More documentation once this has been further cleaned up.
pub fn parse_package_xml<ER: Diagnostic, EU: Diagnostic>(
src: impl LowerSource<UnknownToken, XirToken, XirError>,
air_ctx: AirAggregateCtx,
mut report_err: impl FnMut(&ER) -> Result<(), EU>,
) -> Result<AirAggregateCtx, EU>
where
ER: From<ParseError<UnknownToken, XirError>>
+ FromParseError<XirToXirf<64, Text>>
+ FromParseError<XirfToNir>
+ FromParseError<TplShortDesugar>
+ FromParseError<InterpolateNir>
+ FromParseError<NirToAir>
+ FromParseError<AirAggregate>,
EU: From<FinalizeError>,
{
#[rustfmt::skip] // better visualize the structure despite the line length
let (_, air_ctx) = Lower::<
ParsedObject<UnknownToken, XirToken, XirError>,
XirToXirf<64, RefinedText>,
_,
>::lower::<_, EU>(&mut src.map(|result| result.map_err(ER::from)), |toks| {
Lower::<XirToXirf<64, RefinedText>, XirfToNir, _>::lower(toks, |nir| {
Lower::<XirfToNir, TplShortDesugar, _>::lower(nir, |nir| {
Lower::<TplShortDesugar, InterpolateNir, _>::lower(nir, |nir| {
Lower::<InterpolateNir, NirToAir, _>::lower(nir, |air| {
Lower::<NirToAir, AirAggregate, _>::lower_with_context(air, air_ctx, |end| {
end.fold(Ok(()), |x, result| match result {
Ok(_) => x,
Err(e) => {
report_err(&e)?;
x
}
})
})
})
})
})
})
})?;
Ok(air_ctx)
}