1- use crate :: { Capture , ExitError , ExitFatal , ExitResult , Invoker } ;
1+ use crate :: { Capture , ExitError , ExitFatal , ExitResult , Invoker , InvokerControl } ;
22use core:: convert:: Infallible ;
33
44struct Substack < M , TrD > {
@@ -123,6 +123,7 @@ where
123123 . pop ( )
124124 . expect ( "checked stack is not empty above; qed" ) ;
125125
126+ let machine = self . invoker . deconstruct_machine ( machine) ;
126127 let feedback_result = self . invoker . exit_substack (
127128 exit,
128129 machine,
@@ -153,7 +154,7 @@ where
153154 self . backend ,
154155 self . initial_depth + self . stack . len ( ) + 1 ,
155156 ) {
156- Capture :: Exit ( Ok ( ( trap_data, sub_machine) ) ) => {
157+ Capture :: Exit ( Ok ( ( trap_data, InvokerControl :: Enter ( sub_machine) ) ) ) => {
157158 self . stack . push ( Substack {
158159 invoke : trap_data,
159160 machine,
@@ -164,6 +165,29 @@ where
164165 machine : sub_machine,
165166 } )
166167 }
168+ Capture :: Exit ( Ok ( (
169+ trap_data,
170+ InvokerControl :: DirectExit ( ( exit, sub_machine) ) ,
171+ ) ) ) => {
172+ let feedback_result = self . invoker . exit_substack (
173+ exit,
174+ sub_machine,
175+ trap_data,
176+ & mut machine,
177+ self . backend ,
178+ ) ;
179+
180+ match feedback_result {
181+ Ok ( ( ) ) => Some ( LastSubstack {
182+ status : LastSubstackStatus :: Running ,
183+ machine,
184+ } ) ,
185+ Err ( err) => Some ( LastSubstack {
186+ machine,
187+ status : LastSubstackStatus :: Exited ( Capture :: Exit ( Err ( err) ) ) ,
188+ } ) ,
189+ }
190+ }
167191 Capture :: Exit ( Err ( err) ) => Some ( LastSubstack {
168192 status : LastSubstackStatus :: Exited ( Capture :: Exit ( Err ( err) ) ) ,
169193 machine,
@@ -204,7 +228,7 @@ where
204228 Capture :: Exit ( exit) => return Ok ( ( exit, machine) ) ,
205229 Capture :: Trap ( trap) => {
206230 match invoker. enter_substack ( trap, & mut machine, backend, initial_depth + 1 ) {
207- Capture :: Exit ( Ok ( ( trap_data, sub_machine) ) ) => {
231+ Capture :: Exit ( Ok ( ( trap_data, InvokerControl :: Enter ( sub_machine) ) ) ) => {
208232 let ( sub_result, sub_machine) = if heap_depth
209233 . map ( |hd| initial_depth + 1 >= hd)
210234 . unwrap_or ( false )
@@ -219,6 +243,23 @@ where
219243 execute ( sub_machine, initial_depth + 1 , heap_depth, backend, invoker) ?
220244 } ;
221245
246+ match invoker. exit_substack (
247+ sub_result,
248+ invoker. deconstruct_machine ( sub_machine) ,
249+ trap_data,
250+ & mut machine,
251+ backend,
252+ ) {
253+ Ok ( ( ) ) => {
254+ result = invoker. run_machine ( & mut machine, backend) ;
255+ }
256+ Err ( err) => return Ok ( ( Err ( err) , machine) ) ,
257+ }
258+ }
259+ Capture :: Exit ( Ok ( (
260+ trap_data,
261+ InvokerControl :: DirectExit ( ( sub_result, sub_machine) ) ,
262+ ) ) ) => {
222263 match invoker. exit_substack (
223264 sub_result,
224265 sub_machine,
@@ -240,11 +281,22 @@ where
240281 }
241282}
242283
243- pub struct HeapTransact < ' backend , ' invoker , H , Tr , I : Invoker < H , Tr > > {
244- call_stack : CallStack < ' backend , ' invoker , H , Tr , I > ,
245- transact_invoke : I :: TransactInvoke ,
284+ enum HeapTransactState < ' backend , ' invoker , H , Tr , I : Invoker < H , Tr > > {
285+ Created {
286+ args : I :: TransactArgs ,
287+ invoker : & ' invoker I ,
288+ backend : & ' backend mut H ,
289+ } ,
290+ Running {
291+ call_stack : CallStack < ' backend , ' invoker , H , Tr , I > ,
292+ transact_invoke : I :: TransactInvoke ,
293+ } ,
246294}
247295
296+ pub struct HeapTransact < ' backend , ' invoker , H , Tr , I : Invoker < H , Tr > > (
297+ Option < HeapTransactState < ' backend , ' invoker , H , Tr , I > > ,
298+ ) ;
299+
248300impl < ' backend , ' invoker , H , Tr , I > HeapTransact < ' backend , ' invoker , H , Tr , I >
249301where
250302 I : Invoker < H , Tr > ,
@@ -254,13 +306,11 @@ where
254306 invoker : & ' invoker I ,
255307 backend : & ' backend mut H ,
256308 ) -> Result < Self , ExitError > {
257- let ( transact_invoke, machine) = invoker. new_transact ( args, backend) ?;
258- let call_stack = CallStack :: new ( machine, 0 , backend, invoker) ;
259-
260- Ok ( Self {
261- transact_invoke,
262- call_stack,
263- } )
309+ Ok ( Self ( Some ( HeapTransactState :: Created {
310+ args,
311+ invoker,
312+ backend,
313+ } ) ) )
264314 }
265315
266316 fn step_with < FS > (
@@ -269,22 +319,70 @@ where
269319 ) -> Result < ( ) , Capture < Result < I :: TransactValue , ExitError > , I :: Interrupt > >
270320 where
271321 FS : Fn (
272- & mut CallStack < H , Tr , I > ,
322+ & mut CallStack < ' backend , ' invoker , H , Tr , I > ,
273323 ) -> Result < ( ) , Capture < Result < ( ExitResult , I :: Machine ) , ExitFatal > , I :: Interrupt > > ,
274324 {
275- match fs ( & mut self . call_stack ) {
276- Ok ( ( ) ) => Ok ( ( ) ) ,
277- Err ( Capture :: Trap ( interrupt) ) => Err ( Capture :: Trap ( interrupt) ) ,
278- Err ( Capture :: Exit ( Err ( fatal) ) ) => Err ( Capture :: Exit ( Err ( fatal. into ( ) ) ) ) ,
279- Err ( Capture :: Exit ( Ok ( ( ret, machine) ) ) ) => {
280- Err ( Capture :: Exit ( self . call_stack . invoker . finalize_transact (
281- & self . transact_invoke ,
282- ret,
283- machine,
284- self . call_stack . backend ,
285- ) ) )
325+ let ret;
326+
327+ self . 0 = match self . 0 . take ( ) {
328+ Some ( HeapTransactState :: Running {
329+ mut call_stack,
330+ transact_invoke,
331+ } ) => {
332+ ret = match fs ( & mut call_stack) {
333+ Ok ( ( ) ) => Ok ( ( ) ) ,
334+ Err ( Capture :: Trap ( interrupt) ) => Err ( Capture :: Trap ( interrupt) ) ,
335+ Err ( Capture :: Exit ( Err ( fatal) ) ) => Err ( Capture :: Exit ( Err ( fatal. into ( ) ) ) ) ,
336+ Err ( Capture :: Exit ( Ok ( ( ret, machine) ) ) ) => {
337+ let machine = call_stack. invoker . deconstruct_machine ( machine) ;
338+ Err ( Capture :: Exit ( call_stack. invoker . finalize_transact (
339+ & transact_invoke,
340+ ret,
341+ machine,
342+ call_stack. backend ,
343+ ) ) )
344+ }
345+ } ;
346+
347+ Some ( HeapTransactState :: Running {
348+ call_stack,
349+ transact_invoke,
350+ } )
286351 }
287- }
352+ Some ( HeapTransactState :: Created {
353+ args,
354+ invoker,
355+ backend,
356+ } ) => {
357+ let ( transact_invoke, control) = match invoker. new_transact ( args, backend) {
358+ Ok ( ( transact_invoke, control) ) => ( transact_invoke, control) ,
359+ Err ( err) => return Err ( Capture :: Exit ( Err ( err) ) ) ,
360+ } ;
361+
362+ match control {
363+ InvokerControl :: Enter ( machine) => {
364+ let call_stack = CallStack :: new ( machine, 0 , backend, invoker) ;
365+
366+ ret = Ok ( ( ) ) ;
367+ Some ( HeapTransactState :: Running {
368+ call_stack,
369+ transact_invoke,
370+ } )
371+ }
372+ InvokerControl :: DirectExit ( ( exit, machine) ) => {
373+ return Err ( Capture :: Exit ( invoker. finalize_transact (
374+ & transact_invoke,
375+ exit,
376+ machine,
377+ backend,
378+ ) ) ) ;
379+ }
380+ }
381+ }
382+ None => return Err ( Capture :: Exit ( Err ( ExitFatal :: AlreadyExited . into ( ) ) ) ) ,
383+ } ;
384+
385+ ret
288386 }
289387
290388 pub fn step_run (
@@ -309,10 +407,13 @@ where
309407 }
310408 }
311409
312- pub fn last_machine ( & self ) -> Result < & I :: Machine , ExitError > {
313- match & self . call_stack . last {
314- Some ( last) => Ok ( & last. machine ) ,
315- None => Err ( ExitFatal :: AlreadyExited . into ( ) ) ,
410+ pub fn last_machine ( & self ) -> Option < & I :: Machine > {
411+ match & self . 0 {
412+ Some ( HeapTransactState :: Running { call_stack, .. } ) => match & call_stack. last {
413+ Some ( last) => Some ( & last. machine ) ,
414+ None => None ,
415+ } ,
416+ _ => None ,
316417 }
317418 }
318419}
@@ -322,34 +423,47 @@ where
322423 I : Invoker < H , Tr > ,
323424{
324425 fn drop ( & mut self ) {
325- if let Some ( mut last) = self . call_stack . last . take ( ) {
326- loop {
327- if let Some ( mut parent) = self . call_stack . stack . pop ( ) {
328- let _ = self . call_stack . invoker . exit_substack (
329- ExitFatal :: Unfinished . into ( ) ,
330- last. machine ,
331- parent. invoke ,
332- & mut parent. machine ,
333- self . call_stack . backend ,
334- ) ;
426+ if let Some ( state) = self . 0 . take ( ) {
427+ match state {
428+ HeapTransactState :: Running {
429+ mut call_stack,
430+ transact_invoke,
431+ } => {
432+ if let Some ( mut last) = call_stack. last . take ( ) {
433+ loop {
434+ if let Some ( mut parent) = call_stack. stack . pop ( ) {
435+ let last_machine =
436+ call_stack. invoker . deconstruct_machine ( last. machine ) ;
437+ let _ = call_stack. invoker . exit_substack (
438+ ExitFatal :: Unfinished . into ( ) ,
439+ last_machine,
440+ parent. invoke ,
441+ & mut parent. machine ,
442+ call_stack. backend ,
443+ ) ;
444+
445+ last = LastSubstack {
446+ machine : parent. machine ,
447+ status : LastSubstackStatus :: Exited ( Capture :: Exit (
448+ ExitFatal :: Unfinished . into ( ) ,
449+ ) ) ,
450+ } ;
451+ } else {
452+ break ;
453+ }
454+ }
335455
336- last = LastSubstack {
337- machine : parent . machine ,
338- status : LastSubstackStatus :: Exited ( Capture :: Exit (
456+ let last_machine = call_stack . invoker . deconstruct_machine ( last . machine ) ;
457+ let _ = call_stack . invoker . finalize_transact (
458+ & transact_invoke ,
339459 ExitFatal :: Unfinished . into ( ) ,
340- ) ) ,
341- } ;
342- } else {
343- break ;
460+ last_machine ,
461+ call_stack . backend ,
462+ ) ;
463+ }
344464 }
465+ _ => ( ) ,
345466 }
346-
347- let _ = self . call_stack . invoker . finalize_transact (
348- & self . transact_invoke ,
349- ExitFatal :: Unfinished . into ( ) ,
350- last. machine ,
351- self . call_stack . backend ,
352- ) ;
353467 }
354468 }
355469}
@@ -363,7 +477,16 @@ pub fn transact<H, Tr, I>(
363477where
364478 I : Invoker < H , Tr , Interrupt = Infallible > ,
365479{
366- let ( transact_invoke, machine) = invoker. new_transact ( args, backend) ?;
367- let ( ret, machine) = execute ( machine, 0 , heap_depth, backend, invoker) ?;
368- invoker. finalize_transact ( & transact_invoke, ret, machine, backend)
480+ let ( transact_invoke, control) = invoker. new_transact ( args, backend) ?;
481+
482+ match control {
483+ InvokerControl :: Enter ( machine) => {
484+ let ( ret, machine) = execute ( machine, 0 , heap_depth, backend, invoker) ?;
485+ let machine = invoker. deconstruct_machine ( machine) ;
486+ invoker. finalize_transact ( & transact_invoke, ret, machine, backend)
487+ }
488+ InvokerControl :: DirectExit ( ( exit, machine) ) => {
489+ invoker. finalize_transact ( & transact_invoke, exit, machine, backend)
490+ }
491+ }
369492}
0 commit comments