B - Perl 编译器后端
use B;
B
模块提供了一些类,允许 Perl 程序深入了解其内部结构。它是用于实现 Perl 编译器“后端”的模块。编译器的使用不需要了解此模块:有关用户可见部分,请参见 O 模块。B
模块对想要编写新的编译器后端的人有用。本文档假设读者对 perl 的内部结构有相当的了解,包括 SV、OP 以及程序的内部符号表和语法树等内容。
B
模块包含一组用于查询 Perl 解释器当前状态的实用函数;通常这些函数返回来自 B::SV 和 B::OP 类或其派生类的对象。这些类反过来定义了用于查询结果对象关于其自身内部状态的方法。
B
模块导出各种函数:一些是简单的实用函数,另一些则为 Perl 程序提供了一种获取内部对象初始“句柄”的方法。
B::SV
、B::AV
、B::HV
和 B::CV
对象的函数有关这些对象的类层次结构以及可以调用它们的方法的描述,请参见下面的 "类概述" 和 "与 SV 相关的类"。
返回与 C 变量 sv_undef
相对应的 SV 对象。
返回与 C 变量 sv_yes
相对应的 SV 对象。
返回与 C 变量 sv_no
相对应的 SV 对象。
接受对任何 Perl 值的引用,并将引用的值转换为适当的 B::OP 派生类或 B::SV 派生类中的对象。除了 main_root
等函数之外,这是获取内部 perl 数据结构的初始“句柄”的主要方法,然后可以使用其他访问方法对其进行跟踪。
返回的对象仅在底层 OP 和 SV 继续存在时才有效。不要尝试在底层结构被释放后使用该对象。
返回与 C 变量 amagic_generation
对应的 SV 对象。从 Perl 5.18 开始,这只是 PL_na
的别名,因此其值毫无意义。
返回表示 INIT 块的 AV 对象(即 B::AV 类)。
返回表示 CHECK 块的 AV 对象(即 B::AV 类)。
返回表示 UNITCHECK 块的 AV 对象(即 B::AV 类)。
返回表示 BEGIN 块的 AV 对象(即 B::AV 类)。
返回表示 END 块的 AV 对象(即 B::AV 类)。
返回全局 comppadlist 的 PADLIST 对象(即 B::PADLIST 类)。在 Perl 5.16 及更早版本中,它返回 AV 对象(B::AV 类)。
仅当 perl 使用 ithreads 编译时。
返回与 Perl 程序主部分相对应的(伪造的)CV。
从 SYMREF 开始遍历符号表,并对访问的每个符号(B::GV 对象)调用 METHOD。当遍历到达包符号(例如 "Foo::")时,它会调用 RECURSE,传入符号名称,并且只有在该子例程返回 true 时才会递归到该包中。
PREFIX 是您正在遍历的 SYMREF 的名称。
例如
# Walk CGI's symbol table calling print_subs on each symbol.
# Recurse only into CGI::Util::
walksymtable(\%CGI::, 'print_subs',
sub { $_[0] eq 'CGI::Util::' }, 'CGI::');
print_subs() 是您声明的 B::GV 方法。另请参见下面的 "B::GV 方法"。
B::OP
对象或用于遍历操作树的函数有关这些对象的类层次结构以及可以对它们调用的方法的描述,请参见下面的 "类概述" 和 "与操作相关的类"。
返回 Perl 程序主部分的根操作(即适当的 B::OP 派生类中的对象)。
返回 Perl 程序主部分的起始操作。
对以 OP 为基础的语法树进行树遍历,并对访问的每个操作调用 METHOD。每个节点都在其子节点之前被访问。如果 walkoptree_debug
(见下文)已被调用以打开调试,则在调用 METHOD 之前,会对每个操作调用 walkoptree_debug
方法。
返回 walkoptree
的当前调试标志。如果可选的 DEBUG 参数非零,则将调试标志设置为该参数。有关调试标志的作用,请参见上面 walkoptree
的描述。
返回操作数 OPNUM 的 PP 函数名称(例如“pp_add”)。
返回一个字符串,格式为“0x...”表示 perl 在字符串 STR 上使用的内部哈希函数的值。
将 I 转换为该 perl 使用的内部 I32 类型。
执行等效于 -c
命令行选项的操作。显然,这仅在 BEGIN 块中才有用,否则标志设置得太晚。
返回 STR 的双引号包围的转义版本,该版本可用作 C 源代码中的字符串。
返回 STR 的双引号包围的转义版本,该版本可用作 Perl 源代码中的字符串。
此函数返回的字符串,如果第一个字符是控制字符,则修改第一个字符。它首先将其转换为 ^X 格式,以便“\cG”变为“^G”。这在 B::GV::SAFENAME 内部使用,但您可以直接调用它。
返回对象的类,不包括类名中第一个 "::"
之前的部分。例如,这用于将 "B::UNOP"
转换为 "UNOP"
。
这曾经提供对旧的 5.005 线程模块的支持。现在它什么也不做。
my $op_type = $optype[$op_type_num];
一个简单的映射,将操作类型编号映射到其类型(如“COP”或“BINOP”)。
my $sv_name = $specialsv_name[$sv_index];
某些 SV 类型被认为是“特殊的”。它们由 B::SPECIAL 表示,并由 specialsv_list 中的数字引用。此数组将该数字映射回 SV 的名称(如“Nullsv”或“&PL_sv_undef”)。
Perl 内部用于保存 SV 和 OP 信息的 C 结构(PVIV、AV、HV、...、OP、SVOP、UNOP、...)是根据类层次结构建模的,B
模块通过真正的对象层次结构提供对它们的访问。指向其他对象的结构字段(无论是 SV 类型还是 OP 类型)由 B
模块表示为适当类的 Perl 对象。
B
模块的大部分内容是用于访问这些结构字段的方法。
请注意,所有访问都是只读的。您不能使用此模块修改内部结构。此外,请注意,此模块创建的 B::OP 和 B::SV 对象仅在底层对象存在时有效;它们的创建不会增加底层对象的引用计数。尝试访问已释放对象的字段将导致无法理解的结果,甚至更糟。
B::IV、B::NV、B::PV、B::PVIV、B::PVNV、B::PVMG、B::PVLV、B::AV、B::HV、B::CV、B::GV、B::FM、B::IO。这些类以显而易见的方式对应于具有类似名称的底层 C 结构。继承层次结构模仿底层的 C“继承”。
B::SV
|
+------------+------------+
| | |
B::PV B::IV B::NV
/ \ / /
/ \ / /
B::INVLIST B::PVIV /
\ /
\ /
\ /
B::PVNV
|
|
B::PVMG
|
+-------+-------+---+---+-------+-------+
| | | | | |
B::AV B::GV B::HV B::CV B::IO B::REGEXP
| |
| |
B::PVLV B::FM
访问方法对应于底层 C 宏的字段访问,通常删除前导的“类指示”前缀(Sv、Av、Hv、...)。前导前缀仅在删除会导致方法名称冲突的情况下保留。例如,GvREFCNT
保持原样,因为它的缩写会与“超类”方法 REFCNT
(对应于 C 函数 SvREFCNT
)发生冲突。
如果 SV 是布尔值(真或假),则返回真。然后,您可以使用 TRUE
检查该值是真还是假。
my $something = ( 1 == 1 ) # boolean true
|| ( 1 == 0 ) # boolean false
|| 42 # IV true
|| 0; # IV false
my $sv = B::svref_2object(\$something);
say q[Not a boolean value]
if ! $sv->IsBOOL;
say q[This is a boolean with value: true]
if $sv->IsBOOL && $sv->TRUE_nomg;
say q[This is a boolean with value: false]
if $sv->IsBOOL && ! $sv->TRUE_nomg;
返回指向此 B::SV 对象的对应常规标量的引用。换句话说,此方法是 svref_2object() 子例程的逆运算。此标量及其指向的其他数据应视为只读:修改它们既不安全也不保证产生合理的效果。
返回一个布尔值,指示 Perl 是否会将 SV 评估为真或假。
警告 此调用执行“获取”魔法。如果您只想检查此 SV 的性质,请使用 TRUE_nomg
帮助程序。
这是 SvTRUE($sv)
的别名。
检查值是否为真(不执行“获取”魔法)。返回一个布尔值,指示 Perl 是否会将 SV 评估为真或假。
这是 SvTRUE_nomg($sv)
的别名。
返回 IV 的值,解释为有符号整数。如果 FLAGS & SVf_IVisUV
,这将产生误导。也许您想要 int_value
方法?
此方法返回 IV 的值作为整数。它与 IV
不同,因为它无论存储为有符号还是无符号,都会返回正确的值。
最后这两个仅对垫名称 SV 有效。它们在 Perl 5.22 之前只存在于 B::NV 类中。在 5.22 中,它们被移到了 B::PADNAME 类。
此方法是您通常想要的方法。它使用结构中的长度和偏移信息构建一个字符串:对于普通标量,它将返回您从 Perl 中看到的字符串,即使它包含空字符。
与 B::RV::RV 相同,只是如果 PV 不是引用,它将 die()。
这种方法不太常用。它假设存储在结构体中的字符串以空字符结尾,并忽略长度信息。
如果您需要从 padname 数组中获取词法变量的名称,则应使用此方法。词法变量名始终以空字符结尾,并且长度字段 (CUR) 被重载用于其他目的,因此在这里不可靠。
此方法返回内部长度字段,该字段包含内部字节数,不一定等于逻辑字符数。
此方法返回为存储字符串而分配的字节数(通过 malloc)。如果标量不“拥有”字符串,则为 0。
仅对 r-magic 有效,返回生成正则表达式的字符串。
如果在 r-magic 上调用,将调用 die()。
仅对 r-magic 有效,返回存储在 MAGIC 中的 REGEX 的整数值。
返回上次 invlist_search() 的缓存结果(内部使用)
返回一个布尔值(0 或 1),用于判断 invlist 是否使用偏移量。如果为 false,则列表从代码点 U+0000 开始。如果为 true,则列表从以下元素开始。
返回一个整数,表示用于定义 invlist 的数组的大小。
此方法返回一个整数列表,表示 invlist 使用的数组。注意:在迭代 invlist 的过程中不能使用此方法,否则会引发异常。
如果 GV 的 GP 字段为 NULL,则此方法返回 TRUE。
此方法返回 glob 的名称,但如果名称的第一个字符是控制字符,则它会先将其转换为 ^X,因此 *^G 将返回 "^G" 而不是 "\cG"。
如果您想打印出变量的名称,这很有用。如果您将自己限制在编译时存在的 glob,那么结果应该是明确的,因为像 ${"^G"} = 1
这样的代码被编译为两个操作 - 一个常量字符串和一个解引用 (rv2gv) - 因此 glob 是在运行时创建的。
如果您在运行时处理 glob,并且需要区分 *^G 和 *{"^G"},那么您应该使用原始 NAME 方法。
最后一个仅在 perl 5.22.0 及更高版本中存在。
B::IO 对象从 IO 对象派生,您将从 IO 对象本身获得更多信息。
例如
$gvio = B::svref_2object(\*main::stdin)->IO;
$IO = $gvio->object_2svref();
$fd = $IO->fileno();
表示 IO 处理程序类型的字符。
- STDIN/OUT
I STDIN/OUT/ERR
< read-only
> write-only
a append
+ read and write
s socket
| pipe
I IMPLICIT
# NUMERIC
space closed handle
\0 closed internal handle
接受一个参数('stdin' | 'stdout' | 'stderr'),如果对象的 IoIFP 等于以参数形式传递的名称的句柄,则返回 true;例如,$io->IsSTD('stderr') 如果 IoIFP($io) == PerlIO_stderr() 则为 true。
返回一个 B::PADLIST 对象。
对于常量子例程,返回子例程返回的常量 SV。
返回词法子例程的名称,否则返回 undef
。
B::OP
、B::UNOP
、B::UNOP_AUX
、B::BINOP
、B::LOGOP
、B::LISTOP
、B::PMOP
、B::SVOP
、B::PADOP
、B::PVOP
、B::LOOP
、B::COP
、B::METHOP
。
这些类以明显的方式对应于同名底层 C 结构。继承层次结构模仿底层 C 的“继承”。
B::OP
|
+----------+---------+--------+-------+---------+
| | | | | |
B::UNOP B::SVOP B::PADOP B::COP B::PVOP B::METHOP
|
+---+---+---------+
| | |
B::BINOP B::LOGOP B::UNOP_AUX
|
|
B::LISTOP
|
+---+---+
| |
B::LOOP B::PMOP
访问方法对应于底层 C 结构字段名,去掉了开头的“类指示”前缀("op_"
)。
这些方法获取 OP 数据结构中同名字段的值。有关更多信息,请参阅 op.h
的顶部。
返回 OP 的父级。如果它没有父级,或者如果您的 perl 没有使用 -DPERL_OP_PARENT
构建,则返回 NULL。
请注意,全局变量 $B::OP::does_parent
在不支持 parent
方法的旧版 perl 中未定义,在支持该方法但没有使用 -DPERL_OP_PARENT
构建的 perl 中定义但为假,否则为真。
这将返回操作名称作为字符串(例如“add”、“rv2av”)。
这将返回函数名称作为字符串(例如“PL_ppaddr[OP_ADD]”、“PL_ppaddr[OP_RV2AV]”)。
这将从全局 C PL_op_desc 数组中返回操作描述(例如“addition” “array deref”)。
此方法返回操作的辅助数据结构中的元素列表,如果不存在辅助数据结构,则返回空列表。 返回值取决于对象的类型,但通常是 B::IV
、B::GV
等对象的集合。 cv
是表示包含操作的子例程的 B::CV
对象。
此方法返回对象的文本表示形式(可能对反解析和调试有用),如果操作类型不支持此方法,则返回空字符串。 cv
是表示包含操作的子例程的 B::CV
对象。
仅当 perl 使用 ithreads 编译时。
自 Perl 5.17.1 起
在 Perl 5.22 中添加,此方法返回与操作关联的 B::REGEXP。 虽然 PMOP 在线程化构建中实际上没有 pmregexp
字段,但此方法仍然返回线程下的正则表达式,以方便起见。
B::COP
类用于 "nextstate" 和 "dbstate" 操作。从 Perl 5.22 开始,它也用于最初作为 COP 的 "null" 操作。
Perl 5.18 引入了一个新的类,B::PADLIST,由 B::CV 的 PADLIST
方法返回。
Perl 5.22 引入了 B::PADNAMELIST 和 B::PADNAME 类。
一个 pad 列表。第一个是包含名称的 B::PADNAMELIST。其余的目前是 B::AV 对象,但这可能会在将来的版本中发生变化。
类似于 ARRAY
,但接受一个索引作为参数,以获取单个元素,而不是所有元素的列表。
此方法在 5.22 中引入,返回 B::PADNAMELIST。它等效于带有 0 个参数的 ARRAYelt
。
此方法在 5.22 中引入,返回相同 padlist 克隆共享的 ID。
此方法也在 5.22 中添加,返回外部 padlist 的 ID。
为了向后兼容,如果设置了 PADNAMEt_OUTER 标志,FLAGS 方法也会添加 SVf_FAKE 标志。
表示类型词法作用域的存储区的 B::HV 对象。
TYPE 的向后兼容别名。
表示 'our' 变量的存储区的 B::HV 对象。
'my' 子例程的原型 CV。
表示词法作用域可见范围的序列号。如果设置了 PADNAMEt_OUTER,则无意义。
仅当设置了 PADNAMEt_OUTER 时才有意义。
仅当设置了 PADNAMEt_OUTER 时才有意义。
返回一个布尔值,用于检查 padname 是否为 PL_padname_undef。
虽然 optree 是只读的,但有一个覆盖机制允许您覆盖各种 B::*OP 方法为特定操作返回的值。$B::overlay
应该设置为引用一个两层哈希:按操作地址索引,然后是方法名称。每当调用操作方法时,如果哈希中存在该值,则返回该值。此机制由 B::Deparse 用于“撤消”某些优化。例如
local $B::overlay = {};
...
if ($op->name eq "foo") {
$B::overlay->{$$op} = {
name => 'bar',
next => $op->next->next,
};
}
...
$op->name # returns "bar"
$op->next # returns the next op but one
Malcolm Beattie,[email protected]