Perl的词法范围的编译指示是如何实现的?
-
13-12-2019 - |
题
杂注,像 autodie
, 根据文档,是词汇范围的。
{
use autodie;
..
..
}
# Can die here
这是否适用于加载的所有模块 use
?据我所知, use
几乎和:
BEGIN {
require autodie;
autodie->import(LIST);
}
BEGIN
在编译时发生,并且require不是词汇作用域。那么,如何是 autodie
知道它的范围吗?
解决方案
简短的回答是,词汇范围 语用模块 被明确地写成这样的行为,并使用神奇的内部变量 $^H
和 %^H
在编译期间启用和禁用功能。
编译器通过隐式局部化这些变量来发挥作用,以便在编译代码块结束时将其值恢复到开始时的值。通过这种方式,它提供了词法语义的基础。
最初只有 $^H
变量是可用的。它包含一个位掩码,指示哪些编译器选项在编译期间随时可用。正因为如此,唯一可以写入的词法杂注是那些操纵定义的魔术位集的词法杂注。 $^H
.
后来的 %^H
引入了哈希,任何杂注现在都可以在这个哈希中存储值,其中包含以杂注名称开头的键。由于编译器以与标量相同的方式本地化散列,因此任何杂注都可以在此处存储自动限定范围的状态信息。
该 autodie
模块不操作这些变量中的任何一个,而是子类 Fatal
完成所有艰苦工作的模块。它使用 %^H
跟踪哪些运算符已被视为致命的,并依赖编译器在块的末尾丢弃这些信息。
其他提示
从导入方法 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的胆量纠缠在一起,而不是普通程序员使用的。
不是的 require
真有意思;这就是杂注的作用 import
.
大多数(全部?)杂注用途 $^H
或 %^H
.解析器将它们本地化为正在解析的范围,这意味着它将它们恢复到它们之前的值
以 严格的, 例如。其 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
可供一般使用。例如, 功能::qw_comment 挂钩到解析器一次,当它被加载 require
, ,但不做任何事情,除非 $^H{'feature::qw_comments::'}
是真的。它的导入相当于
sub import { $^H{'feature::qw_comments::'} = 1; }