From 0f89852908219e54e76a72bb21e1847305166d52 Mon Sep 17 00:00:00 2001 From: Nikolay Nikolov Date: Tue, 13 Jun 2023 09:34:54 +0300 Subject: [PATCH] + support 'suspending last' externals as well --- compiler/pdecsub.pas | 5 +++++ compiler/symconst.pas | 3 ++- compiler/symcreat.pas | 26 ++++++++++++++++++++------ compiler/tokens.pas | 2 ++ tests/test/wasm/tjspromise2.pp | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 tests/test/wasm/tjspromise2.pp diff --git a/compiler/pdecsub.pas b/compiler/pdecsub.pas index cd4ba8eb03..593cbce1b6 100644 --- a/compiler/pdecsub.pas +++ b/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 diff --git a/compiler/symconst.pas b/compiler/symconst.pas index b91a65117d..5417564805 100644 --- a/compiler/symconst.pas +++ b/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 ); diff --git a/compiler/symcreat.pas b/compiler/symcreat.pas index 84c0f43c7c..25b4756467 100644 --- a/compiler/symcreat.pas +++ b/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} diff --git a/compiler/tokens.pas b/compiler/tokens.pas index 4257cfdd5b..692e144959 100644 --- a/compiler/tokens.pas +++ b/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), diff --git a/tests/test/wasm/tjspromise2.pp b/tests/test/wasm/tjspromise2.pp new file mode 100644 index 0000000000..33f85ebc23 --- /dev/null +++ b/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.