@@ -1459,7 +1459,7 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
14591459 }
14601460
14611461 fn type_map ( & mut self , _id : TypeId , _name : & str , _key : & Type , _value : & Type , _docs : & Docs ) {
1462- todo ! ( "map types are not yet supported in the MoonBit backend" )
1462+ // Not needed. Maps become `Map[K, V]` inline in MoonBit
14631463 }
14641464
14651465 fn type_future ( & mut self , _id : TypeId , _name : & str , _ty : & Option < Type > , _docs : & Docs ) {
@@ -2889,12 +2889,118 @@ impl Bindgen for FunctionBindgen<'_, '_> {
28892889 results. push ( format ! ( "FixedArray::from_array({array}[:])" ) ) ;
28902890 }
28912891
2892- Instruction :: MapLower { .. }
2893- | Instruction :: MapLift { .. }
2894- | Instruction :: IterMapKey { .. }
2895- | Instruction :: IterMapValue { .. }
2896- | Instruction :: GuestDeallocateMap { .. } => {
2897- todo ! ( "map types are not yet supported in this backend" )
2892+ Instruction :: MapLower {
2893+ key,
2894+ value,
2895+ realloc,
2896+ } => {
2897+ let Block {
2898+ body,
2899+ results : block_results,
2900+ } = self . blocks . pop ( ) . unwrap ( ) ;
2901+ assert ! ( block_results. is_empty( ) ) ;
2902+
2903+ let op = & operands[ 0 ] ;
2904+ let entry = self . interface_gen . world_gen . sizes . record ( [ * key, * value] ) ;
2905+ let size = entry. size . size_wasm32 ( ) ;
2906+ let address = self . locals . tmp ( "address" ) ;
2907+ let index = self . locals . tmp ( "index" ) ;
2908+ let iter_map_key = self . locals . tmp ( "iter_map_key" ) ;
2909+ let iter_map_value = self . locals . tmp ( "iter_map_value" ) ;
2910+
2911+ self . use_ffi ( ffi:: MALLOC ) ;
2912+ uwrite ! (
2913+ self . src,
2914+ "
2915+ let {address} = mbt_ffi_malloc(({op}).length() * {size});
2916+ let mut {index} = 0
2917+ ({op}).each(fn({iter_map_key}, {iter_map_value}) {{
2918+ let iter_map_key = {iter_map_key}
2919+ let iter_map_value = {iter_map_value}
2920+ let iter_base = {address} + ({index} * {size})
2921+ {body}
2922+ {index} = {index} + 1
2923+ }})
2924+ " ,
2925+ ) ;
2926+
2927+ results. push ( address. clone ( ) ) ;
2928+ results. push ( format ! ( "({op}).length()" ) ) ;
2929+
2930+ if realloc. is_none ( ) {
2931+ self . cleanup . push ( Cleanup { address } ) ;
2932+ }
2933+ }
2934+
2935+ Instruction :: MapLift { key, value, .. } => {
2936+ let Block {
2937+ body,
2938+ results : block_results,
2939+ } = self . blocks . pop ( ) . unwrap ( ) ;
2940+ let address = & operands[ 0 ] ;
2941+ let length = & operands[ 1 ] ;
2942+ let map = self . locals . tmp ( "map" ) ;
2943+ let key_ty = self . resolve_type_name ( key) ;
2944+ let value_ty = self . resolve_type_name ( value) ;
2945+ let entry = self . interface_gen . world_gen . sizes . record ( [ * key, * value] ) ;
2946+ let size = entry. size . size_wasm32 ( ) ;
2947+ let index = self . locals . tmp ( "index" ) ;
2948+
2949+ let ( body_key, body_value) = match & block_results[ ..] {
2950+ [ k, v] => ( k, v) ,
2951+ _ => todo ! (
2952+ "expected 2 results from map lift block, got {}" ,
2953+ block_results. len( )
2954+ ) ,
2955+ } ;
2956+
2957+ self . use_ffi ( ffi:: FREE ) ;
2958+ uwrite ! (
2959+ self . src,
2960+ "
2961+ let {map} : Map[{key_ty}, {value_ty}] = {{}}
2962+ for {index} = 0; {index} < ({length}); {index} = {index} + 1 {{
2963+ let iter_base = ({address}) + ({index} * {size})
2964+ {body}
2965+ {map}[{body_key}] = {body_value}
2966+ }}
2967+ mbt_ffi_free({address})
2968+ " ,
2969+ ) ;
2970+
2971+ results. push ( map) ;
2972+ }
2973+
2974+ Instruction :: IterMapKey { .. } => results. push ( "iter_map_key" . into ( ) ) ,
2975+
2976+ Instruction :: IterMapValue { .. } => results. push ( "iter_map_value" . into ( ) ) ,
2977+
2978+ Instruction :: GuestDeallocateMap { key, value } => {
2979+ let Block { body, results, .. } = self . blocks . pop ( ) . unwrap ( ) ;
2980+ assert ! ( results. is_empty( ) ) ;
2981+
2982+ let address = & operands[ 0 ] ;
2983+ let length = & operands[ 1 ] ;
2984+
2985+ let entry = self . interface_gen . world_gen . sizes . record ( [ * key, * value] ) ;
2986+ let size = entry. size . size_wasm32 ( ) ;
2987+
2988+ if !body. trim ( ) . is_empty ( ) {
2989+ let index = self . locals . tmp ( "index" ) ;
2990+
2991+ uwrite ! (
2992+ self . src,
2993+ "
2994+ for {index} = 0; {index} < ({length}); {index} = {index} + 1 {{
2995+ let iter_base = ({address}) + ({index} * {size})
2996+ {body}
2997+ }}
2998+ "
2999+ ) ;
3000+ }
3001+
3002+ self . use_ffi ( ffi:: FREE ) ;
3003+ uwriteln ! ( self . src, "mbt_ffi_free({address})" , ) ;
28983004 }
28993005 }
29003006 }
0 commit comments