1+ use std:: collections:: BTreeMap ;
2+
13use genco:: { prelude:: * , tokens:: Tokens } ;
2- use wit_bindgen_core:: wit_parser:: { Record , Resolve , Type , TypeDef , TypeDefKind } ;
4+ use wit_bindgen_core:: wit_parser:: { Resolve , SizeAlign , World } ;
35
46use crate :: {
5- codegen:: wasm:: { Wasm , WasmData } ,
6- go:: * ,
7- resolve_type,
7+ codegen:: {
8+ FactoryGenerator ,
9+ factory:: FactoryConfig ,
10+ imports:: { ImportAnalyzer , ImportCodeGenerator } ,
11+ ir:: AnalyzedImports ,
12+ wasm:: { Wasm , WasmData } ,
13+ } ,
14+ go:: { GoIdentifier , GoImports } ,
815} ;
916
1017/// The WIT bindings for a world.
11- pub struct Bindings {
18+ pub struct Bindings < ' a > {
19+ resolve : & ' a Resolve ,
20+ world : & ' a World ,
1221 /// The cumulative output tokens containing the Go bindings.
1322 // TODO(#16): Don't use the internal bindings.out field
1423 pub out : Tokens < Go > ,
1524
1625 /// The identifier of the Go variable containing the WebAssembly bytes.
1726 raw_wasm_var : GoIdentifier ,
27+
28+ /// The Go imports for the bindings.
29+ go_imports : GoImports ,
30+
31+ /// The sizes of the architecture.
32+ sizes : & ' a SizeAlign ,
1833}
1934
20- impl Bindings {
35+ impl < ' a > Bindings < ' a > {
2136 /// Creates a new bindings generator for the selected world.
22- pub fn new ( world : & str ) -> Self {
23- let wasm_var = GoIdentifier :: private ( format ! ( "wasm-file-{world}" ) ) ;
37+ pub fn new ( resolve : & ' a Resolve , world : & ' a World , sizes : & ' a SizeAlign ) -> Self {
38+ let world_name = & world. name ;
39+ let wasm_var = GoIdentifier :: private ( format ! ( "wasm-file-{world_name}" ) ) ;
2440 Self {
25- // world,
41+ resolve,
42+ world,
2643 out : Tokens :: new ( ) ,
2744 raw_wasm_var : wasm_var,
45+ go_imports : GoImports :: new ( ) ,
46+ sizes,
2847 }
2948 }
3049
@@ -33,96 +52,31 @@ impl Bindings {
3352 Wasm :: new ( & self . raw_wasm_var , wasm) . format_into ( & mut self . out )
3453 }
3554
36- pub fn define_type ( & mut self , typ_def : & TypeDef , resolve : & Resolve ) {
37- let TypeDef { name, kind, .. } = typ_def;
38- match kind {
39- TypeDefKind :: Record ( Record { fields } ) => {
40- let name = GoIdentifier :: public ( name. as_deref ( ) . expect ( "record to have a name" ) ) ;
41- let fields = fields. iter ( ) . map ( |field| {
42- (
43- GoIdentifier :: public ( & field. name ) ,
44- resolve_type ( & field. ty , resolve) ,
45- )
46- } ) ;
47-
48- quote_in ! { self . out =>
49- $[ '\n' ]
50- type $name struct {
51- $( for ( name, typ) in fields join ( $[ '\r' ] ) => $name $typ)
52- }
53- }
54- }
55- TypeDefKind :: Resource => todo ! ( "TODO(#5): implement resources" ) ,
56- TypeDefKind :: Handle ( _) => todo ! ( "TODO(#5): implement resources" ) ,
57- TypeDefKind :: Flags ( _) => todo ! ( "TODO(#4):generate flags type definition" ) ,
58- TypeDefKind :: Tuple ( _) => todo ! ( "TODO(#4):generate tuple type definition" ) ,
59- TypeDefKind :: Variant ( _) => {
60- // TODO(#4): Generate aliases if the variant name doesn't match the struct name
61- }
62- TypeDefKind :: Enum ( inner) => {
63- let name = name. clone ( ) . expect ( "enum to have a name" ) ;
64- let enum_type = & GoIdentifier :: private ( & name) ;
65-
66- let enum_interface = GoIdentifier :: public ( & name) ;
67-
68- let enum_function = & GoIdentifier :: private ( format ! ( "is-{}" , & name) ) ;
55+ /// Generates the imports for the bindings.
56+ pub fn generate_imports ( & mut self ) -> ( AnalyzedImports , BTreeMap < String , Tokens < Go > > ) {
57+ let analyzer = ImportAnalyzer :: new ( self . resolve , self . world ) ;
58+ let analyzed = analyzer. analyze ( ) ;
6959
70- let variants = inner
71- . cases
72- . iter ( )
73- . map ( |variant| GoIdentifier :: public ( & variant. name ) ) ;
74-
75- quote_in ! { self . out =>
76- $[ '\n' ]
77- type $enum_interface interface {
78- $enum_function( )
79- }
80-
81- type $enum_type int
82-
83- func ( $enum_type) $enum_function( ) { }
60+ let generator =
61+ ImportCodeGenerator :: new ( self . resolve , & self . go_imports , & analyzed, self . sizes ) ;
62+ let import_chains = generator. import_chains ( ) ;
63+ generator. format_into ( & mut self . out ) ;
64+ ( analyzed, import_chains)
65+ }
8466
85- const (
86- $( for name in variants join ( $[ '\r' ] ) => $name $enum_type = iota)
87- )
88- }
89- }
90- TypeDefKind :: Option ( _) => todo ! ( "TODO(#4): generate option type definition" ) ,
91- TypeDefKind :: Result ( _) => todo ! ( "TODO(#4): generate result type definition" ) ,
92- TypeDefKind :: List ( _) => todo ! ( "TODO(#4): generate list type definition" ) ,
93- TypeDefKind :: Future ( _) => todo ! ( "TODO(#4): generate future type definition" ) ,
94- TypeDefKind :: Stream ( _) => todo ! ( "TODO(#4): generate stream type definition" ) ,
95- TypeDefKind :: Type ( Type :: Id ( _) ) => {
96- // TODO(#4): Only skip this if we have already generated the type
97- }
98- TypeDefKind :: Type ( Type :: Bool ) => todo ! ( "TODO(#4): generate bool type alias" ) ,
99- TypeDefKind :: Type ( Type :: U8 ) => todo ! ( "TODO(#4): generate u8 type alias" ) ,
100- TypeDefKind :: Type ( Type :: U16 ) => todo ! ( "TODO(#4): generate u16 type alias" ) ,
101- TypeDefKind :: Type ( Type :: U32 ) => todo ! ( "TODO(#4): generate u32 type alias" ) ,
102- TypeDefKind :: Type ( Type :: U64 ) => todo ! ( "TODO(#4): generate u64 type alias" ) ,
103- TypeDefKind :: Type ( Type :: S8 ) => todo ! ( "TODO(#4): generate s8 type alias" ) ,
104- TypeDefKind :: Type ( Type :: S16 ) => todo ! ( "TODO(#4): generate s16 type alias" ) ,
105- TypeDefKind :: Type ( Type :: S32 ) => todo ! ( "TODO(#4): generate s32 type alias" ) ,
106- TypeDefKind :: Type ( Type :: S64 ) => todo ! ( "TODO(#4): generate s64 type alias" ) ,
107- TypeDefKind :: Type ( Type :: F32 ) => todo ! ( "TODO(#4): generate f32 type alias" ) ,
108- TypeDefKind :: Type ( Type :: F64 ) => todo ! ( "TODO(#4): generate f64 type alias" ) ,
109- TypeDefKind :: Type ( Type :: Char ) => todo ! ( "TODO(#4): generate char type alias" ) ,
110- TypeDefKind :: Type ( Type :: String ) => {
111- let name =
112- GoIdentifier :: public ( name. as_deref ( ) . expect ( "string alias to have a name" ) ) ;
113- // TODO(#4): We might want a Type Definition (newtype) instead of Type Alias here
114- quote_in ! { self . out =>
115- $[ '\n' ]
116- type $name = string
117- }
118- }
119- TypeDefKind :: Type ( Type :: ErrorContext ) => {
120- todo ! ( "TODO(#4): generate error context definition" )
121- }
122- TypeDefKind :: FixedSizeList ( _, _) => {
123- todo ! ( "TODO(#4): generate fixed size list definition" )
124- }
125- TypeDefKind :: Unknown => panic ! ( "cannot generate Unknown type" ) ,
126- }
67+ /// Generates the factory and instantiate functions, including any
68+ /// required interfaces.
69+ pub fn generate_factory (
70+ & mut self ,
71+ analyzed_imports : & AnalyzedImports ,
72+ import_chains : BTreeMap < String , Tokens < Go > > ,
73+ ) {
74+ let config = FactoryConfig {
75+ analyzed_imports,
76+ go_imports : & self . go_imports ,
77+ import_chains,
78+ wasm_var_name : & self . raw_wasm_var ,
79+ } ;
80+ FactoryGenerator :: new ( config) . format_into ( & mut self . out )
12781 }
12882}
0 commit comments