@@ -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
- | Prompt of handle_table * code
76
- | Suspending of tag_inst * value stack * (int32 * ref_) option * ctxt
76
+ | Prompt of handler_name option * handle_table * code
77
+ | Suspending of tag_inst * value stack * (int32 * 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', [Prompt (hs, ctxt (args, [] )) @@ e.at]
409
+ vs', [Prompt (None , 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', [Prompt (hs, ctxt ([] , [Throwing (tagt, args) @@ e.at])) @@ e.at]
423
+ vs', [Prompt (None , 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', [Prompt (Some Name , 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]
@@ -419,7 +451,7 @@ let rec step (c : config) : config =
419
451
let arity = Lib.List32. length ts' in
420
452
let tagt = tag c.frame.inst y in
421
453
let args, vs' = i32_split (Int32. sub n 1l ) vs e.at in
422
- vs', [Suspending (tagt, args, Some (arity, ContRef cont), fun code -> code) @@ e.at]
454
+ vs', [Suspending (tagt, args, Some (arity, ContRef cont), None , fun code -> code) @@ e.at]
423
455
424
456
| ReturnCall x , vs ->
425
457
(match (step {c with code = (vs, [Plain (Call x) @@ e.at])}).code with
@@ -1180,9 +1212,9 @@ let rec step (c : config) : config =
1180
1212
| Label (n , es0 , (vs' , [] )), vs ->
1181
1213
vs' @ vs, []
1182
1214
1183
- | Label (n , es0 , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1215
+ | Label (n , es0 , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1184
1216
let ctxt' code = [], [Label (n, es0, 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
| Label (n , es0 , (vs' , {it = ReturningInvoke (vs0 , f ); at} :: es' )), vs ->
1188
1220
vs, [ReturningInvoke (vs0, f) @@ at]
@@ -1209,9 +1241,9 @@ let rec step (c : config) : config =
1209
1241
| Frame (n , frame' , (vs' , {it = Throwing (a , vs0 ); at} :: es' )), vs ->
1210
1242
vs, [Throwing (a, vs0) @@ at]
1211
1243
1212
- | Frame (n , frame' , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1244
+ | Frame (n , frame' , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1213
1245
let ctxt' code = [], [Frame (n, frame', compose (ctxt code) (vs', es')) @@ e.at] in
1214
- vs, [Suspending (tagt, vs1, contref, ctxt') @@ at]
1246
+ vs, [Suspending (tagt, vs1, contref, href, ctxt') @@ at]
1215
1247
1216
1248
| Frame (n , frame' , (vs' , {it = Returning vs0 ; at} :: es' )), vs ->
1217
1249
take n vs0 e.at @ vs, []
@@ -1251,9 +1283,9 @@ let rec step (c : config) : config =
1251
1283
| Handler (n , [] , (vs' , {it = Throwing (a , vs0 ); at} :: es' )), vs ->
1252
1284
vs, [Throwing (a, vs0) @@ at]
1253
1285
1254
- | Handler (n , cs , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1286
+ | Handler (n , cs , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1255
1287
let ctxt' code = [], [Handler (n, cs, compose (ctxt code) (vs', es')) @@ e.at] in
1256
- vs, [Suspending (tagt, vs1, contref, ctxt') @@ at]
1288
+ vs, [Suspending (tagt, vs1, contref, href, ctxt') @@ at]
1257
1289
1258
1290
| Handler (n , cs , (vs' , e' :: es' )), vs when is_jumping e' ->
1259
1291
vs, [e']
@@ -1285,36 +1317,44 @@ let rec step (c : config) : config =
1285
1317
with Crash (_ , msg ) -> Crash. error e.at msg)
1286
1318
)
1287
1319
1288
- | Prompt (hso , (vs' , [] )), vs ->
1320
+ | Prompt (name , hso , (vs' , [] )), vs ->
1289
1321
vs' @ vs, []
1290
1322
1291
- | Prompt ((hs, _), (vs', {it = Suspending (tagt, vs1, None , ctxt); at} :: es')), vs
1323
+ | Prompt (name, (hs, _), (vs', {it = Suspending (tagt, vs1, None , None , ctxt); at} :: es')), vs
1292
1324
when List. mem_assq tagt hs ->
1293
1325
let FuncT (_, ts) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
1294
1326
let ctxt' code = compose (ctxt code) (vs', es') in
1295
1327
[Ref (ContRef (ref (Some (Lib.List32. length ts, ctxt'))))] @ vs1 @ vs,
1296
1328
[Plain (Br (List. assq tagt hs)) @@ e.at]
1297
1329
1298
- | Prompt ((_, hs) as hso, (vs', {it = Suspending (tagt, vs1, Some (ar, ContRef ({contents = Some (_, ctxt)} as cont)), ctxt'); at} :: es')), vs
1330
+ | Prompt (Some h, (hs, _), (vs', {it = Suspending (tagt, vs1, None , Some (HandlerRef ({contents = Some h'} as href)), ctxt); at} :: es')), vs
1331
+ when h == h' && List. mem_assq tagt hs ->
1332
+ let FuncT (_, ts) = func_type_of_tag_type c.frame.inst (Tag. type_of tagt) in
1333
+ let ctxt' code = compose (ctxt code) (vs', es') in
1334
+ href := None ;
1335
+ [Ref (ContRef (ref (Some (Int32. add (Lib.List32. length ts) 1l , ctxt'))))] @ vs1 @ vs,
1336
+ [Plain (Br (List. assq tagt hs)) @@ e.at]
1337
+
1338
+ | Prompt (None , ((_, hs) as hso), (vs', {it = Suspending (tagt, vs1, Some (ar, ContRef ({contents = Some (_, ctxt)} as cont)), None , ctxt'); at} :: es')), vs
1299
1339
when List. memq tagt hs ->
1300
1340
let ctxt'' code = compose (ctxt' code) (vs', es') in
1301
1341
let cont' = Ref (ContRef (ref (Some (ar, ctxt'')))) in
1302
1342
let args = cont' :: vs1 in
1303
1343
cont := None ;
1304
- vs' @ vs, [Prompt (hso, ctxt (args, [] )) @@ e.at]
1344
+ vs' @ vs, [Prompt (None , hso, ctxt (args, [] )) @@ e.at]
1305
1345
1306
- | Prompt (hso , (vs' , {it = Suspending (tagt , vs1 , contref , ctxt ); at} :: es' )), vs ->
1307
- let ctxt' code = [], [Prompt (hso, compose (ctxt code) (vs', es')) @@ e.at] in
1308
- vs, [Suspending (tagt, vs1, contref, ctxt') @@ at]
1346
+ | Prompt (name , hso , (vs' , {it = Suspending (tagt , vs1 , contref , href , ctxt ); at} :: es' )), vs ->
1347
+ let ctxt' code = [], [Prompt (name, hso, compose (ctxt code) (vs', es')) @@ e.at] in
1348
+ vs, [Suspending (tagt, vs1, contref, href, ctxt') @@ at]
1309
1349
1310
- | Prompt (hso , (vs' , e' :: es' )), vs when is_jumping e' ->
1350
+ | Prompt (name , hso , (vs' , e' :: es' )), vs when is_jumping e' ->
1311
1351
vs, [e']
1312
1352
1313
- | Prompt (hso , code' ), vs ->
1353
+ | Prompt (name , hso , code' ), vs ->
1314
1354
let c' = step {c with code = code'} in
1315
- vs, [Prompt (hso, c'.code) @@ e.at]
1355
+ vs, [Prompt (name, hso, c'.code) @@ e.at]
1316
1356
1317
- | Suspending (_ , _ , _ , _ ), _ -> assert false
1357
+ | Suspending (_ , _ , _ , _ , _ ), _ -> assert false
1318
1358
1319
1359
in {c with code = vs', es' @ List. tl es}
1320
1360
0 commit comments