Is it possible to add a CONTROL
phaser from a trait?
Following the example from the docs, it's simple to add a custom control exception in runtime code:
class CX::Oops does X::Control {};
sub f { CONTROL { when CX::Oops { note 'Oops!'; .resume}}
CX::Oops.new.throw; }
f; # OUTPUT: «Oops»
However, my attempts to do so from a trait haven't worked:
sub trait_mod:<is>(Sub $fn, :$oopsable) {
$fn.add_phaser: 'CONTROL', { when CX::Oops { note 'Oops!'; .resume} }}
sub g is oopsable { CX::Oops.new.throw; }
g; # OUTPUT: «control exception without handler»
From the .has_phasers
and fire_phasers
(fun name!) methods, I can tell that this is adding the control phaser. Do I need to do something to register it as a handler, or is there something else I'm missing?
It's an interesting question whether CATCH
and CONTROL
really are phasers. They fit insofar as they use capital letters and that they react to something that happens at a certain time. However, they are also parsed in a different part of the grammar, as statement controls, and so are restricted to occurring at statement level. And the compiler doesn't handle them with a call to add_phasers
, either. An exception handler implies some code generation, and it is the generated code in the body of the routine that actually results in the exception being handled.
One could reasonably ask if the compiler should not look to see if a trait did call add_phasers
with CATCH
or CONTROL
and then generate code accordingly. However, since in the current compiler implementation the handlers are part of the routine body, and all work (except optimization) is completed on the routine body before trait handlers are called, it's simply too late for the trait to have an effect.
Additionally, the body of a CATCH
and CONTROL
block is not compiled simply as an ordinary block, but also gets code generated to handle the when
smartmatching, and to rethrow the exception if none of the handlers match; at least this final step would need to be done manually. There's also something about updating $!
, if I remember correctly.
The one bit of good news is that the forthcoming rakuast
-based compiler frontend will:
CATCH
/CONTROL
handler at AST level, and thus will get all of the correct semantics and perform the same as one written literally into the code.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With