@@ -5,7 +5,7 @@ use heck::ToUpperCamelCase;
55use std:: fmt:: Write ;
66use std:: mem;
77use std:: ops:: Deref ;
8- use wit_bindgen_core:: abi:: { self , Bindgen , Bitcast , Instruction } ;
8+ use wit_bindgen_core:: abi:: { Bindgen , Bitcast , Instruction } ;
99use wit_bindgen_core:: { Direction , Ns , uwrite, uwriteln} ;
1010use wit_parser:: abi:: WasmType ;
1111use wit_parser:: {
@@ -32,7 +32,7 @@ pub(crate) struct FunctionBindgen<'a, 'b> {
3232 is_block : bool ,
3333 fixed_statments : Vec < Fixed > ,
3434 parameter_type : ParameterType ,
35- result_type : Option < Type > ,
35+ pub ( crate ) result_type : Option < Type > ,
3636 pub ( crate ) resource_type_name : Option < String > ,
3737}
3838
@@ -384,7 +384,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
384384 ret
385385 }
386386
387- fn emit_allocation_for_type ( & mut self , results : & [ WasmType ] ) -> String {
387+ pub fn emit_allocation_for_type ( & mut self , results : & [ WasmType ] ) -> String {
388388 let address = self . locals . tmp ( "address" ) ;
389389 let buffer_size = self . get_size_for_type ( results) ;
390390 let align = self . get_align_for_type ( results) ;
@@ -1030,40 +1030,23 @@ impl Bindgen for FunctionBindgen<'_, '_> {
10301030 }
10311031
10321032 Instruction :: CallWasm { sig, .. } => {
1033- let is_async = InterfaceGenerator :: is_async ( self . kind ) ;
1034-
1035- let requires_async_return_buffer_param = is_async && sig. results . len ( ) >= 1 ;
1036- let async_return_buffer = if requires_async_return_buffer_param {
1037- let buffer = self . emit_allocation_for_type ( & sig. results ) ;
1038- uwriteln ! ( self . src, "//TODO: store somewhere with the TaskCompletionSource, possibly in the state, using Task.AsyncState to retrieve it later." ) ;
1039- Some ( buffer)
1040- } else {
1041- None
1042- } ;
1043-
1033+ let mut result = String :: new ( ) ;
10441034 let assignment = match & sig. results [ ..] {
10451035 [ _] => {
1046- let result = self . locals . tmp ( "result" ) ;
1036+ result = self . locals . tmp ( "result" ) ;
10471037 let assignment = format ! ( "var {result} = " ) ;
1048- if !requires_async_return_buffer_param {
1049- results. push ( result) ;
1050- }
10511038 assignment
10521039 }
10531040
1054- [ ] => String :: new ( ) ,
1041+ [ ] => {
1042+ String :: new ( )
1043+ }
10551044
10561045 _ => unreachable ! ( ) ,
10571046 } ;
10581047
10591048 let func_name = self . func_name . to_upper_camel_case ( ) ;
1060-
1061- // Async functions that return a result need to pass a buffer where the result will later be written.
1062- let operands = match async_return_buffer {
1063- Some ( ref buffer) if operands. is_empty ( ) => buffer. clone ( ) ,
1064- Some ( ref buffer) => format ! ( "{}, {}" , operands. join( ", " ) , buffer) ,
1065- None => operands. join ( ", " ) ,
1066- } ;
1049+ let operands = operands. join ( ", " ) ;
10671050
10681051 let ( _namespace, interface_name) =
10691052 & CSharp :: get_class_name_from_qualified_name ( self . interface_gen . name ) ;
@@ -1093,18 +1076,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
10931076 "{assignment} {interop_name}{resource_type_name}.{func_name}WasmInterop.wasmImport{func_name}({operands});"
10941077 ) ;
10951078
1096- if let Some ( buffer) = async_return_buffer {
1097- let result = abi:: lift_from_memory (
1098- self . interface_gen . resolve ,
1099- self ,
1100- buffer. clone ( ) ,
1101- & self . result_type . unwrap ( ) ,
1102- ) ;
1103- uwriteln ! (
1104- self . src,
1105- "global::System.Runtime.InteropServices.NativeMemory.Free({});" ,
1106- buffer
1107- ) ;
1079+ if sig. results . len ( ) >= 1 {
11081080 results. push ( result) ;
11091081 }
11101082 }
@@ -1177,9 +1149,21 @@ impl Bindgen for FunctionBindgen<'_, '_> {
11771149 {name}TaskReturn({ret_param});
11781150 return (uint)CallbackCode.Exit;
11791151 }}
1152+
1153+ ret.ContinueWith(t =>
1154+ {{
1155+ if (t.IsFaulted)
1156+ {{
1157+ // TODO
1158+ Console.Error.WriteLine("Async function {name} IsFaulted. This scenario is not yet implemented.");
1159+ throw new NotImplementedException("Async function {name} IsFaulted. This scenario is not yet implemented.");
1160+ }}
1161+
1162+ {name}TaskReturn({ret_param});
1163+ }});
11801164
11811165 // TODO: Defer dropping borrowed resources until a result is returned.
1182- return (uint)CallbackCode.Yield ;
1166+ return (uint)CallbackCode.Wait | (uint)(AsyncSupport.WaitableSet.Handle << 4) ;
11831167 "# ) ;
11841168 }
11851169
@@ -1400,31 +1384,53 @@ impl Bindgen for FunctionBindgen<'_, '_> {
14001384 results. extend ( operands. iter ( ) . take ( * amt) . cloned ( ) ) ;
14011385 }
14021386
1403- Instruction :: FutureLower { payload, ty } => {
1387+ Instruction :: FutureLower { payload, ty }
1388+ | Instruction :: StreamLower { payload, ty } => {
14041389 let op = & operands[ 0 ] ;
14051390 let generic_type_name = match payload {
14061391 Some ( generic_type) => {
14071392 & self . interface_gen . type_name_with_qualifier ( generic_type, false )
14081393 }
14091394 None => ""
14101395 } ;
1411- self . interface_gen . add_future ( self . func_name , & generic_type_name, ty) ;
1396+
1397+ match inst {
1398+ Instruction :: FutureLower { .. } => {
1399+ self . interface_gen . add_future ( self . func_name , & generic_type_name, ty) ;
1400+ }
1401+ _ => {
1402+ self . interface_gen . add_stream ( self . func_name , & generic_type_name, ty) ;
1403+ }
1404+ }
14121405
14131406 results. push ( format ! ( "{op}.TakeHandle()" ) ) ;
14141407 }
14151408
14161409 Instruction :: AsyncTaskReturn { name : _, params : _ } => {
1417- uwriteln ! ( self . src, "// TODO_task_cancel .forget();" ) ;
1410+ uwriteln ! ( self . src, "// TODO: task_cancel .forget();" ) ;
14181411 }
14191412
1420- Instruction :: FutureLift { payload, ty } => {
1413+ Instruction :: FutureLift { payload, ty }
1414+ | Instruction :: StreamLift { payload, ty } => {
1415+ let generic_type_name_with_qualifier = match payload {
1416+ Some ( generic_type) => {
1417+ & self . interface_gen . type_name_with_qualifier ( generic_type, true )
1418+ }
1419+ None => ""
1420+ } ;
14211421 let generic_type_name = match payload {
14221422 Some ( generic_type) => {
14231423 & self . interface_gen . type_name_with_qualifier ( generic_type, false )
14241424 }
14251425 None => ""
14261426 } ;
14271427 let upper_camel = generic_type_name. to_upper_camel_case ( ) ;
1428+ let bracketed_generic = match payload {
1429+ Some ( _) => {
1430+ format ! ( "<{generic_type_name_with_qualifier}>" )
1431+ }
1432+ None => String :: new ( )
1433+ } ;
14281434 // let sig_type_name = "Void";
14291435 let reader_var = self . locals . tmp ( "reader" ) ;
14301436 let module = self . interface_gen . name ;
@@ -1435,16 +1441,29 @@ impl Bindgen for FunctionBindgen<'_, '_> {
14351441 . strip_prefix ( "I" ) . unwrap ( )
14361442 . replace ( "Imports" , "Exports" ) ; // TODO: This is fragile and depends on the interface name.
14371443
1438- uwriteln ! ( self . src, "var {reader_var} = new FutureReader({}, {export_name}.{base_interface_name}Interop.FutureVTable{});" , operands[ 0 ] , upper_camel) ;
1444+ let future_stream_name = match inst {
1445+ Instruction :: FutureLift { payload : _, ty : _} => "Future" ,
1446+ Instruction :: StreamLift { payload : _, ty : _} => "Stream" ,
1447+ _ => {
1448+ panic ! ( "Unexpected instruction for lift" ) ;
1449+ }
1450+ } ;
1451+ uwriteln ! ( self . src, "var {reader_var} = new {future_stream_name}Reader{bracketed_generic}({}, {export_name}.{base_interface_name}Interop.{future_stream_name}VTable{});" , operands[ 0 ] , upper_camel) ;
14391452 results. push ( reader_var) ;
14401453
1441- self . interface_gen . add_future ( self . func_name , & generic_type_name, ty) ;
1454+ match inst {
1455+ Instruction :: FutureLift { .. } => {
1456+ self . interface_gen . add_future ( self . func_name , & generic_type_name, ty) ;
1457+ }
1458+ _ => {
1459+ self . interface_gen . add_stream ( self . func_name , & generic_type_name, ty) ;
1460+ }
1461+ }
1462+
14421463 self . interface_gen . csharp_gen . needs_async_support = true ;
14431464 }
14441465
1445- Instruction :: StreamLower { .. }
1446- | Instruction :: StreamLift { .. }
1447- | Instruction :: ErrorContextLower { .. }
1466+ Instruction :: ErrorContextLower { .. }
14481467 | Instruction :: ErrorContextLift { .. }
14491468 | Instruction :: DropHandle { .. }
14501469 | Instruction :: FixedLengthListLift { .. }
0 commit comments