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

Commit ce15f85

Browse files
author
Hendrik van Antwerpen
committed
Replace PartialPath::find_* with ForwardPartialPathStitcher::find_*
1 parent cf602ea commit ce15f85

17 files changed

+266
-330
lines changed

stack-graphs/src/assert.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ impl Assertion {
178178
let mut actual_paths = Vec::new();
179179
for reference in &references {
180180
let mut reference_paths = Vec::new();
181-
ForwardPartialPathStitcher::<Handle<PartialPath>>::find_all_complete_partial_paths(
181+
ForwardPartialPathStitcher::find_all_complete_partial_paths(
182182
graph,
183183
partials,
184184
db,

stack-graphs/src/c.rs

Lines changed: 29 additions & 24 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
@@ -1532,7 +1535,9 @@ pub extern "C" fn sg_forward_partial_path_stitcher_process_next_phase(
15321535
let partials = unsafe { &mut (*partials).inner };
15331536
let db = unsafe { &mut (*db).inner };
15341537
let stitcher = unsafe { &mut *(stitcher as *mut InternalForwardPartialPathStitcher) };
1535-
stitcher.stitcher.process_next_phase(graph, partials, db);
1538+
stitcher
1539+
.stitcher
1540+
.process_next_phase(graph, partials, db, |_, _, _| true);
15361541
stitcher.update_previous_phase_partial_paths(partials);
15371542
}
15381543

stack-graphs/src/cycles.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,10 @@ where
265265
let cyclic_path = maybe_cyclic_path
266266
.unwrap_or_else(|| PartialPath::from_node(graph, partials, end_node));
267267
cyclic_path.append_to(graph, partials, &mut prefix_path)?;
268-
if let Some(cyclicity) = prefix_path.is_cyclic(graph, partials) {
269-
cycles |= cyclicity;
268+
if prefix_path.edges.len() > 0 {
269+
if let Some(cyclicity) = prefix_path.is_cyclic(graph, partials) {
270+
cycles |= cyclicity;
271+
}
270272
}
271273
maybe_cyclic_path = Some(prefix_path);
272274
}

stack-graphs/src/partial.rs

Lines changed: 0 additions & 192 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
//!
3434
//! [concatenate]: struct.PartialPath.html#method.concatenate
3535
36-
use std::collections::VecDeque;
3736
use std::convert::TryFrom;
3837
use std::fmt::Display;
3938
use std::num::NonZeroU32;
@@ -46,21 +45,14 @@ use smallvec::SmallVec;
4645
use crate::arena::Deque;
4746
use crate::arena::DequeArena;
4847
use crate::arena::Handle;
49-
use crate::cycles::Appendables;
50-
use crate::cycles::AppendingCycleDetector;
5148
use crate::graph::Edge;
52-
use crate::graph::File;
5349
use crate::graph::Node;
5450
use crate::graph::NodeID;
5551
use crate::graph::StackGraph;
5652
use crate::graph::Symbol;
57-
use crate::paths::Extend;
5853
use crate::paths::PathResolutionError;
59-
use crate::stitching::GraphEdges;
6054
use crate::utils::cmp_option;
6155
use crate::utils::equals_option;
62-
use crate::CancellationError;
63-
use crate::CancellationFlag;
6456

6557
//-------------------------------------------------------------------------------------------------
6658
// Displaying stuff
@@ -2232,54 +2224,6 @@ impl PartialPath {
22322224

22332225
Ok(())
22342226
}
2235-
2236-
/// Attempts to extend one partial path as part of the partial-path-finding algorithm. If a file
2237-
/// is provided, only outgoing edges that belong to that file are used. When calling this function,
2238-
/// you are responsible for ensuring that `graph` already contains data for all of the possible edges
2239-
/// that we might want to extend `path` with.
2240-
///
2241-
/// The resulting extended partial paths will be added to `result`. We have you pass that in
2242-
/// as a parameter, instead of building it up ourselves, so that you have control over which
2243-
/// particular collection type to use, and so that you can reuse result collections across
2244-
/// multiple calls.
2245-
fn extend<R: Extend<(PartialPath, AppendingCycleDetector<Edge>)>>(
2246-
&self,
2247-
graph: &StackGraph,
2248-
partials: &mut PartialPaths,
2249-
file: Option<Handle<File>>,
2250-
edges: &mut Appendables<Edge>,
2251-
path_cycle_detector: AppendingCycleDetector<Edge>,
2252-
result: &mut R,
2253-
) {
2254-
let extensions = graph.outgoing_edges(self.end_node);
2255-
result.reserve(extensions.size_hint().0);
2256-
for extension in extensions {
2257-
copious_debugging!(
2258-
" -> with edge {} -> {}",
2259-
extension.source.display(graph),
2260-
extension.sink.display(graph)
2261-
);
2262-
if let Some(file) = file {
2263-
if !graph[extension.sink].is_in_file(file) {
2264-
copious_debugging!(" * outside file");
2265-
continue;
2266-
}
2267-
}
2268-
let mut new_path = self.clone();
2269-
// If there are errors adding this edge to the partial path, or resolving the resulting
2270-
// partial path, just skip the edge — it's not a fatal error.
2271-
if new_path.append(graph, partials, extension).is_err() {
2272-
copious_debugging!(" * invalid extension");
2273-
continue;
2274-
}
2275-
// We assume languages do not introduce similar paths (paths between the same nodes with
2276-
// equivalent pre- and postconditions), so we do not guard against that here. We may need
2277-
// to revisit that assumption in the future.
2278-
let mut new_cycle_detector = path_cycle_detector.clone();
2279-
new_cycle_detector.append(edges, extension);
2280-
result.push((new_path, new_cycle_detector));
2281-
}
2282-
}
22832227
}
22842228

22852229
impl Node {
@@ -2513,142 +2457,6 @@ impl Node {
25132457
}
25142458
}
25152459

2516-
impl PartialPaths {
2517-
/// Finds a minimal set of partial paths in a file, calling the `visit` closure for each one.
2518-
///
2519-
/// This function ensures that the set of visited partial paths
2520-
/// (a) is minimal, no path can be constructed by stitching other paths in the set, and
2521-
/// (b) covers all complete paths, from references to definitions, when used for path stitching
2522-
///
2523-
/// This function will not return until all reachable partial paths have been processed, so
2524-
/// `graph` must already contain a complete stack graph. If you have a very large stack graph
2525-
/// stored in some other storage system, and want more control over lazily loading only the
2526-
/// necessary pieces, then you should code up your own loop that calls
2527-
/// [`PartialPath::extend`][] manually.
2528-
///
2529-
/// Caveat: Edges between nodes of different files are not used. Hence the returned set of partial
2530-
/// paths will not cover paths going through those edges.
2531-
///
2532-
/// [`PartialPath::extend`]: struct.PartialPath.html#method.extend
2533-
pub fn find_minimal_partial_path_set_in_file<F>(
2534-
&mut self,
2535-
graph: &StackGraph,
2536-
file: Handle<File>,
2537-
cancellation_flag: &dyn CancellationFlag,
2538-
mut visit: F,
2539-
) -> Result<(), CancellationError>
2540-
where
2541-
F: FnMut(&StackGraph, &mut PartialPaths, PartialPath),
2542-
{
2543-
fn as_complete_as_necessary(graph: &StackGraph, path: &PartialPath) -> bool {
2544-
path.starts_at_endpoint(graph)
2545-
&& (path.ends_at_endpoint(graph) || graph[path.end_node].is_jump_to())
2546-
}
2547-
2548-
copious_debugging!("Find all partial paths in {}", graph[file]);
2549-
let mut queue = VecDeque::new();
2550-
let mut edges = Appendables::new();
2551-
queue.extend(
2552-
graph
2553-
.nodes_for_file(file)
2554-
.chain(std::iter::once(StackGraph::root_node()))
2555-
.filter(|node| graph[*node].is_endpoint())
2556-
.map(|node| {
2557-
(
2558-
PartialPath::from_node(graph, self, node),
2559-
AppendingCycleDetector::new(),
2560-
)
2561-
}),
2562-
);
2563-
while let Some((path, path_cycle_detector)) = queue.pop_front() {
2564-
cancellation_flag.check("finding partial paths in file")?;
2565-
let is_seed = path.edges.is_empty();
2566-
copious_debugging!(" => {}", path.display(graph, self));
2567-
if !is_seed && as_complete_as_necessary(graph, &path) {
2568-
copious_debugging!(" * visit");
2569-
visit(graph, self, path);
2570-
} else if !path_cycle_detector
2571-
.is_cyclic(graph, self, &GraphEdges(Some(file)), &mut edges)
2572-
.expect("cyclic test failed when finding partial paths")
2573-
.is_empty()
2574-
{
2575-
copious_debugging!(" * cycle");
2576-
} else {
2577-
copious_debugging!(" * extend");
2578-
path.extend(
2579-
graph,
2580-
self,
2581-
Some(file),
2582-
&mut edges,
2583-
path_cycle_detector,
2584-
&mut queue,
2585-
);
2586-
}
2587-
}
2588-
Ok(())
2589-
}
2590-
2591-
/// Finds all complete paths reachable from a set of starting nodes, calling the `visit` closure
2592-
/// for each one.
2593-
///
2594-
/// This function will not return until all reachable paths have been processed, so `graph`
2595-
/// must already contain a complete stack graph. If you have a very large stack graph stored
2596-
/// in some other storage system, and want more control over lazily loading only the necessary
2597-
/// pieces, then you should code up your own loop that calls [`Path::extend`][] manually.
2598-
///
2599-
/// [`Path::extend`]: struct.Path.html#method.extend
2600-
pub fn find_all_complete_paths<I, F>(
2601-
&mut self,
2602-
graph: &StackGraph,
2603-
starting_nodes: I,
2604-
cancellation_flag: &dyn CancellationFlag,
2605-
mut visit: F,
2606-
) -> Result<(), CancellationError>
2607-
where
2608-
I: IntoIterator<Item = Handle<Node>>,
2609-
F: FnMut(&StackGraph, &mut PartialPaths, PartialPath),
2610-
{
2611-
copious_debugging!("Find all complete paths from nodes");
2612-
let mut queue = starting_nodes
2613-
.into_iter()
2614-
.filter(|node| graph[*node].is_reference())
2615-
.map(|node| {
2616-
let mut p = PartialPath::from_node(graph, self, node);
2617-
p.eliminate_precondition_stack_variables(self);
2618-
(p, AppendingCycleDetector::new())
2619-
})
2620-
.collect::<VecDeque<_>>();
2621-
let mut partials = PartialPaths::new();
2622-
let mut edges = Appendables::new();
2623-
while let Some((path, path_cycle_detector)) = queue.pop_front() {
2624-
cancellation_flag.check("finding complete paths")?;
2625-
if path.is_complete(graph) {
2626-
copious_debugging!(" * visit");
2627-
visit(graph, self, path.clone());
2628-
}
2629-
if !path_cycle_detector
2630-
.is_cyclic(graph, &mut partials, &GraphEdges(None), &mut edges)
2631-
.expect("cyclic test failed when finding complete paths")
2632-
.into_iter()
2633-
.all(|c| c == Cyclicity::StrengthensPrecondition)
2634-
{
2635-
copious_debugging!(" * cycle");
2636-
} else {
2637-
copious_debugging!(" * extend");
2638-
path.extend(
2639-
graph,
2640-
self,
2641-
None,
2642-
&mut edges,
2643-
path_cycle_detector,
2644-
&mut queue,
2645-
);
2646-
}
2647-
}
2648-
Ok(())
2649-
}
2650-
}
2651-
26522460
//-------------------------------------------------------------------------------------------------
26532461
// Extending partial paths with partial paths
26542462

0 commit comments

Comments
 (0)