Raku 程序编译和执行的顺序可能是嵌套编译阶段?

问题描述

以下程序无法正确编译:

sub f(Int $a) { my Str $b = $a }
say f 42;
say f 'foo';

具体来说,第 3 行导致编译错误(带有 ===SORRY!=== 错误消息);此错误发生在第 2 行执行之前,因此永远不会达到 &f 中的类型不匹配。

但是这个错误具体是什么时候发生的?我以为它发生在 CHECK phase 期间,但惊讶地注意到 raku -c 没有生成编译错误;它报告 Syntax OK

为了更深入地研究这一点,我在上面的代码片段中添加了日志记录代码:

BEGIN note 'begin';
CHECK note 'check';
INIT  note 'init';
END   note 'end';

sub f(Int $a) { my Str $b = $a }
say f 42;
say f 'foo';

使用 raku -c 运行修改后的代码会打印“begin\n check\n Syntax OK”;使用 raku 运行它会打印“begin\n check\n ===SORRY!==="(以及其余的错误消息)。

如果我删除 say f 'foo' 行(因此会出现编译错误),raku -c 仍会打印“begin\n check\n Syntax OK”但 raku 会打印“begin\n check \n init\n 类型检查失败... \n end”(再次省略错误消息的正文)。

这是怎么回事?生成 ===SORRY!=== 的编译错误是否发生在 CHECK 和 INIT 之间的某个时间(是否有这样的时间?)?或者 raku -c 实际上并没有像 raku --help 所指示的那样“运行 BEGIN 和 CHECK 块”?还是别的什么?

相关:如果有的话,这些与“嵌套编译时间”的想法有什么联系?这段代码的执行是否涉及任何嵌套的编译时间,还是仅在使用模块时才会发生?有什么方法可以记录/记录单独的编译阶段(可能正确放置了 BEGIN 块?)还是没有暴露的东西?

解决方法

SORRY 消息是静态优化器的副作用。观察以下行为的差异:

$ raku -e 'sub foo(Int $a) { }; foo "foo"'
===SORRY!=== Error while compiling -e
Calling foo(Str) will never work with declared signature (Int $a)

和:

$ raku --optimize=off -e 'sub foo(Int $a) { }; foo "foo"'
Type check failed in binding to parameter '$a'; expected Int but got Str ("foo")
  in sub foo at -e line 1

发生在 CHECKINIT 之间的某个时间,除非它已被禁用。请注意,禁用静态优化器会导致运行时错误。

相关问答

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