tame/tamer/src/asg/graph/visit/test.rs

107 lines
3.4 KiB
Rust

// ASG IR
//
// Copyright (C) 2014-2023 Ryan Specialty, LLC.
//
// This file is part of TAME.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// 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::*;
use crate::{
asg::{
air::{Air, AirAggregate},
graph::object::ObjectRelTy,
ExprOp,
},
f::Functor,
parse::{util::SPair, ParseState},
span::{dummy::*, Span},
};
use std::fmt::Debug;
use Air::*;
fn asg_from_toks<I: IntoIterator<Item = Air>>(toks: I) -> Asg
where
I::IntoIter: Debug,
{
let mut parser = AirAggregate::parse(toks.into_iter());
assert!(parser.all(|x| x.is_ok()));
parser.finalize().unwrap().into_context()
}
// Note that this is an integration test beginning at AIR.
//
// We will construct a test ASG using the same subsystem as the user;
// we want to be sure that the traversal works as we expect it to in
// practice,
// since the system is fairly complex and failures are more likely
// to occur at integration points.
#[test]
fn traverses_ontological_tree() {
let id_a = SPair("expr_a".into(), S3);
let id_b = SPair("expr_b".into(), S9);
#[rustfmt::skip]
let toks = vec![
PkgOpen(S1),
ExprOpen(ExprOp::Sum, S2),
ExprIdent(id_a),
ExprOpen(ExprOp::Sum, S4),
ExprClose(S5),
ExprRef(SPair(id_b.symbol(), S6)),
ExprClose(S7),
ExprOpen(ExprOp::Sum, S8),
ExprIdent(id_b),
ExprClose(S10),
PkgClose(S11),
];
let asg = asg_from_toks(toks);
// From the above graph,
// we're going to traverse in such a way as to reconstruct the source
// tree.
let sut = tree_reconstruction(&asg);
// We need more concise expressions for the below table of values.
use ObjectRelTy as Ty;
let d = DynObjectRel::new;
let m = |a: Span, b: Span| a.merge(b).unwrap();
// Note that the `Depth` beings at 1 because the actual root of the
// graph is not emitted.
// Further note that the depth is the depth of the _path_,
// and so identifiers contribute to the depth even though the source
// language doesn't have such nesting.
#[rustfmt::skip]
assert_eq!(
vec![
(d(Ty::Root, Ty::Pkg, m(S1, S11), None ), Depth(1)),
(d(Ty::Pkg, Ty::Ident, S3, None ), Depth(2)),
(d(Ty::Ident, Ty::Expr, m(S2, S7), None ), Depth(3)),
(d(Ty::Expr, Ty::Expr, m(S4, S5), None ), Depth(4)),
(d(Ty::Expr, Ty::Ident, S9, Some(S6)), Depth(4)),
(d(Ty::Pkg, Ty::Ident, S9, None ), Depth(2)),
(d(Ty::Ident, Ty::Expr, m(S8, S10), None ), Depth(3)),
],
sut.map(|TreeWalkRel(rel, depth)| {
(rel.map(|oi| oi.resolve(&asg).span()), depth)
}).collect::<Vec<_>>(),
);
}