diff options
author | Nico Williams <nico@cryptonector.com> | 2023-07-24 06:20:21 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-24 13:20:21 +0200 |
commit | 1cf6515c0638f409ea266463bd29a5f87fb054e0 (patch) | |
tree | 34c36860942562abd96156e54f32501e066840d7 /src/opcode_list.h | |
parent | 98f709d0c1fd87a8b6a3e10c679442667712b264 (diff) |
Fix try/catch catches more than it should #1859
Close #1885, #2140, #2011, #2220, #2485, #2073
Rename the FORK_OPT opcode to TRY_BEGIN, add a TRY_END opcode, and wrap
errors when raising through a TRY_END so that they will not be caught by
the matching TRY_BEGIN.
Now a `try exp catch handler` expression generates code like:
TRY_BEGIN handler
<exp>
TRY_END
JUMP past_handler
handler: <handler>
past_handler:
...
On backtrack through TRY_BEGIN it just backtracks.
If anything past the whole thing raises when <exp> produced a value,
then the TRY_END will catch the error, wrap it in another, and
backtrack. The TRY_BEGIN will see a wrapped error and then it will
unwrap and re-raise the error.
If <exp> raises, then TRY_BEGIN will catch the error and jump to the
handler, but the TRY_BEGIN will not stack_save() in that case, so on
raise/backtrack the TRY_BEGIN will not execute again (nor will the
TRY_END).
Diffstat (limited to 'src/opcode_list.h')
-rw-r--r-- | src/opcode_list.h | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/src/opcode_list.h b/src/opcode_list.h index 886131d7..06147f0f 100644 --- a/src/opcode_list.h +++ b/src/opcode_list.h @@ -11,9 +11,10 @@ OP(STORE_GLOBAL, GLOBAL, 0, 0) OP(INDEX, NONE, 2, 1) OP(INDEX_OPT, NONE, 2, 1) OP(EACH, NONE, 1, 1) -OP(EACH_OPT, NONE, 1, 1) +OP(EACH_OPT, NONE, 1, 1) OP(FORK, BRANCH, 0, 0) -OP(FORK_OPT, BRANCH, 0, 0) +OP(TRY_BEGIN, BRANCH, 0, 0) +OP(TRY_END, NONE, 0, 0) OP(JUMP, BRANCH, 0, 0) OP(JUMP_F,BRANCH, 1, 0) OP(BACKTRACK, NONE, 0, 0) |