Add try..finally
Why
JavaScript code cleans up with finally blocks: after an await, around break and continue, and in generators, where cancellation is only seen by finally. ReScript had no way to express them.
try takes finally { ... } after its body or after its catch. finally stays an identifier: after a catch it only starts a finally block when a brace follows. The block is a statement and must not break or continue out of it. Supersedes #7903.
modifiedAST Pexp_try
let f = g => try g() catch { | Not_found => 0 } finally { Console.log("done") }
diagnostic
`finally` was not valid after a catch.parse
expression├─ Pexp_try├─ expression│ ├─ Pexp_apply│ ├─ expression│ │ └─ Pexp_ident "g"│ ├─ …│ └─ <case>│ ├─ pattern│ │ └─ Ppat_construct "Not_found"│ └─ expression│ └─ Pexp_constant PConst_int (0,None)└─ Some └─ expression ├─ Pexp_apply ├─ expression │ └─ Pexp_ident "Console.log" └─ …
addedLambda Ltryfinally
lambda
(try (try (apply g/1002 unit) with raw_exn/1062 …) finally (seq (js_call[console.log] "done") unit))
addedJS try..catch..finally
js
function f(g) { try { return g(); } catch (raw_exn) { let exn = Primitive_exceptions.internalToException(raw_exn); if (exn.RE_EXN_ID === "Not_found") { return 0; } throw exn; } finally { console.log("done"); }}
addedDiagnostic break out of finally
while true { try { () } finally { break }}
diagnostic
`break` cannot leave a `finally` block. Only a loop inside the block can be broken out of.Review
- Why a separate Ltryfinally instead of an optional finally on Ltrywith? Ltrywith keeps its meaning in every pass, a try without catch needs no exception ident, and try..catch..finally is an Ltryfinally around an Ltrywith that the JS backend prints as one statement.
- Why is the catch handler no longer in tail position? With a finally, a self tail call in the handler would become a loop
continuethat runs the finally before the recursive call instead of after it. - Why reject break and continue in finally? JavaScript allows them, but they silently drop a pending exception or return value.