-
Notifications
You must be signed in to change notification settings - Fork 15
Named handlers #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: named-handlers
Are you sure you want to change the base?
Named handlers #129
Conversation
This patch implements a semantics for named handlers. It is a fairly direct transcription of multi-prompt continuations as found in the literature. This patch adds the following new types and instructions: * `handler ts*` - A new reference type for handler names. * `resume_with $ct (on ...) : [ts1* (ref null $ct)] -> [ts2*]` - where `$ct ~~ func [ts1* (ref $handler)] -> [ts2*]` - and `$handler ~~ handler ts2*` - Operationally, it works like `resume`, but with the small tweak that it generates and passes a unique name to the continuation. * `suspend_to $handler $tag : [ts1* (ref null $handler)] -> [ts2*]` - where `$handler ~~ handler $ts3` - and `$tag ~~ func [ts1*] -> [ts2*]` - It is similar to `suspend`, but rather than suspending to the nearest enclosing handler, it suspend to a particular given handler. I've added a few tests too.
and array_type = ArrayT of field_type | ||
and func_type = FuncT of result_type * result_type | ||
and cont_type = ContT of heap_type | ||
and handler_type = HandlerT of result_type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid confusion with exn handlers, and to match the Prompt admin instruction, shouldn't this rather be called a prompt_type?
| -0x17 -> (Null, ExnHT) | ||
| -0x18 -> (Null, ContHT) | ||
| -0x19 -> (Null, HandlerHT) | ||
| -0x1a -> (Null, NoHandlerHT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's getting crowded here...
| DefArrayT _, ArrayHT -> true | ||
| DefFuncT _, FuncHT -> true | ||
| DefContT _, ContHT -> true | ||
| DefHandlerT _, HandlerHT -> true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't there be a new case for DefHandlerT in match_str_type as well?
let FuncT (ts3, ts4) = | ||
match hrt with | ||
| Some rt -> | ||
let FuncT (ts3, ts4) = func_type_of_tag_type c (tag c x1) x1.at in | ||
FuncT (ts3, ts4 @ [RefT rt]) | ||
| None -> func_type_of_tag_type c (tag c x1) x1.at | ||
in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let FuncT (ts3, ts4) = | |
match hrt with | |
| Some rt -> | |
let FuncT (ts3, ts4) = func_type_of_tag_type c (tag c x1) x1.at in | |
FuncT (ts3, ts4 @ [RefT rt]) | |
| None -> func_type_of_tag_type c (tag c x1) x1.at | |
in | |
let FuncT (ts3, ts4') = func_type_of_tag_type c (tag c x1) x1.at in | |
let ts4 = ts4' @ match hrt with Some rt -> [RefT rt] | None -> [] in |
| SuspendTo (x, y) -> | ||
let _hty = handler_type c x in | ||
let tag = tag c y in | ||
let FuncT (ts1, ts2) = func_type_of_tag_type c tag x.at in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let FuncT (ts1, ts2) = func_type_of_tag_type c tag x.at in | |
let FuncT (ts1, ts2) = func_type_of_tag_type c tag y.at in |
let args, href = | ||
match args with | ||
| Ref r :: rest -> rest, r | ||
| _ -> Crash.error e.at "type mismatch at suspend to" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| _ -> Crash.error e.at "type mismatch at suspend to" | |
| _ -> Crash.error e.at "type mismatch at suspend_to" |
let name = | ||
Ref (HandlerRef (ref (Some Name))) | ||
in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let name = | |
Ref (HandlerRef (ref (Some Name))) | |
in | |
let name = Ref (HandlerRef (ref (Some Name))) in |
| ResumeWith (x, xls), Ref (ContRef ({contents = Some (n, ctxt)} as cont)) :: vs -> | ||
let hs = handle_table c xls in | ||
let args, vs' = i32_split (Int32.sub n 1l) vs e.at in | ||
let exception Name in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of abusing exceptions, can we define our own extensible datatype prompt_name above and extend that here? Unfortunately, this:
let exception Name in | |
let type prompt_name += Name in |
doesn't work, you'll have to do
let exception Name in | |
let module N = struct type prompt_name += Name end in |
and use N.name
.
let args = cont' :: vs1 in | ||
cont := None; | ||
vs' @ vs, [Prompt (hso, ctxt (args, [])) @@ e.at] | ||
| Prompt (Some h, (hs, _), (vs', {it = Suspending (tagt, vs1, None, Some (HandlerRef ({contents = Some h'} as href)), ctxt); at} :: es')), vs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we can avoid doubling the rules by factoring out an auxiliary
let matches_name name1 name2 =
match name1, name2 with
| None, _-> true
| _, None -> false
| Some n1, Some n2 -> n1 == n2
[Ref (ContRef (ref (Some (Int32.add (Lib.List32.length ts) 1l, ctxt'))))] @ vs1 @ vs, | ||
[Plain (Br (List.assq tagt hs)) @@ e.at] | ||
|
||
| Prompt (None, ((_, hs) as hso), (vs', {it = Suspending (tagt, vs1, Some (ar, ContRef ({contents = Some (_, ctxt)} as cont)), None, ctxt'); at} :: es')), vs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this missing an equivalent rule for bubbling a named Suspending? (But see previous comment about avoiding duplication.)
This patch implements a semantics for named handlers. It is a fairly direct transcription of multi-prompt continuations as found in the literature. This patch adds the following new types and instructions:
handler ts*
resume_with $ct (on ...) : [ts1* (ref null $ct)] -> [ts2*]
$ct ~~ func [ts1* (ref $handler)] -> [ts2*]
$handler ~~ handler ts2*
resume
, but with the small tweak that it generates and passes a unique name to the continuation.suspend_to $handler $tag : [ts1* (ref null $handler)] -> [ts2*]
$handler ~~ handler $ts3
$tag ~~ func [ts1*] -> [ts2*]
suspend
, but rather than suspending to the nearest enclosing handler, it suspend to a particular given handler.I've added a few tests too.