【问题标题】:How are Perl's lexically-scoped pragmas implemented?Perl 的词法范围的编译指示是如何实现的?
【发布时间】:2012-07-27 13:10:08
【问题描述】:

根据文档,像 autodie 这样的编译指示是词法范围的。

{
use autodie;
  ..
  ..
}
# Can die here

这是否适用于所有使用use 加载的模块? 据我所知,use 几乎是一样的:

BEGIN {
  require autodie;
  autodie->import(LIST);
}

BEGIN 发生在编译时,并且 require 没有词法范围。那么autodie 是如何知道它的作用域的呢?

【问题讨论】:

  • 您有什么想做的吗?还是纯粹出于好奇?

标签: perl scope internals lexical-scope compiler-directives


【解决方案1】:

简短的回答是,词法范围的pragmatic modules 被显式编写为以这种方式运行,并在编译时使用神奇的内部变量$^H%^H 来启用和禁用功能。

编译器通过隐式本地化这些变量来发挥作用,以便在编译代码块结束时将它们的值恢复为开始时的值。通过这种方式,它提供了词汇语义的基础。

最初只有$^H 变量可用。它包含一个位掩码,指示在编译期间随时可用的编译器选项。因此,唯一可以编写的词法编译指示是那些操纵$^H 中定义的魔法位集的编译指示。

后来引入了 %^H 哈希,现在任何 pragma 都可以使用以 pragma 名称开头的键将值存储在此哈希中。因为编译器以与标量相同的方式本地化哈希,所以任何 pragma 都可以在此处存储自动范围内的状态信息。

autodie 模块不操纵这些变量中的任何一个,而是继承了 Fatal 模块,它完成了所有艰苦的工作。它使用%^H 来跟踪哪些运算符已成为致命的,并依赖编译器在块末尾丢弃此信息。

【讨论】:

    【解决方案2】:

    Fatal.pm的导入方法,autodie的后端,享受这个:

    # Dark magic to have autodie work under 5.8
    # Copied from namespace::clean, that copied it from
    # autobox, that found it on an ancient scroll written
    # in blood.
    
    # This magic bit causes %^H to be lexically scoped.
    $^H |= 0x020000;
    

    所以答案是确实有一种方法可以让您的导入了解它们的词法范围,但它与 perl 的胆量深深纠缠在一起,并不适合普通程序员使用。

    【讨论】:

    • 不,它只解释了使基于%^H 的编译指示在 5.8 中工作所需的额外步骤,而不仅仅是 5.10+。
    • 是的,我真的只展示了其中最可怕的部分,以传达对所涉及魔法的总体感觉。从某种意义上说,这是一个答案,它证实了提问者的感觉,即无法使用“正常”模块导入技术实现词汇编译指示。
    • 但这是完全错误的......它们可以很容易地实现。见perldoc.perl.org/perlpragma.html
    【解决方案3】:

    有趣的不是require;这就是编译指示在import 中所做的。

    大多数(全部?)pragma 使用$^H%^H。解析器将这些本地化到被解析的范围,这意味着它将它们恢复到它们之前的值

    strict 为例。它的import 修改了$^H$^H 包含一系列标志,指示编译器如何运行。

    $ perl -e'
        BEGIN { printf "%04X\n", $^H }
        {
           use strict;
           BEGIN { printf "%04X\n", $^H }
        }
        BEGIN { printf "%04X\n", $^H }
    '
    0100
    0702
    0100
    

    $^H 保留供 Perl 使用,但类似本地化的 %^H 可用于一般用途。例如,feature::qw_comment 钩入解析器一次,当它被require 加载时,但除非$^H{'feature::qw_comments::'} 为真,否则不会做任何事情。它的 import 相当于

    sub import { $^H{'feature::qw_comments::'} = 1; }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      相关资源
      最近更新 更多