EXTUTILS::PARSEXS::NODE(3perl)
π ExtUtils::ParseXS::Node β the Perl Programmers Reference Guide, but make it cute π
okay bestie, welcome to the manpage for ExtUtils::ParseXS::Node, straight out of the Perl Programmers Reference Guide. this is the AST node class situation. it's giving compiler internals. let's get into it β¨
πΈ NAME πΈ
ExtUtils::ParseXS::Node β Classes for nodes of an Abstract Syntax Tree π¦
β¨ SYNOPSIS β¨
so here's the whole vibe in code form, no notes:
# Create a node to represent the Foo part of an XS file; then
# top-down parse it into a subtree; then top-down emit the
# contents of the subtree as C code.
my $foo = ExtUtils::ParseXS::Node::Foo->new();
$foo->parse(...)
or die;
$foo->as_code(...);
print STDERR $foo->as_concise(1); # for debugging
like, make a Foo node, parse it top-down into a subtree, then emit that subtree's contents top-down as C code. and if you wanna see what's going on, as_concise(1) to STDERR is your debug slay. π
π DESCRIPTION π
π¨ heads up bestie: this API is currently private and subject to change. don't build your whole personality on it yet.
the ExtUtils::ParseXS::Node class, plus all its various subclasses, hold the state for the nodes of an Abstract Syntax Tree (AST) β and that AST represents the parsed state of an XS file. iykyk. π§
every node is a hash of fields. which field names are legal varies by the node type. and here's the thing β you access the hash keys and values directly: there are no getter/setter methods. we're going straight to the hash, no middleman, main character energy. π
each node may have a "kids" field which points to an array of all the children of that node β that's literally what makes it a tree π«Ά. on top of that, some of those kids may also have direct links from fields for quick access. for example, the "xsub_decl" child object of an "xsub" object can be reached in either of these two ways:
$xsub_object->{kids}[0]
$xsub_object->{decl}
most object-valued node fields inside a tree point only to their direct children. HOWEVER β and this is the plot twist π β both "INPUT_line" and "OUTPUT_line" have an "ioparam" field which points to the "IO_Param" object associated with this line, and that guy is located elsewhere in the tree. not a direct child. just vibing somewhere else. iconic.
the various "foo_part" nodes divide the parsing of the main body of an XSUB into sections where different sets of keywords are allowable, and where various bits of code can be conveniently emitted. β¨
π Methods π
there are two main methods in addition to new(), and they're present in all subclasses. ok so:
first, parse() consumes lines from the source to satisfy the construct being parsed. it may itself create objects of lower-level constructs and call parse on them. for example, Node::xbody::parse() may create a "Node::input_part" node and call parse() on it, which will create "Node::INPUT" or "Node::PREINIT" nodes as appropriate, and so on. it's turtles all the way down, bestie. π’
second, as_code() descends its sub-tree, outputting the tree as C code. π
the as_concise() method returns a line-per-node string representation of the node and any children. most node classes just inherit this method from the base "Node" class. it's intended mainly for debugging. π
some nodes also have an as_boot_code() method for adding any code to the boot XSUB. this returns two array refs: one containing a list of code lines to be inserted early into the boot XSUB, and a second for later lines. two refs, two moods. π
finally, in the IO_Param subclass, as_code() is replaced with "as_input_code" and as_output_code(), since that node may need to generate two sets of C code β one to assign a Perl argument to a C variable, and the other to return the value of a variable to Perl. double duty, she works hard. π
β note that parsing and code-generation are done as two separate phases; parse() should only build a tree and never emit code. don't make her do both jobs at once, that's not the assignment.
in addition to $self, methods may commonly have some of these parameters:
$pxsβ an"ExtUtils::ParseXS"object which contains the overall processing state. in particular, it has warning and croaking methods, and holds the lines read in from the source file for the current paragraph. π$xsubβ for nodes related to parsing an XSUB, the current"ExtUtils::ParseXS::xsub"node being processed.$xbodyβ for nodes related to parsing an XSUB, the current"ExtUtils::ParseXS::xbody"node being processed. note that in the presence of a"CASE"keyword, an XSUB can have multiple bodies. oh she contains multitudes. π
the parse() and as_code() methods for some subclasses may have parameters in addition to those. some subclasses may also have additional helper methods. so many little bonus features, obsessed. β¨
π¦ Class Hierachy π¦
(preserving the original's spelling, bestie, i'm not touching that π)
"Node" and its sub-classes form the following inheritance hierarchy. various abstract classes are used by concrete subclasses where the processing and/or fields are similar: for example, "CODE", "PPCODE" etc all consume a block of uninterpreted lines from the source file until the next keyword, and emit that code, possibly wrapped in "#line" directives. this common behaviour is provided by the "codeblock" class. sharing is caring fr fr. π«Ά
Node
XS_file
preamble
C_part
C_part_POD
C_part_code
C_part_postamble
cpp_scope
global_cpp_line
BOOT
TYPEMAP
pre_boot
boot_xsub
xsub
xsub_decl
ReturnType
Param
IO_Param
Params
xbody
input_part
init_part
code_part
output_part
cleanup_part
autocall
oneline
MODULE
REQUIRE
FALLBACK
include
INCLUDE
INCLUDE_COMMAND
NOT_IMPLEMENTED_YET
CASE
enable
EXPORT_XSUB_SYMBOLS
PROTOTYPES
SCOPE
VERSIONCHECK
multiline
multiline_merged
C_ARGS
INTERFACE
INTERFACE_MACRO
OVERLOAD
ATTRS
PROTOTYPE
codeblock
CODE
CLEANUP
INIT
POSTCALL
PPCODE
PREINIT
keylines
ALIAS
INPUT
OUTPUT
keyline
ALIAS_line
INPUT_line
OUTPUT_line
π Abstract Syntax Tree structure π
a typical XS file might compile to a tree with a node structure similar to the following. note that this is unrelated to the inheritance hierarchy shown above β different tree, different energy, don't get it twisted. π
in this example, the XS file includes another file, and has a couple of XSUBs within a "#if/#else/#endif". note that a "cpp_scope" node is the parent of all the nodes within the same branch of an "#if", or in the absence of "#if", within the same file. πΈ
XS_file
preamble
C_part
C_part_POD
C_part_code
C_part_postamble
cpp_scope: type="main"
MODULE
PROTOTYPES
BOOT
TYPEMAP
INCLUDE
cpp_scope: type="include"
xsub
...
global_cpp_line: directive="ifdef"
cpp_scope: type="if"
xsub
...
global_cpp_line: directive="else"
cpp_scope: type="if"
xsub
...
global_cpp_line: directive="endif"
xsub
...
pre_boot
boot_xsub
and a typical XSUB might compile to a tree with a structure similar to this one. so pretty. β¨
xsub
xsub_decl
ReturnType
Params
Param
Param
...
CASE # for when a CASE keyword being present implies multiple
# bodies; otherwise, just a bare xbody node.
xbody
# per-body copy of declaration Params, augmented by
# data from INPUT and OUTPUT sections
Params
IO_Param
IO_Param
...
input_part
INPUT
INPUT_line
INPUT_line
...
PREINIT
init_part
INIT
code_part
CODE
output_part
OUTPUT
OUTPUT_line
OUTPUT_line
...
POSTCALL
cleanup_part
CLEANUP
CASE
xbody
...
aaaand that's the whole page bestie, you ate it, no crumbs left ππ
oh and for the record, this was perl v5.44.0, dated 2026-10-17, and it lives in the Perl Programmers Reference Guide as ExtUtils::ParseXS::Node(3perl). go forth and parse. ππ¦β¨
π¦ where this page comes from
- arch rolling: perl 5.44.0-1 Β· Artistic-1.0-Perl AND GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms