@@ -58,6 +58,7 @@ type frame =
58
58
}
59
59
60
60
type code = value stack * admin_instr list
61
+ and handler_name = exn
61
62
62
63
and admin_instr = admin_instr' phrase
63
64
and admin_instr' =
@@ -72,25 +73,28 @@ and admin_instr' =
72
73
| Label of int * instr list * code
73
74
| Frame of int * frame * code
74
75
| Handler of int * catch list * code
75
- | Handle of handle_table * code
76
- | Suspending of tag_inst * value stack * ref_ option * ctxt
76
+ | Handle of handler_name option * handle_table option * code
77
+ | Suspending of tag_inst * value stack * ref_ option * ref_ option * ctxt
77
78
78
79
and ctxt = code -> code
79
80
and handle_table = (tag_inst * idx) list * tag_inst list
80
81
81
82
type cont = int32 * ctxt (* TODO: represent type properly *)
82
83
type ref_ + = ContRef of cont option ref
84
+ type ref_ + = HandlerRef of handler_name option ref
83
85
84
86
let () =
85
87
let type_of_ref' = ! Value. type_of_ref' in
86
88
Value. type_of_ref' := function
87
89
| ContRef _ -> ContHT
90
+ | HandlerRef _ -> HandlerHT
88
91
| r -> type_of_ref' r
89
92
90
93
let () =
91
94
let string_of_ref' = ! Value. string_of_ref' in
92
95
Value. string_of_ref' := function
93
96
| ContRef _ -> " cont"
97
+ | HandlerRef _ -> " handler"
94
98
| r -> string_of_ref' r
95
99
96
100
let plain e = Plain e.it @@ e.at
@@ -379,7 +383,18 @@ let rec step (c : config) : config =
379
383
let tagt = tag c.frame.inst x in
380
384
let FuncT (ts, _) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
381
385
let args, vs' = i32_split (Lib.List32. length ts) vs e.at in
382
- vs', [Suspending (tagt, args, None , fun code -> code) @@ e.at]
386
+ vs', [Suspending (tagt, args, None , None , fun code -> code) @@ e.at]
387
+
388
+ | SuspendTo (x , y ), vs ->
389
+ let tagt = tag c.frame.inst y in
390
+ let FuncT (ts, _) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
391
+ let args, vs' = i32_split (Lib.List32. length ts) vs e.at in
392
+ let args, href =
393
+ match Lib.List. lead args, Lib.List. last args with
394
+ | args , Ref r -> args, r
395
+ | _ -> Crash. error e.at " type mismatch at suspend to"
396
+ in
397
+ vs', [Suspending (tagt, args, None , Some href, fun code -> code) @@ e.at]
383
398
384
399
| Resume (x , xls ), Ref (NullRef _ ) :: vs ->
385
400
vs, [Trapping " null continuation reference" @@ e.at]
@@ -391,7 +406,7 @@ let rec step (c : config) : config =
391
406
let hs = handle_table c xls in
392
407
let args, vs' = i32_split n vs e.at in
393
408
cont := None ;
394
- vs', [Handle (hs, ctxt (args, [] )) @@ e.at]
409
+ vs', [Handle (None , Some hs, ctxt (args, [] )) @@ e.at]
395
410
396
411
| ResumeThrow (x , y , xls ), Ref (NullRef _ ) :: vs ->
397
412
vs, [Trapping " null continuation reference" @@ e.at]
@@ -405,7 +420,24 @@ let rec step (c : config) : config =
405
420
let hs = handle_table c xls in
406
421
let args, vs' = i32_split (Lib.List32. length ts) vs e.at in
407
422
cont := None ;
408
- vs', [Handle (hs, ctxt ([] , [Throwing (tagt, args) @@ e.at])) @@ e.at]
423
+ vs', [Handle (None , Some hs, ctxt ([] , [Throwing (tagt, args) @@ e.at])) @@ e.at]
424
+
425
+ | ResumeWith (x , xls ), Ref (NullRef _ ) :: vs ->
426
+ vs, [Trapping " null continuation reference" @@ e.at]
427
+
428
+ | ResumeWith (x , xls ), Ref (ContRef {contents = None } ) :: vs ->
429
+ vs, [Trapping " continuation already consumed" @@ e.at]
430
+
431
+ | ResumeWith (x , xls ), Ref (ContRef ({contents = Some (n , ctxt )} as cont )) :: vs ->
432
+ let hs = handle_table c xls in
433
+ Printf. printf " arity: %s\n %!" (I32. to_string_u n);
434
+ let args, vs' = i32_split (I32. sub n 1l ) vs e.at in
435
+ let exception Name in
436
+ let name =
437
+ Ref (HandlerRef (ref (Some Name )))
438
+ in
439
+ cont := None ;
440
+ vs', [Handle (Some Name , Some hs, ctxt (args @ [name], [] )) @@ e.at]
409
441
410
442
| Switch (x , y ), Ref (NullRef _ ) :: vs ->
411
443
vs, [Trapping " null continuation reference" @@ e.at]
@@ -416,7 +448,7 @@ let rec step (c : config) : config =
416
448
| Switch (x , y ), Ref (ContRef {contents = Some (n , ctxt )} as cont ) :: vs ->
417
449
let tagt = tag c.frame.inst y in
418
450
let args, vs' = i32_split (Int32. sub n 1l ) vs e.at in
419
- vs', [Suspending (tagt, args, Some cont, fun code -> code) @@ e.at]
451
+ vs', [Suspending (tagt, args, Some cont, None , fun code -> code) @@ e.at]
420
452
421
453
| ReturnCall x , vs ->
422
454
(match (step {c with code = (vs, [Plain (Call x) @@ e.at])}).code with
@@ -1177,9 +1209,9 @@ let rec step (c : config) : config =
1177
1209
| Label (n , es0 , (vs' , [] )), vs ->
1178
1210
vs' @ vs, []
1179
1211
1180
- | Label (n , es0 , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1212
+ | Label (n , es0 , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1181
1213
let ctxt' code = [], [Label (n, es0, compose (ctxt code) (vs', es')) @@ e.at] in
1182
- vs, [Suspending (tagt, vs1, contref, ctxt') @@ at]
1214
+ vs, [Suspending (tagt, vs1, contref, href, ctxt') @@ at]
1183
1215
1184
1216
| Label (n , es0 , (vs' , {it = ReturningInvoke (vs0 , f ); at} :: es' )), vs ->
1185
1217
vs, [ReturningInvoke (vs0, f) @@ at]
@@ -1206,9 +1238,9 @@ let rec step (c : config) : config =
1206
1238
| Frame (n , frame' , (vs' , {it = Throwing (a , vs0 ); at} :: es' )), vs ->
1207
1239
vs, [Throwing (a, vs0) @@ at]
1208
1240
1209
- | Frame (n , frame' , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1241
+ | Frame (n , frame' , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1210
1242
let ctxt' code = [], [Frame (n, frame', compose (ctxt code) (vs', es')) @@ e.at] in
1211
- vs, [Suspending (tagt, vs1, contref, ctxt') @@ at]
1243
+ vs, [Suspending (tagt, vs1, contref, href, ctxt') @@ at]
1212
1244
1213
1245
| Frame (n , frame' , (vs' , {it = Returning vs0 ; at} :: es' )), vs ->
1214
1246
take n vs0 e.at @ vs, []
@@ -1248,9 +1280,9 @@ let rec step (c : config) : config =
1248
1280
| Handler (n , [] , (vs' , {it = Throwing (a , vs0 ); at} :: es' )), vs ->
1249
1281
vs, [Throwing (a, vs0) @@ at]
1250
1282
1251
- | Handler (n , cs , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1283
+ | Handler (n , cs , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1252
1284
let ctxt' code = [], [Handler (n, cs, compose (ctxt code) (vs', es')) @@ e.at] in
1253
- vs, [Suspending (tagt, vs1, contref, ctxt') @@ at]
1285
+ vs, [Suspending (tagt, vs1, contref, href, ctxt') @@ at]
1254
1286
1255
1287
| Handler (n , cs , (vs' , e' :: es' )), vs when is_jumping e' ->
1256
1288
vs, [e']
@@ -1282,37 +1314,45 @@ let rec step (c : config) : config =
1282
1314
with Crash (_ , msg ) -> Crash. error e.at msg)
1283
1315
)
1284
1316
1285
- | Handle (hso , (vs' , [] )), vs ->
1317
+ | Handle (name , hso , (vs' , [] )), vs ->
1286
1318
vs' @ vs, []
1287
1319
1288
- | Handle ((hs, _), (vs', {it = Suspending (tagt, vs1, None , ctxt); at} :: es')), vs
1320
+ | Handle (name, Some (hs, _), (vs', {it = Suspending (tagt, vs1, None , None , ctxt); at} :: es')), vs
1289
1321
when List. mem_assq tagt hs ->
1290
1322
let FuncT (_, ts) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
1291
1323
let ctxt' code = compose (ctxt code) (vs', es') in
1292
1324
[Ref (ContRef (ref (Some (Lib.List32. length ts, ctxt'))))] @ vs1 @ vs,
1293
1325
[Plain (Br (List. assq tagt hs)) @@ e.at]
1294
1326
1295
- | Handle ((_, hs) as hso, (vs', {it = Suspending (tagt, vs1, Some (ContRef ({contents = Some (_, ctxt)} as cont)), ctxt'); at} :: es')), vs
1327
+ | Handle (Some h, Some (hs, _), (vs', {it = Suspending (tagt, vs1, None , Some (HandlerRef ({contents = Some h'} as href)), ctxt); at} :: es')), vs
1328
+ when h == h' && List. mem_assq tagt hs ->
1329
+ let FuncT (_, ts) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
1330
+ let ctxt' code = compose (ctxt code) (vs', es') in
1331
+ href := None ;
1332
+ [Ref (ContRef (ref (Some (Int32. add (Lib.List32. length ts) 1l , ctxt'))))] @ vs1 @ vs,
1333
+ [Plain (Br (List. assq tagt hs)) @@ e.at]
1334
+
1335
+ | Handle (None , (Some (_, hs) as hso), (vs', {it = Suspending (tagt, vs1, Some (ContRef ({contents = Some (_, ctxt)} as cont)), None , ctxt'); at} :: es')), vs
1296
1336
when List. memq tagt hs ->
1297
1337
let FuncT (_, ts) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
1298
1338
let ctxt'' code = compose (ctxt' code) (vs', es') in
1299
1339
let cont' = Ref (ContRef (ref (Some (Int32. add (Lib.List32. length ts) 1l , ctxt'')))) in
1300
1340
let args = cont' :: vs1 in
1301
1341
cont := None ;
1302
- vs' @ vs, [Handle (hso, ctxt (args, [] )) @@ e.at]
1342
+ vs' @ vs, [Handle (None , hso, ctxt (args, [] )) @@ e.at]
1303
1343
1304
- | Handle (hso , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1305
- let ctxt' code = [], [Handle (hso, compose (ctxt code) (vs', es')) @@ e.at] in
1306
- vs, [Suspending (tagt, vs1, contref, ctxt') @@ at]
1344
+ | Handle (name , hso , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1345
+ let ctxt' code = [], [Handle (name, hso, compose (ctxt code) (vs', es')) @@ e.at] in
1346
+ vs, [Suspending (tagt, vs1, contref, href, ctxt') @@ at]
1307
1347
1308
- | Handle (hso , (vs' , e' :: es' )), vs when is_jumping e' ->
1348
+ | Handle (name , hso , (vs' , e' :: es' )), vs when is_jumping e' ->
1309
1349
vs, [e']
1310
1350
1311
- | Handle (hso , code' ), vs ->
1351
+ | Handle (name , hso , code' ), vs ->
1312
1352
let c' = step {c with code = code'} in
1313
- vs, [Handle (hso, c'.code) @@ e.at]
1353
+ vs, [Handle (name, hso, c'.code) @@ e.at]
1314
1354
1315
- | Suspending (_ , _ , _ , _ ), _ -> assert false
1355
+ | Suspending (_ , _ , _ , _ , _ ), _ -> assert false
1316
1356
1317
1357
in {c with code = vs', es' @ List. tl es}
1318
1358
0 commit comments