从特性控制移相器

问题描述

是否可以从特征中添加 CONTROL 移相器?

按照example from the docs,在运行时代码中添加自定义控件异常很简单:

class CX::Oops does X::Control {};
sub f { CONTROL { when CX::Oops { note 'Oops!'; .resume}}
        CX::Oops.new.throw;  }

f; # OUTPUT: «Oops»

但是,我尝试从特征中这样做没有奏效:

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»

.has_phasersfire_phasers(有趣的名字!)方法,我可以看出这是添加控制移相器。我需要做些什么来将其注册为处理程序,还是我缺少其他东西?

解决方法

CATCHCONTROL 是否真的是移相器是一个有趣的问题。它们适合使用大写字母并对特定时间发生的事情做出反应。但是,它们也在语法的不同部分进行解析,作为语句控制,因此仅限于在语句级别发生。并且编译器也不通过调用 add_phasers 来处理它们。异常处理程序隐含了一些代码生成,而正是例程主体中生成的代码实际导致异常被处理。

可以合理地询问编译器是否不应该查看特征是否确实使用 add_phasersCATCH 调用了 CONTROL,然后相应地生成代码。但是,由于在当前的编译器实现中,处理程序是例程主体的一部分,并且所有工作(优化除外)都在调用 trait 处理程序之前在例程主体上完成,所以现在对 trait 产生影响为时已晚。>

另外,CATCHCONTROL 块的主体不是简单地编译为普通块,而是生成代码来处理 when 智能匹配,并重新抛出异常如果没有一个处理程序匹配;至少这最后一步需要手动完成。如果我没记错的话,还有一些关于更新 $! 的内容。

一个好消息是即将推出的基于 rakuast 的编译器前端将:

  1. 为特征处理程序中的例程的 AST 提供 API。然后可以使用它在 AST 级别添加 CATCH/CONTROL 处理程序,从而获得所有正确的语义并执行与直接写入代码的语义相同的语义。
  2. 将代码生成推迟到更晚的时间,以便时间也安排妥当。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...