@@ -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
@@ -377,7 +381,18 @@ let rec step (c : config) : config =
377
381
let tagt = tag c.frame.inst x in
378
382
let FuncT (ts, _) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
379
383
let args, vs' = i32_split (Lib.List32. length ts) vs e.at in
380
- vs', [Suspending (tagt, args, None , fun code -> code) @@ e.at]
384
+ vs', [Suspending (tagt, args, None , None , fun code -> code) @@ e.at]
385
+
386
+ | SuspendTo (x , y ), vs ->
387
+ let tagt = tag c.frame.inst y in
388
+ let FuncT (ts, _) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
389
+ let args, vs' = i32_split (Lib.List32. length ts) vs e.at in
390
+ let args, href =
391
+ match Lib.List. lead args, Lib.List. last args with
392
+ | args , Ref r -> args, r
393
+ | _ -> Crash. error e.at " type mismatch at suspend to"
394
+ in
395
+ vs', [Suspending (tagt, args, None , Some href, fun code -> code) @@ e.at]
381
396
382
397
| Resume (x , xls ), Ref (NullRef _ ) :: vs ->
383
398
vs, [Trapping " null continuation reference" @@ e.at]
@@ -389,7 +404,7 @@ let rec step (c : config) : config =
389
404
let hs = handle_table c xls in
390
405
let args, vs' = i32_split n vs e.at in
391
406
cont := None ;
392
- vs', [Handle (hs, ctxt (args, [] )) @@ e.at]
407
+ vs', [Handle (None , Some hs, ctxt (args, [] )) @@ e.at]
393
408
394
409
| ResumeThrow (x , y , xls ), Ref (NullRef _ ) :: vs ->
395
410
vs, [Trapping " null continuation reference" @@ e.at]
@@ -403,7 +418,24 @@ let rec step (c : config) : config =
403
418
let hs = handle_table c xls in
404
419
let args, vs' = i32_split (Lib.List32. length ts) vs e.at in
405
420
cont := None ;
406
- vs', [Handle (hs, ctxt ([] , [Throwing (tagt, args) @@ e.at])) @@ e.at]
421
+ vs', [Handle (None , Some hs, ctxt ([] , [Throwing (tagt, args) @@ e.at])) @@ e.at]
422
+
423
+ | ResumeWith (x , xls ), Ref (NullRef _ ) :: vs ->
424
+ vs, [Trapping " null continuation reference" @@ e.at]
425
+
426
+ | ResumeWith (x , xls ), Ref (ContRef {contents = None } ) :: vs ->
427
+ vs, [Trapping " continuation already consumed" @@ e.at]
428
+
429
+ | ResumeWith (x , xls ), Ref (ContRef ({contents = Some (n , ctxt )} as cont )) :: vs ->
430
+ let hs = handle_table c xls in
431
+ Printf. printf " arity: %s\n %!" (I32. to_string_u n);
432
+ let args, vs' = i32_split (I32. sub n 1l ) vs e.at in
433
+ let exception Name in
434
+ let name =
435
+ Ref (HandlerRef (ref (Some Name )))
436
+ in
437
+ cont := None ;
438
+ vs', [Handle (Some Name , Some hs, ctxt (args @ [name], [] )) @@ e.at]
407
439
408
440
| Switch (x , y ), Ref (NullRef _ ) :: vs ->
409
441
vs, [Trapping " null continuation reference" @@ e.at]
@@ -414,7 +446,7 @@ let rec step (c : config) : config =
414
446
| Switch (x , y ), Ref (ContRef {contents = Some (n , ctxt )} as cont ) :: vs ->
415
447
let tagt = tag c.frame.inst y in
416
448
let args, vs' = i32_split (Int32. sub n 1l ) vs e.at in
417
- vs', [Suspending (tagt, args, Some cont, fun code -> code) @@ e.at]
449
+ vs', [Suspending (tagt, args, Some cont, None , fun code -> code) @@ e.at]
418
450
419
451
| ReturnCall x , vs ->
420
452
(match (step {c with code = (vs, [Plain (Call x) @@ e.at])}).code with
@@ -1151,9 +1183,9 @@ let rec step (c : config) : config =
1151
1183
| Label (n , es0 , (vs' , [] )), vs ->
1152
1184
vs' @ vs, []
1153
1185
1154
- | Label (n , es0 , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1186
+ | Label (n , es0 , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1155
1187
let ctxt' code = [], [Label (n, es0, compose (ctxt code) (vs', es')) @@ e.at] in
1156
- vs, [Suspending (tagt, vs1, contref, ctxt') @@ at]
1188
+ vs, [Suspending (tagt, vs1, contref, href, ctxt') @@ at]
1157
1189
1158
1190
| Label (n , es0 , (vs' , {it = ReturningInvoke (vs0 , f ); at} :: es' )), vs ->
1159
1191
vs, [ReturningInvoke (vs0, f) @@ at]
@@ -1180,9 +1212,9 @@ let rec step (c : config) : config =
1180
1212
| Frame (n , frame' , (vs' , {it = Throwing (a , vs0 ); at} :: es' )), vs ->
1181
1213
vs, [Throwing (a, vs0) @@ at]
1182
1214
1183
- | Frame (n , frame' , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1215
+ | Frame (n , frame' , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1184
1216
let ctxt' code = [], [Frame (n, frame', compose (ctxt code) (vs', es')) @@ e.at] in
1185
- vs, [Suspending (tagt, vs1, contref, ctxt') @@ at]
1217
+ vs, [Suspending (tagt, vs1, contref, href, ctxt') @@ at]
1186
1218
1187
1219
| Frame (n , frame' , (vs' , {it = Returning vs0 ; at} :: es' )), vs ->
1188
1220
take n vs0 e.at @ vs, []
@@ -1222,9 +1254,9 @@ let rec step (c : config) : config =
1222
1254
| Handler (n , [] , (vs' , {it = Throwing (a , vs0 ); at} :: es' )), vs ->
1223
1255
vs, [Throwing (a, vs0) @@ at]
1224
1256
1225
- | Handler (n , cs , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1257
+ | Handler (n , cs , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1226
1258
let ctxt' code = [], [Handler (n, cs, compose (ctxt code) (vs', es')) @@ e.at] in
1227
- vs, [Suspending (tagt, vs1, contref, ctxt') @@ at]
1259
+ vs, [Suspending (tagt, vs1, contref, href, ctxt') @@ at]
1228
1260
1229
1261
| Handler (n , cs , (vs' , e' :: es' )), vs when is_jumping e' ->
1230
1262
vs, [e']
@@ -1256,37 +1288,45 @@ let rec step (c : config) : config =
1256
1288
with Crash (_ , msg ) -> Crash. error e.at msg)
1257
1289
)
1258
1290
1259
- | Handle (hso , (vs' , [] )), vs ->
1291
+ | Handle (name , hso , (vs' , [] )), vs ->
1260
1292
vs' @ vs, []
1261
1293
1262
- | Handle ((hs, _), (vs', {it = Suspending (tagt, vs1, None , ctxt); at} :: es')), vs
1294
+ | Handle (name, Some (hs, _), (vs', {it = Suspending (tagt, vs1, None , None , ctxt); at} :: es')), vs
1263
1295
when List. mem_assq tagt hs ->
1264
1296
let FuncT (_, ts) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
1265
1297
let ctxt' code = compose (ctxt code) (vs', es') in
1266
1298
[Ref (ContRef (ref (Some (Lib.List32. length ts, ctxt'))))] @ vs1 @ vs,
1267
1299
[Plain (Br (List. assq tagt hs)) @@ e.at]
1268
1300
1269
- | Handle ((_, hs) as hso, (vs', {it = Suspending (tagt, vs1, Some (ContRef ({contents = Some (_, ctxt)} as cont)), ctxt'); at} :: es')), vs
1301
+ | Handle (Some h, Some (hs, _), (vs', {it = Suspending (tagt, vs1, None , Some (HandlerRef ({contents = Some h'} as href)), ctxt); at} :: es')), vs
1302
+ when h == h' && List. mem_assq tagt hs ->
1303
+ let FuncT (_, ts) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
1304
+ let ctxt' code = compose (ctxt code) (vs', es') in
1305
+ href := None ;
1306
+ [Ref (ContRef (ref (Some (Int32. add (Lib.List32. length ts) 1l , ctxt'))))] @ vs1 @ vs,
1307
+ [Plain (Br (List. assq tagt hs)) @@ e.at]
1308
+
1309
+ | Handle (None , (Some (_, hs) as hso), (vs', {it = Suspending (tagt, vs1, Some (ContRef ({contents = Some (_, ctxt)} as cont)), None , ctxt'); at} :: es')), vs
1270
1310
when List. memq tagt hs ->
1271
1311
let FuncT (_, ts) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
1272
1312
let ctxt'' code = compose (ctxt' code) (vs', es') in
1273
1313
let cont' = Ref (ContRef (ref (Some (Int32. add (Lib.List32. length ts) 1l , ctxt'')))) in
1274
1314
let args = cont' :: vs1 in
1275
1315
cont := None ;
1276
- vs' @ vs, [Handle (hso, ctxt (args, [] )) @@ e.at]
1316
+ vs' @ vs, [Handle (None , hso, ctxt (args, [] )) @@ e.at]
1277
1317
1278
- | Handle (hso , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1279
- let ctxt' code = [], [Handle (hso, compose (ctxt code) (vs', es')) @@ e.at] in
1280
- vs, [Suspending (tagt, vs1, contref, ctxt') @@ at]
1318
+ | Handle (name , hso , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1319
+ let ctxt' code = [], [Handle (name, hso, compose (ctxt code) (vs', es')) @@ e.at] in
1320
+ vs, [Suspending (tagt, vs1, contref, href, ctxt') @@ at]
1281
1321
1282
- | Handle (hso , (vs' , e' :: es' )), vs when is_jumping e' ->
1322
+ | Handle (name , hso , (vs' , e' :: es' )), vs when is_jumping e' ->
1283
1323
vs, [e']
1284
1324
1285
- | Handle (hso , code' ), vs ->
1325
+ | Handle (name , hso , code' ), vs ->
1286
1326
let c' = step {c with code = code'} in
1287
- vs, [Handle (hso, c'.code) @@ e.at]
1327
+ vs, [Handle (name, hso, c'.code) @@ e.at]
1288
1328
1289
- | Suspending (_ , _ , _ , _ ), _ -> assert false
1329
+ | Suspending (_ , _ , _ , _ , _ ), _ -> assert false
1290
1330
1291
1331
in {c with code = vs', es' @ List. tl es}
1292
1332
0 commit comments