1+ use crate :: document:: value:: TaggedValue ;
12use crate :: document:: { InlineRust , value} ;
23use crate :: document:: { NodeId , OriginalLocation } ;
34pub use graphene_core:: registry:: * ;
@@ -296,15 +297,68 @@ impl ProtoNetwork {
296297 /// Inserts context nullification nodes to optimize caching
297298 /// This analysis is performed after topological sorting to ensure proper dependency tracking
298299 pub fn insert_context_nullification_nodes ( & mut self ) -> Result < ( ) , String > {
299- // TODO: Implement full context flow analysis with:
300- // 1. DFS traversal to track context feature requirements
301- // 2. Branch convergence analysis
302- // 3. Post-injection nullification
303- // 4. Insert ContextModificationNode instances where beneficial
300+ // Perform topological sort once
301+ self . reorder_ids ( ) ?;
302+
304303 let mut out_nodes = Vec :: with_capacity ( 10 ) ;
305304 self . find_context_dependencies ( self . output , & mut out_nodes) ;
306305 out_nodes. sort_by_key ( |& ( id, _) | id) ;
307306
307+ // TODO: use outwards edges tracked in original node location instead
308+ // Collect outward edges once
309+ let outwards_edges = self . collect_outwards_edges ( ) ;
310+
311+ for ( node_id, context_deps) in out_nodes {
312+ let memo_node_id = NodeId ( self . nodes . len ( ) as u64 ) ;
313+ let ( _, node) = & self . nodes [ node_id. 0 as usize ] ;
314+ let path = node. original_location . path . clone ( ) ;
315+
316+ self . nodes . push ( (
317+ memo_node_id,
318+ ProtoNode {
319+ construction_args : ConstructionArgs :: Nodes ( vec ! [ node_id] ) ,
320+ call_argument : concrete ! ( Context ) ,
321+ identifier : graphene_core:: memo:: memo:: IDENTIFIER ,
322+ original_location : OriginalLocation {
323+ path : path. clone ( ) ,
324+ ..Default :: default ( )
325+ } ,
326+ ..Default :: default ( )
327+ } ,
328+ ) ) ;
329+
330+ let nullification_value_node_id = NodeId ( self . nodes . len ( ) as u64 ) ;
331+
332+ self . nodes . push ( (
333+ nullification_value_node_id,
334+ ProtoNode {
335+ construction_args : ConstructionArgs :: Value ( MemoHash :: new ( TaggedValue :: ContextFeatures ( context_deps) ) ) ,
336+ call_argument : concrete ! ( Context ) ,
337+ identifier : ProtoNodeIdentifier :: new ( "graphene_core::value::ClonedNode" ) ,
338+ original_location : OriginalLocation {
339+ path : path. clone ( ) ,
340+ ..Default :: default ( )
341+ } ,
342+ ..Default :: default ( )
343+ } ,
344+ ) ) ;
345+ let nullification_node_id = NodeId ( self . nodes . len ( ) as u64 ) ;
346+ self . nodes . push ( (
347+ nullification_node_id,
348+ ProtoNode {
349+ construction_args : ConstructionArgs :: Nodes ( vec ! [ memo_node_id, nullification_node_id] ) ,
350+ call_argument : concrete ! ( Context ) ,
351+ identifier : graphene_core:: context_modification:: context_modification:: IDENTIFIER ,
352+ original_location : OriginalLocation {
353+ path : path. clone ( ) ,
354+ ..Default :: default ( )
355+ } ,
356+ ..Default :: default ( )
357+ } ,
358+ ) ) ;
359+ self . replace_node_id ( & outwards_edges, node_id, nullification_node_id) ;
360+ }
361+
308362 Ok ( ( ) )
309363 }
310364
@@ -321,7 +375,7 @@ impl ProtoNetwork {
321375 } ;
322376
323377 // Compute the dependencies for each branch and combine all of them
324- for & ( node, _ ) in inputs {
378+ for & node in inputs {
325379 let branch = self . find_context_dependencies ( node, out_nodes) ;
326380 branch_dependencies. push ( branch) ;
327381 combined_deps |= branch;
@@ -338,7 +392,7 @@ impl ProtoNetwork {
338392 let we_introduce_new_deps = !combined_deps. contains ( new_deps) ;
339393
340394 // For diverging branches, we can add a cache node for all branches which don't reqire all dependencies
341- for ( & ( node, _ ) , deps) in inputs. iter ( ) . zip ( branch_dependencies. into_iter ( ) ) {
395+ for ( & node, deps) in inputs. iter ( ) . zip ( branch_dependencies. into_iter ( ) ) {
342396 if we_introduce_new_deps || deps != combined_deps {
343397 out_nodes. push ( ( node, deps) ) ;
344398 }
0 commit comments