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

Commit 8f732b8

Browse files
ioannadaheejinrossberg
authored
Add prose for reduction rules involving thrown exceptions, (#226)
- Add prose for reduction rules involving thrown exceptions. - Change administrative handler instructions and adding caught exceptions to the runtime stack. + In particular: * Switched to handler ::= (tagaddr? instr*)* | labelidx exn ::= tagaddr val* instr ::= … | handler_n{handler} instr* end | caught_n{exn} instr* end removing DELEGATEadm - Changed prose to just push and pop handlers and exceptions, in the runtime, in the execution steps of the instructions, in the formal overview, and partly in appendix/properties. - Apply suggestions from code review Co-authored-by: Heejin Ahn <[email protected]> Co-authored-by: Andreas Rossberg <[email protected]>
1 parent 95d87ba commit 8f732b8

File tree

6 files changed

+257
-175
lines changed

6 files changed

+257
-175
lines changed

document/core/appendix/properties.rst

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -612,64 +612,65 @@ To that end, all previous typing judgements :math:`C \vdash \X{prop}` are genera
612612
}
613613
614614
615-
.. index:: catch, throw context
615+
.. index:: handler, throw context
616616

617-
:math:`\CATCHadm\{\tagaddr^?~\instr_1^\ast\}^\ast~\instr_2^\ast~\END`
618-
.....................................................................
617+
:math:`\HANDLERadm_n\{(\tagaddr^?~\instr_1^\ast)^\ast\}~\instr_2^\ast~\END`
618+
...........................................................................
619619

620620
* Let :math:`C'` be the same :ref:`context <context>` as :math:`C`, but with the :ref:`label type <syntax-labeltype>` :math:`[t_2^\ast]` prepended to the |CLABELS| vector.
621621

622622
* Under context :math:`C'`,
623-
the instruction sequence :math:`\instr_2^\ast` must be :ref:`valid <valid-instr-seq>` with type :math:`[] \to [t_2^\ast]`.
623+
the instruction sequence :math:`\instr_2^\ast` must be :ref:`valid <valid-instr-seq>` with type :math:`[] \to [t_2^n]`.
624624

625-
* Let :math:`C''` be the same :ref:`context <context>` as :math:`C`, but with the :ref:`label type <syntax-labeltype>` :math:`(\LCATCH~[t_2^\ast])` prepended to the |CLABELS| vector.
625+
* Let :math:`C''` be the same :ref:`context <context>` as :math:`C`, but with the :ref:`label type <syntax-labeltype>` :math:`(\LCATCH~[t_2^n])` prepended to the |CLABELS| vector.
626626

627627
* Under context :math:`C''`,
628628
for every :math:`\tagaddr^?` and associated instruction sequence :math:`\instr_1^\ast`:
629629

630-
* If :math:`\tagaddr^? = \epsilon`, then :math:`\instr_1^\ast` must be :ref:`valid <valid-instr-seq>` with type :math:`[] \to [t_2^\ast]`.
630+
* If :math:`\tagaddr^? = \epsilon`, then :math:`\instr_1^\ast` must be :ref:`valid <valid-instr-seq>` with type :math:`[] \to [t_2^n]`.
631631

632632
* Else:
633633

634634
* The :ref:`external tag value <syntax-externval>` :math:`\EVTAG~\tagaddr` must be :ref:`valid <valid-externval-tag>` with some :ref:`external tag type <syntax-externtype>` :math:`\ETTAG~[t_1^\ast] \to []`.
635635

636-
* The instruction sequence :math:`\instr_1^\ast` must be :ref:`valid <valid-instr-seq>` with type :math:`[t_1^\ast] \to [t_2^\ast]`.
636+
* The instruction sequence :math:`\instr_1^\ast` must be :ref:`valid <valid-instr-seq>` with type :math:`[t_1^\ast] \to [t_2^n]`.
637637

638-
* Then the compound instruction is valid under context :math:`C'` with type :math:`[] \to [t_2^\ast]`.
638+
* Then the compound instruction is valid under context :math:`C'` with type :math:`[] \to [t_2^n]`.
639639

640640
.. math::
641641
\frac{
642642
\begin{array}{@{}c@{}}
643643
((S \vdashexternval \EVTAG~\tagaddr : \ETTAG~[t_1^\ast]\to[])^? \\
644-
~~S; C,\CLABELS\,(\LCATCH~[t_2^\ast]) \vdashinstrseq \instr_1^\ast : [(t_1^\ast)^?] \to [t_2^\ast])^\ast \\
645-
S; C,\CLABELS\,[t_2^\ast] \vdashinstrseq \instr_2^\ast : [] \to [t_2^\ast] \\
644+
~~S; C,\CLABELS\,(\LCATCH~[t_2^n]) \vdashinstrseq \instr_1^\ast : [(t_1^\ast)^?] \to [t_2^n])^\ast \\
645+
S; C,\CLABELS\,[t_2^n] \vdashinstrseq \instr_2^\ast : [] \to [t_2^n] \\
646646
\end{array}
647647
}{
648-
S; C,\CLABELS\,[t_2^\ast] \vdashadmininstr \CATCHadm\{\tagaddr^?~{\instr_1}^\ast\}^\ast~\instr_2^\ast~\END : [] \to [t_2^\ast]
648+
S; C,\CLABELS\,[t_2^n] \vdashadmininstr \HANDLERadm_n\{(\tagaddr^?~{\instr_1}^\ast)^\ast\}~\instr_2^\ast~\END : [] \to [t_2^n]
649649
}
650650
651651
652-
.. index:: delegate, throw context
652+
.. index:: handler, throw context
653+
.. _valid-handleradm:
653654

654-
:math:`\DELEGATEadm\{l\}~\instr^\ast~\END`
655-
..........................................
655+
:math:`\HANDLERadm_n\{l\}~\instr^\ast~\END`
656+
...........................................
656657

657658
* The label :math:`C.\CLABELS[l]` must be defined in the context.
658659

659660
* Let :math:`C'` be the same :ref:`context <context>` as :math:`C`, but with the label :math:`[t^\ast]` prepended to the |CLABELS| vector.
660661

661662
* Under context :math:`C'`,
662-
the instruction sequence :math:`\instr^\ast` must be :ref:`valid <valid-instr-seq>` with type :math:`[]\to[t^\ast]`.
663+
the instruction sequence :math:`\instr^\ast` must be :ref:`valid <valid-instr-seq>` with type :math:`[]\to[t^n]`.
663664

664-
* Then the compound instruction is valid under context :math:`C'` with type :math:`[] \to [t^\ast]`.
665+
* Then the compound instruction is valid under context :math:`C'` with type :math:`[] \to [t^n]`.
665666

666667
.. math::
667668
\frac{
668-
S; C,\CLABELS\,[t^\ast] \vdashinstrseq \instr^\ast : [] \to [t^\ast]
669+
S; C,\CLABELS\,[t^n] \vdashinstrseq \instr^\ast : [] \to [t^n]
669670
\qquad
670671
C.\CLABELS[l] = \LCATCH^?~[t_0^\ast]
671672
}{
672-
S; C,\CLABELS\,[t^\ast] \vdashadmininstr \DELEGATEadm\{l\}~\instr^\ast~\END : [] \to [t^\ast]
673+
S; C,\CLABELS\,[t^n] \vdashadmininstr \HANDLERadm_n\{l\}~\instr^\ast~\END : [] \to [t^n]
673674
}
674675
675676

document/core/exec/instructions.rst

Lines changed: 107 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,26 +2636,26 @@ Control Instructions
26362636

26372637
b. Let :math:`a_i` be the tag address :math:`F.\AMODULE.\MITAGS[x_i]`.
26382638

2639-
c. Let :math:`H_i` be the handler clause :math:`\{a_i~\instr_{2i}^\ast\}`.
2639+
c. Let :math:`H_i` be the handler :math:`(a_i~\instr_{2i}^\ast)`.
26402640

26412641
8. If there is a catch all clause :math:`(\CATCHALL~\instr_3^\ast)`, then:
26422642

2643-
a. Let :math:`H'^?` be the handler clause :math:`\{\epsilon~\instr_3^\ast\}`.
2643+
a. Let :math:`H'^?` be the handler :math:`(\epsilon~\instr_3^\ast)`.
26442644

26452645
9. Else:
26462646

2647-
a. Let :math:`H'^?` be the empty handler clause :math:`\epsilon`.
2647+
a. Let :math:`H'^?` be the empty handler :math:`\epsilon`.
26482648

2649-
10. Let :math:`H^\ast` be the :ref:`catching exception handler <syntax-handler>` containing the concatenation of the handler clauses :math:`H_i` and :math:`H'^?`.
2649+
10. Let :math:`H^\ast` be the concatenation of :math:`H_i` and :math:`H'^?`.
26502650

2651-
11. :ref:`Enter <exec-handler-enter>` the block :math:`\val^m~\instr_1^\ast` with label :math:`L` and exception handler :math:`H`.
2651+
11. :ref:`Enter <exec-handler-enter>` the block :math:`\val^m~\instr_1^\ast` with label :math:`L` and exception handler :math:`H^\ast`.
26522652

26532653
.. math::
26542654
~\\[-1ex]
26552655
\begin{array}{l}
26562656
F; \val^m~(\TRY~\X{bt}~\instr_1^\ast~(\CATCH~x~\instr_2^\ast)^\ast~(\CATCHALL~\instr_3^\ast)^?~\END
26572657
\quad \stepto \\
2658-
\qquad F; \LABEL_n\{\epsilon\}~(\CATCHadm\{a_x~\instr_2^\ast\}^\ast\{\epsilon~\instr_3\ast\}^?~\val^m~\instr_1^\ast~\END)~\END \\
2658+
\qquad F; \LABEL_n\{\epsilon\}~(\HANDLERadm_n\{(a_x~\instr_2^\ast)^\ast~(\epsilon~\instr_3^\ast)^?\}~\val^m~\instr_1^\ast~\END)~\END \\
26592659
(\iff \expand_F(\X{bt}) = [t_1^m] \to [t_2^n] \land (F.\AMODULE.\MITAGS[x]=a_x)^\ast)
26602660
\end{array}
26612661
@@ -2671,21 +2671,19 @@ Control Instructions
26712671

26722672
3. Let :math:`L` be the label whose arity is :math:`n` and whose continuation is the end of the |TRY| instruction.
26732673

2674-
4. Let :math:`H` be the :ref:`delegating exception handler <syntax-handler>` :math:`\DELEGATEadm\{l\}`, targeting the :math:`l`-th surrounding block.
2674+
4. Let :math:`H` be the :ref:`exception handler <syntax-handler>` :math:`l`, targeting the :math:`l`-th surrounding block.
26752675

26762676
5. Assert: due to :ref:`validation <valid-try-delegate>`, there are at least :math:`m` values on the top of the stack.
26772677

26782678
6. Pop the values :math:`\val^m` from the stack.
26792679

2680-
7. :ref:`Enter <exec-instr-seq-enter>` the block :math:`H~(\val^n~\instr^\ast)~\END` with label :math:`L`.
2681-
2682-
8. :ref:`Install <exec-handler-enter>` the exception handler `H` containing :math:`\val^m~\instr^\ast`.
2680+
7. :ref:`Enter <exec-handler-enter>` the block :math:`\val^m~\instr^\ast` with label :math:`L` and exception handler `H`.
26832681

26842682
.. math::
26852683
~\\[-1ex]
26862684
\begin{array}{lcl}
26872685
F; \val^m~(\TRY~\X{bt}~\instr^\ast~\DELEGATE~l) &\stepto&
2688-
F; \LABEL_n\{\epsilon\}~(\DELEGATEadm\{l\}~\val^m~\instr^\ast~\END)~\END \\
2686+
F; \LABEL_n\{\epsilon\}~(\HANDLERadm_n\{l\}~\val^m~\instr^\ast~\END)~\END \\
26892687
&& (\iff \expand_F(\X{bt}) = [t_1^m] \to [t_2^n])
26902688
\end{array}
26912689
@@ -2730,8 +2728,8 @@ Control Instructions
27302728
.. math::
27312729
~\\[-1ex]
27322730
\begin{array}{lclr@{\qquad}}
2733-
\CAUGHTadm\{a~\val^\ast\}~\XB^l[\RETHROW~l]~\END &\stepto&
2734-
\CAUGHTadm\{a~\val^\ast\}~\XB^l[\val^\ast~(\THROWadm~a)]~\END \\
2731+
\CAUGHTadm_n\{a~\val^n\}~\XB^l[\RETHROW~l]~\END &\stepto&
2732+
\CAUGHTadm_n\{a~\val^n\}~\XB^l[\val^n~(\THROWadm~a)]~\END \\
27352733
\end{array}
27362734
27372735
@@ -3053,8 +3051,7 @@ When the end of a :ref:`try <syntax-try>` instruction is reached without a jump,
30533051
.. math::
30543052
~\\[-1ex]
30553053
\begin{array}{lcl@{\qquad}l}
3056-
\CATCHadm\{a^?~\instr^\ast\}^\ast~\val^m~\END &\stepto& \val^m \\
3057-
\DELEGATEadm\{l\}~\val^m~\END &\stepto& \val^m
3054+
\HANDLERadm_m\{\handler\}~\val^m~\END &\stepto& \val^m \\
30583055
\end{array}
30593056
30603057
@@ -3063,53 +3060,128 @@ When the end of a :ref:`try <syntax-try>` instruction is reached without a jump,
30633060
Throwing an exception with :ref:`tag address <syntax-tagaddr>` :math:`a`
30643061
........................................................................
30653062

3066-
.. todo::
3067-
Add prose for the following execution steps.
3063+
When a throw occurs, then values, labels, active catch clauses,
3064+
and call frames are popped if necessary, until an appropriate exception handler is found
3065+
on the top of the stack.
3066+
3067+
1. Assert: due to :ref:`validation <valid-throw>`, :math:`S.\STAGS[a]` exists.
3068+
3069+
2. Let :math:`[t^n] \to []` be the :ref:`tag type <syntax-tagtype>` :math:`S.\STAGS[a].\TAGITYPE`.
3070+
3071+
3. Assert: due to :ref:`validation <valid-throw>`, there are :math:`n` values on the top of the stack.
3072+
3073+
4. Pop the :math:`n` values :math:`\val^n` from the stack.
3074+
3075+
5. While the stack is not empty and the top of the stack is not an :ref:`exception handler <syntax-handler>`, do:
3076+
3077+
a. Pop the top element from the stack.
3078+
3079+
6. Assert: the stack is now either empty, or there is an exception handler on the top of the stack.
3080+
3081+
7. If the stack is empty, then:
3082+
3083+
a. Return the uncaught exception :math:`\val^n~(\THROWadm~a)` as a :ref:`result <syntax-result>`.
3084+
3085+
8. Else assert: there is an :ref:`exception handler <syntax-handler>` :math:`H` on the top of the stack.
3086+
3087+
9. Pop the exception handler :math:`H` from the stack.
3088+
3089+
10. If :math:`H` is list of handlers, then:
3090+
3091+
a. While :math:`H` is not empty, do:
3092+
3093+
i. Let :math:`(a_1^?~\instr^\ast)` be the first handler in :math:`H`.
3094+
3095+
ii. If :math:`a_1^? = \epsilon`, then:
3096+
3097+
* :ref:`Enter <exec-caughtadm-enter>` the block :math:`\instr^\ast` with caught exception :math:`a~\val^n`.
3098+
3099+
iii. Else if :math:`a_1^? = a`, then:
3100+
3101+
* :ref:`Enter <exec-caughtadm-enter>` the block :math:`\val^n~\instr^\ast` with caught exception :math:`a~\val^n`.
3102+
3103+
iv. Else, pop the first handler from :math:`H`.
3104+
3105+
b. Else, the exception was not caught by :math:`H`:
30683106

3107+
i. Put the values :math:`\val^n` back onto the stack.
3108+
3109+
ii. :ref:`Throw <exec-throwadm>` an exception with tag address :math:`a`.
3110+
3111+
11. Else :math:`H` is a label index :math:`l`.
3112+
3113+
a. Assert: due to :ref:`validation <valid-handleradm>`, the stack contains at least :math:`l` labels.
3114+
3115+
b. Repeat :math:`l` times:
3116+
3117+
i. While the top of the stack is not a label, do:
3118+
3119+
* Pop the top element from the stack.
3120+
3121+
c. Assert: due to :ref:`validation <valid-handleradm>`, the top of the stack now is a label.
3122+
3123+
d. Pop the label from the stack.
3124+
3125+
e. Push the values :math:`\val^n` onto the stack.
3126+
3127+
f. :ref:`Throw <exec-throwadm>` an exception with tag address :math:`a`.
30693128

30703129
.. math::
30713130
\begin{array}{rcl}
3072-
\CATCHadm\{a_1^?~\instr^\ast\}\{a'^?~\instr'^\ast\}^\ast~\XT[(\THROWadm~a)]~\END &\stepto&
3073-
\CATCHadm\{a'^?~\instr'^\ast\}^\ast~\XT[(\THROWadm~a)]~\END \\
3131+
\HANDLERadm_n\{\}~\XT[(\THROWadm~a)]~\END &\stepto&
3132+
\XT[(\THROWadm~a)] \\
3133+
\HANDLERadm_n\{(a_1^?~\instr^\ast)~(a'^?~\instr'^\ast)^\ast\}~\XT[(\THROWadm~a)]~\END &\stepto&
3134+
\HANDLERadm_n\{(a'^?~\instr'^\ast)^\ast~\XT[(\THROWadm~a)]~\END \\
30743135
&& (\iff a_1^? \neq \epsilon \land a_1^? \neq a) \\
3075-
S;~\CATCHadm\{a_1^?~\instr^\ast\}\{a'^?~\instr'^\ast\}^\ast~\XT[\val^n~(\THROWadm~a)]~\END &\stepto&
3076-
S;~\CAUGHTadm\{a~\val^n\}~(\val^n)?~\instr^\ast~\END \\
3136+
S;~\HANDLERadm_n\{(a_1^?~\instr^\ast)~(a'^?~\instr'^\ast)^\ast\}~\XT[\val^n~(\THROWadm~a)]~\END &\stepto&
3137+
S;~\CAUGHTadm_n\{a~\val^n\}~(\val^n)^?~\instr^\ast~\END \\
30773138
&& (\iff~(a_1^? = \epsilon \lor a_1^? = a)~\land\\
30783139
&& \ S.\STAGS[a].\TAGITYPE = [t^n]\to[]) \\
3079-
\LABEL_n\{\}~\XB^l[\DELEGATEadm\{l\}~\XT[(\THROWadm~a)]~\END]~\END &\stepto&
3140+
\LABEL_n\{\}~\XB^l[\HANDLERadm_n\{l\}~\XT[(\THROWadm~a)]~\END]~\END &\stepto&
30803141
\XT[(\THROWadm~a)] \\
30813142
\end{array}
30823143
3144+
.. note::
3145+
The rules are formulated in this way to allow looking up the exception values in the throw context,
3146+
only when a thrown exception is caught.
30833147

3084-
.. todo::
3085-
Add explainer note.
30863148

3087-
.. _exec-caughtadm:
3149+
.. _exec-caughtadm-enter:
30883150

3089-
Exiting a catch clause
3090-
......................
3151+
Entering :math:`\instr^\ast` with caught exception :math:`\{\exn\}`
3152+
...................................................................
3153+
3154+
1. Push the caught exception |exn| onto the stack.
3155+
3156+
2. Jump to the start of the instruction sequence :math:`\instr^\ast`.
30913157

3092-
When the |END| of a catch clause is reached without a jump, exception, or trap, then the following steps are performed.
30933158

3094-
1. Let :math:`\val^\ast` be the values on the top of the stack.
3159+
.. _exec-caughtadm-exit:
30953160

3096-
2. Pop the values :math:`\val^\ast` from the stack.
3161+
Exiting a block with a caught exception
3162+
.......................................
30973163

3098-
3. Assert: due to :ref:`validation <valid-instr-seq>`, a caught exception :math:`\{a~\val_0^\ast\}` is now on the top of the stack.
3164+
When the |END| of a block with a caught exception is reached without a jump, thrown exception, or trap, then the following steps are performed.
3165+
3166+
1. Let :math:`\val^m` be the values on the top of the stack.
3167+
3168+
2. Pop the values :math:`\val^m` from the stack.
3169+
3170+
3. Assert: due to :ref:`validation <valid-caughtadm>`, a caught exception is now on the top of the stack.
30993171

31003172
4. Pop the caught exception from the stack.
31013173

3102-
5. Push :math:`\val^\ast` back to the stack.
3174+
5. Push :math:`\val^m` back to the stack.
31033175

3104-
6. Jump to the position after the |END| of the administrative instruction associated with the catch clause.
3176+
6. Jump to the position after the |END| of the administrative instruction associated with the caught exception.
31053177

31063178
.. math::
31073179
\begin{array}{rcl}
3108-
\CAUGHTadm\{a~\val_0^\ast\}~\val^\ast~\END &\stepto& \val^\ast
3180+
\CAUGHTadm_n\{\exn\}~\val^m~\END &\stepto& \val^m
31093181
\end{array}
31103182
31113183
.. note::
3112-
An exception can only be rethrown from the scope of the |CAUGHTadm| administrative instruction holding it, i.e., from the scope of the |CATCH| or |CATCHALL| block of a :ref:`try-catch <syntax-try-catch>` instruction that caught it. Upon exit from a |CAUGHTadm|, the exception it holds is discarded.
3184+
A caught exception can only be rethrown from the scope of the administrative instruction associated with it, i.e., from the scope of the |CATCH| or |CATCHALL| block of a :ref:`try-catch <syntax-try-catch>` instruction that caught it. Upon exit from that block, the caught exception is discarded.
31133185

31143186

31153187
.. index:: ! call, function, function instance, label, frame

0 commit comments

Comments
 (0)