@@ -655,6 +655,73 @@ impl NodeNetwork {
655655 }
656656}
657657
658+ // Functions for resolving scope inputs
659+ impl NodeNetwork {
660+ pub fn resolve_scope_inputs ( & mut self ) {
661+ let mut leftover = Vec :: new ( ) ;
662+ self . resolve_scope_inputs_impl ( None , & mut leftover) ;
663+ assert ! ( leftover. is_empty( ) , "Unresolved scope keys at top level: {leftover:?}" ) ;
664+ }
665+
666+ fn resolve_scope_inputs_impl ( & mut self , parent : Option < & ScopeChain < ' _ > > , network_inputs : & mut Vec < NodeInput > ) {
667+ let scope_chain = ScopeChain {
668+ scopes : & self . scope_injections ,
669+ parent,
670+ } ;
671+
672+ for node in self . nodes . values_mut ( ) {
673+ let DocumentNodeImplementation :: Network ( network) = & mut node. implementation else { continue } ;
674+ network. resolve_scope_inputs_impl ( Some ( & scope_chain) , & mut node. inputs ) ;
675+ }
676+
677+ let mut key_to_idx: FxHashMap < Cow < ' static , str > , usize > = FxHashMap :: default ( ) ;
678+ for node in self . nodes . values_mut ( ) {
679+ for input in node. inputs . iter_mut ( ) {
680+ let NodeInput :: Scope ( key) = input else { continue } ;
681+ * input = match scope_chain. lookup ( key) {
682+ ScopeChainLookup :: Current ( node_id, _ty) => NodeInput :: node ( * node_id, 0 ) ,
683+ ScopeChainLookup :: Parent ( _node_id, ty) => {
684+ let import_index = * key_to_idx. entry ( key. clone ( ) ) . or_insert_with ( || {
685+ let index = network_inputs. len ( ) ;
686+ network_inputs. push ( NodeInput :: Scope ( key. clone ( ) ) ) ;
687+ index
688+ } ) ;
689+ NodeInput :: Import {
690+ import_type : ty. clone ( ) ,
691+ import_index,
692+ }
693+ }
694+ ScopeChainLookup :: None => panic ! ( "Scope key `{key}` not found in any ancestor scope_injections" ) ,
695+ } ;
696+ }
697+ }
698+ }
699+ }
700+
701+ struct ScopeChain < ' a > {
702+ scopes : & ' a FxHashMap < String , ( NodeId , Type ) > ,
703+ parent : Option < & ' a ScopeChain < ' a > > ,
704+ }
705+ enum ScopeChainLookup < ' a > {
706+ Current ( & ' a NodeId , & ' a Type ) ,
707+ Parent ( & ' a NodeId , & ' a Type ) ,
708+ None ,
709+ }
710+ impl ScopeChain < ' _ > {
711+ fn lookup ( & ' _ self , key : & str ) -> ScopeChainLookup < ' _ > {
712+ self . scopes
713+ . get ( key)
714+ . map ( |( id, ty) | ScopeChainLookup :: Current ( id, ty) )
715+ . or_else ( || {
716+ self . parent . and_then ( |parent| match parent. lookup ( key) {
717+ ScopeChainLookup :: Current ( id, ty) | ScopeChainLookup :: Parent ( id, ty) => Some ( ScopeChainLookup :: Parent ( id, ty) ) ,
718+ ScopeChainLookup :: None => None ,
719+ } )
720+ } )
721+ . unwrap_or ( ScopeChainLookup :: None )
722+ }
723+ }
724+
658725/// Functions for compiling the network
659726impl NodeNetwork {
660727 /// Replace all references in the graph of a node ID with a new node ID defined by the function `f`.
@@ -784,18 +851,6 @@ impl NodeNetwork {
784851 are_inputs_used
785852 }
786853
787- pub fn resolve_scope_inputs ( & mut self ) {
788- for node in self . nodes . values_mut ( ) {
789- for input in node. inputs . iter_mut ( ) {
790- if let NodeInput :: Scope ( key) = input {
791- let ( import_id, _ty) = self . scope_injections . get ( key. as_ref ( ) ) . expect ( "Tried to import a non existent key from scope" ) ;
792- // TODO use correct output index
793- * input = NodeInput :: node ( * import_id, 0 ) ;
794- }
795- }
796- }
797- }
798-
799854 /// Remove all nodes that contain [`DocumentNodeImplementation::Network`] by moving the nested nodes into the parent network.
800855 pub fn flatten ( & mut self , node_id : NodeId ) {
801856 self . flatten_with_fns ( node_id, merge_ids, NodeId :: new)
@@ -886,11 +941,7 @@ impl NodeNetwork {
886941 }
887942 NodeInput :: Value { .. } => unreachable ! ( "Value inputs should have been replaced with value nodes" ) ,
888943 NodeInput :: Inline ( _) => ( ) ,
889- NodeInput :: Scope ( ref key) => {
890- let ( import_id, _ty) = self . scope_injections . get ( key. as_ref ( ) ) . expect ( "Tried to import a non existent key from scope" ) ;
891- // TODO use correct output index
892- nested_node. inputs [ nested_input_index] = NodeInput :: node ( * import_id, 0 ) ;
893- }
944+ NodeInput :: Scope ( _) => unreachable ! ( "Scope inputs should have been resolved by resolve_scope_inputs_recursive before flattening" ) ,
894945 NodeInput :: Reflection ( _) => unreachable ! ( "Reflection inputs should have been replaced with value nodes" ) ,
895946 }
896947 }
@@ -906,21 +957,8 @@ impl NodeNetwork {
906957 }
907958 }
908959
960+ /// Connect all nodes that were previously connected to this node to the nodes of the inner network
909961 fn replace_node_with_its_exports ( & mut self , id : NodeId , original_location : & OriginalLocation , exports : & [ NodeInput ] ) {
910- // Connect scope injections to the inner network export
911- self . scope_injections . values_mut ( ) . for_each ( |( node_id, _ty) | {
912- if node_id == & id {
913- let Some ( export) = exports. first ( ) else {
914- log:: error!( "Inner network should have at least one export" ) ;
915- return ;
916- } ;
917- if let NodeInput :: Node { node_id : export_id, output_index : _ } = export {
918- * node_id = * export_id;
919- }
920- }
921- } ) ;
922-
923- // Connect all nodes that were previously connected to this node to the nodes of the inner network
924962 for ( i, export) in exports. iter ( ) . enumerate ( ) {
925963 if let NodeInput :: Node { node_id, output_index, .. } = & export {
926964 for deps in & original_location. dependants {
0 commit comments