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

Commit 3a02ff5

Browse files
author
Hendrik van Antwerpen
authored
Merge pull request #286 from github/unified-path-finding
Unify path finding and path stitching
2 parents 730fd89 + e11f004 commit 3a02ff5

20 files changed

+983
-568
lines changed

stack-graphs/CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## Unreleased
9+
10+
### Changed
11+
12+
- The `Appendable` trait has been simplified. Its `Ctx` type parameter is gone, in favor of a separate trait `ToAppendable` that is used to find appendables for a handle. The type itself moved from the `cycles` to the `stitching` module.
13+
- The `ForwardPartialPathStitcher` has been generalized so that it can be used to build paths from a database or from graph edges. It now takes a type parameter indicating the type of candidates it uses. Instead of a `Database` instance, it expects a value that implements the `Candidates` and `ToAppendable` traits. The `ForwardPartialPathStitcher::process_next_phase` expects an additional `extend_until` closure that controls whether the extended paths are considered for further extension or not (using `|_,_,_| true` retains old behavior).
14+
15+
### Fixed
16+
17+
- A panic in `AppendingCycleDetector::is_cyclic` that occurred because variables were not always renamed before attempting to concatenate partial paths.
18+
- An inverted condition in `PartialSymbolStack::has_variable` that resulted in incorrect return values.
19+
- A bug in `Partial*Stack::unify` that resulted in recursive bindings (`$1 => SYMBOL,$1`). Any unification that would result in a recursive binding now returns an error.
20+
- A bug in `PartialPath::append` that would incorrectly allow appending edges that added symbols to the precondition symbol stack, even if that stack had no variable.
21+
22+
### Removed
23+
24+
- The `ForwardPartialPathStitcher::from_nodes` function has been removed. Callers are responsible for creating the right initial paths, which can be done using `PartialPath::from_node`.
25+
- The `PartialPaths::find_minimal_partial_path_set_in_file` method has been removed in favor of `ForwardPartialPathStitcher::find_minimal_partial_path_set_in_file`.
26+
- The `PartialPaths::find_all_complete_paths` method has been removed in favor of `ForwardPartialPathStitcher::find_all_complete_partial_paths` using `GraphEdges(None)` for the `db` argument.
27+
- The `OwnedOrDatabasePath` has been removed because it was obsolete with the changes to `Appendable`.
28+
829
## v0.11.0 -- 2023-06-08
930

1031
### Added

stack-graphs/include/stack-graphs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ void sg_partial_path_database_mark_local_nodes(struct sg_partial_path_database *
801801
struct sg_node_handle_set sg_partial_path_database_local_nodes(const struct sg_partial_path_database *db);
802802

803803
// Creates a new forward partial path stitcher that is "seeded" with a set of starting stack graph
804-
// nodes.
804+
// nodes. The path stitcher will be set up to find complete paths only.
805805
struct sg_forward_partial_path_stitcher *sg_forward_partial_path_stitcher_from_nodes(const struct sg_stack_graph *graph,
806806
struct sg_partial_path_arena *partials,
807807
size_t count,

stack-graphs/src/c.rs

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use crate::partial::PartialScopedSymbol;
3030
use crate::partial::PartialSymbolStack;
3131
use crate::stitching::Database;
3232
use crate::stitching::ForwardPartialPathStitcher;
33+
use crate::stitching::GraphEdges;
3334
use crate::CancellationError;
3435
use crate::CancellationFlag;
3536

@@ -1179,17 +1180,18 @@ pub extern "C" fn sg_partial_path_arena_find_partial_paths_in_file(
11791180
let partial_path_list = unsafe { &mut *partial_path_list };
11801181
let cancellation_flag: Option<&AtomicUsize> =
11811182
unsafe { std::mem::transmute(cancellation_flag.as_ref()) };
1182-
partials
1183-
.find_minimal_partial_path_set_in_file(
1184-
graph,
1185-
file,
1186-
&AtomicUsizeCancellationFlag(cancellation_flag),
1187-
|_graph, partials, mut path| {
1188-
path.ensure_both_directions(partials);
1189-
partial_path_list.partial_paths.push(path);
1190-
},
1191-
)
1192-
.into()
1183+
ForwardPartialPathStitcher::find_minimal_partial_path_set_in_file(
1184+
graph,
1185+
partials,
1186+
file,
1187+
&AtomicUsizeCancellationFlag(cancellation_flag),
1188+
|_graph, partials, path| {
1189+
let mut path = path.clone();
1190+
path.ensure_both_directions(partials);
1191+
partial_path_list.partial_paths.push(path);
1192+
},
1193+
)
1194+
.into()
11931195
}
11941196

11951197
/// Finds all complete paths reachable from a set of starting nodes, placing the result into the
@@ -1215,18 +1217,19 @@ pub extern "C" fn sg_partial_path_arena_find_all_complete_paths(
12151217
let path_list = unsafe { &mut *path_list };
12161218
let cancellation_flag: Option<&AtomicUsize> =
12171219
unsafe { std::mem::transmute(cancellation_flag.as_ref()) };
1218-
partials
1219-
.find_all_complete_paths(
1220-
graph,
1221-
starting_nodes.iter().copied().map(sg_node_handle::into),
1222-
&AtomicUsizeCancellationFlag(cancellation_flag),
1223-
|graph, _partials, path| {
1224-
if path.is_complete(graph) {
1225-
path_list.partial_paths.push(path);
1226-
}
1227-
},
1228-
)
1229-
.into()
1220+
ForwardPartialPathStitcher::find_all_complete_partial_paths(
1221+
graph,
1222+
partials,
1223+
&mut GraphEdges(None),
1224+
starting_nodes.iter().copied().map(sg_node_handle::into),
1225+
&AtomicUsizeCancellationFlag(cancellation_flag),
1226+
|graph, _partials, path| {
1227+
if path.is_complete(graph) {
1228+
path_list.partial_paths.push(path.clone());
1229+
}
1230+
},
1231+
)
1232+
.into()
12301233
}
12311234

12321235
/// A handle to a partial path in a partial path database. A zero handle represents a missing
@@ -1404,12 +1407,12 @@ struct InternalForwardPartialPathStitcher {
14041407
previous_phase_partial_paths: *const PartialPath,
14051408
previous_phase_partial_paths_length: usize,
14061409
is_complete: bool,
1407-
stitcher: ForwardPartialPathStitcher,
1410+
stitcher: ForwardPartialPathStitcher<Handle<PartialPath>>,
14081411
}
14091412

14101413
impl InternalForwardPartialPathStitcher {
14111414
fn new(
1412-
stitcher: ForwardPartialPathStitcher,
1415+
stitcher: ForwardPartialPathStitcher<Handle<PartialPath>>,
14131416
partials: &mut PartialPaths,
14141417
) -> InternalForwardPartialPathStitcher {
14151418
let mut this = InternalForwardPartialPathStitcher {
@@ -1434,7 +1437,7 @@ impl InternalForwardPartialPathStitcher {
14341437
}
14351438

14361439
/// Creates a new forward partial path stitcher that is "seeded" with a set of starting stack graph
1437-
/// nodes.
1440+
/// nodes. The path stitcher will be set up to find complete paths only.
14381441
#[no_mangle]
14391442
pub extern "C" fn sg_forward_partial_path_stitcher_from_nodes(
14401443
graph: *const sg_stack_graph,
@@ -1445,11 +1448,17 @@ pub extern "C" fn sg_forward_partial_path_stitcher_from_nodes(
14451448
let graph = unsafe { &(*graph).inner };
14461449
let partials = unsafe { &mut (*partials).inner };
14471450
let starting_nodes = unsafe { std::slice::from_raw_parts(starting_nodes, count) };
1448-
let stitcher = ForwardPartialPathStitcher::from_nodes(
1449-
graph,
1450-
partials,
1451-
starting_nodes.iter().copied().map(sg_node_handle::into),
1452-
);
1451+
let initial_paths = starting_nodes
1452+
.iter()
1453+
.copied()
1454+
.map(sg_node_handle::into)
1455+
.map(|n| {
1456+
let mut p = PartialPath::from_node(graph, partials, n);
1457+
p.eliminate_precondition_stack_variables(partials);
1458+
p
1459+
})
1460+
.collect::<Vec<_>>();
1461+
let stitcher = ForwardPartialPathStitcher::from_partial_paths(graph, partials, initial_paths);
14531462
Box::into_raw(Box::new(InternalForwardPartialPathStitcher::new(
14541463
stitcher, partials,
14551464
))) as *mut _
@@ -1526,7 +1535,9 @@ pub extern "C" fn sg_forward_partial_path_stitcher_process_next_phase(
15261535
let partials = unsafe { &mut (*partials).inner };
15271536
let db = unsafe { &mut (*db).inner };
15281537
let stitcher = unsafe { &mut *(stitcher as *mut InternalForwardPartialPathStitcher) };
1529-
stitcher.stitcher.process_next_phase(graph, partials, db);
1538+
stitcher
1539+
.stitcher
1540+
.process_next_phase(graph, partials, db, |_, _, _| true);
15301541
stitcher.update_previous_phase_partial_paths(partials);
15311542
}
15321543

0 commit comments

Comments
 (0)