Răsfoiți Sursa

+ support 'suspending last' externals as well

Nikolay Nikolov 2 ani în urmă
părinte
comite
0f89852908

+ 5 - 0
compiler/pdecsub.pas

@@ -2406,6 +2406,11 @@ begin
              consume(_SUSPENDING);
              include(procoptions,po_wasm_suspending);
              synthetickind:=tsk_wasm_suspending;
+             if idtoken=_LAST then
+               begin
+                 consume(_LAST);
+                 synthetickind:=tsk_wasm_suspending_last;
+               end;
            end;
           { default is to used the realname of the procedure }
           if (import_nr=0) and not assigned(import_name) then

+ 2 - 1
compiler/symconst.pas

@@ -506,7 +506,8 @@ type
     tsk_block_invoke_procvar,  // Call a procvar to invoke inside a block
     tsk_interface_wrapper,     // Call through to a method from an interface wrapper
     tsk_call_no_parameters,    // Call skpara procedure without passing any parameters nor returning a result
-    tsk_wasm_suspending,       // WebAssembly suspending external wrapper
+    tsk_wasm_suspending,       // WebAssembly suspending external wrapper, suspender object is first argument
+    tsk_wasm_suspending_last,  // WebAssembly suspending external wrapper, suspender object is last argument
     tsk_wasm_promising         // WebAssembly promising export wrapper
   );
 

+ 20 - 6
compiler/symcreat.pas

@@ -917,7 +917,7 @@ implementation
         end;
     end;
 
-  procedure implement_wasm_suspending(pd: tcpuprocdef);
+  procedure implement_wasm_suspending(pd: tcpuprocdef; last: Boolean);
     var
       str: ansistring;
       wrapper_name: ansistring;
@@ -928,10 +928,21 @@ implementation
         str:='procedure '
       else
         str:='function ';
-      str:=str+wrapper_name+'(__fpc_wasm_susp: WasmExternRef;';
-      addvisibleparameterdeclarations(str,pd);
-      if str[Length(str)]=';' then
-        delete(str,Length(str),1);
+      str:=str+wrapper_name+'(';
+      if last then
+        begin
+          addvisibleparameterdeclarations(str,pd);
+          if str[Length(str)]<>'(' then
+            str:=str+';';
+          str:=str+'__fpc_wasm_susp: WasmExternRef';
+        end
+      else
+        begin
+          str:=str+'__fpc_wasm_susp: WasmExternRef;';
+          addvisibleparameterdeclarations(str,pd);
+          if str[Length(str)]=';' then
+            delete(str,Length(str),1);
+        end;
       str:=str+')';
       if not is_void(pd.returndef) then
         str:=str+': '+pd.returndef.fulltypename;
@@ -1229,11 +1240,14 @@ implementation
 {$endif jvm}
 {$ifdef wasm}
             tsk_wasm_suspending:
-              implement_wasm_suspending(tcpuprocdef(pd));
+              implement_wasm_suspending(tcpuprocdef(pd),false);
+            tsk_wasm_suspending_last:
+              implement_wasm_suspending(tcpuprocdef(pd),true);
             tsk_wasm_promising:
               implement_wasm_promising(tcpuprocdef(pd));
 {$else wasm}
             tsk_wasm_suspending,
+            tsk_wasm_suspending_last,
             tsk_wasm_promising:
               internalerror(2023061107);
 {$endif wasm}

+ 2 - 0
compiler/tokens.pas

@@ -141,6 +141,7 @@ type
     _FILE,
     _GOTO,
     _HUGE,
+    _LAST,
     _NAME,
     _NEAR,
     _READ,
@@ -486,6 +487,7 @@ const
       (str:'FILE'          ;special:false;keyword:alllanguagemodes;op:NOTOKEN),
       (str:'GOTO'          ;special:false;keyword:alllanguagemodes;op:NOTOKEN),
       (str:'HUGE'          ;special:false;keyword:[m_none];op:NOTOKEN),
+      (str:'LAST'          ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'NAME'          ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'NEAR'          ;special:false;keyword:[m_none];op:NOTOKEN),
       (str:'READ'          ;special:false;keyword:[m_none];op:NOTOKEN),

+ 34 - 0
tests/test/wasm/tjspromise2.pp

@@ -0,0 +1,34 @@
+{ %cpu=wasm32 }
+{ %norun }
+
+library tjspromise2;
+
+var
+  state: double;
+
+function init_state: double; external 'js';
+function compute_delta: double; external 'js' suspending last;
+
+procedure init;
+begin
+  state := init_state;
+end;
+
+function get_state: double;
+begin
+  get_state := state;
+end;
+
+function update_state: double;
+begin
+  state := state + compute_delta;
+  update_state := state;
+end;
+
+exports
+  get_state,
+  update_state promising;
+
+begin
+  init;
+end.