Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit c830a2f

Browse files
authored
Reflect spec changes in delegate immediate operand (#178)
This adds the changes decided in #176 and adds a modified version from #146 (comment) for clarification. (The example is not the same by the way; the `catch` from the outermost `try` has been moved)
1 parent ea7f2c0 commit c830a2f

File tree

1 file changed

+101
-20
lines changed

1 file changed

+101
-20
lines changed

proposals/exception-handling/Exceptions.md

Lines changed: 101 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,10 @@ try label and delegates exception handling to a `catch`/`catch_all`/`delegate`
274274
specified by the `try` label. For example, consider this code:
275275

276276
```
277-
try $l1
277+
try $l0
278278
try
279279
call $foo
280-
delegate $l1 ;; (= delegate 0)
280+
delegate $l0 ;; (= delegate 0)
281281
catch
282282
...
283283
catch_all
@@ -288,28 +288,109 @@ end
288288
If `call $foo` throws, searching for a catching block first finds `delegate`,
289289
and because it delegates exception handling to catching instructions associated
290290
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:
293317

294-
Note that the example below is a validation failure:
295318
```
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
298342
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+
)
304393
```
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.
313394

314395
### JS API
315396

0 commit comments

Comments
 (0)