diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:43:11 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:43:11 +0000 |
commit | fc22b3d6507c6745911b9dfcc68f1e665ae13dbc (patch) | |
tree | ce1e3bce06471410239a6f41282e328770aa404a /upstream/fedora-rawhide/man1/perlinterp.1 | |
parent | Initial commit. (diff) | |
download | manpages-l10n-fc22b3d6507c6745911b9dfcc68f1e665ae13dbc.tar.xz manpages-l10n-fc22b3d6507c6745911b9dfcc68f1e665ae13dbc.zip |
Adding upstream version 4.22.0.upstream/4.22.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'upstream/fedora-rawhide/man1/perlinterp.1')
-rw-r--r-- | upstream/fedora-rawhide/man1/perlinterp.1 | 1024 |
1 files changed, 1024 insertions, 0 deletions
diff --git a/upstream/fedora-rawhide/man1/perlinterp.1 b/upstream/fedora-rawhide/man1/perlinterp.1 new file mode 100644 index 00000000..e69e6d98 --- /dev/null +++ b/upstream/fedora-rawhide/man1/perlinterp.1 @@ -0,0 +1,1024 @@ +.\" -*- mode: troff; coding: utf-8 -*- +.\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. +.ie n \{\ +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "PERLINTERP 1" +.TH PERLINTERP 1 2024-01-25 "perl v5.38.2" "Perl Programmers Reference Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH NAME +perlinterp \- An overview of the Perl interpreter +.SH DESCRIPTION +.IX Header "DESCRIPTION" +This document provides an overview of how the Perl interpreter works at +the level of C code, along with pointers to the relevant C source code +files. +.SH "ELEMENTS OF THE INTERPRETER" +.IX Header "ELEMENTS OF THE INTERPRETER" +The work of the interpreter has two main stages: compiling the code +into the internal representation, or bytecode, and then executing it. +"Compiled code" in perlguts explains exactly how the compilation stage +happens. +.PP +Here is a short breakdown of perl's operation: +.SS Startup +.IX Subsection "Startup" +The action begins in \fIperlmain.c\fR. (or \fIminiperlmain.c\fR for miniperl) +This is very high-level code, enough to fit on a single screen, and it +resembles the code found in perlembed; most of the real action takes +place in \fIperl.c\fR +.PP +\&\fIperlmain.c\fR is generated by \f(CW\*(C`ExtUtils::Miniperl\*(C'\fR from +\&\fIminiperlmain.c\fR at make time, so you should make perl to follow this +along. +.PP +First, \fIperlmain.c\fR allocates some memory and constructs a Perl +interpreter, along these lines: +.PP +.Vb 9 +\& 1 PERL_SYS_INIT3(&argc,&argv,&env); +\& 2 +\& 3 if (!PL_do_undump) { +\& 4 my_perl = perl_alloc(); +\& 5 if (!my_perl) +\& 6 exit(1); +\& 7 perl_construct(my_perl); +\& 8 PL_perl_destruct_level = 0; +\& 9 } +.Ve +.PP +Line 1 is a macro, and its definition is dependent on your operating +system. Line 3 references \f(CW\*(C`PL_do_undump\*(C'\fR, a global variable \- all +global variables in Perl start with \f(CW\*(C`PL_\*(C'\fR. This tells you whether the +current running program was created with the \f(CW\*(C`\-u\*(C'\fR flag to perl and +then \fIundump\fR, which means it's going to be false in any sane context. +.PP +Line 4 calls a function in \fIperl.c\fR to allocate memory for a Perl +interpreter. It's quite a simple function, and the guts of it looks +like this: +.PP +.Vb 1 +\& my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter)); +.Ve +.PP +Here you see an example of Perl's system abstraction, which we'll see +later: \f(CW\*(C`PerlMem_malloc\*(C'\fR is either your system's \f(CW\*(C`malloc\*(C'\fR, or Perl's +own \f(CW\*(C`malloc\*(C'\fR as defined in \fImalloc.c\fR if you selected that option at +configure time. +.PP +Next, in line 7, we construct the interpreter using perl_construct, +also in \fIperl.c\fR; this sets up all the special variables that Perl +needs, the stacks, and so on. +.PP +Now we pass Perl the command line options, and tell it to go: +.PP +.Vb 2 +\& if (!perl_parse(my_perl, xs_init, argc, argv, (char **)NULL)) +\& perl_run(my_perl); +\& +\& exitstatus = perl_destruct(my_perl); +\& +\& perl_free(my_perl); +.Ve +.PP +\&\f(CW\*(C`perl_parse\*(C'\fR is actually a wrapper around \f(CW\*(C`S_parse_body\*(C'\fR, as defined +in \fIperl.c\fR, which processes the command line options, sets up any +statically linked XS modules, opens the program and calls \f(CW\*(C`yyparse\*(C'\fR to +parse it. +.SS Parsing +.IX Subsection "Parsing" +The aim of this stage is to take the Perl source, and turn it into an +op tree. We'll see what one of those looks like later. Strictly +speaking, there's three things going on here. +.PP +\&\f(CW\*(C`yyparse\*(C'\fR, the parser, lives in \fIperly.c\fR, although you're better off +reading the original YACC input in \fIperly.y\fR. (Yes, Virginia, there +\&\fBis\fR a YACC grammar for Perl!) The job of the parser is to take your +code and "understand" it, splitting it into sentences, deciding which +operands go with which operators and so on. +.PP +The parser is nobly assisted by the lexer, which chunks up your input +into tokens, and decides what type of thing each token is: a variable +name, an operator, a bareword, a subroutine, a core function, and so +on. The main point of entry to the lexer is \f(CW\*(C`yylex\*(C'\fR, and that and its +associated routines can be found in \fItoke.c\fR. Perl isn't much like +other computer languages; it's highly context sensitive at times, it +can be tricky to work out what sort of token something is, or where a +token ends. As such, there's a lot of interplay between the tokeniser +and the parser, which can get pretty frightening if you're not used to +it. +.PP +As the parser understands a Perl program, it builds up a tree of +operations for the interpreter to perform during execution. The +routines which construct and link together the various operations are +to be found in \fIop.c\fR, and will be examined later. +.SS Optimization +.IX Subsection "Optimization" +Now the parsing stage is complete, and the finished tree represents the +operations that the Perl interpreter needs to perform to execute our +program. Next, Perl does a dry run over the tree looking for +optimisations: constant expressions such as \f(CW\*(C`3 + 4\*(C'\fR will be computed +now, and the optimizer will also see if any multiple operations can be +replaced with a single one. For instance, to fetch the variable +\&\f(CW$foo\fR, instead of grabbing the glob \f(CW*foo\fR and looking at the scalar +component, the optimizer fiddles the op tree to use a function which +directly looks up the scalar in question. The main optimizer is \f(CW\*(C`peep\*(C'\fR +in \fIop.c\fR, and many ops have their own optimizing functions. +.SS Running +.IX Subsection "Running" +Now we're finally ready to go: we have compiled Perl byte code, and all +that's left to do is run it. The actual execution is done by the +\&\f(CW\*(C`runops_standard\*(C'\fR function in \fIrun.c\fR; more specifically, it's done +by these three innocent looking lines: +.PP +.Vb 3 +\& while ((PL_op = PL_op\->op_ppaddr(aTHX))) { +\& PERL_ASYNC_CHECK(); +\& } +.Ve +.PP +You may be more comfortable with the Perl version of that: +.PP +.Vb 1 +\& PERL_ASYNC_CHECK() while $Perl::op = &{$Perl::op\->{function}}; +.Ve +.PP +Well, maybe not. Anyway, each op contains a function pointer, which +stipulates the function which will actually carry out the operation. +This function will return the next op in the sequence \- this allows for +things like \f(CW\*(C`if\*(C'\fR which choose the next op dynamically at run time. The +\&\f(CW\*(C`PERL_ASYNC_CHECK\*(C'\fR makes sure that things like signals interrupt +execution if required. +.PP +The actual functions called are known as PP code, and they're spread +between four files: \fIpp_hot.c\fR contains the "hot" code, which is most +often used and highly optimized, \fIpp_sys.c\fR contains all the +system-specific functions, \fIpp_ctl.c\fR contains the functions which +implement control structures (\f(CW\*(C`if\*(C'\fR, \f(CW\*(C`while\*(C'\fR and the like) and \fIpp.c\fR +contains everything else. These are, if you like, the C code for Perl's +built-in functions and operators. +.PP +Note that each \f(CW\*(C`pp_\*(C'\fR function is expected to return a pointer to the +next op. Calls to perl subs (and eval blocks) are handled within the +same runops loop, and do not consume extra space on the C stack. For +example, \f(CW\*(C`pp_entersub\*(C'\fR and \f(CW\*(C`pp_entertry\*(C'\fR just push a \f(CW\*(C`CXt_SUB\*(C'\fR or +\&\f(CW\*(C`CXt_EVAL\*(C'\fR block struct onto the context stack, which contain the address +of the op following the sub call or eval. They then return the first op +of that sub or eval block, and so execution continues of that sub or +block. Later, a \f(CW\*(C`pp_leavesub\*(C'\fR or \f(CW\*(C`pp_leavetry\*(C'\fR op pops the \f(CW\*(C`CXt_SUB\*(C'\fR +or \f(CW\*(C`CXt_EVAL\*(C'\fR, retrieves the return op from it, and returns it. +.SS "Exception handing" +.IX Subsection "Exception handing" +Perl's exception handing (i.e. \f(CW\*(C`die\*(C'\fR etc.) is built on top of the +low-level \f(CWsetjmp()\fR/\f(CWlongjmp()\fR C\-library functions. These basically +provide a way to capture the current PC and SP registers of the CPU and +later restore them: i.e. a \f(CWlongjmp()\fR continues at the point in code +where a previous \f(CWsetjmp()\fR was done, with anything further up on the C +stack being lost. (This is why code should always save values using +\&\f(CW\*(C`SAVE_\fR\f(CIFOO\fR\f(CW\*(C'\fR rather than in auto variables.) +.PP +The perl core wraps \f(CWsetjmp()\fR and \f(CWlongjmp()\fR in the macros +\&\f(CW\*(C`JMPENV_PUSH\*(C'\fR and \f(CW\*(C`JMPENV_JUMP\*(C'\fR. The push operation, as well as setting +a \f(CWsetjump()\fR, stores some temporary state in a struct local to the +current function (allocated by \f(CW\*(C`dJMPENV\*(C'\fR). In particular, it stores a +pointer to the previous \f(CW\*(C`JMPENV\*(C'\fR struct, and updates \f(CW\*(C`PL_top_env\*(C'\fR to +point to the newest one, forming a chain of \f(CW\*(C`JMPENV\*(C'\fR states. Both the +push and jump can output debugging information under \f(CW\*(C`perl \-Dl\*(C'\fR. +.PP +A basic rule of the perl internals is that all interpreter exits are +achieved via a \f(CWJMPENV_JUMP()\fR. In particular: +.IP \(bu 4 +level 2: perl-level \fBexit()\fR and internals \fBmy_exit()\fR +.Sp +These unwind all stacks, then perform a \fBJMPENV_JUMP\fR\|(2). +.IP \(bu 4 +level 3: perl-level \fBdie()\fR and internals \fBcroak()\fR +.Sp +If currently within an eval, these pop the context stack back to the +nearest \f(CW\*(C`CXt_EVAL\*(C'\fR frame, set \f(CW$@\fR as appropriate, set \f(CW\*(C`PL_restartop\*(C'\fR +to the op which follows the eval associated with that frame, then perform +a \fBJMPENV_JUMP\fR\|(3). +.Sp +Otherwise, the error message is printed to \f(CW\*(C`STDERR\*(C'\fR, then it is treated +as an exit: unwind all stacks and perform a \fBJMPENV_JUMP\fR\|(2). +.IP \(bu 4 +level 1: unused +.Sp +\&\fBJMPENV_JUMP\fR\|(1) is currently unused except in \fBperl_run()\fR. +.IP \(bu 4 +level 0: normal return. +.Sp +The zero value is for a normal return from \fBJMPENV_PUSH()\fR +.PP +So the perl interpreter expects that, at all times, there is a suitable +\&\f(CW\*(C`JMPENV_PUSH\*(C'\fR set up (and at a suitable location within the CPU call +stack) that can catch and process a 2\- or 3\-valued jump; and in the case +of a 3, start a new runops loop to execute \f(CW\*(C`PL_restartop\*(C'\fR and all +remaining ops (as will be explained shortly). +.PP +The entry points to the perl interpreter all provide such a facility. For +example, \fBperl_parse()\fR, \fBperl_run()\fR and \f(CW\*(C`call_sv(cv, G_EVAL)\*(C'\fR all contain +something similar in outline to: +.PP +.Vb 10 +\& { +\& dJMPENV; +\& JMPENV_PUSH(ret); +\& switch (ret) { +\& case 0: /* normal return from JMPENV_PUSH() */ +\& redo_body: +\& CALLRUNOPS(aTHX); +\& break; +\& case 2: /* caught longjmp(2) \- exit / die */ +\& break; +\& case 3: /* caught longjmp(3) \- eval { die } */ +\& PL_op = PL_restartop; +\& goto redo_body; +\& } +\& +\& JMPENV_POP; +\& } +.Ve +.PP +A runops loop such as \fBPerl_runops_standard()\fR (as set up by \fBCALLRUNOPS()\fR) +is, at its heart, just a simple: +.PP +.Vb 1 +\& while ((PL_op = PL_op\->op_ppaddr(aTHX))) { 1; } +.Ve +.PP +which calls the \fBpp()\fR function associated with each op, relying on that to +return a pointer to the next op to be executed. +.PP +As well as setting catches at the entry points to the perl interpreter, +you might expect perl to also do a \fBJMPENV_PUSH()\fR in places like +\&\fBpp_entertry()\fR, just before some trappable ops are executed. In fact perl +doesn't normally do this. The drawback with doing it is that with nested +or recursive code such as: +.PP +.Vb 1 +\& sub foo { my ($i) = @_; return if $i < 0; eval { foo(\-\-$i) } } +.Ve +.PP +Then the C stack would quickly overflow with pairs of entries like +.PP +.Vb 6 +\& ... +\& #N+3 Perl_runops() +\& #N+2 Perl_pp_entertry() +\& #N+1 Perl_runops() +\& #N Perl_pp_entertry() +\& ... +.Ve +.PP +Instead, perl puts its guards at the \fIcallers\fR of runops loops. Then as +many nested subroutine calls and evals may be called as you like, all +within the one runops loop. If an exception occurs, control passes back to +the caller of the loop, which just immediately restarts a new loop with +\&\f(CW\*(C`PL_restartop\*(C'\fR being the next op to call. +.PP +So in normal operation where there are several nested evals, there +will be multiple \f(CW\*(C`CXt_EVAL\*(C'\fR context stack entries, but only a single +runops loop, guarded by a single \f(CW\*(C`JMPENV_PUSH\*(C'\fR. Each caught eval will pop +the next \f(CW\*(C`CXt_EVAL\*(C'\fR off the stack, set \f(CW\*(C`PL_restartop\*(C'\fR, then \fBlongjmp()\fR +back to \fBperl_run()\fR and continue. +.PP +However, ops are sometimes executed within an inner runops loop, such as +in a tie, sort, or overload code. In this case, something like +.PP +.Vb 1 +\& sub FETCH { eval { die }; .... } +.Ve +.PP +would, unless handled specially, cause a \fBlongjmp()\fR right back to the guard +in \fBperl_run()\fR, popping \fIboth\fR the runops loops \- which is clearly +incorrect. One way to avoid this is for the tie code to do a +\&\f(CW\*(C`JMPENV_PUSH\*(C'\fR before executing \f(CW\*(C`FETCH\*(C'\fR in the inner runops loop, but for +efficiency reasons, perl in fact just temporarily sets a flag using +\&\f(CWCATCH_SET(TRUE)\fR. This flag warns any subsequent \f(CW\*(C`require\*(C'\fR, +\&\f(CW\*(C`entereval\*(C'\fR or \f(CW\*(C`entertry\*(C'\fR ops that the caller is no longer promising to +catch any raised exceptions on their behalf. +.PP +These ops check this flag, and if true, they (via \fBdocatch()\fR) do a +\&\f(CW\*(C`JMPENV_PUSH\*(C'\fR and start a new runops loop to execute the code, rather +than doing it with the current loop. +.PP +As a consequence, on exit from the eval block in the \f(CW\*(C`FETCH\*(C'\fR above, +execution of the code following the block is still carried on in the +inner loop (i.e. the one established by the \fBpp_entertry()\fR). To avoid +confusion, if a further exception is then raised, \fBdocatch()\fR compares the +\&\f(CW\*(C`JMPENV\*(C'\fR level of the \f(CW\*(C`CXt_EVAL\*(C'\fR with \f(CW\*(C`PL_top_env\*(C'\fR and if they differ, +just re-throws the exception. In this way any inner loops get popped, +and the exception will be dealt with properly by the level which is +expecting it. +.PP +Here's an example. +.PP +.Vb 5 +\& 1: eval { tie @a, \*(AqA\*(Aq }; +\& 2: sub A::TIEARRAY { +\& 3: eval { die }; +\& 4: die; +\& 5: } +.Ve +.PP +To run this code, \fBperl_run()\fR is called, which does a \fBJMPENV_PUSH()\fR, +then enters a runops loop. This loop executes the \f(CW\*(C`entereval\*(C'\fR and \f(CW\*(C`tie\*(C'\fR +ops on line 1, with the \f(CW\*(C`entereval\*(C'\fR pushing a \f(CW\*(C`CXt_EVAL\*(C'\fR onto the context +stack. +.PP +The \fBpp_tie()\fR does a \f(CWCATCH_SET(TRUE)\fR, then starts a second runops +loop to execute the body of \fBTIEARRAY()\fR. When the loop executes the +\&\f(CW\*(C`entertry\*(C'\fR op on line 3, \fBCATCH_GET()\fR is true, so \fBpp_entertry()\fR calls +\&\fBdocatch()\fR which does a \f(CW\*(C`JMPENV_PUSH\*(C'\fR and starts a third runops loop, +which restarts the \fBpp_entertry()\fR, then executes the \f(CW\*(C`die\*(C'\fR op. At this +point the C call stack looks like this: +.PP +.Vb 11 +\& #10 Perl_pp_die() +\& #9 Perl_runops() # runops loop 3 +\& #8 S_docatch() # JMPENV level 2 +\& #7 Perl_pp_entertry() +\& #6 Perl_runops() # runops loop 2 +\& #5 Perl_call_sv() +\& #4 Perl_pp_tie() +\& #3 Perl_runops() # runops loop 1 +\& #2 S_run_body() +\& #1 perl_run() # JMPENV level 1 +\& #0 main() +.Ve +.PP +and the context and data stacks, as shown by \f(CW\*(C`perl \-Dstv\*(C'\fR, look like: +.PP +.Vb 9 +\& STACK 0: MAIN +\& CX 0: BLOCK => +\& CX 1: EVAL => AV() PV("A"\e0) +\& retop=leave +\& STACK 1: MAGIC +\& CX 0: SUB => +\& retop=(null) +\& CX 1: EVAL => * +\& retop=nextstate +.Ve +.PP +The \fBdie()\fR pops the first \f(CW\*(C`CXt_EVAL\*(C'\fR off the context stack, sets +\&\f(CW\*(C`PL_restartop\*(C'\fR from it, does a \f(CWJMPENV_JUMP(3)\fR, and control returns +to the \f(CW\*(C`JMPENV\*(C'\fR level set in \fBdocatch()\fR. This then starts another +third-level runops level, which executes the \f(CW\*(C`nextstate\*(C'\fR, \f(CW\*(C`pushmark\*(C'\fR and +\&\f(CW\*(C`die\*(C'\fR ops from line 4. At the point that the second \fBpp_die()\fR is called, +the C call stack looks exactly like that above, even though we are no +longer within an inner eval. However, the context stack now looks like +this, i.e. with the top CXt_EVAL popped: +.PP +.Vb 7 +\& STACK 0: MAIN +\& CX 0: BLOCK => +\& CX 1: EVAL => AV() PV("A"\e0) +\& retop=leave +\& STACK 1: MAGIC +\& CX 0: SUB => +\& retop=(null) +.Ve +.PP +The \fBdie()\fR on line 4 pops the context stack back down to the \f(CW\*(C`CXt_EVAL\*(C'\fR, +leaving it as: +.PP +.Vb 2 +\& STACK 0: MAIN +\& CX 0: BLOCK => +.Ve +.PP +As usual, \f(CW\*(C`PL_restartop\*(C'\fR is extracted from the \f(CW\*(C`CXt_EVAL\*(C'\fR, and a +\&\fBJMPENV_JUMP\fR\|(3) done, which pops the C stack back to the \fBdocatch()\fR: +.PP +.Vb 9 +\& #8 S_docatch() # JMPENV level 2 +\& #7 Perl_pp_entertry() +\& #6 Perl_runops() # runops loop 2 +\& #5 Perl_call_sv() +\& #4 Perl_pp_tie() +\& #3 Perl_runops() # runops loop 1 +\& #2 S_run_body() +\& #1 perl_run() # JMPENV level 1 +\& #0 main() +.Ve +.PP +In this case, because the \f(CW\*(C`JMPENV\*(C'\fR level recorded in the \f(CW\*(C`CXt_EVAL\*(C'\fR +differs from the current one, \fBdocatch()\fR just does a \fBJMPENV_JUMP\fR\|(3) +to re-throw the exception, and the C stack unwinds to: +.PP +.Vb 2 +\& #1 perl_run() # JMPENV level 1 +\& #0 main() +.Ve +.PP +Because \f(CW\*(C`PL_restartop\*(C'\fR is non-null, \fBrun_body()\fR starts a new runops +loop, and execution continues. +.SS "INTERNAL VARIABLE TYPES" +.IX Subsection "INTERNAL VARIABLE TYPES" +You should by now have had a look at perlguts, which tells you about +Perl's internal variable types: SVs, HVs, AVs and the rest. If not, do +that now. +.PP +These variables are used not only to represent Perl-space variables, +but also any constants in the code, as well as some structures +completely internal to Perl. The symbol table, for instance, is an +ordinary Perl hash. Your code is represented by an SV as it's read into +the parser; any program files you call are opened via ordinary Perl +filehandles, and so on. +.PP +The core Devel::Peek module lets us examine SVs from a +Perl program. Let's see, for instance, how Perl treats the constant +\&\f(CW"hello"\fR. +.PP +.Vb 7 +\& % perl \-MDevel::Peek \-e \*(AqDump("hello")\*(Aq +\& 1 SV = PV(0xa041450) at 0xa04ecbc +\& 2 REFCNT = 1 +\& 3 FLAGS = (POK,READONLY,pPOK) +\& 4 PV = 0xa0484e0 "hello"\e0 +\& 5 CUR = 5 +\& 6 LEN = 6 +.Ve +.PP +Reading \f(CW\*(C`Devel::Peek\*(C'\fR output takes a bit of practise, so let's go +through it line by line. +.PP +Line 1 tells us we're looking at an SV which lives at \f(CW0xa04ecbc\fR in +memory. SVs themselves are very simple structures, but they contain a +pointer to a more complex structure. In this case, it's a PV, a +structure which holds a string value, at location \f(CW0xa041450\fR. Line 2 +is the reference count; there are no other references to this data, so +it's 1. +.PP +Line 3 are the flags for this SV \- it's OK to use it as a PV, it's a +read-only SV (because it's a constant) and the data is a PV internally. +Next we've got the contents of the string, starting at location +\&\f(CW0xa0484e0\fR. +.PP +Line 5 gives us the current length of the string \- note that this does +\&\fBnot\fR include the null terminator. Line 6 is not the length of the +string, but the length of the currently allocated buffer; as the string +grows, Perl automatically extends the available storage via a routine +called \f(CW\*(C`SvGROW\*(C'\fR. +.PP +You can get at any of these quantities from C very easily; just add +\&\f(CW\*(C`Sv\*(C'\fR to the name of the field shown in the snippet, and you've got a +macro which will return the value: \f(CWSvCUR(sv)\fR returns the current +length of the string, \f(CWSvREFCOUNT(sv)\fR returns the reference count, +\&\f(CW\*(C`SvPV(sv, len)\*(C'\fR returns the string itself with its length, and so on. +More macros to manipulate these properties can be found in perlguts. +.PP +Let's take an example of manipulating a PV, from \f(CW\*(C`sv_catpvn\*(C'\fR, in +\&\fIsv.c\fR +.PP +.Vb 5 +\& 1 void +\& 2 Perl_sv_catpvn(pTHX_ SV *sv, const char *ptr, STRLEN len) +\& 3 { +\& 4 STRLEN tlen; +\& 5 char *junk; +\& +\& 6 junk = SvPV_force(sv, tlen); +\& 7 SvGROW(sv, tlen + len + 1); +\& 8 if (ptr == junk) +\& 9 ptr = SvPVX(sv); +\& 10 Move(ptr,SvPVX(sv)+tlen,len,char); +\& 11 SvCUR(sv) += len; +\& 12 *SvEND(sv) = \*(Aq\e0\*(Aq; +\& 13 (void)SvPOK_only_UTF8(sv); /* validate pointer */ +\& 14 SvTAINT(sv); +\& 15 } +.Ve +.PP +This is a function which adds a string, \f(CW\*(C`ptr\*(C'\fR, of length \f(CW\*(C`len\*(C'\fR onto +the end of the PV stored in \f(CW\*(C`sv\*(C'\fR. The first thing we do in line 6 is +make sure that the SV \fBhas\fR a valid PV, by calling the \f(CW\*(C`SvPV_force\*(C'\fR +macro to force a PV. As a side effect, \f(CW\*(C`tlen\*(C'\fR gets set to the current +value of the PV, and the PV itself is returned to \f(CW\*(C`junk\*(C'\fR. +.PP +In line 7, we make sure that the SV will have enough room to +accommodate the old string, the new string and the null terminator. If +\&\f(CW\*(C`LEN\*(C'\fR isn't big enough, \f(CW\*(C`SvGROW\*(C'\fR will reallocate space for us. +.PP +Now, if \f(CW\*(C`junk\*(C'\fR is the same as the string we're trying to add, we can +grab the string directly from the SV; \f(CW\*(C`SvPVX\*(C'\fR is the address of the PV +in the SV. +.PP +Line 10 does the actual catenation: the \f(CW\*(C`Move\*(C'\fR macro moves a chunk of +memory around: we move the string \f(CW\*(C`ptr\*(C'\fR to the end of the PV \- that's +the start of the PV plus its current length. We're moving \f(CW\*(C`len\*(C'\fR bytes +of type \f(CW\*(C`char\*(C'\fR. After doing so, we need to tell Perl we've extended +the string, by altering \f(CW\*(C`CUR\*(C'\fR to reflect the new length. \f(CW\*(C`SvEND\*(C'\fR is a +macro which gives us the end of the string, so that needs to be a +\&\f(CW"\e0"\fR. +.PP +Line 13 manipulates the flags; since we've changed the PV, any IV or NV +values will no longer be valid: if we have \f(CW\*(C`$a=10; $a.="6";\*(C'\fR we don't +want to use the old IV of 10. \f(CW\*(C`SvPOK_only_utf8\*(C'\fR is a special +UTF\-8\-aware version of \f(CW\*(C`SvPOK_only\*(C'\fR, a macro which turns off the IOK +and NOK flags and turns on POK. The final \f(CW\*(C`SvTAINT\*(C'\fR is a macro which +launders tainted data if taint mode is turned on. +.PP +AVs and HVs are more complicated, but SVs are by far the most common +variable type being thrown around. Having seen something of how we +manipulate these, let's go on and look at how the op tree is +constructed. +.SH "OP TREES" +.IX Header "OP TREES" +First, what is the op tree, anyway? The op tree is the parsed +representation of your program, as we saw in our section on parsing, +and it's the sequence of operations that Perl goes through to execute +your program, as we saw in "Running". +.PP +An op is a fundamental operation that Perl can perform: all the +built-in functions and operators are ops, and there are a series of ops +which deal with concepts the interpreter needs internally \- entering +and leaving a block, ending a statement, fetching a variable, and so +on. +.PP +The op tree is connected in two ways: you can imagine that there are +two "routes" through it, two orders in which you can traverse the tree. +First, parse order reflects how the parser understood the code, and +secondly, execution order tells perl what order to perform the +operations in. +.PP +The easiest way to examine the op tree is to stop Perl after it has +finished parsing, and get it to dump out the tree. This is exactly what +the compiler backends B::Terse, B::Concise +and CPAN module <B::Debug do. +.PP +Let's have a look at how Perl sees \f(CW\*(C`$a = $b + $c\*(C'\fR: +.PP +.Vb 12 +\& % perl \-MO=Terse \-e \*(Aq$a=$b+$c\*(Aq +\& 1 LISTOP (0x8179888) leave +\& 2 OP (0x81798b0) enter +\& 3 COP (0x8179850) nextstate +\& 4 BINOP (0x8179828) sassign +\& 5 BINOP (0x8179800) add [1] +\& 6 UNOP (0x81796e0) null [15] +\& 7 SVOP (0x80fafe0) gvsv GV (0x80fa4cc) *b +\& 8 UNOP (0x81797e0) null [15] +\& 9 SVOP (0x8179700) gvsv GV (0x80efeb0) *c +\& 10 UNOP (0x816b4f0) null [15] +\& 11 SVOP (0x816dcf0) gvsv GV (0x80fa460) *a +.Ve +.PP +Let's start in the middle, at line 4. This is a BINOP, a binary +operator, which is at location \f(CW0x8179828\fR. The specific operator in +question is \f(CW\*(C`sassign\*(C'\fR \- scalar assignment \- and you can find the code +which implements it in the function \f(CW\*(C`pp_sassign\*(C'\fR in \fIpp_hot.c\fR. As a +binary operator, it has two children: the add operator, providing the +result of \f(CW\*(C`$b+$c\*(C'\fR, is uppermost on line 5, and the left hand side is +on line 10. +.PP +Line 10 is the null op: this does exactly nothing. What is that doing +there? If you see the null op, it's a sign that something has been +optimized away after parsing. As we mentioned in "Optimization", the +optimization stage sometimes converts two operations into one, for +example when fetching a scalar variable. When this happens, instead of +rewriting the op tree and cleaning up the dangling pointers, it's +easier just to replace the redundant operation with the null op. +Originally, the tree would have looked like this: +.PP +.Vb 2 +\& 10 SVOP (0x816b4f0) rv2sv [15] +\& 11 SVOP (0x816dcf0) gv GV (0x80fa460) *a +.Ve +.PP +That is, fetch the \f(CW\*(C`a\*(C'\fR entry from the main symbol table, and then look +at the scalar component of it: \f(CW\*(C`gvsv\*(C'\fR (\f(CW\*(C`pp_gvsv\*(C'\fR in \fIpp_hot.c\fR) +happens to do both these things. +.PP +The right hand side, starting at line 5 is similar to what we've just +seen: we have the \f(CW\*(C`add\*(C'\fR op (\f(CW\*(C`pp_add\*(C'\fR, also in \fIpp_hot.c\fR) add +together two \f(CW\*(C`gvsv\*(C'\fRs. +.PP +Now, what's this about? +.PP +.Vb 3 +\& 1 LISTOP (0x8179888) leave +\& 2 OP (0x81798b0) enter +\& 3 COP (0x8179850) nextstate +.Ve +.PP +\&\f(CW\*(C`enter\*(C'\fR and \f(CW\*(C`leave\*(C'\fR are scoping ops, and their job is to perform any +housekeeping every time you enter and leave a block: lexical variables +are tidied up, unreferenced variables are destroyed, and so on. Every +program will have those first three lines: \f(CW\*(C`leave\*(C'\fR is a list, and its +children are all the statements in the block. Statements are delimited +by \f(CW\*(C`nextstate\*(C'\fR, so a block is a collection of \f(CW\*(C`nextstate\*(C'\fR ops, with +the ops to be performed for each statement being the children of +\&\f(CW\*(C`nextstate\*(C'\fR. \f(CW\*(C`enter\*(C'\fR is a single op which functions as a marker. +.PP +That's how Perl parsed the program, from top to bottom: +.PP +.Vb 10 +\& Program +\& | +\& Statement +\& | +\& = +\& / \e +\& / \e +\& $a + +\& / \e +\& $b $c +.Ve +.PP +However, it's impossible to \fBperform\fR the operations in this order: +you have to find the values of \f(CW$b\fR and \f(CW$c\fR before you add them +together, for instance. So, the other thread that runs through the op +tree is the execution order: each op has a field \f(CW\*(C`op_next\*(C'\fR which +points to the next op to be run, so following these pointers tells us +how perl executes the code. We can traverse the tree in this order +using the \f(CW\*(C`exec\*(C'\fR option to \f(CW\*(C`B::Terse\*(C'\fR: +.PP +.Vb 9 +\& % perl \-MO=Terse,exec \-e \*(Aq$a=$b+$c\*(Aq +\& 1 OP (0x8179928) enter +\& 2 COP (0x81798c8) nextstate +\& 3 SVOP (0x81796c8) gvsv GV (0x80fa4d4) *b +\& 4 SVOP (0x8179798) gvsv GV (0x80efeb0) *c +\& 5 BINOP (0x8179878) add [1] +\& 6 SVOP (0x816dd38) gvsv GV (0x80fa468) *a +\& 7 BINOP (0x81798a0) sassign +\& 8 LISTOP (0x8179900) leave +.Ve +.PP +This probably makes more sense for a human: enter a block, start a +statement. Get the values of \f(CW$b\fR and \f(CW$c\fR, and add them together. +Find \f(CW$a\fR, and assign one to the other. Then leave. +.PP +The way Perl builds up these op trees in the parsing process can be +unravelled by examining \fItoke.c\fR, the lexer, and \fIperly.y\fR, the YACC +grammar. Let's look at the code that constructs the tree for \f(CW$a = $b + +$c\fR. +.PP +First, we'll look at the \f(CW\*(C`Perl_yylex\*(C'\fR function in the lexer. We want to +look for \f(CW\*(C`case \*(Aqx\*(Aq\*(C'\fR, where x is the first character of the operator. +(Incidentally, when looking for the code that handles a keyword, you'll +want to search for \f(CW\*(C`KEY_foo\*(C'\fR where "foo" is the keyword.) Here is the code +that handles assignment (there are quite a few operators beginning with +\&\f(CW\*(C`=\*(C'\fR, so most of it is omitted for brevity): +.PP +.Vb 5 +\& 1 case \*(Aq=\*(Aq: +\& 2 s++; +\& ... code that handles == => etc. and pod ... +\& 3 pl_yylval.ival = 0; +\& 4 OPERATOR(ASSIGNOP); +.Ve +.PP +We can see on line 4 that our token type is \f(CW\*(C`ASSIGNOP\*(C'\fR (\f(CW\*(C`OPERATOR\*(C'\fR is a +macro, defined in \fItoke.c\fR, that returns the token type, among other +things). And \f(CW\*(C`+\*(C'\fR: +.PP +.Vb 10 +\& 1 case \*(Aq+\*(Aq: +\& 2 { +\& 3 const char tmp = *s++; +\& ... code for ++ ... +\& 4 if (PL_expect == XOPERATOR) { +\& ... +\& 5 Aop(OP_ADD); +\& 6 } +\& ... +\& 7 } +.Ve +.PP +Line 4 checks what type of token we are expecting. \f(CW\*(C`Aop\*(C'\fR returns a token. +If you search for \f(CW\*(C`Aop\*(C'\fR elsewhere in \fItoke.c\fR, you will see that it +returns an \f(CW\*(C`ADDOP\*(C'\fR token. +.PP +Now that we know the two token types we want to look for in the parser, +let's take the piece of \fIperly.y\fR we need to construct the tree for +\&\f(CW\*(C`$a = $b + $c\*(C'\fR +.PP +.Vb 4 +\& 1 term : term ASSIGNOP term +\& 2 { $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); } +\& 3 | term ADDOP term +\& 4 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } +.Ve +.PP +If you're not used to reading BNF grammars, this is how it works: +You're fed certain things by the tokeniser, which generally end up in +upper case. \f(CW\*(C`ADDOP\*(C'\fR and \f(CW\*(C`ASSIGNOP\*(C'\fR are examples of "terminal symbols", +because you can't get any simpler than +them. +.PP +The grammar, lines one and three of the snippet above, tells you how to +build up more complex forms. These complex forms, "non-terminal +symbols" are generally placed in lower case. \f(CW\*(C`term\*(C'\fR here is a +non-terminal symbol, representing a single expression. +.PP +The grammar gives you the following rule: you can make the thing on the +left of the colon if you see all the things on the right in sequence. +This is called a "reduction", and the aim of parsing is to completely +reduce the input. There are several different ways you can perform a +reduction, separated by vertical bars: so, \f(CW\*(C`term\*(C'\fR followed by \f(CW\*(C`=\*(C'\fR +followed by \f(CW\*(C`term\*(C'\fR makes a \f(CW\*(C`term\*(C'\fR, and \f(CW\*(C`term\*(C'\fR followed by \f(CW\*(C`+\*(C'\fR +followed by \f(CW\*(C`term\*(C'\fR can also make a \f(CW\*(C`term\*(C'\fR. +.PP +So, if you see two terms with an \f(CW\*(C`=\*(C'\fR or \f(CW\*(C`+\*(C'\fR, between them, you can +turn them into a single expression. When you do this, you execute the +code in the block on the next line: if you see \f(CW\*(C`=\*(C'\fR, you'll do the code +in line 2. If you see \f(CW\*(C`+\*(C'\fR, you'll do the code in line 4. It's this +code which contributes to the op tree. +.PP +.Vb 2 +\& | term ADDOP term +\& { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } +.Ve +.PP +What this does is creates a new binary op, and feeds it a number of +variables. The variables refer to the tokens: \f(CW$1\fR is the first token +in the input, \f(CW$2\fR the second, and so on \- think regular expression +backreferences. \f(CW$$\fR is the op returned from this reduction. So, we +call \f(CW\*(C`newBINOP\*(C'\fR to create a new binary operator. The first parameter +to \f(CW\*(C`newBINOP\*(C'\fR, a function in \fIop.c\fR, is the op type. It's an addition +operator, so we want the type to be \f(CW\*(C`ADDOP\*(C'\fR. We could specify this +directly, but it's right there as the second token in the input, so we +use \f(CW$2\fR. The second parameter is the op's flags: 0 means "nothing +special". Then the things to add: the left and right hand side of our +expression, in scalar context. +.PP +The functions that create ops, which have names like \f(CW\*(C`newUNOP\*(C'\fR and +\&\f(CW\*(C`newBINOP\*(C'\fR, call a "check" function associated with each op type, before +returning the op. The check functions can mangle the op as they see fit, +and even replace it with an entirely new one. These functions are defined +in \fIop.c\fR, and have a \f(CW\*(C`Perl_ck_\*(C'\fR prefix. You can find out which +check function is used for a particular op type by looking in +\&\fIregen/opcodes\fR. Take \f(CW\*(C`OP_ADD\*(C'\fR, for example. (\f(CW\*(C`OP_ADD\*(C'\fR is the token +value from the \f(CWAop(OP_ADD)\fR in \fItoke.c\fR which the parser passes to +\&\f(CW\*(C`newBINOP\*(C'\fR as its first argument.) Here is the relevant line: +.PP +.Vb 1 +\& add addition (+) ck_null IfsT2 S S +.Ve +.PP +The check function in this case is \f(CW\*(C`Perl_ck_null\*(C'\fR, which does nothing. +Let's look at a more interesting case: +.PP +.Vb 1 +\& readline <HANDLE> ck_readline t% F? +.Ve +.PP +And here is the function from \fIop.c\fR: +.PP +.Vb 10 +\& 1 OP * +\& 2 Perl_ck_readline(pTHX_ OP *o) +\& 3 { +\& 4 PERL_ARGS_ASSERT_CK_READLINE; +\& 5 +\& 6 if (o\->op_flags & OPf_KIDS) { +\& 7 OP *kid = cLISTOPo\->op_first; +\& 8 if (kid\->op_type == OP_RV2GV) +\& 9 kid\->op_private |= OPpALLOW_FAKE; +\& 10 } +\& 11 else { +\& 12 OP * const newop +\& 13 = newUNOP(OP_READLINE, 0, newGVOP(OP_GV, 0, +\& 14 PL_argvgv)); +\& 15 op_free(o); +\& 16 return newop; +\& 17 } +\& 18 return o; +\& 19 } +.Ve +.PP +One particularly interesting aspect is that if the op has no kids (i.e., +\&\f(CWreadline()\fR or \f(CW\*(C`<>\*(C'\fR) the op is freed and replaced with an entirely +new one that references \f(CW*ARGV\fR (lines 12\-16). +.SH STACKS +.IX Header "STACKS" +When perl executes something like \f(CW\*(C`addop\*(C'\fR, how does it pass on its +results to the next op? The answer is, through the use of stacks. Perl +has a number of stacks to store things it's currently working on, and +we'll look at the three most important ones here. +.SS "Argument stack" +.IX Subsection "Argument stack" +Arguments are passed to PP code and returned from PP code using the +argument stack, \f(CW\*(C`ST\*(C'\fR. The typical way to handle arguments is to pop +them off the stack, deal with them how you wish, and then push the +result back onto the stack. This is how, for instance, the cosine +operator works: +.PP +.Vb 4 +\& NV value; +\& value = POPn; +\& value = Perl_cos(value); +\& XPUSHn(value); +.Ve +.PP +We'll see a more tricky example of this when we consider Perl's macros +below. \f(CW\*(C`POPn\*(C'\fR gives you the NV (floating point value) of the top SV on +the stack: the \f(CW$x\fR in \f(CWcos($x)\fR. Then we compute the cosine, and +push the result back as an NV. The \f(CW\*(C`X\*(C'\fR in \f(CW\*(C`XPUSHn\*(C'\fR means that the +stack should be extended if necessary \- it can't be necessary here, +because we know there's room for one more item on the stack, since +we've just removed one! The \f(CW\*(C`XPUSH*\*(C'\fR macros at least guarantee safety. +.PP +Alternatively, you can fiddle with the stack directly: \f(CW\*(C`SP\*(C'\fR gives you +the first element in your portion of the stack, and \f(CW\*(C`TOP*\*(C'\fR gives you +the top SV/IV/NV/etc. on the stack. So, for instance, to do unary +negation of an integer: +.PP +.Vb 1 +\& SETi(\-TOPi); +.Ve +.PP +Just set the integer value of the top stack entry to its negation. +.PP +Argument stack manipulation in the core is exactly the same as it is in +XSUBs \- see perlxstut, perlxs and perlguts for a longer +description of the macros used in stack manipulation. +.SS "Mark stack" +.IX Subsection "Mark stack" +I say "your portion of the stack" above because PP code doesn't +necessarily get the whole stack to itself: if your function calls +another function, you'll only want to expose the arguments aimed for +the called function, and not (necessarily) let it get at your own data. +The way we do this is to have a "virtual" bottom-of-stack, exposed to +each function. The mark stack keeps bookmarks to locations in the +argument stack usable by each function. For instance, when dealing with +a tied variable, (internally, something with "P" magic) Perl has to +call methods for accesses to the tied variables. However, we need to +separate the arguments exposed to the method to the argument exposed to +the original function \- the store or fetch or whatever it may be. +Here's roughly how the tied \f(CW\*(C`push\*(C'\fR is implemented; see \f(CW\*(C`av_push\*(C'\fR in +\&\fIav.c\fR: +.PP +.Vb 8 +\& 1 PUSHMARK(SP); +\& 2 EXTEND(SP,2); +\& 3 PUSHs(SvTIED_obj((SV*)av, mg)); +\& 4 PUSHs(val); +\& 5 PUTBACK; +\& 6 ENTER; +\& 7 call_method("PUSH", G_SCALAR|G_DISCARD); +\& 8 LEAVE; +.Ve +.PP +Let's examine the whole implementation, for practice: +.PP +.Vb 1 +\& 1 PUSHMARK(SP); +.Ve +.PP +Push the current state of the stack pointer onto the mark stack. This +is so that when we've finished adding items to the argument stack, Perl +knows how many things we've added recently. +.PP +.Vb 3 +\& 2 EXTEND(SP,2); +\& 3 PUSHs(SvTIED_obj((SV*)av, mg)); +\& 4 PUSHs(val); +.Ve +.PP +We're going to add two more items onto the argument stack: when you +have a tied array, the \f(CW\*(C`PUSH\*(C'\fR subroutine receives the object and the +value to be pushed, and that's exactly what we have here \- the tied +object, retrieved with \f(CW\*(C`SvTIED_obj\*(C'\fR, and the value, the SV \f(CW\*(C`val\*(C'\fR. +.PP +.Vb 1 +\& 5 PUTBACK; +.Ve +.PP +Next we tell Perl to update the global stack pointer from our internal +variable: \f(CW\*(C`dSP\*(C'\fR only gave us a local copy, not a reference to the +global. +.PP +.Vb 3 +\& 6 ENTER; +\& 7 call_method("PUSH", G_SCALAR|G_DISCARD); +\& 8 LEAVE; +.Ve +.PP +\&\f(CW\*(C`ENTER\*(C'\fR and \f(CW\*(C`LEAVE\*(C'\fR localise a block of code \- they make sure that +all variables are tidied up, everything that has been localised gets +its previous value returned, and so on. Think of them as the \f(CW\*(C`{\*(C'\fR and +\&\f(CW\*(C`}\*(C'\fR of a Perl block. +.PP +To actually do the magic method call, we have to call a subroutine in +Perl space: \f(CW\*(C`call_method\*(C'\fR takes care of that, and it's described in +perlcall. We call the \f(CW\*(C`PUSH\*(C'\fR method in scalar context, and we're +going to discard its return value. The \fBcall_method()\fR function removes +the top element of the mark stack, so there is nothing for the caller +to clean up. +.SS "Save stack" +.IX Subsection "Save stack" +C doesn't have a concept of local scope, so perl provides one. We've +seen that \f(CW\*(C`ENTER\*(C'\fR and \f(CW\*(C`LEAVE\*(C'\fR are used as scoping braces; the save +stack implements the C equivalent of, for example: +.PP +.Vb 4 +\& { +\& local $foo = 42; +\& ... +\& } +.Ve +.PP +See "Localizing changes" in perlguts for how to use the save stack. +.SH "MILLIONS OF MACROS" +.IX Header "MILLIONS OF MACROS" +One thing you'll notice about the Perl source is that it's full of +macros. Some have called the pervasive use of macros the hardest thing +to understand, others find it adds to clarity. Let's take an example, +a stripped-down version the code which implements the addition operator: +.PP +.Vb 10 +\& 1 PP(pp_add) +\& 2 { +\& 3 dSP; dATARGET; +\& 4 tryAMAGICbin_MG(add_amg, AMGf_assign|AMGf_numeric); +\& 5 { +\& 6 dPOPTOPnnrl_ul; +\& 7 SETn( left + right ); +\& 8 RETURN; +\& 9 } +\& 10 } +.Ve +.PP +Every line here (apart from the braces, of course) contains a macro. +The first line sets up the function declaration as Perl expects for PP +code; line 3 sets up variable declarations for the argument stack and +the target, the return value of the operation. Line 4 tries to see +if the addition operation is overloaded; if so, the appropriate +subroutine is called. +.PP +Line 6 is another variable declaration \- all variable declarations +start with \f(CW\*(C`d\*(C'\fR \- which pops from the top of the argument stack two NVs +(hence \f(CW\*(C`nn\*(C'\fR) and puts them into the variables \f(CW\*(C`right\*(C'\fR and \f(CW\*(C`left\*(C'\fR, +hence the \f(CW\*(C`rl\*(C'\fR. These are the two operands to the addition operator. +Next, we call \f(CW\*(C`SETn\*(C'\fR to set the NV of the return value to the result +of adding the two values. This done, we return \- the \f(CW\*(C`RETURN\*(C'\fR macro +makes sure that our return value is properly handled, and we pass the +next operator to run back to the main run loop. +.PP +Most of these macros are explained in perlapi, and some of the more +important ones are explained in perlxs as well. Pay special +attention to "Background and MULTIPLICITY" in perlguts for +information on the \f(CW\*(C`[pad]THX_?\*(C'\fR macros. +.SH "FURTHER READING" +.IX Header "FURTHER READING" +For more information on the Perl internals, please see the documents +listed at "Internals and C Language Interface" in perl. |