@@ -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,123 @@ 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 { key, value, realloc } => {
2893+ let Block {
2894+ body,
2895+ results : block_results,
2896+ } = self . blocks . pop ( ) . unwrap ( ) ;
2897+ assert ! ( block_results. is_empty( ) ) ;
2898+
2899+ let op = & operands[ 0 ] ;
2900+ let entry = self
2901+ . interface_gen
2902+ . world_gen
2903+ . sizes
2904+ . 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}).size() * {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}).size()" ) ) ;
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
2946+ . interface_gen
2947+ . world_gen
2948+ . sizes
2949+ . record ( [ * key, * value] ) ;
2950+ let size = entry. size . size_wasm32 ( ) ;
2951+ let index = self . locals . tmp ( "index" ) ;
2952+
2953+ let ( body_key, body_value) = match & block_results[ ..] {
2954+ [ k, v] => ( k, v) ,
2955+ _ => todo ! ( "expected 2 results from map lift block, got {}" , block_results. len( ) ) ,
2956+ } ;
2957+
2958+ self . use_ffi ( ffi:: FREE ) ;
2959+ uwrite ! (
2960+ self . src,
2961+ "
2962+ let {map} : Map[{key_ty}, {value_ty}] = {{}}
2963+ for {index} = 0; {index} < ({length}); {index} = {index} + 1 {{
2964+ let iter_base = ({address}) + ({index} * {size})
2965+ {body}
2966+ {map}[{body_key}] = {body_value}
2967+ }}
2968+ mbt_ffi_free({address})
2969+ " ,
2970+ ) ;
2971+
2972+ results. push ( map) ;
2973+ }
2974+
2975+ Instruction :: IterMapKey { .. } => results. push ( "iter_map_key" . into ( ) ) ,
2976+
2977+ Instruction :: IterMapValue { .. } => results. push ( "iter_map_value" . into ( ) ) ,
2978+
2979+ Instruction :: GuestDeallocateMap { key, value } => {
2980+ let Block { body, results, .. } = self . blocks . pop ( ) . unwrap ( ) ;
2981+ assert ! ( results. is_empty( ) ) ;
2982+
2983+ let address = & operands[ 0 ] ;
2984+ let length = & operands[ 1 ] ;
2985+
2986+ let entry = self
2987+ . interface_gen
2988+ . world_gen
2989+ . sizes
2990+ . record ( [ * key, * value] ) ;
2991+ let size = entry. size . size_wasm32 ( ) ;
2992+
2993+ if !body. trim ( ) . is_empty ( ) {
2994+ let index = self . locals . tmp ( "index" ) ;
2995+
2996+ uwrite ! (
2997+ self . src,
2998+ "
2999+ for {index} = 0; {index} < ({length}); {index} = {index} + 1 {{
3000+ let iter_base = ({address}) + ({index} * {size})
3001+ {body}
3002+ }}
3003+ "
3004+ ) ;
3005+ }
3006+
3007+ self . use_ffi ( ffi:: FREE ) ;
3008+ uwriteln ! ( self . src, "mbt_ffi_free({address})" , ) ;
28983009 }
28993010 }
29003011 }
0 commit comments