summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorPaul "LeoNerd" Evans <leonerd@leonerd.org.uk>2021-02-09 00:52:18 +0000
committerPaul "LeoNerd" Evans <leonerd@leonerd.org.uk>2021-02-14 13:40:50 +0000
commit383bf72f374cd3608e3ae2a186dd0c3a8d2fbf53 (patch)
tree6ce924a3e6c0059d1c46fd9926bce2828bc12967 /pp_ctl.c
parent656489102eb44a763e82ae9961a7097021182677 (diff)
downloadperl-383bf72f374cd3608e3ae2a186dd0c3a8d2fbf53.tar.gz
A totally new optree structure for try/catch involving three new optypes
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c66
1 files changed, 44 insertions, 22 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 6ef2ba17bb..9d7de39bcf 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -4616,15 +4616,52 @@ PP(pp_leaveeval)
return retop;
}
+/* Ops that implement try/catch syntax
+ * Note the asymmetry here:
+ * pp_entertrycatch does two pushblocks
+ * pp_leavetrycatch pops only the outer one; the inner one is popped by
+ * pp_poptry or by stack-unwind of die within the try block
+ */
+
+PP(pp_entertrycatch)
+{
+ PERL_CONTEXT *cx;
+ const U8 gimme = GIMME_V;
+
+ RUN_PP_CATCHABLY(Perl_pp_entertrycatch);
+
+ assert(!CATCH_GET);
+
+ Perl_pp_enter(aTHX); /* performs cx_pushblock(CXt_BLOCK, ...) */
+
+ save_scalar(PL_errgv);
+ CLEAR_ERRSV();
+
+ cx = cx_pushblock((CXt_EVAL|CXp_EVALBLOCK|CXp_TRY), gimme,
+ PL_stack_sp, PL_savestack_ix);
+ cx_pusheval(cx, cLOGOP->op_other, NULL);
+
+ PL_in_eval = EVAL_INEVAL;
+
+ return NORMAL;
+}
+
+PP(pp_leavetrycatch)
+{
+ /* leavetrycatch is leave */
+ return Perl_pp_leave(aTHX);
+}
+
+PP(pp_poptry)
+{
+ /* poptry is leavetry */
+ return Perl_pp_leavetry(aTHX);
+}
+
PP(pp_catch)
{
dTARGET;
- if(!SvROK(ERRSV) && !SvTRUE(ERRSV)) {
- /* ERRSV is neither an object nor true, therefore no exception happened */
- return cLOGOP->op_next;
- }
-
save_clearsv(&(PAD_SVl(PL_op->op_targ)));
sv_setsv(TARG, ERRSV);
CLEAR_ERRSV();
@@ -4676,22 +4713,7 @@ PP(pp_entertry)
assert(!CATCH_GET);
- if(PL_op->op_flags & OPf_SPECIAL) { /* a try {} block */
- PERL_CONTEXT *cx;
- const U8 gimme = GIMME_V;
-
- save_scalar(PL_errgv);
- CLEAR_ERRSV();
-
- cx = cx_pushblock((CXt_EVAL|CXp_EVALBLOCK|CXp_TRY), gimme,
- PL_stack_sp, PL_savestack_ix);
- cx_pusheval(cx, retop, NULL);
-
- PL_in_eval = EVAL_INEVAL;
- }
- else { /* an eval {} block */
- create_eval_scope(retop, 0);
- }
+ create_eval_scope(retop, 0);
return PL_op->op_next;
}
@@ -4723,7 +4745,7 @@ PP(pp_leavetry)
CX_LEAVE_SCOPE(cx);
cx_popeval(cx);
cx_popblock(cx);
- retop = cx->blk_eval.retop;
+ retop = CxTRY(cx) ? PL_op->op_next : cx->blk_eval.retop;
CX_POP(cx);
CLEAR_ERRSV();