@@ -42,6 +42,7 @@ use crate::graph::StackGraph;
4242use crate :: partial:: PartialPath ;
4343use crate :: partial:: PartialPaths ;
4444use crate :: paths:: Path ;
45+ use crate :: paths:: PathResolutionError ;
4546use crate :: stitching:: Database ;
4647use crate :: stitching:: OwnedOrDatabasePath ;
4748
@@ -136,43 +137,64 @@ where
136137}
137138
138139// ----------------------------------------------------------------------------
139- // Cycle detector when appending edges
140+ // Cycle detector
141+
142+ pub trait Appendable {
143+ type Ctx ;
144+
145+ fn append_to (
146+ & self ,
147+ graph : & StackGraph ,
148+ partials : & mut PartialPaths ,
149+ ctx : & mut Self :: Ctx ,
150+ path : & mut PartialPath ,
151+ ) -> Result < ( ) , PathResolutionError > ;
152+ fn start_node ( & self , ctx : & mut Self :: Ctx ) -> Handle < Node > ;
153+ fn end_node ( & self , ctx : & mut Self :: Ctx ) -> Handle < Node > ;
154+ }
140155
141156#[ derive( Clone ) ]
142- pub struct EdgeAppendingCycleDetector {
143- edges : List < Edge > ,
157+ pub struct AppendingCycleDetector < A > {
158+ appendages : List < A > ,
144159}
145160
146- pub type AppendedEdges = ListArena < Edge > ;
161+ pub type Appendages < A > = ListArena < A > ;
147162
148- impl EdgeAppendingCycleDetector {
163+ impl < A : Appendable + Clone > AppendingCycleDetector < A > {
149164 pub fn new ( ) -> Self {
150165 Self {
151- edges : List :: empty ( ) ,
166+ appendages : List :: empty ( ) ,
152167 }
153168 }
154169
155- pub fn append_edge (
170+ pub fn from ( appendages : & mut Appendages < A > , appendage : A ) -> Self {
171+ let mut result = Self :: new ( ) ;
172+ result. appendages . push_front ( appendages, appendage) ;
173+ result
174+ }
175+
176+ pub fn append (
156177 & mut self ,
157178 graph : & StackGraph ,
158179 partials : & mut PartialPaths ,
159- appended_edges : & mut AppendedEdges ,
160- edge : Edge ,
161- ) -> Result < ( ) , ( ) > {
162- let end_node = edge. sink ;
163- self . edges . push_front ( appended_edges, edge) ;
180+ ctx : & mut A :: Ctx ,
181+ appendages : & mut Appendages < A > ,
182+ appendage : A ,
183+ ) -> Result < ( ) , PathResolutionError > {
184+ let end_node = appendage. end_node ( ctx) ;
185+ self . appendages . push_front ( appendages, appendage) ;
164186
165187 let mut maybe_cyclic_path = None ;
166- let mut index = self . edges ;
167- let mut edges = self . edges ;
188+ let mut index = self . appendages ;
189+ let mut values = self . appendages ;
168190 loop {
169191 // find loop point
170192 let mut count = 0usize ;
171193 loop {
172- match index. pop_front ( appended_edges ) {
173- Some ( edge ) => {
194+ match index. pop_front ( appendages ) {
195+ Some ( appendage ) => {
174196 count += 1 ;
175- if edge . source == end_node {
197+ if appendage . start_node ( ctx ) == end_node {
176198 break ;
177199 }
178200 }
@@ -181,18 +203,21 @@ impl EdgeAppendingCycleDetector {
181203 }
182204
183205 // get prefix edges
184- let mut prefix_edges = List :: empty ( ) ;
206+ let mut prefix_appendages = List :: empty ( ) ;
185207 for _ in 0 ..count {
186- prefix_edges. push_front ( appended_edges, * edges. pop_front ( appended_edges) . unwrap ( ) ) ;
208+ let appendage = values. pop_front ( appendages) . unwrap ( ) ;
209+ prefix_appendages. push_front ( appendages, appendage. clone ( ) ) ;
187210 }
188211
189- // build prefix path
212+ // build prefix path -- prefix starts at end_node, because this is a cycle
190213 let mut prefix_path = PartialPath :: from_node ( graph, partials, end_node) ;
191- while let Some ( edge ) = prefix_edges . pop_front ( appended_edges ) {
214+ while let Some ( appendage ) = prefix_appendages . pop_front ( appendages ) {
192215 prefix_path
193- . resolve_to ( graph, partials, edge. source )
216+ . resolve_to ( graph, partials, appendage. start_node ( ctx) )
217+ . unwrap ( ) ;
218+ appendage
219+ . append_to ( graph, partials, ctx, & mut prefix_path)
194220 . unwrap ( ) ;
195- prefix_path. append ( graph, partials, * edge) . unwrap ( ) ;
196221 }
197222
198223 // build cyclic path
@@ -206,99 +231,54 @@ impl EdgeAppendingCycleDetector {
206231 . concatenate ( graph, partials, & cyclic_path)
207232 . unwrap ( ) ;
208233 if !prefix_path. is_productive ( graph, partials) {
209- return Err ( ( ) ) ;
234+ return Err ( PathResolutionError :: DisallowedCycle ) ;
210235 }
211236 maybe_cyclic_path = Some ( prefix_path) ;
212237 }
213238 }
214239}
215240
216- // ----------------------------------------------------------------------------
217- // Cycle detector when appending partial paths
241+ impl Appendable for Edge {
242+ type Ctx = ( ) ;
218243
219- #[ derive( Clone ) ]
220- pub struct PartialPathAppendingCycleDetector {
221- paths : List < OwnedOrDatabasePath > ,
222- }
244+ fn append_to (
245+ & self ,
246+ graph : & StackGraph ,
247+ partials : & mut PartialPaths ,
248+ _: & mut ( ) ,
249+ path : & mut PartialPath ,
250+ ) -> Result < ( ) , PathResolutionError > {
251+ path. append ( graph, partials, * self )
252+ }
223253
224- pub type AppendedPartialPaths = ListArena < OwnedOrDatabasePath > ;
225-
226- impl PartialPathAppendingCycleDetector {
227- pub fn from_partial_path (
228- _graph : & StackGraph ,
229- _partials : & mut PartialPaths ,
230- _db : & mut Database ,
231- appended_paths : & mut AppendedPartialPaths ,
232- path : OwnedOrDatabasePath ,
233- ) -> Self {
234- let mut paths = List :: empty ( ) ;
235- paths. push_front ( appended_paths, path) ;
236- Self { paths }
254+ fn start_node ( & self , _: & mut ( ) ) -> Handle < Node > {
255+ self . source
237256 }
238257
239- pub fn append_partial_path (
240- & mut self ,
241- graph : & StackGraph ,
242- partials : & mut PartialPaths ,
243- db : & Database ,
244- appended_paths : & mut AppendedPartialPaths ,
245- path : OwnedOrDatabasePath ,
246- ) -> Result < ( ) , ( ) > {
247- let end_node = path. get ( db) . end_node ;
248- self . paths . push_front ( appended_paths, path) ;
258+ fn end_node ( & self , _: & mut ( ) ) -> Handle < Node > {
259+ self . sink
260+ }
261+ }
249262
250- let mut maybe_cyclic_path = None ;
251- let mut index = self . paths ;
252- let mut paths = self . paths ;
253- loop {
254- // find loop point
255- let mut count = 0usize ;
256- loop {
257- match index. pop_front ( appended_paths) {
258- Some ( path) => {
259- count += 1 ;
260- if path. get ( db) . start_node == end_node {
261- break ;
262- }
263- }
264- None => return Ok ( ( ) ) ,
265- }
266- }
263+ impl Appendable for OwnedOrDatabasePath {
264+ type Ctx = Database ;
267265
268- // get prefix paths
269- let mut prefix_paths = List :: empty ( ) ;
270- for _ in 0 ..count {
271- prefix_paths. push_front (
272- appended_paths,
273- paths. pop_front ( appended_paths) . unwrap ( ) . clone ( ) ,
274- ) ;
275- }
266+ fn append_to (
267+ & self ,
268+ graph : & StackGraph ,
269+ partials : & mut PartialPaths ,
270+ db : & mut Database ,
271+ path : & mut PartialPath ,
272+ ) -> Result < ( ) , PathResolutionError > {
273+ path. ensure_no_overlapping_variables ( partials, self . get ( db) ) ;
274+ path. concatenate ( graph, partials, self . get ( db) )
275+ }
276276
277- // build prefix path
278- let mut prefix_path = PartialPath :: from_node ( graph, partials, end_node) ;
279- while let Some ( path) = prefix_paths. pop_front ( appended_paths) {
280- let path = path. get ( db) ;
281- prefix_path
282- . resolve_to ( graph, partials, path. start_node )
283- . unwrap ( ) ;
284- prefix_path. ensure_no_overlapping_variables ( partials, path) ;
285- prefix_path. concatenate ( graph, partials, path) . unwrap ( ) ;
286- }
277+ fn start_node ( & self , db : & mut Database ) -> Handle < Node > {
278+ self . get ( db) . start_node
279+ }
287280
288- // build cyclic path
289- let cyclic_path = maybe_cyclic_path
290- . unwrap_or_else ( || PartialPath :: from_node ( graph, partials, end_node) ) ;
291- prefix_path
292- . resolve_to ( graph, partials, cyclic_path. start_node )
293- . unwrap ( ) ;
294- prefix_path. ensure_no_overlapping_variables ( partials, & cyclic_path) ;
295- prefix_path
296- . concatenate ( graph, partials, & cyclic_path)
297- . unwrap ( ) ;
298- if !prefix_path. is_productive ( graph, partials) {
299- return Err ( ( ) ) ;
300- }
301- maybe_cyclic_path = Some ( prefix_path) ;
302- }
281+ fn end_node ( & self , db : & mut Database ) -> Handle < Node > {
282+ self . get ( db) . end_node
303283 }
304284}
0 commit comments