Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Commit d08b38e

Browse files
author
Hendrik van Antwerpen
committed
Rename concatenate to append_partial_path and add prepend_partial_path operation
1 parent b8d894b commit d08b38e

File tree

4 files changed

+86
-14
lines changed

4 files changed

+86
-14
lines changed

stack-graphs/src/cycles.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,9 @@ impl JoiningCycleDetector {
260260
cyclic_path.resolve(graph, partials).unwrap();
261261
}
262262
cyclic_path.ensure_no_overlapping_variables(partials, path);
263-
cyclic_path.concatenate(graph, partials, path).unwrap();
263+
cyclic_path
264+
.append_partial_path(graph, partials, path)
265+
.unwrap();
264266
}
265267

266268
// process path if it is productive

stack-graphs/src/partial.rs

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@
2828
//! “import/export” points.
2929
//!
3030
//! At query time, we can then load in the _partial paths_ for each file, instead of the files'
31-
//! full stack graph structure. We can efficiently [concatenate][] partial paths together,
31+
//! full stack graph structure. We can efficiently [append][] or [prepend][] partial paths together,
3232
//! producing the original "full" path that represents a name binding.
3333
//!
34-
//! [concatenate]: struct.PartialPath.html#method.concatenate
34+
//! [append]: struct.PartialPath.html#method.append_partial_path
35+
//! [prepend]: struct.PartialPath.html#method.prepend_partial_path
3536
3637
use std::collections::VecDeque;
3738
use std::convert::TryFrom;
@@ -814,8 +815,8 @@ impl PartialSymbolStack {
814815
/// account any existing variable assignments, and updates those variable assignments with
815816
/// whatever constraints are necessary to produce a correct result.
816817
///
817-
/// Note that this operation is commutative. (Concatenating partial paths, defined in
818-
/// [`PartialPath::concatenate`][], is not.)
818+
/// Note that this operation is commutative. (Appending and prepending partial paths, defined in
819+
/// [`PartialPath::append_partial_path`][]/[`PartialPath::prepend_partial_path`][], is not.)
819820
pub fn unify(
820821
self,
821822
partials: &mut PartialPaths,
@@ -1242,8 +1243,8 @@ impl PartialScopeStack {
12421243
/// account any existing variable assignments, and updates those variable assignments with
12431244
/// whatever constraints are necessary to produce a correct result.
12441245
///
1245-
/// Note that this operation is commutative. (Concatenating partial paths, defined in
1246-
/// [`PartialPath::concatenate`][], is not.)
1246+
/// Note that this operation is commutative. (Appending and prepending partial paths, defined in
1247+
/// [`PartialPath::append_partial_path`][]/[`PartialPath::prepend_partial_path`][], is not.)
12471248
pub fn unify(
12481249
self,
12491250
partials: &mut PartialPaths,
@@ -2795,16 +2796,15 @@ impl Path {
27952796
// Extending partial paths with partial paths
27962797

27972798
impl PartialPath {
2798-
/// Attempts to concatenate two partial paths. If the postcondition of the “left” partial path
2799-
/// is not compatible with the precondition of the “right” path, we return an error describing
2800-
/// why.
2799+
/// Attempts to append a partial path to this one. If the postcondition of the “left” partial path
2800+
/// is not compatible with the precondition of the “right” path, we return an error describing why.
28012801
///
28022802
/// If the left- and right-hand partial paths have any symbol or scope stack variables in
28032803
/// common, then we ensure that the variables bind to the same values on both sides. It's your
28042804
/// responsibility to update the two partial paths so that they have no variables in common, if
28052805
/// that's needed for your use case.
28062806
#[cfg_attr(not(feature = "copious-debugging"), allow(unused_variables))]
2807-
pub fn concatenate(
2807+
pub fn append_partial_path(
28082808
&mut self,
28092809
graph: &StackGraph,
28102810
partials: &mut PartialPaths,
@@ -2864,6 +2864,74 @@ impl PartialPath {
28642864
Ok(())
28652865
}
28662866

2867+
/// Attempts to prepend a partial path to this one. If the postcondition of the “left” partial path
2868+
/// is not compatible with the precondition of the “right” path, we return an error describing why.
2869+
///
2870+
/// If the left- and right-hand partial paths have any symbol or scope stack variables in
2871+
/// common, then we ensure that the variables bind to the same values on both sides. It's your
2872+
/// responsibility to update the two partial paths so that they have no variables in common, if
2873+
/// that's needed for your use case.
2874+
#[cfg_attr(not(feature = "copious-debugging"), allow(unused_variables))]
2875+
pub fn prepend_partial_path(
2876+
&mut self,
2877+
graph: &StackGraph,
2878+
partials: &mut PartialPaths,
2879+
lhs: &PartialPath,
2880+
) -> Result<(), PathResolutionError> {
2881+
let rhs = self;
2882+
2883+
#[cfg_attr(not(feature = "copious-debugging"), allow(unused_mut))]
2884+
let mut join = Self::compute_join(graph, partials, lhs, rhs)?;
2885+
#[cfg(feature = "copious-debugging")]
2886+
{
2887+
let unified_symbol_stack = join
2888+
.unified_symbol_stack
2889+
.display(graph, partials)
2890+
.to_string();
2891+
let unified_scope_stack = join
2892+
.unified_scope_stack
2893+
.display(graph, partials)
2894+
.to_string();
2895+
let symbol_bindings = join.symbol_bindings.display(graph, partials).to_string();
2896+
let scope_bindings = join.scope_bindings.display(graph, partials).to_string();
2897+
copious_debugging!(
2898+
" via <{}> ({}) {} {}",
2899+
unified_symbol_stack,
2900+
unified_scope_stack,
2901+
symbol_bindings,
2902+
scope_bindings,
2903+
);
2904+
}
2905+
2906+
rhs.symbol_stack_precondition = lhs.symbol_stack_precondition.apply_partial_bindings(
2907+
partials,
2908+
&join.symbol_bindings,
2909+
&join.scope_bindings,
2910+
)?;
2911+
rhs.symbol_stack_postcondition = rhs.symbol_stack_postcondition.apply_partial_bindings(
2912+
partials,
2913+
&join.symbol_bindings,
2914+
&join.scope_bindings,
2915+
)?;
2916+
2917+
rhs.scope_stack_precondition = lhs
2918+
.scope_stack_precondition
2919+
.apply_partial_bindings(partials, &join.scope_bindings)?;
2920+
rhs.scope_stack_postcondition = rhs
2921+
.scope_stack_postcondition
2922+
.apply_partial_bindings(partials, &join.scope_bindings)?;
2923+
2924+
let mut edges = lhs.edges;
2925+
while let Some(edge) = edges.pop_back(partials) {
2926+
rhs.edges.push_front(partials, edge);
2927+
}
2928+
rhs.start_node = lhs.start_node;
2929+
2930+
rhs.resolve(graph, partials)?;
2931+
2932+
Ok(())
2933+
}
2934+
28672935
/// Compute the bindings to join to partial paths. It is the caller's responsibility
28682936
/// to ensure non-overlapping variables, if that is required.
28692937
fn compute_join(

stack-graphs/src/stitching.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,9 @@ impl ForwardPartialPathStitcher {
915915
// partial path, just skip the extension — it's not a fatal error.
916916
#[cfg_attr(not(feature = "copious-debugging"), allow(unused_variables))]
917917
{
918-
if let Err(err) = new_partial_path.concatenate(graph, partials, &extension_path) {
918+
if let Err(err) =
919+
new_partial_path.append_partial_path(graph, partials, &extension_path)
920+
{
919921
copious_debugging!(" is invalid: {:?}", err);
920922
continue;
921923
}

stack-graphs/tests/it/partial.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ fn can_create_partial_path_from_node() {
514514
}
515515

516516
#[test]
517-
fn can_concatenate_partial_paths() -> Result<(), PathResolutionError> {
517+
fn can_append_partial_paths() -> Result<(), PathResolutionError> {
518518
let mut graph = StackGraph::new();
519519
let file = graph.add_file("test").expect("");
520520

@@ -568,7 +568,7 @@ fn can_concatenate_partial_paths() -> Result<(), PathResolutionError> {
568568
let mut r = create_partial_path_and_edges(&mut g, &mut ps, right).expect("");
569569

570570
r.ensure_no_overlapping_variables(&mut ps, &l);
571-
l.concatenate(&g, &mut ps, &r)?;
571+
l.append_partial_path(&g, &mut ps, &r)?;
572572
let actual = l.display(&g, &mut ps).to_string();
573573
assert_eq!(actual, expected);
574574

0 commit comments

Comments
 (0)