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

cod*_*ons 8 compilation rakudo compile-time raku

以下程序无法正确编译:

sub f(Int $a) { my Str $b = $a }
say f 42;
say f 'foo';
Run Code Online (Sandbox Code Playgroud)

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

但是,具体是什么时候发生此错误?我以为它发生在 CHECK阶段,但惊讶地发现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';
Run Code Online (Sandbox Code Playgroud)

运行此修改后的代码并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 Type check failed... \n end”(再次省略正文错误信息)。

这里发生了什么?生成的编译错误是否CHECK 和 INIT之间===SORRY!===发生了一段时间(是否有这样的时间?)?或者实际上并没有按照指示“运行 BEGIN 和 CHECK 块” ?或者是其他东西?raku -craku --help

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

Eli*_*sen 8

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)
Run Code Online (Sandbox Code Playgroud)

和:

$ 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
Run Code Online (Sandbox Code Playgroud)

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

  • 预计目前正在开发的新编译器前端将重新排序,并且通常会围绕各种错误处理进行调整,因为构建 Raku 编译器的合理方法不止一种。我宁愿怀疑问题中当前不在“-c”中的类型错误可能最终会作为结构变化的副作用而出现。 (5认同)
  • 有趣,谢谢!如果其他人好奇,那是**那个** SORRY 消息,但不是所有 SORRY 消息。如果我们引入语法错误(例如 `raku --optimize=off -e 'sb foo(Int $a) { }; foo "foo"`),在没有优化器的情况下我们仍然会得到一个 SORRY 错误。 (4认同)
  • 的确。SORRY 表示这是编译过程中发生的错误。好吧,更准确地说:在 INIT 移相器运行之前。 (2认同)