@@ -274,10 +274,10 @@ try label and delegates exception handling to a `catch`/`catch_all`/`delegate`
274
274
specified by the ` try ` label. For example, consider this code:
275
275
276
276
```
277
- try $l1
277
+ try $l0
278
278
try
279
279
call $foo
280
- delegate $l1 ;; (= delegate 0)
280
+ delegate $l0 ;; (= delegate 0)
281
281
catch
282
282
...
283
283
catch_all
@@ -288,28 +288,109 @@ end
288
288
If ` call $foo ` throws, searching for a catching block first finds ` delegate ` ,
289
289
and because it delegates exception handling to catching instructions associated
290
290
with ` $l1 ` , it will be next checked by the outer ` catch ` and then ` catch_all `
291
- instructions. When the specified label within a ` delegate ` instruction does not
292
- correspond to a ` try ` instruction, it is a validation failure.
291
+ instructions.
292
+
293
+ ` delegate ` can also target ` catch ` -less ` try ` s or non-` try ` block constructs
294
+ like ` block ` s or ` loop ` s, in which case the delegated exception is assumed to
295
+ propagate to the outer scope and will be caught by the next matching
296
+ try-catches, or rethrown to the caller if there is no outer try block. In the
297
+ examples, catches are annotated with ` ($label_name) ` to clarify which ` try ` it
298
+ belongs to for clarification; it is not the official syntax.
299
+ ```
300
+ try $l0
301
+ block $l1
302
+ try
303
+ call $foo
304
+ delegate $l1 ;; delegates to 'catch ($l0)'
305
+ end
306
+ catch ($l0)
307
+ end
308
+ ```
309
+
310
+ Like branches, ` delegate ` can only target outer blocks, and effectively
311
+ rethrows the exception in that block. Consequently, delegating to a specific
312
+ ` catch ` or ` catch_all ` handler requires targeting the respective label from
313
+ within the associated ` try ` block. Delegating to a label from within a ` catch `
314
+ block does delegate the exception to the next enclosing handler -- analogous to
315
+ performing a ` throw ` within a ` catch ` block, that handler is no longer active
316
+ at that point. Here is another example:
293
317
294
- Note that the example below is a validation failure:
295
318
```
296
- try $l1
297
- catch
319
+ try $l0
320
+ try $l1
321
+ catch ($l1)
322
+ try
323
+ call $foo
324
+ delegate $l1 ;; delegates to 'catch ($l0)'
325
+ catch_all
326
+ ...
327
+ end
328
+ catch ($l0)
329
+ ```
330
+
331
+ Here the ` delegate ` is targeting ` catch ($l1) ` , which exists before the
332
+ ` delegate ` . So in case an exception occurs, it propagates out and ends up
333
+ targetting ` catch ($l0) ` , if the catch has a matching tag. If not, it will
334
+ propagate further out. Even if the ` catch_all ` is below the ` delegate ` ,
335
+ ` delegate ` targets catches of a ` try ` as a whole and does not target an
336
+ individual ` catch ` /` catch_all ` , so it doesn't apply.
337
+
338
+ If ` delegate ` targets the implicit function body block, then in effect it
339
+ delegates the exception to the caller of the current function. For example:
340
+ ```
341
+ (func $test
298
342
try
299
- call $foo
300
- delegate $l1 ;; (= delegate 0)
301
- catch_all
302
- ...
303
- end
343
+ try
344
+ call $foo
345
+ delegate 1 ;; delegates to the caller
346
+ catch
347
+ ...
348
+ catch_all
349
+ ...
350
+ end
351
+ )
352
+ ```
353
+ In case ` foo ` throws, ` delegate 1 ` here delegates the exception handling to the
354
+ caller, i.e., the exception escapes the current function. If the immediate is
355
+ greater than or equal to the number of block nesting including the implicit
356
+ function-level block, it is a validation failure. In this example, any number
357
+ equal to or greater than 2 is not allowed.
358
+
359
+ The below is an example that includes all the cases explained. The numbers
360
+ within ` () ` after ` delegate ` s are the label operands in immediate values.
361
+ ```
362
+ (func $test
363
+ try $lA
364
+ block $lB
365
+ try $lC
366
+ try
367
+ delegate $lC (0) ;; delegates to 'catch ($lC)'
368
+ try
369
+ delegate $lB (1) ;; $lB is a block, so delegates to 'catch ($lA)'
370
+ try
371
+ delegate $lA (2) ;; delegates to 'catch ($lA)'
372
+ try
373
+ delegate 3 ;; propagates to the caller
374
+ try
375
+ delegate 4 ;; validation failure
376
+ catch ($lC)
377
+ try
378
+ delegate $lC (0) ;; 'catch ($lC)' is above this instruction,
379
+ ;; so delegates to 'catch ($lA)'
380
+ try
381
+ delegate $lB (1) ;; $lB is a block, so delegates to 'catch ($lA)'
382
+ try
383
+ delegate $lA (2) ;; delegates to 'catch ($lA)'
384
+ try
385
+ delegate 3 ;; propagates to the caller
386
+ try
387
+ delegate 4 ;; validation failure
388
+ end ;; try $lC
389
+ end ;; block $lB
390
+ catch ($lA)
391
+ end ;; try $lA
392
+ )
304
393
```
305
- Here ` delegate ` is trying to delegate to ` catch ` , which exists before the
306
- ` delegate ` . The ` delegate ` instruction can only target ` try ` label whose
307
- catching instructions (` catch ` /` catch_all ` /` delegate ` ) come after the
308
- ` delegate ` instruction.
309
-
310
- ` delegate ` can also target ` catch ` -less ` try ` , in which case the effect is the
311
- same as if the ` try ` has catches but none of the catches are able to handle the
312
- exception.
313
394
314
395
### JS API
315
396
0 commit comments