Perl的词法范围的pragma是如何实现的?

时间:2012-07-29 18:23:08

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

根据文档,像autodie这样的Pragma是词法范围的。

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

这适用于所有加载use的模块吗? 据我所知,use几乎与:

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

BEGIN在编译时发生,而require不是词法范围的。那么autodie如何了解其范围呢?

3 个答案:

答案 0 :(得分:11)

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

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

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

稍后引入了%^H哈希,并且任何编译指示现在都可以使用以编译指示的名称开头的键在此哈希中存储值。因为编译器以与标量相同的方式对散列进行本地化,所以任何pragma都可以在此处存储自动作用域状态信息。

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

答案 1 :(得分:8)

来自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的内容深深纠缠在一起,并不适合普通的程序员使用。

答案 2 :(得分:1)

这不是require有趣的;这就是pragma在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可供一般使用。例如,当require$^H{'feature::qw_comments::'}加载时,feature::qw_comment挂钩到解析器中,但除非sub import { $^H{'feature::qw_comments::'} = 1; } 为真,否则不执行任何操作。它的导入相当于

{{1}}