tamer: asg::graph::xmli::AsgTreeToXirf::parse_token: Cleanup

This tidies this method up into a decent state that I'm fairly content
with.  This goes to emphasize my dislike of returns, which muddies control
flow and makes the code more difficult to read at a glance, which increase
the likelihood of logic bugs.

`match` statements in tail position, on the other hand, are very clear, and
less cognitively burdensome since you can see each individual code path at a
glance.

DEV-13708
main
Mike Gerwitz 2023-02-24 13:54:25 -05:00
parent e3e50c38c7
commit 506d3e9d11
1 changed files with 62 additions and 36 deletions

View File

@ -82,42 +82,28 @@ impl<'a> ParseState for AsgTreeToXirf<'a> {
fn parse_token(
self,
tok: Self::Token,
TreeWalkRel(dyn_rel, depth): Self::Token,
TreeContext(toks, asg): &mut TreeContext,
) -> TransitionResult<Self::Super> {
if let Some(emit) = toks.pop() {
return Transition(self).ok(emit).with_lookahead(tok);
}
match (toks.pop(), depth) {
// Empty the token stack before processing any further.
// Note that we must yield the token as lookahead to ensure that
// we do eventually process it.
(Some(emit), _) => Transition(self)
.ok(emit)
.with_lookahead(TreeWalkRel(dyn_rel, depth)),
let tok_span = tok.span();
let TreeWalkRel(dyn_rel, depth) = tok;
// Used by `eof_tok` only to empty the token stack,
// which we're now done with.
// We consume the token by not yielding any lookahead.
(None, Depth(0)) => Transition(self).incomplete(),
if depth == Depth(0) {
return Transition(self).incomplete();
}
// TODO: Verify that the binary does not perform unnecessary
// resolution in branches that do not utilize the source.
let paired_rel = dyn_rel.resolve_oi_pairs(asg);
let xirf_tok = match paired_rel.target() {
Object::Pkg((pkg, _)) => emit_package(toks, pkg, depth),
// Identifiers will be considered in context;
// pass over it for now.
Object::Ident(..) => None,
Object::Expr((expr, _)) => {
emit_expr(toks, expr, paired_rel.source(), depth)
// The stack is empty,
// so proceed with processing the provided relation.
(None, depth) => {
derive_src(toks, asg, dyn_rel, depth).transition(self)
}
Object::Root(..) => diagnostic_unreachable!(
vec![tok_span.error("unexpected Root")],
"tree walk is not expected to emit Root",
),
};
xirf_tok.transition(self)
}
}
fn is_accepting(&self, TreeContext(toks, _): &Self::Context) -> bool {
@ -146,6 +132,51 @@ impl<'a> ParseState for AsgTreeToXirf<'a> {
}
}
/// Size of the token stack.
///
/// See [`TokenStack`] for more information.
const TOK_STACK_SIZE: usize = 8;
/// Given a [`DynObjectRel`],
/// derive a legacy TAME representation that will faithfully represent an
/// equivalent program when compiled by the XSLT-based TAME compiler.
///
/// The [`TokenStack`] may be used to pre-generate [XIRF](Xirf) to be
/// yielded on subsequent iterations rather than having to introduce
/// [`AsgTreeToXirf`] states for each individual token.
/// Adjust [`TOK_STACK_SIZE`] as necessary.
///
/// The provided [`Depth`] represent the depth of the tree at the position
/// of the provided [`DynObjectRel`].
/// See [`TreeWalkRel`] for more information.
fn derive_src(
toks: &mut TokenStack,
asg: &Asg,
dyn_rel: DynObjectRel,
depth: Depth,
) -> Option<Xirf> {
// TODO: Verify that the binary does not perform unnecessary
// resolution in branches that do not utilize the source.
let paired_rel = dyn_rel.resolve_oi_pairs(asg);
match paired_rel.target() {
Object::Pkg((pkg, _)) => emit_package(toks, pkg, depth),
// Identifiers will be considered in context;
// pass over it for now.
Object::Ident(..) => None,
Object::Expr((expr, _)) => {
emit_expr(toks, expr, paired_rel.source(), depth)
}
Object::Root(..) => diagnostic_unreachable!(
vec![],
"tree walk is not expected to emit Root",
),
}
}
/// Emit tokens representing the root package element.
fn emit_package(
toks: &mut TokenStack,
@ -252,11 +283,6 @@ impl<'a> From<&'a Asg> for TreeContext<'a> {
}
}
/// Size of the token stack.
///
/// See [`TokenStack`] for more information.
const TOK_STACK_SIZE: usize = 8;
/// Token stack to hold generated tokens between [`AsgTreeToXirf`]
/// iterations.
///