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-13708main
parent
bc8586e4b3
commit
a5a5a99dbd
|
@ -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> {
|
||||
|
|
|
@ -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`.
|
||||
///
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<_>>(),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue