11//! Exporting HUGR graphs to their `hugr-model` representation.
22use crate :: {
33 extension:: { ExtensionId , OpDef , SignatureFunc } ,
4- hugr:: { IdentList , NodeMetadataMap } ,
4+ hugr:: IdentList ,
55 ops:: {
66 constant:: CustomSerialized , DataflowBlock , DataflowOpTrait , OpName , OpTrait , OpType , Value ,
77 } ,
@@ -12,10 +12,10 @@ use crate::{
1212 types:: {
1313 type_param:: { TypeArgVariable , TypeParam } ,
1414 type_row:: TypeRowBase ,
15- CustomType , FuncTypeBase , MaybeRV , PolyFuncTypeBase , RowVariable , SumType , TypeArg ,
16- TypeBase , TypeBound , TypeEnum , TypeRow ,
15+ CustomType , EdgeKind , FuncTypeBase , MaybeRV , PolyFuncTypeBase , RowVariable , SumType ,
16+ TypeArg , TypeBase , TypeBound , TypeEnum , TypeRow ,
1717 } ,
18- Direction , Hugr , HugrView , IncomingPort , Node , Port ,
18+ Direction , Hugr , HugrView , IncomingPort , Node , NodeIndex as _ , Port ,
1919} ;
2020
2121use fxhash:: { FxBuildHasher , FxHashMap } ;
@@ -467,10 +467,7 @@ impl<'a> Context<'a> {
467467 let inputs = self . make_ports ( node, Direction :: Incoming , num_inputs) ;
468468 let outputs = self . make_ports ( node, Direction :: Outgoing , num_outputs) ;
469469
470- let meta = match self . hugr . get_node_metadata ( node) {
471- Some ( metadata_map) => self . export_node_metadata ( metadata_map) ,
472- None => & [ ] ,
473- } ;
470+ let meta = self . export_node_metadata ( node) ;
474471
475472 self . module . nodes [ node_id. index ( ) ] = table:: Node {
476473 operation,
@@ -577,6 +574,7 @@ impl<'a> Context<'a> {
577574 let mut targets: & [ _ ] = & [ ] ;
578575 let mut input_types = None ;
579576 let mut output_types = None ;
577+ let mut meta = Vec :: new ( ) ;
580578
581579 let children = self . hugr . children ( node) ;
582580 let mut region_children = BumpVec :: with_capacity_in ( children. size_hint ( ) . 0 - 2 , self . bump ) ;
@@ -591,9 +589,25 @@ impl<'a> Context<'a> {
591589 targets = self . make_ports ( child, Direction :: Incoming , output. types . len ( ) ) ;
592590 output_types = Some ( & output. types ) ;
593591 }
594- _ => {
592+ child_optype => {
595593 if let Some ( child_id) = self . export_node_shallow ( child) {
596594 region_children. push ( child_id) ;
595+
596+ // Record all order edges that originate from this node in metadata.
597+ let successors = child_optype
598+ . other_output_port ( )
599+ . into_iter ( )
600+ . flat_map ( |port| self . hugr . linked_inputs ( child, port) )
601+ . map ( |( successor, _) | successor)
602+ . filter ( |successor| !self . hugr . get_optype ( * successor) . is_output ( ) ) ;
603+
604+ for successor in successors {
605+ let a =
606+ self . make_term ( model:: Literal :: Nat ( child. index ( ) as u64 ) . into ( ) ) ;
607+ let b = self
608+ . make_term ( model:: Literal :: Nat ( successor. index ( ) as u64 ) . into ( ) ) ;
609+ meta. push ( self . make_term_apply ( model:: ORDER_HINT_ORDER , & [ a, b] ) ) ;
610+ }
597611 }
598612 }
599613 }
@@ -623,7 +637,7 @@ impl<'a> Context<'a> {
623637 sources,
624638 targets,
625639 children : region_children. into_bump_slice ( ) ,
626- meta : & [ ] , // TODO: Export metadata
640+ meta : self . bump . alloc_slice_copy ( & meta ) ,
627641 signature,
628642 scope,
629643 } ;
@@ -1002,11 +1016,37 @@ impl<'a> Context<'a> {
10021016 }
10031017 }
10041018
1005- pub fn export_node_metadata ( & mut self , metadata_map : & NodeMetadataMap ) -> & ' a [ table:: TermId ] {
1006- let mut meta = BumpVec :: with_capacity_in ( metadata_map. len ( ) , self . bump ) ;
1019+ pub fn export_node_metadata ( & mut self , node : Node ) -> & ' a [ table:: TermId ] {
1020+ let metadata_map = self . hugr . get_node_metadata ( node) ;
1021+
1022+ let has_order_edges = {
1023+ fn is_relevant_node ( hugr : & Hugr , node : Node ) -> bool {
1024+ let optype = hugr. get_optype ( node) ;
1025+ !optype. is_input ( ) && !optype. is_output ( )
1026+ }
1027+
1028+ let optype = self . hugr . get_optype ( node) ;
1029+
1030+ Direction :: BOTH
1031+ . iter ( )
1032+ . filter ( |dir| optype. other_port_kind ( * * dir) == Some ( EdgeKind :: StateOrder ) )
1033+ . filter_map ( |dir| optype. other_port ( * dir) )
1034+ . flat_map ( |port| self . hugr . linked_ports ( node, port) )
1035+ . any ( |( other, _) | is_relevant_node ( self . hugr , other) )
1036+ } ;
1037+
1038+ let meta_capacity = metadata_map. map_or ( 0 , |map| map. len ( ) ) + has_order_edges as usize ;
1039+ let mut meta = BumpVec :: with_capacity_in ( meta_capacity, self . bump ) ;
1040+
1041+ if let Some ( metadata_map) = metadata_map {
1042+ for ( name, value) in metadata_map {
1043+ meta. push ( self . export_json_meta ( name, value) ) ;
1044+ }
1045+ }
10071046
1008- for ( name, value) in metadata_map {
1009- meta. push ( self . export_json_meta ( name, value) ) ;
1047+ if has_order_edges {
1048+ let key = self . make_term ( model:: Literal :: Nat ( node. index ( ) as u64 ) . into ( ) ) ;
1049+ meta. push ( self . make_term_apply ( model:: ORDER_HINT_KEY , & [ key] ) ) ;
10101050 }
10111051
10121052 meta. into_bump_slice ( )
0 commit comments