tamer: asg::graph::visit::TreeWalkRel: New token type

This introduces a `Token` in place of the original tuple for
`TreePreOrderDfs` so that it can be used as input to a parser that will
lower into XIRF.

This requires that various things be describable (using `Display`), which
this also adds.  This is an example of where the parsing framework itself
enforces system observability by ensuring that every part of the system can
describe its state.

DEV-13708
main
Mike Gerwitz 2023-02-16 13:59:48 -05:00
parent bc8586e4b3
commit a5a5a99dbd
4 changed files with 78 additions and 6 deletions

View File

@ -384,6 +384,20 @@ pub trait ObjectKind = Into<Object> where Object: Into<Self> + AsRef<Self>;
#[derive(Debug)]
pub struct ObjectIndex<O: ObjectKind>(NodeIndex, Span, PhantomData<O>);
impl<O: ObjectKind + ObjectRelatable> Display for ObjectIndex<O> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let Self(ni, _, _) = self;
write!(f, "ObjectIndex<{}>({ni:?})", O::rel_ty())
}
}
impl Display for ObjectIndex<Object> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let Self(ni, _, _) = self;
write!(f, "ObjectIndex<Object>({ni:?})")
}
}
// Deriving this trait seems to silently fail at the time of writing
// (2022-12-22, Rust 1.68.0-nightly).
impl<O: ObjectKind> Clone for ObjectIndex<O> {

View File

@ -20,8 +20,8 @@
//!
//! See (parent module)[super] for more information.
use std::fmt::Display;
use crate::{f::Functor, span::Span};
use super::{Expr, Ident, Object, ObjectIndex, ObjectKind, Pkg, Root};
/// Object types corresponding to variants in [`Object`].
@ -41,6 +41,14 @@ pub enum ObjectRelTy {
Expr,
}
impl Display for ObjectRelTy {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
// At the time of writing,
// this happens to be sufficient.
std::fmt::Debug::fmt(self, f)
}
}
/// A dynamic relationship (edge) from one object to another before it has
/// been narrowed.
///
@ -164,6 +172,14 @@ impl<T, U> Functor<T, U> for DynObjectRel<T> {
}
}
impl<T: Display> Display for DynObjectRel<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self((from_ty, to_ty), x, _) = self;
write!(f, "dynamic edge {from_ty}->{to_ty} with {x}",)
}
}
/// Indicate that an [`ObjectKind`] `Self` can be related to
/// [`ObjectKind`] `OB` by creating an edge from `Self` to `OB`.
///

View File

@ -23,8 +23,13 @@
//! reconstruct a source representation of the program from the current
//! state of [`Asg`].
use std::fmt::Display;
use super::{object::DynObjectRel, Asg, Object, ObjectIndex};
use crate::span::UNKNOWN_SPAN;
use crate::{
parse::Token,
span::{Span, UNKNOWN_SPAN},
};
// Re-export so that users of this API can avoid an awkward import from a
// completely different module hierarchy.
@ -203,7 +208,7 @@ impl<'a> TreePreOrderDfs<'a> {
}
impl<'a> Iterator for TreePreOrderDfs<'a> {
type Item = (DynObjectRel, Depth);
type Item = TreeWalkRel;
/// Produce the next [`ObjectIndex`] from the traversal in pre-order.
///
@ -225,7 +230,43 @@ impl<'a> Iterator for TreePreOrderDfs<'a> {
self.push_edges_of(*rel.target(), depth);
}
Some((rel, depth))
Some(TreeWalkRel(rel, depth))
}
}
#[derive(Debug, PartialEq)]
pub struct TreeWalkRel(pub DynObjectRel, pub Depth);
impl Display for TreeWalkRel {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self(dyn_rel, depth) => {
write!(f, "{dyn_rel} at tree depth {depth}")
}
}
}
}
impl Token for TreeWalkRel {
fn ir_name() -> &'static str {
"ASG ontological tree pre-order DFS walk"
}
/// Token context span.
///
/// Note that this is _not_ the same span as other token
/// implementations,
/// and may default to [`UNKNOWN_SPAN`].
/// This is because the token is derived from the relationships on the
/// graph,
/// while concrete spans are stored on the objects that those
/// relationships reference.
/// This will return a potentially-useful span only if the inner
/// [`DynObjectRel::ctx_span`] does.
fn span(&self) -> Span {
match self {
Self(dyn_rel, _) => dyn_rel.ctx_span().unwrap_or(UNKNOWN_SPAN),
}
}
}

View File

@ -99,7 +99,8 @@ fn traverses_ontological_tree() {
(d(Ty::Pkg, Ty::Ident, S9, None ), Depth(2)),
(d(Ty::Ident, Ty::Expr, m(S8, S10), None ), Depth(3)),
],
sut.map(|(rel, depth)| (rel.map(|oi| oi.resolve(&asg).span()), depth))
.collect::<Vec<_>>(),
sut.map(|TreeWalkRel(rel, depth)| {
(rel.map(|oi| oi.resolve(&asg).span()), depth)
}).collect::<Vec<_>>(),
);
}