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/6] 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/6] 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/6] 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/6] 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/6] 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/6] 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 ```