@@ -21,6 +21,7 @@ use wit_bindgen_core::{
2121 WorldKey ,
2222 } ,
2323} ;
24+ use wit_parser:: TypeIdVisitor ;
2425
2526// mod wamr;
2627mod symbol_name;
@@ -879,11 +880,10 @@ impl CppInterfaceGenerator<'_> {
879880 fn types ( & mut self , iface : InterfaceId ) {
880881 let iface_data = & self . resolve ( ) . interfaces [ iface] ;
881882
882- // Second pass: emit full type definitions for all types.
883- //
884- // Here we sort the types topologically, taking into consideration the
885- // parameter and return types of functions associated with resource
886- // types. This ensures each type is declared before any uses of it.
883+ // Here we sort the types topologically before emitting code for them,
884+ // taking into consideration the parameter and return types of functions
885+ // associated with resource types. This ensures each type is declared
886+ // before any uses of it.
887887 for ( name, id) in sort_types ( self . resolve , & iface_data. types ) {
888888 self . define_type ( name, id) ;
889889 }
@@ -3628,119 +3628,72 @@ fn sort_types<'a>(
36283628 resolve : & Resolve ,
36293629 types : & ' a IndexMap < String , TypeId > ,
36303630) -> IndexMap < & ' a str , TypeId > {
3631- let mut sorted = IndexSet :: new ( ) ;
3632- let mut visited = HashSet :: new ( ) ;
3633- for id in types . values ( ) {
3634- sort ( resolve , Type :: Id ( * id ) , & mut sorted , & mut visited ) ;
3631+ struct Visitor < ' a > {
3632+ resolve : & ' a Resolve ,
3633+ sorted : IndexSet < TypeId > ,
3634+ visited : HashSet < TypeId > ,
36353635 }
3636- let names = types
3637- . iter ( )
3638- . map ( |( k, v) | ( * v, k. as_str ( ) ) )
3639- . collect :: < HashMap < _ , _ > > ( ) ;
3640- sorted
3641- . into_iter ( )
3642- . filter_map ( |v| names. get ( & v) . map ( |k| ( * k, v) ) )
3643- . collect ( )
3644- }
36453636
3646- fn sort ( resolve : & Resolve , ty : Type , sorted : & mut IndexSet < TypeId > , visited : & mut HashSet < TypeId > ) {
3647- match ty {
3648- Type :: Bool
3649- | Type :: U8
3650- | Type :: U16
3651- | Type :: U32
3652- | Type :: S8
3653- | Type :: S16
3654- | Type :: S32
3655- | Type :: Char
3656- | Type :: U64
3657- | Type :: S64
3658- | Type :: F32
3659- | Type :: F64
3660- | Type :: String
3661- | Type :: ErrorContext => ( ) ,
3662- Type :: Id ( id) => {
3663- let ty = & resolve. types [ id] ;
3664- match & ty. kind {
3665- TypeDefKind :: Record ( record) => {
3666- for field in & record. fields {
3667- sort ( resolve, field. ty , sorted, visited) ;
3668- }
3669- sorted. insert ( id) ;
3670- }
3671- TypeDefKind :: Variant ( variant) => {
3672- for case in & variant. cases {
3673- if let Some ( ty) = case. ty {
3674- sort ( resolve, ty, sorted, visited) ;
3675- }
3676- }
3677- sorted. insert ( id) ;
3678- }
3679- TypeDefKind :: Enum ( _) | TypeDefKind :: Flags ( _) => {
3680- sorted. insert ( id) ;
3681- }
3682- TypeDefKind :: Handle ( Handle :: Borrow ( resource) | Handle :: Own ( resource) ) => {
3683- sort ( resolve, Type :: Id ( * resource) , sorted, visited) ;
3684- sorted. insert ( id) ;
3685- }
3686- TypeDefKind :: Option ( some) => {
3687- sort ( resolve, * some, sorted, visited) ;
3688- sorted. insert ( id) ;
3689- }
3690- TypeDefKind :: Result ( result) => {
3691- if let Some ( ty) = result. ok {
3692- sort ( resolve, ty, sorted, visited) ;
3693- }
3694- if let Some ( ty) = result. err {
3695- sort ( resolve, ty, sorted, visited) ;
3696- }
3697- sorted. insert ( id) ;
3698- }
3699- TypeDefKind :: Tuple ( tuple) => {
3700- for ty in & tuple. types {
3701- sort ( resolve, * ty, sorted, visited) ;
3702- }
3703- sorted. insert ( id) ;
3704- }
3705- TypeDefKind :: List ( ty) | TypeDefKind :: FixedLengthList ( ty, _) => {
3706- sort ( resolve, * ty, sorted, visited) ;
3707- }
3708- TypeDefKind :: Type ( ty) => {
3709- sort ( resolve, * ty, sorted, visited) ;
3710- }
3711- TypeDefKind :: Resource => {
3712- // Here we avoid infinite recursion by remembering if we've
3713- // seen this type already.
3714- if !visited. contains ( & id) {
3715- visited. insert ( id) ;
3716-
3717- if let TypeOwner :: Interface ( interface) = ty. owner {
3718- for function in resolve. interfaces [ interface] . functions . values ( ) {
3719- if let Some ( resource) = function. kind . resource ( )
3720- && resource == id
3721- {
3722- for parameter in & function. params {
3723- sort ( resolve, parameter. ty , & mut * sorted, & mut * visited) ;
3724- }
3725-
3726- if let Some ( ty) = function. result {
3727- sort ( resolve, ty, & mut * sorted, & mut * visited) ;
3728- }
3637+ impl TypeIdVisitor for Visitor < ' _ > {
3638+ fn before_visit_type_id ( & mut self , id : TypeId ) -> bool {
3639+ let ty = & self . resolve . types [ id] ;
3640+ if let TypeDefKind :: Resource = & ty. kind {
3641+ // Here we avoid infinite recursion by remembering if we've seen
3642+ // this type already.
3643+ if self . visited . contains ( & id) {
3644+ false
3645+ } else {
3646+ self . visited . insert ( id) ;
3647+
3648+ // TypeIdVisitor does not consider the parameter and return
3649+ // types of resource associated functions to be transitive
3650+ // types, so we need to handle that ourselves here.
3651+ if let TypeOwner :: Interface ( interface) = ty. owner {
3652+ for function in self . resolve . interfaces [ interface] . functions . values ( ) {
3653+ if let Some ( resource) = function. kind . resource ( )
3654+ && resource == id
3655+ {
3656+ for parameter in & function. params {
3657+ self . visit_type ( self . resolve , & parameter. ty ) ;
3658+ }
3659+
3660+ if let Some ( ty) = function. result {
3661+ self . visit_type ( self . resolve , & ty) ;
37293662 }
37303663 }
37313664 }
3732-
3733- sorted. insert ( id) ;
37343665 }
3666+
3667+ true
37353668 }
3736- TypeDefKind :: Stream ( ty) | TypeDefKind :: Future ( ty) => {
3737- if let Some ( ty) = ty {
3738- sort ( resolve, * ty, sorted, visited) ;
3739- }
3740- sorted. insert ( id) ;
3741- }
3742- kind => todo ! ( "{kind:?}" ) ,
3669+ } else {
3670+ true
37433671 }
37443672 }
3673+
3674+ fn after_visit_type_id ( & mut self , id : TypeId ) {
3675+ self . sorted . insert ( id) ;
3676+ }
37453677 }
3678+
3679+ let mut visitor = Visitor {
3680+ resolve,
3681+ sorted : Default :: default ( ) ,
3682+ visited : Default :: default ( ) ,
3683+ } ;
3684+
3685+ for & id in types. values ( ) {
3686+ visitor. visit_type_id ( resolve, id) ;
3687+ }
3688+
3689+ let names = types
3690+ . iter ( )
3691+ . map ( |( k, v) | ( * v, k. as_str ( ) ) )
3692+ . collect :: < HashMap < _ , _ > > ( ) ;
3693+
3694+ visitor
3695+ . sorted
3696+ . into_iter ( )
3697+ . filter_map ( |v| names. get ( & v) . map ( |k| ( * k, v) ) )
3698+ . collect ( )
37463699}
0 commit comments