From 9ad8d551b9c68465e1d64fb0a8c0aee5359e8680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Hillerstr=C3=B6m?= Date: Wed, 22 Jan 2025 10:17:00 +0000 Subject: [PATCH 1/9] Reduction semantics This patch populates the "Execution" section of the Explainer document with the reduction rules for stack switching. --- proposals/stack-switching/Explainer.md | 122 ++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 1 deletion(-) diff --git a/proposals/stack-switching/Explainer.md b/proposals/stack-switching/Explainer.md index 152aef33..e2896ed7 100644 --- a/proposals/stack-switching/Explainer.md +++ b/proposals/stack-switching/Explainer.md @@ -833,6 +833,126 @@ events and only `(on $e switch)` handlers can handle `switch` events. The handler search continues past handlers for the wrong kind of event, even if they use the correct tag. +#### Store extensions + +* A store component `tags` for allocated tags (from the exception + handling proposal) + - `S ::= {..., tags *}` + +* A *tag instance* represents a control tag (from the exception + handling proposal) + - `taginst ::= {type }` + +* New store component `conts` for allocated continuations + - `S ::= {..., conts ?*}` + +* A continuation is a context annotated with its hole's arity + - `cont ::= (E : n)` + + +#### Administrative instructions + +* `(ref.cont a)` represents a continuation value, where `a` is a *continuation address* indexing into the store's `conts` component + - `ref.cont a : [] -> [(ref $ct)]` + - iff `S.conts[a] = epsilon \/ S.conts[a] = (E : n)` + - and `$ct ~~ cont $ft` + - and `$ft ~~ [t1^n] -> [t2*]` + +* `(prompt{*} * end)` represents an active handler + - `(prompt{((a $l) | (b switch))*}? instr* end) : [t1*] -> [t2*]` + - iff `instr* : [t1*] -> [t2*]` + - and `(S.tags[a].type = [te1*] -> [te2*])*` + - and `(S.tags[b].type = [] -> [te2*])*` + - and `(label $l : [te1'* (ref null? $ct')])*` + - and `([te1*] <: [te1'*])*` + - and `($ct' = cont $ft')*` + - and `([te2*] -> [t2*] <: $ft')*` + +The administrative structure `hdl` is defined as. +``` +hdl ::= ( $l) hdl | ( switch) +``` + +#### Handler contexts + +``` +H^ea ::= + _ + val* H^ea instr* + label_n{instr*} H^ea end + frame_n{F} H^ea end + catch{...} H^ea end + prompt{hdl*} H^ea end (iff ea notin ea'*) +``` + + +#### Reduction + +* `S; F; (ref.null t) (cont.new $ct) --> S; F; trap` + +* `S; F; (ref.func fa) (cont.new $ct) --> S'; F; (ref.cont |S.conts|)` + - iff `S' = S with conts += (E : n)` + - and `E = _ (invoke fa)` + - and `$ct ~~ cont $ft` + - and `$ft ~~ [t1^n] -> [t2*]` + +* `S; F; (ref.null t) (cont.bind $ct $ct') --> S; F; trap` + +* `S; F; (ref.cont ca) (cont.bind $ct $ct') --> S'; F; trap` + - iff `S.conts[ca] = epsilon` + +* `S; F; v^n (ref.cont ca) (cont.bind $ct $ct') --> S'; F; (ref.const |S.conts|)` + - iff `S.conts[ca] = (E' : n')` + - and `$ct' ~~ cont $ft'` + - and `$ft' ~~ [t1'*] -> [t2'*]` + - and `n = n' - |t1'*|` + - and `S' = S with conts[ca] = epsilon with conts += (E : |t1'*|)` + - and `E = E'[v^n _]` + +* `S; F; (ref.null t) (resume $ct (on $e $l)*) --> S; F; trap` + +* `S; F; (ref.cont ca) (resume $ct (on $e $l)*) --> S; F; trap` + - iff `S.conts[ca] = epsilon` + +* `S; F; v^n (ref.cont ca) (resume $ct hdl*) --> S'; F; prompt{hdl*} E[v^n] end` + - iff `S.conts[ca] = (E : n)` + - and `(ea = F.tags[$t])*` + - and `S' = S with conts[ca] = epsilon` + +* `S; F; (ref.null t) (resume_throw $ct $e (on $t $l)*) --> S; F; trap` + +* `S; F; (ref.cont ca) (resume_throw $ct $e (on $t $l)*) --> S; F; trap` + - iff `S.conts[ca] = epsilon` + +* `S; F; v^m (ref.cont ca) (resume_throw $ct $e hdl*) --> S'; F; prompt{hdl*} E[v^m (throw $e)] end` + - iff `S.conts[ca] = (E : n)` + - and `(ea = F.tags[$t])*` + - and `S.tags[F.tags[$e]].type ~~ [t1^m] -> [t2*]` + - and `S' = S with conts[ca] = epsilon` + +* `S; F; (prompt{(e $l)*}? v* end) --> S; F; v*` + +* `S; F; (prompt H^ea[(suspend $e)] end) --> S; F; trap` + - iff `ea = F.tags[$e]` + +* `S; F; (prompt{hdl1* (ea $l) hdl2*} H^ea[v^n (suspend $e)] end) --> S'; F; v^n (ref.cont |S.conts|) (br $l)` + - iff `ea notin ea1*` + - and `ea = F.tags[$e]` + - and `S.tags[ea].type ~~ [t1^n] -> [t2^m]` + - and `S' = S with conts += (H^ea : m)` + +* `S; F; (prompt{hdl* (ea switch) hdl2*} H^ea[v^n (ref.cont ca) (switch $ct $e)] end) --> S''; F; prompt{hdl1* (ea switch) hdl2*} E[v^n (ref.cont |S.conts|)] end` + - iff `S.conts[ca] = (E : n')` + - and `n' = 1 + n` + - and `ea notin ea1*` + - and `ea = F.tags[$e]` + - and `$ct ~~ cont $ft` + - and `$ft ~~ [t1* (ref $ct2)] -> [t2*]` + - and `$ct2 ~~ cont $ft2` + - and `$ft2 ~~ [t1'^m] -> [t2'*]` + - and `S' = S with conts[ca] = epsilon` + - and `S'' = S' with conts += (H^ea : m)` + ### Binary format We extend the binary format of composite types, heap types, and instructions. @@ -856,7 +976,7 @@ The opcode for heap types is encoded as an `s33`. #### Instructions -We use the use the opcode space `0xe0-0xe5` for the seven new instructions. +We use the use the opcode space `0xe0-0xe5` for the six new instructions. | Opcode | Instruction | Immediates | | ------ | ------------------------ | ---------- | From db96405bcae51c268aa0820fde1e4be20428c6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Hillerstr=C3=B6m?= Date: Wed, 22 Jan 2025 10:20:58 +0000 Subject: [PATCH 2/9] Some type expansions --- proposals/stack-switching/Explainer.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/stack-switching/Explainer.md b/proposals/stack-switching/Explainer.md index e2896ed7..7c4ece01 100644 --- a/proposals/stack-switching/Explainer.md +++ b/proposals/stack-switching/Explainer.md @@ -861,11 +861,11 @@ of event, even if they use the correct tag. * `(prompt{*} * end)` represents an active handler - `(prompt{((a $l) | (b switch))*}? instr* end) : [t1*] -> [t2*]` - iff `instr* : [t1*] -> [t2*]` - - and `(S.tags[a].type = [te1*] -> [te2*])*` - - and `(S.tags[b].type = [] -> [te2*])*` + - and `(S.tags[a].type ~~ [te1*] -> [te2*])*` + - and `(S.tags[b].type ~~ [] -> [te2*])*` - and `(label $l : [te1'* (ref null? $ct')])*` - and `([te1*] <: [te1'*])*` - - and `($ct' = cont $ft')*` + - and `($ct' ~~ cont $ft')*` - and `([te2*] -> [t2*] <: $ft')*` The administrative structure `hdl` is defined as. From 2330933c41e49cbe68ef4be44aeaf65287a2d994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Hillerstr=C3=B6m?= Date: Wed, 22 Jan 2025 10:21:49 +0000 Subject: [PATCH 3/9] Fix minor typo, hdl => hdl1 --- proposals/stack-switching/Explainer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/stack-switching/Explainer.md b/proposals/stack-switching/Explainer.md index 7c4ece01..d4305f72 100644 --- a/proposals/stack-switching/Explainer.md +++ b/proposals/stack-switching/Explainer.md @@ -941,7 +941,7 @@ H^ea ::= - and `S.tags[ea].type ~~ [t1^n] -> [t2^m]` - and `S' = S with conts += (H^ea : m)` -* `S; F; (prompt{hdl* (ea switch) hdl2*} H^ea[v^n (ref.cont ca) (switch $ct $e)] end) --> S''; F; prompt{hdl1* (ea switch) hdl2*} E[v^n (ref.cont |S.conts|)] end` +* `S; F; (prompt{hdl1* (ea switch) hdl2*} H^ea[v^n (ref.cont ca) (switch $ct $e)] end) --> S''; F; prompt{hdl1* (ea switch) hdl2*} E[v^n (ref.cont |S.conts|)] end` - iff `S.conts[ca] = (E : n')` - and `n' = 1 + n` - and `ea notin ea1*` From d8ad9ede01e858eb85e86a87df67ebafa29cb377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Hillerstr=C3=B6m?= Date: Wed, 22 Jan 2025 10:23:20 +0000 Subject: [PATCH 4/9] Fix typo: stray ' --- proposals/stack-switching/Explainer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/stack-switching/Explainer.md b/proposals/stack-switching/Explainer.md index d4305f72..6f7bb21d 100644 --- a/proposals/stack-switching/Explainer.md +++ b/proposals/stack-switching/Explainer.md @@ -898,7 +898,7 @@ H^ea ::= * `S; F; (ref.null t) (cont.bind $ct $ct') --> S; F; trap` -* `S; F; (ref.cont ca) (cont.bind $ct $ct') --> S'; F; trap` +* `S; F; (ref.cont ca) (cont.bind $ct $ct') --> S; F; trap` - iff `S.conts[ca] = epsilon` * `S; F; v^n (ref.cont ca) (cont.bind $ct $ct') --> S'; F; (ref.const |S.conts|)` From 79e59f64734715193a1e1bce1377d4d3224a8e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Hillerstr=C3=B6m?= Date: Thu, 6 Feb 2025 09:48:13 +0000 Subject: [PATCH 5/9] Address Andreas' feedback --- proposals/stack-switching/Explainer.md | 45 ++++++++++++-------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/proposals/stack-switching/Explainer.md b/proposals/stack-switching/Explainer.md index 6f7bb21d..f352f9a4 100644 --- a/proposals/stack-switching/Explainer.md +++ b/proposals/stack-switching/Explainer.md @@ -835,14 +835,6 @@ of event, even if they use the correct tag. #### Store extensions -* A store component `tags` for allocated tags (from the exception - handling proposal) - - `S ::= {..., tags *}` - -* A *tag instance* represents a control tag (from the exception - handling proposal) - - `taginst ::= {type }` - * New store component `conts` for allocated continuations - `S ::= {..., conts ?*}` @@ -855,23 +847,33 @@ of event, even if they use the correct tag. * `(ref.cont a)` represents a continuation value, where `a` is a *continuation address* indexing into the store's `conts` component - `ref.cont a : [] -> [(ref $ct)]` - iff `S.conts[a] = epsilon \/ S.conts[a] = (E : n)` + + iff `E[val^n] : t2*` + + and `(val : t1)^n` - and `$ct ~~ cont $ft` - and `$ft ~~ [t1^n] -> [t2*]` * `(prompt{*} * end)` represents an active handler - - `(prompt{((a $l) | (b switch))*}? instr* end) : [t1*] -> [t2*]` + - `(prompt{hdl*}? instr* end) : [t1*] -> [t2*]` - iff `instr* : [t1*] -> [t2*]` - - and `(S.tags[a].type ~~ [te1*] -> [te2*])*` - - and `(S.tags[b].type ~~ [] -> [te2*])*` + - and `(hdl : [t2^*])*` + +The administrative structure `hdl` is defined as +``` +hdl ::= ( $l) | ( switch) +``` + +where + +* `(a $l)` represents a tag-label association + - `(a $l) : [t2*]` + - iff `(S.tags[a].type ~~ [te1*] -> [te2*])*` - and `(label $l : [te1'* (ref null? $ct')])*` - and `([te1*] <: [te1'*])*` - and `($ct' ~~ cont $ft')*` - and `([te2*] -> [t2*] <: $ft')*` -The administrative structure `hdl` is defined as. -``` -hdl ::= ( $l) hdl | ( switch) -``` +* `(a switch)` represents a tag-switch association + - `(a switch)` and `(S.tags[b].type ~~ [] -> [te2*])*` #### Handler contexts @@ -882,7 +884,7 @@ H^ea ::= label_n{instr*} H^ea end frame_n{F} H^ea end catch{...} H^ea end - prompt{hdl*} H^ea end (iff ea notin ea'*) + prompt{hdl*} H^ea end (iff ea notin tagaddr(hdl*)) ``` @@ -916,7 +918,6 @@ H^ea ::= * `S; F; v^n (ref.cont ca) (resume $ct hdl*) --> S'; F; prompt{hdl*} E[v^n] end` - iff `S.conts[ca] = (E : n)` - - and `(ea = F.tags[$t])*` - and `S' = S with conts[ca] = epsilon` * `S; F; (ref.null t) (resume_throw $ct $e (on $t $l)*) --> S; F; trap` @@ -926,17 +927,13 @@ H^ea ::= * `S; F; v^m (ref.cont ca) (resume_throw $ct $e hdl*) --> S'; F; prompt{hdl*} E[v^m (throw $e)] end` - iff `S.conts[ca] = (E : n)` - - and `(ea = F.tags[$t])*` - and `S.tags[F.tags[$e]].type ~~ [t1^m] -> [t2*]` - and `S' = S with conts[ca] = epsilon` -* `S; F; (prompt{(e $l)*}? v* end) --> S; F; v*` - -* `S; F; (prompt H^ea[(suspend $e)] end) --> S; F; trap` - - iff `ea = F.tags[$e]` +* `S; F; (prompt{hdl*} v* end) --> S; F; v*` * `S; F; (prompt{hdl1* (ea $l) hdl2*} H^ea[v^n (suspend $e)] end) --> S'; F; v^n (ref.cont |S.conts|) (br $l)` - - iff `ea notin ea1*` + - iff `ea notin tagaddr(hdl1*)` - and `ea = F.tags[$e]` - and `S.tags[ea].type ~~ [t1^n] -> [t2^m]` - and `S' = S with conts += (H^ea : m)` @@ -944,7 +941,7 @@ H^ea ::= * `S; F; (prompt{hdl1* (ea switch) hdl2*} H^ea[v^n (ref.cont ca) (switch $ct $e)] end) --> S''; F; prompt{hdl1* (ea switch) hdl2*} E[v^n (ref.cont |S.conts|)] end` - iff `S.conts[ca] = (E : n')` - and `n' = 1 + n` - - and `ea notin ea1*` + - and `ea notin tagaddr(hdl1*)` - and `ea = F.tags[$e]` - and `$ct ~~ cont $ft` - and `$ft ~~ [t1* (ref $ct2)] -> [t2*]` From d7e176dcae4a1c341e661d2194731688ceb4c44a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Hillerstr=C3=B6m?= Date: Thu, 6 Feb 2025 10:18:02 +0000 Subject: [PATCH 6/9] Remove stray ^ --- proposals/stack-switching/Explainer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/stack-switching/Explainer.md b/proposals/stack-switching/Explainer.md index f352f9a4..c584112c 100644 --- a/proposals/stack-switching/Explainer.md +++ b/proposals/stack-switching/Explainer.md @@ -855,7 +855,7 @@ of event, even if they use the correct tag. * `(prompt{*} * end)` represents an active handler - `(prompt{hdl*}? instr* end) : [t1*] -> [t2*]` - iff `instr* : [t1*] -> [t2*]` - - and `(hdl : [t2^*])*` + - and `(hdl : [t2*])*` The administrative structure `hdl` is defined as ``` From 86c97787b1383f0c8b0a273fda8a4bdf6732c90c Mon Sep 17 00:00:00 2001 From: mlegoupil <90708290+mlegoupil@users.noreply.github.com> Date: Fri, 22 Aug 2025 19:07:23 +0200 Subject: [PATCH 7/9] Incorporated comments Incorporated comments from before The biggest thing I am unsure of is lines 814 and 826. This pertains to what point the tag argument of suspend and switch is translated into a tag address. Doing it in the reduction rule for resume (as was the case in the previous version of Explainer.md) is wrong, for reasons explained in the comment I wrote at the time. I believe I was told in the actual implementation, the change happens during the validation phase, which is why I propose these lines 814 and 826; however my phrasing can perhaps be improved. --- proposals/stack-switching/Explainer.md | 41 ++++++++++++++++---------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/proposals/stack-switching/Explainer.md b/proposals/stack-switching/Explainer.md index c584112c..704908fb 100644 --- a/proposals/stack-switching/Explainer.md +++ b/proposals/stack-switching/Explainer.md @@ -811,6 +811,7 @@ This abbreviation will be formalised with an auxiliary function or other means i - `suspend $t : [t1*] -> [t2*]` - iff `C.tags[$t] = tag $ft` - and `C.types[$ft] ~~ func [t1*] -> [t2*]` + - During the validation phase, the tag name `$t` is replaced by the corresponding `` - `switch ` - Switch to executing a given continuation directly, suspending the current execution. @@ -822,6 +823,7 @@ This abbreviation will be formalised with an auxiliary function or other means i - and `te1* <: t*` - and `C.types[$ct2] ~~ cont [t2*] -> [te2*]` - and `t* <: te2*` + - During the validation phase, the tag name `$t` is replaced by the corresponding `` ### Execution @@ -853,9 +855,9 @@ of event, even if they use the correct tag. - and `$ft ~~ [t1^n] -> [t2*]` * `(prompt{*} * end)` represents an active handler - - `(prompt{hdl*}? instr* end) : [t1*] -> [t2*]` - - iff `instr* : [t1*] -> [t2*]` - - and `(hdl : [t2*])*` + - `(prompt{hdl*}? instr* end) : [] -> [t*]` + - iff `instr* : [] -> [t*]` in the empty context + - and `(hdl : [t*])*` The administrative structure `hdl` is defined as ``` @@ -873,7 +875,10 @@ where - and `([te2*] -> [t2*] <: $ft')*` * `(a switch)` represents a tag-switch association - - `(a switch)` and `(S.tags[b].type ~~ [] -> [te2*])*` + - `(a switch) : [t2*]` + - iff `(S.tags[b].type ~~ [] -> [te2*])*` + +Note: `(a $l)` and `(a switch)` use a separate namespace for the name `a` #### Handler contexts @@ -884,7 +889,7 @@ H^ea ::= label_n{instr*} H^ea end frame_n{F} H^ea end catch{...} H^ea end - prompt{hdl*} H^ea end (iff ea notin tagaddr(hdl*)) + prompt{hdl*} H^ea end (iff ea notin hdl*) ``` @@ -903,7 +908,7 @@ H^ea ::= * `S; F; (ref.cont ca) (cont.bind $ct $ct') --> S; F; trap` - iff `S.conts[ca] = epsilon` -* `S; F; v^n (ref.cont ca) (cont.bind $ct $ct') --> S'; F; (ref.const |S.conts|)` +* `S; F; v^n (ref.cont ca) (cont.bind $ct $ct') --> S'; F; (ref.cont |S.conts|)` - iff `S.conts[ca] = (E' : n')` - and `$ct' ~~ cont $ft'` - and `$ft' ~~ [t1'*] -> [t2'*]` @@ -911,38 +916,42 @@ H^ea ::= - and `S' = S with conts[ca] = epsilon with conts += (E : |t1'*|)` - and `E = E'[v^n _]` -* `S; F; (ref.null t) (resume $ct (on $e $l)*) --> S; F; trap` +* `S; F; (ref.null t) (resume $ct hdl*) --> S; F; trap` -* `S; F; (ref.cont ca) (resume $ct (on $e $l)*) --> S; F; trap` +* `S; F; (ref.cont ca) (resume $ct hdl*) --> S; F; trap` - iff `S.conts[ca] = epsilon` -* `S; F; v^n (ref.cont ca) (resume $ct hdl*) --> S'; F; prompt{hdl*} E[v^n] end` +* `S; F; v^n (ref.cont ca) (resume $ct hdl*) --> S'; F; prompt{hdl'*} E[v^n] end` - iff `S.conts[ca] = (E : n)` - and `S' = S with conts[ca] = epsilon` + - and `hdl'*` is obtained by translating the `` from `hdl*` into `` using `F.tag`: + - if `on $a $l` is in `hdl*` and `F.tags[$e]=ea`, then `ea $l` is in `hdl'*` + - if `on $a switch` is in `hdl'*` and `F.tags[$e]=ea`, then `ea switch` is in `hdl'*` -* `S; F; (ref.null t) (resume_throw $ct $e (on $t $l)*) --> S; F; trap` +* `S; F; (ref.null t) (resume_throw $ct $e hdl*) --> S; F; trap` -* `S; F; (ref.cont ca) (resume_throw $ct $e (on $t $l)*) --> S; F; trap` +* `S; F; (ref.cont ca) (resume_throw $ct $e hdl*) --> S; F; trap` - iff `S.conts[ca] = epsilon` -* `S; F; v^m (ref.cont ca) (resume_throw $ct $e hdl*) --> S'; F; prompt{hdl*} E[v^m (throw $e)] end` +* `S; F; v^m (ref.cont ca) (resume_throw $ct $e hdl*) --> S'; F; prompt{hdl'*} E[v^m (throw $e)] end` - iff `S.conts[ca] = (E : n)` - and `S.tags[F.tags[$e]].type ~~ [t1^m] -> [t2*]` - and `S' = S with conts[ca] = epsilon` + - and `hdl'*` is obtained by translating the `` from `hdl*` into `` using `F.tag`: + - if `on $a $l` is in `hdl*` and `F.tags[$e]=ea`, then `ea $l` is in `hdl'*` + - if `on $a switch` is in `hdl'*` and `F.tags[$e]=ea`, then `ea switch` is in `hdl'*` * `S; F; (prompt{hdl*} v* end) --> S; F; v*` -* `S; F; (prompt{hdl1* (ea $l) hdl2*} H^ea[v^n (suspend $e)] end) --> S'; F; v^n (ref.cont |S.conts|) (br $l)` +* `S; F; (prompt{hdl1* (ea $l) hdl2*} H^ea[v^n (suspend ea)] end) --> S'; F; v^n (ref.cont |S.conts|) (br $l)` - iff `ea notin tagaddr(hdl1*)` - - and `ea = F.tags[$e]` - and `S.tags[ea].type ~~ [t1^n] -> [t2^m]` - and `S' = S with conts += (H^ea : m)` -* `S; F; (prompt{hdl1* (ea switch) hdl2*} H^ea[v^n (ref.cont ca) (switch $ct $e)] end) --> S''; F; prompt{hdl1* (ea switch) hdl2*} E[v^n (ref.cont |S.conts|)] end` +* `S; F; (prompt{hdl1* (ea switch) hdl2*} H^ea[v^n (ref.cont ca) (switch $ct ea)] end) --> S''; F; prompt{hdl1* (ea switch) hdl2*} E[v^n (ref.cont |S.conts|)] end` - iff `S.conts[ca] = (E : n')` - and `n' = 1 + n` - and `ea notin tagaddr(hdl1*)` - - and `ea = F.tags[$e]` - and `$ct ~~ cont $ft` - and `$ft ~~ [t1* (ref $ct2)] -> [t2*]` - and `$ct2 ~~ cont $ft2` From 97b28005eae51aceae5f035195a00bef547f919b Mon Sep 17 00:00:00 2001 From: mlegoupil <90708290+mlegoupil@users.noreply.github.com> Date: Fri, 29 Aug 2025 14:19:33 +0200 Subject: [PATCH 8/9] rectified the suspend address translation to its correct place Incorporating Thomas Lively's comment, I have rectified the spot where suspend and switch translate the tag index into a tag address, by creating new instructions suspend.addr and switch.addr that take addresses (rather than indices) as arguments. This allows for a rule focused on translating suspend to suspend.addr (and likewise for switch), enforcing that the correct wasm frame F is used. --- proposals/stack-switching/Explainer.md | 29 +++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/proposals/stack-switching/Explainer.md b/proposals/stack-switching/Explainer.md index 704908fb..059e5752 100644 --- a/proposals/stack-switching/Explainer.md +++ b/proposals/stack-switching/Explainer.md @@ -808,10 +808,9 @@ This abbreviation will be formalised with an auxiliary function or other means i - `suspend ` - Use a control tag to suspend the current computation. - - `suspend $t : [t1*] -> [t2*]` - - iff `C.tags[$t] = tag $ft` + - `suspend $e : [t1*] -> [t2*]` + - iff `C.tags[$e] = tag $ft` - and `C.types[$ft] ~~ func [t1*] -> [t2*]` - - During the validation phase, the tag name `$t` is replaced by the corresponding `` - `switch ` - Switch to executing a given continuation directly, suspending the current execution. @@ -823,7 +822,6 @@ This abbreviation will be formalised with an auxiliary function or other means i - and `te1* <: t*` - and `C.types[$ct2] ~~ cont [t2*] -> [te2*]` - and `t* <: te2*` - - During the validation phase, the tag name `$t` is replaced by the corresponding `` ### Execution @@ -854,6 +852,18 @@ of event, even if they use the correct tag. - and `$ct ~~ cont $ft` - and `$ft ~~ [t1^n] -> [t2*]` +* `(suspend.addr ea)` represents a `(suspend $e)` instruction where the tag index `$e` has been replaced with the physical address `ea` of the tag. + - `suspend.addr ea : [t1*] -> [t2*]` + - iff `S.tags[ea].type ~~ [t1*] -> [t2*]` + +* `(switch.addr $ct ea)` represents a `(switch $ct $e)` instruction where the tag index `$e` has been replaced with the physical address `ea` of the tag. + - `switch.addr $ct ea : : [t1* (ref null $ct1)] -> [t2*]` + - iff `S.tags[$e].type ~~ [] -> [t*]` + - and `C.types[$ct] ~~ cont [t1* (ref null? $ct2)] -> [te1*]` + - and `te1* <: t*` + - and `C.types[$ct2] ~~ cont [t2*] -> [te2*]` + - and `t* <: te2*` + * `(prompt{*} * end)` represents an active handler - `(prompt{hdl*}? instr* end) : [] -> [t*]` - iff `instr* : [] -> [t*]` in the empty context @@ -878,7 +888,6 @@ where - `(a switch) : [t2*]` - iff `(S.tags[b].type ~~ [] -> [te2*])*` -Note: `(a $l)` and `(a switch)` use a separate namespace for the name `a` #### Handler contexts @@ -943,12 +952,18 @@ H^ea ::= * `S; F; (prompt{hdl*} v* end) --> S; F; v*` -* `S; F; (prompt{hdl1* (ea $l) hdl2*} H^ea[v^n (suspend ea)] end) --> S'; F; v^n (ref.cont |S.conts|) (br $l)` +* `S; F; (suspend $e) --> S; F; (suspend.addr ea)` + - iff `ea = F.tags[$e]` + +* `S; F; (prompt{hdl1* (ea $l) hdl2*} H^ea[v^n (suspend.addr ea)] end) --> S'; F; v^n (ref.cont |S.conts|) (br $l)` - iff `ea notin tagaddr(hdl1*)` - and `S.tags[ea].type ~~ [t1^n] -> [t2^m]` - and `S' = S with conts += (H^ea : m)` -* `S; F; (prompt{hdl1* (ea switch) hdl2*} H^ea[v^n (ref.cont ca) (switch $ct ea)] end) --> S''; F; prompt{hdl1* (ea switch) hdl2*} E[v^n (ref.cont |S.conts|)] end` +* `S; F; (switch $ct $e) --> S; F; (switch.addr $ct ea)` + - iff `ea = F.tags[$e]` + +* `S; F; (prompt{hdl1* (ea switch) hdl2*} H^ea[v^n (ref.cont ca) (switch.addr $ct ea)] end) --> S''; F; prompt{hdl1* (ea switch) hdl2*} E[v^n (ref.cont |S.conts|)] end` - iff `S.conts[ca] = (E : n')` - and `n' = 1 + n` - and `ea notin tagaddr(hdl1*)` From 515e806b9358d8f55f8dbfe3cc0ec1c8eb616ab2 Mon Sep 17 00:00:00 2001 From: Sam Lindley Date: Sat, 30 Aug 2025 00:06:33 +0100 Subject: [PATCH 9/9] Update proposals/stack-switching/Explainer.md Co-authored-by: Thomas Lively --- proposals/stack-switching/Explainer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/stack-switching/Explainer.md b/proposals/stack-switching/Explainer.md index 059e5752..ee79a894 100644 --- a/proposals/stack-switching/Explainer.md +++ b/proposals/stack-switching/Explainer.md @@ -857,7 +857,7 @@ of event, even if they use the correct tag. - iff `S.tags[ea].type ~~ [t1*] -> [t2*]` * `(switch.addr $ct ea)` represents a `(switch $ct $e)` instruction where the tag index `$e` has been replaced with the physical address `ea` of the tag. - - `switch.addr $ct ea : : [t1* (ref null $ct1)] -> [t2*]` + - `switch.addr $ct ea : [t1* (ref null $ct1)] -> [t2*]` - iff `S.tags[$e].type ~~ [] -> [t*]` - and `C.types[$ct] ~~ cont [t1* (ref null? $ct2)] -> [te1*]` - and `te1* <: t*`