=encoding utf8 =for comment Consistent formatting of this file is achieved with: perl ./Porting/podtidy pod/perlinterp.pod =head1 NAME =begin original perlinterp - An overview of the Perl interpreter =end original perlinterp - Perl インタプリタの概要 =head1 DESCRIPTION =begin original 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. =end original この文書は、C コードのレベルで Perl インタプリタがどのように動作しているかの 概要を、関連する C ソースコードファイルへのポインタと共に提供します。 =head1 ELEMENTS OF THE INTERPRETER (インタプリタの要素) =begin original The work of the interpreter has two main stages: compiling the code into the internal representation, or bytecode, and then executing it. L explains exactly how the compilation stage happens. =end original インタプリタの動作には二つの主要なステージがあります: コードを内部表現(バイトコード)にコンパイルし、それを実行します。 L は、コンパイルステージがどのように起こるかを 正確に説明しています。 =begin original Here is a short breakdown of perl's operation: =end original perl の操作について簡単に説明します: =head2 Startup (開始) =begin original The action begins in F. (or F for miniperl) This is very high-level code, enough to fit on a single screen, and it resembles the code found in L; most of the real action takes place in F =end original アクションは F で始まります(miniperl の場合は F)。 これは非常に高レベルのコードで、一つの画面に収まります; また、L のコードに似ています; 実際のアクションのほとんどは F で行われます。 =begin original F is generated by C from F at make time, so you should make perl to follow this along. =end original F は C によって F から make 時に生成されますので、perl はこれに従うようにしてください。 =begin original First, F allocates some memory and constructs a Perl interpreter, along these lines: =end original まず、F はメモリを割り当て、次の行に従って Perl インタプリタを 構築します: 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 } =begin original Line 1 is a macro, and its definition is dependent on your operating system. Line 3 references C, a global variable - all global variables in Perl start with C. This tells you whether the current running program was created with the C<-u> flag to perl and then F, which means it's going to be false in any sane context. =end original 1 行目はマクロで、その定義はオペレーティングシステムによって異なります。 3 行目はグローバル変数 C を参照しています; Perl のグローバル変数はすべて C で始まります。 これにより、現在実行中のプログラムが perl に対して C<-u> フラグを付けて 作成され、次に F フラグを付けて作成されたかどうかがわかります。 これは、まともなコンテキストでは偽になることを意味します。 =begin original Line 4 calls a function in F to allocate memory for a Perl interpreter. It's quite a simple function, and the guts of it looks like this: =end original 4 行目では、Perl インタプリタにメモリを割り当てるために F の関数を呼び出しています。 これは非常に単純な関数で、その中身は次のようになります: my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter)); =begin original Here you see an example of Perl's system abstraction, which we'll see later: C is either your system's C, or Perl's own C as defined in F if you selected that option at configure time. =end original C は、システムの C か、または F で 定義されている Perl 自身の C (設定時にこのオプションを選択した場合)の いずれかです。 =begin original Next, in line 7, we construct the interpreter using perl_construct, also in F; this sets up all the special variables that Perl needs, the stacks, and so on. =end original 次に、7 行目で、同じく F で perl_construct を使用して インタプリタを作成します; これにより、Perl が必要とするすべての特殊変数やスタックなどが設定されます。 =begin original Now we pass Perl the command line options, and tell it to go: =end original 次に、Perl にコマンドラインオプションを渡し、実行するように指示します: exitstatus = perl_parse(my_perl, xs_init, argc, argv, (char **)NULL); if (!exitstatus) perl_run(my_perl); exitstatus = perl_destruct(my_perl); perl_free(my_perl); =begin original C is actually a wrapper around C, as defined in F, which processes the command line options, sets up any statically linked XS modules, opens the program and calls C to parse it. =end original C は実際には、F で定義されている C の ラッパーです; このラッパーはコマンドラインオプションを処理し、静的にリンクされた XS モジュールを設定し、プログラムを開き、C を 呼び出して構文解析します。 =head2 Parsing (パース) =begin original 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. =end original このステージの目的は、Perl ソースを取得し、それを op 木に変換することです。 これらのうちの一つがどのように見えるかについては、後で説明します。 厳密に言えば、ここでは三つのことが起こっています。 =begin original C, the parser, lives in F, although you're better off reading the original YACC input in F. (Yes, Virginia, there B 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. =end original パーサである C は F にありますが、 元の YACC 入力を F で読んだ方が良いでしょう。 (そう、バージニア、これが Perl のための YACC 文法です!)。 パーサの仕事は、コードを「理解」し、それを文に分割し、 どのオペランドがどの演算子と合うかなどを決定することです。 =begin original 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 C, and that and its associated routines can be found in F. 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. =end original パーサは字句解析器の支援を受けます; 字句解析器は入力をトークンに分割し、変数名、演算子、裸の単語、サブルーチン、 コア関数など、各トークンがどのような種類のものであるかを判断します。 字句解析器への主なエントリポイントは C です; 字句解析器とそれに関連するルーチンは F にあります。 Perl は他のコンピュータ言語とはあまり似ていません; コンテキストに非常に敏感な場合があり、トークンがどのような種類の ものであるか、トークンがどこで終わるかを理解するのは難しい場合があります。 そのため、トークン解析器とパーサの間には多くの相互作用があり、 これに慣れていないと非常に恐ろしくなります。 =begin original 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 F, and will be examined later. =end original パーサは Perl プログラムを理解すると、実行中にインタプリタが 実行するための操作木を構築します。 さまざまな操作を構築してリンクするルーチンは Fにあり、 これは後で検討します。 =head2 Optimization (最適化) =begin original 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 C<3 + 4> 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 C<$foo>, instead of grabbing the glob C<*foo> 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 C in F, and many ops have their own optimizing functions. =end original これで構文解析段階が完了し、完成した木は Perl インタプリタが プログラムを実行するために実行する必要のある操作を表します。 次に、Perl は木を仮ここで走査して最適化を探します: C<3 + 4> のような定数式はここで計算され、オプティマイザは複数の操作が 単一の操作に置き換えられるかどうかも調べます。 例えば、変数 C<$foo> をフェッチするために、glob C<*foo> を取得して スカラ成分を調べる代わりに、オプティマイザは、問題のスカラを 直接検索する関数を使用するように op 木を操作します。 メインオプティマイザは F の C であり、多くの op は 独自の最適化関数を持っています。 =head2 Running (実行) =begin original 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 C function in F; more specifically, it's done by these three innocent looking lines: =end original Perl バイトコードをコンパイルし、あとはそれを実行するだけです。 実際の実行は、F の C 関数によって行われます; 具体的には、次の三つの無邪気に見える行によって行われます: while ((PL_op = PL_op->op_ppaddr(aTHX))) { PERL_ASYNC_CHECK(); } =begin original You may be more comfortable with the Perl version of that: =end original 次のような Perl バージョンの方が使いやすいかもしれません: PERL_ASYNC_CHECK() while $Perl::op = &{$Perl::op->{function}}; =begin original 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 C which choose the next op dynamically at run time. The C makes sure that things like signals interrupt execution if required. =end original ええと、違うかも知れません。 とにかく、各 op には関数ポインタが含まれていて、実際に操作を実行する関数を 指定します。 この関数は、シーケンス内の次の op を返します - これにより、 C のようなものが実行時に動的に次の op を選択することができます。 C は、シグナルのようなものが必要に応じて実行を 中断するようにします。 =begin original The actual functions called are known as PP code, and they're spread between four files: F contains the "hot" code, which is most often used and highly optimized, F contains all the system-specific functions, F contains the functions which implement control structures (C, C and the like) and F contains everything else. These are, if you like, the C code for Perl's built-in functions and operators. =end original 実際に呼び出される関数は PP コードと呼ばれ、四つのファイルに分散されます。 F には最も頻繁に使用され高度に最適化された "hot"コードが含まれ、 F にはシステム固有の関数がすべて含まれ、 F には制御構造を実装する関数(C、C など)が含まれ、 Fにはその他のすべてが含まれます。 これらは、言ってみれば、Perl の組み込み関数と演算子の C コードです。 =begin original Note that each C 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, C and C just push a C or C 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 C or C op pops the C or C, retrieves the return op from it, and returns it. =end original 各 C 関数は、次の op へのポインタを返すことが期待されていることに 注意してください。 perl サブルーチン (および eval ブロック)への呼び出しは、同じ runops ループ内で処理され、C スタック上の余分なスペースを消費しません。 たとえば、C と C は、 C または C ブロック構造体を、サブルーチン呼び出しまたは eval に続く op のアドレスを含むコンテキストスタックにプッシュします。 次に、それらはそのサブルーチンまたは eval ブロックの最初の op を返すので、 そのサブルーチンまたはブロックの実行が継続されます。 その後、C または C op が C または C をポップし、そこから return op を取得して返します。 =head2 Exception handing (例外処理) =begin original Perl's exception handing (i.e. C etc.) is built on top of the low-level C/C C-library functions. These basically provide a way to capture the current PC and SP registers and later restore them; i.e. a C continues at the point in code where a previous C was done, with anything further up on the C stack being lost. This is why code should always save values using C rather than in auto variables. =end original Perl の例外処理(C など)は、低レベルの C/C C ライブラリ関数の上に構築されています。 これらは基本的に、現在の PC と SP レジスタを取得し、後で復元する方法を 提供します; つまり、C は、コード内で前の C が実行された時点で 継続され、C スタック上の上位のものは失われます。 これが、コードが常に自動変数ではなく C を使用して 値を保存すべき理由です。 =begin original The perl core wraps C etc in the macros C and C. The basic rule of perl exceptions is that C, and C (in the absence of C) perform a C, while C within C does a C. =end original perl コアは、マクロ C と C で C などをラップします。 perl 例外の基本的なルールは、C と C(C がない場合)は C を実行し、C 内の C は C を 実行するということです。 =begin original At entry points to perl, such as C, C and C each does a C, then enter a runops loop or whatever, and handle possible exception returns. For a 2 return, final cleanup is performed, such as popping stacks and calling C or C blocks. Amongst other things, this is how scope cleanup still occurs during an C. =end original C, C, C などの perl へのエントリポイントでは、それぞれ C を実行し、 runops ループなどに入り、考えられる例外リターンを処理します。 2 リターンの場合は、スタックをポップしたり、C または C ブロックを呼び出すなど、最終的なクリーンアップが実行されます。 とりわけ、C の実行中にスコープのクリーンアップが行われる方法は このようになっています。 =begin original If a C can find a C block on the context stack, then the stack is popped to that level and the return op in that block is assigned to C; then a C is performed. This normally passes control back to the guard. In the case of C and C, a non-null C triggers re-entry to the runops loop. The is the normal way that C or C is handled within an C. =end original C がコンテキストスタック上に C ブロックを見つけることが できる場合、スタックはそのレベルにポップされ、そのブロック内の return op が C に割り当てられます; 次に C が実行されます。 これにより、通常は制御がガードに戻されます。 C と C の場合、非 NULL の C が runops ループへの再エントリを引き起こします。 これは、C 内で C または C を処理する通常の方法です。 =begin original Sometimes ops are executed within an inner runops loop, such as tie, sort or overload code. In this case, something like =end original 内部 runops ループ(tie、sort、overload コードなど)内で op が 実行されることがあります。 この場合、以下のようになります: sub FETCH { eval { die } } =begin original would cause a longjmp right back to the guard in C, popping both runops loops, which is clearly incorrect. One way to avoid this is for the tie code to do a C before executing C in the inner runops loop, but for efficiency reasons, perl in fact just sets a flag, using C. The C, C and C ops check this flag, and if true, they call C, which does a C and starts a new runops level to execute the code, rather than doing it on the current loop. =end original これは、C のガードに対して longjmp を引き起こし、両方の runops ループをポップさせますが、これは明らかに正しくありません。 これを回避する一つの方法は、内部 runops ループで C を実行する前に、 tie コードが C を実行することですが、効率性の理由から、 perl は実際には C を使用してフラグを設定するだけです。 C, C, C op はこのフラグをチェックし、 真の場合は C を呼び出します; これは C を実行し、新しい runops レベルを開始して コードを実行します; 現在のループでは実行されません。 =begin original As a further optimisation, on exit from the eval block in the C, execution of the code following the block is still carried on in the inner loop. When an exception is raised, C compares the C level of the C with C and if they differ, just re-throws the exception. In this way any inner loops get popped. =end original さらなる最適化として、C の eval ブロックを終了すると、 ブロックに続くコードの実行は依然として内側のループで実行されます。 例外が発生すると、C は C の C レベルと C を比較し、両者が異なる場合は例外を再スローします。 このようにして、内側のループはポップされます。 =begin original Here's an example. =end original 以下は例です: 1: eval { tie @a, 'A' }; 2: sub A::TIEARRAY { 3: eval { die }; 4: die; 5: } =begin original To run this code, C is called, which does a C then enters a runops loop. This loop executes the eval and tie ops on line 1, with the eval pushing a C onto the context stack. =end original このコードを実行するために、C が呼び出され、C を 実行して runops ループに入ります。 このループは 1 行目の eval と tie op を実行します; eval は C をコンテキストスタックにプッシュします。 =begin original The C does a C, then starts a second runops loop to execute the body of C. When it executes the entertry op on line 3, C is true, so C calls C which does a C and starts a third runops loop, which then executes the die op. At this point the C call stack looks like this: =end original C は C を実行し、2 番目の runops ループを開始して C の本体を実行します。 3 行目の entertry op を実行すると、C は真であるため、 C は C を呼び出して C を実行し、 3 番目の runops ループを開始して die op を実行します。 この時点で、C コールスタックは次のようになります。 Perl_pp_die Perl_runops # third loop S_docatch_body S_docatch Perl_pp_entertry Perl_runops # second loop S_call_body Perl_call_sv Perl_pp_tie Perl_runops # first loop S_run_body perl_run main =begin original and the context and data stacks, as shown by C<-Dstv>, look like: =end original コンテキストスタックとデータスタックは、C<-Dstv> で示すように、 次のようになります: STACK 0: MAIN CX 0: BLOCK => CX 1: EVAL => AV() PV("A"\0) retop=leave STACK 1: MAGIC CX 0: SUB => retop=(null) CX 1: EVAL => * retop=nextstate =begin original The die pops the first C off the context stack, sets C from it, does a C, and control returns to the top C. This then starts another third-level runops level, which executes the nextstate, pushmark and die ops on line 4. At the point that the second C is called, the C call stack looks exactly like that above, even though we are no longer within an inner eval; this is because of the optimization mentioned earlier. However, the context stack now looks like this, ie with the top CxEVAL popped: =end original die はコンテキストスタックから最初の C をポップし、そこから C をセットし、C を実行し、制御はトップの C に戻ります。 これにより、もう一つの第 3 レベルの runops レベルが開始され、 4 行目の nextstate、pushmark、die ops が実行されます。 2 番目の C が呼び出された時点で、C のコールスタックは上記と まったく同じように見えますが、内側の eval 内ではありません; これは前述の最適化のためです。 しかし、コンテキストスタックは次のように見えます; つまり、トップ CxEVAL がポップされます: STACK 0: MAIN CX 0: BLOCK => CX 1: EVAL => AV() PV("A"\0) retop=leave STACK 1: MAGIC CX 0: SUB => retop=(null) =begin original The die on line 4 pops the context stack back down to the CxEVAL, leaving it as: =end original 4 行目の die は、コンテキストスタックを CxEVAL にポップダウンし、 次のように残します: STACK 0: MAIN CX 0: BLOCK => =begin original As usual, C is extracted from the C, and a C done, which pops the C stack back to the docatch: =end original いつものように、C から C が抽出され、 C が実行されて C スタックが docatch に戻されます: S_docatch Perl_pp_entertry Perl_runops # second loop S_call_body Perl_call_sv Perl_pp_tie Perl_runops # first loop S_run_body perl_run main =begin original In this case, because the C level recorded in the C differs from the current one, C just does a C and the C stack unwinds to: =end original この場合、C に記録されている C レベルが現在のレベルと 異なるため、C は C を実行し、C スタックは 以下のように巻き戻します: perl_run main =begin original Because C is non-null, C starts a new runops loop and execution continues. =end original C は NULL でないため、C は新しい runops ループを 開始し、実行が継続されます。 =head2 INTERNAL VARIABLE TYPES (内部変数型) =begin original You should by now have had a look at L, which tells you about Perl's internal variable types: SVs, HVs, AVs and the rest. If not, do that now. =end original L を見ると、Perl の内部変数型(SV、HV、AVなど)について 知ることができます。 そうでない場合は、今すぐ見てください。 =begin original 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. =end original これらの変数は、Perl スペース変数だけでなく、コード内の任意の定数や、 完全に Perl 内部の構造体を表すためにも使用されます。 例えば、シンボルテーブルは通常の Perl ハッシュです。 コードはパーサに読み込まれるときに SV によって表されます; 呼び出したプログラムファイルは通常の Perl ファイルハンドルを 介して開かれます; といったことです。 =begin original The core L module lets us examine SVs from a Perl program. Let's see, for instance, how Perl treats the constant C<"hello">. =end original コア L モジュールを使用すると、Perl プログラムから SV を調べることができます。 例えば、Perl が定数 C<"hello"> をどのように処理するかを見てみましょう。 % perl -MDevel::Peek -e 'Dump("hello")' 1 SV = PV(0xa041450) at 0xa04ecbc 2 REFCNT = 1 3 FLAGS = (POK,READONLY,pPOK) 4 PV = 0xa0484e0 "hello"\0 5 CUR = 5 6 LEN = 6 =begin original Reading C output takes a bit of practise, so let's go through it line by line. =end original C の出力を読むには少し練習が必要なので、1 行ずつ 見ていきましょう。 =begin original Line 1 tells us we're looking at an SV which lives at C<0xa04ecbc> 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 C<0xa041450>. Line 2 is the reference count; there are no other references to this data, so it's 1. =end original 1 行目は、メモリ内の C<0xa04ecbc> に存在する SV を見ていることを示しています。 SV 自体は非常に単純な構造ですが、より複雑な構造へのポインタを含んでいます。 この場合は、それは PV で、場所 C<0xa041450> にある文字列値を保持する構造です。 2 行目は参照カウントです; このデータへの他の参照はないので 1 です。 =begin original 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 C<0xa0484e0>. =end original 3 行目はこの SV のフラグです - これをPVとして使用しても問題ありません; これは読み取り専用の SV (定数であるため)であり、データは内部的に PV です。 次に、位置 C<0xa0484e0> から始まる文字列の内容を取得します。 =begin original Line 5 gives us the current length of the string - note that this does B 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 C. =end original 5 行目は、文字列の現在の長さを示しています - これは ヌル終端文字が含まれて B<いない> ことに注意してください。 6 行目は文字列の長さではなく、現在割り当てられているバッファの長さです; 文字列が大きくなると、Perl は自動的に C というルーチンを使って 利用可能な記憶域を拡張します。 =begin original You can get at any of these quantities from C very easily; just add C to the name of the field shown in the snippet, and you've got a macro which will return the value: C returns the current length of the string, C returns the reference count, C returns the string itself with its length, and so on. More macros to manipulate these properties can be found in L. =end original これらの値は C から非常に簡単に得ることができます; スニペットに示されているフィールドの名前に C を追加するだけで、 その値を返すマクロができます: C は文字列の現在の長さを返し、C は 参照カウントを返し、C は文字列そのものとその長さを返します。 これらのプロパティを操作するもっと多くのマクロは L にあります。 =begin original Let's take an example of manipulating a PV, from C, in F =end original F の C から PV を操作する例を見てみましょう。 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) = '\0'; 13 (void)SvPOK_only_UTF8(sv); /* validate pointer */ 14 SvTAINT(sv); 15 } =begin original This is a function which adds a string, C, of length C onto the end of the PV stored in C. The first thing we do in line 6 is make sure that the SV B a valid PV, by calling the C macro to force a PV. As a side effect, C gets set to the current value of the PV, and the PV itself is returned to C. =end original これは、長さ C の文字列 C を、C に保存されている PV の末尾に 追加する関数です。 6 行目で最初に行うことは、C マクロを呼び出して PV を 強制することによって、SV が有効な PV を B<持っている> ことを確認することです。 副作用として、C は PV の現在の値に設定され、PV 自体は C に 戻されます。 =begin original 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 C isn't big enough, C will reallocate space for us. =end original 7 行目では、SV に古い文字列、新しい文字列、ヌルターミネータを収容する 十分なスペースがあることを確認しています。 C が十分に大きくない場合は、C がスペースを再割り当てします。 =begin original Now, if C is the same as the string we're trying to add, we can grab the string directly from the SV; C is the address of the PV in the SV. =end original C が追加しようとしている文字列と同じであれば、その文字列を SV から 直接取得できます; C は SV 内の PV のアドレスです。 =begin original Line 10 does the actual catenation: the C macro moves a chunk of memory around: we move the string C to the end of the PV - that's the start of the PV plus its current length. We're moving C bytes of type C. After doing so, we need to tell Perl we've extended the string, by altering C to reflect the new length. C is a macro which gives us the end of the string, so that needs to be a C<"\0">. =end original 10 行目で実際の結合が行われます: C マクロはメモリの塊を移動します: 文字列 C を PV の末尾に移動します - これは PV の先頭に現在の長さを加えたものです。 C 型の C バイトを移動します。 その後、新しい長さを反映するように C を変更して文字列を拡張したことを Perl に伝える必要があります。 C は文字列の末尾を与えるマクロなので、C<"\0"> である必要があります。 =begin original Line 13 manipulates the flags; since we've changed the PV, any IV or NV values will no longer be valid: if we have C<$a=10; $a.="6";> we don't want to use the old IV of 10. C is a special UTF-8-aware version of C, a macro which turns off the IOK and NOK flags and turns on POK. The final C is a macro which launders tainted data if taint mode is turned on. =end original 13 行目はフラグを操作します; PV を変更したため、IV や NV の値は無効になります: C<$a=10; $a.="6";> があれば、古い IV の 10 は使いたくありません。 C は C の特別な UTF-8 対応バージョンで、 IOK と NOK フラグをオフにし、POK をオンにするマクロです。 最後の C は、汚染チェックモードがオンになっていれば、汚染された データを洗浄するマクロです。 =begin original 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. =end original AV と HV はもっと複雑ですが、SV は群を抜いて最も一般的な変数型です。 これらを操作する方法を見てきたので、次に op 木がどのように構築されるかを 見ていきましょう。 =head1 OP TREES (op 木) =begin original 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 L. =end original まず、op 木とは何でしょうか? op 木は、構文解析のセクションで説明したように、プログラムを構文解析した 表現であり、L で説明したように、Perl がプログラムを実行するために 行う一連の操作です。 =begin original 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. =end original op は Perl が実行できる基本的な操作です: すべての組み込み関数と演算子は op であり、ブロックの出入り、文の 終了、変数のフェッチなど、インタプリタが内部的に必要とする概念を処理する 一連の op があります。 =begin original 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. =end original op 木は二つの方法で接続されています: op 木には二つの「ルート」があり、ツリーをトラバースできる二つの 順序があると想像できます。 第 1 に、構文解析順序はパーサがコードをどのように理解したかを反映し、 第 2 に、実行順序は perl に操作を実行する順序を指示します。 =begin original 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 L, L and L do. =end original op 木を調べる最も簡単な方法は、Perl が構文解析を完了した後で Perl を停止し、 Perl に木をダンプさせることです。 これはまさに、コンパイラのバックエンド L、 L、L が行うことです。 =begin original Let's have a look at how Perl sees C<$a = $b + $c>: =end original Perl が C<$a = $b + $c> をどのように見るかを見てみましょう。 % perl -MO=Terse -e '$a=$b+$c' 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 =begin original Let's start in the middle, at line 4. This is a BINOP, a binary operator, which is at location C<0x8179828>. The specific operator in question is C - scalar assignment - and you can find the code which implements it in the function C in F. As a binary operator, it has two children: the add operator, providing the result of C<$b+$c>, is uppermost on line 5, and the left hand side is on line 10. =end original 真ん中の 4 行目から始めましょう。 これは BINOP (二項演算子)で、位置 C<0x8179828> にあります。 問題となっている特定の演算子は C - スカラ代入 - です; この演算子を実装するコードは、F の関数 C にあります。 二項演算子としては二つの子があります: C<$b+$c> の結果を与える加算演算子は 5 行目の一番上にあり、左側は 10 行目にあります。 =begin original 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 L, 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: =end original 10 行目は null op です: これは何もしません。 そこで何をしているのでしょう? null op が表示された場合は、解析後に何かが最適化されたことを示しています。 L で説明したように、最適化ステージでは、スカラ変数を フェッチする場合など、二つの演算が一つに変換されることがあります。 このような場合は、op 木を書き直して相手がいないポインタを クリーンアップする代わりに、冗長な演算を null op に置き換える方が簡単です。 本来、木は次のように表示されます: 10 SVOP (0x816b4f0) rv2sv [15] 11 SVOP (0x816dcf0) gv GV (0x80fa460) *a =begin original That is, fetch the C entry from the main symbol table, and then look at the scalar component of it: C (C into F) happens to do both these things. =end original つまり、メインシンボルテーブルから C エントリを取得し、その スカラコンポーネントを調べます: C(F の C)は、これらの両方を実行します。 =begin original The right hand side, starting at line 5 is similar to what we've just seen: we have the C op (C also in F) add together two Cs. =end original 5 行目から始まる右側は、先ほど見たものと似ています: C op (C も F にあります) が二つの C を 加算します。 =begin original Now, what's this about? =end original ここで、これは何でしょう? 1 LISTOP (0x8179888) leave 2 OP (0x81798b0) enter 3 COP (0x8179850) nextstate =begin original C and C 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: C is a list, and its children are all the statements in the block. Statements are delimited by C, so a block is a collection of C ops, with the ops to be performed for each statement being the children of C. C is a single op which functions as a marker. =end original C と C はスコープ op であり、それらの仕事は、ブロックに 入ったり出たりするたびにハウスキーピングを実行することです: レキシカル変数は整理され、参照されていない変数は破棄され、などです。 すべてのプログラムには最初の 3 行があります: C はリストであり、その子はブロック内のすべての文です。 文は C で区切られているため、ブロックは C op の集合であり、各文に対して実行される op は C の子となります。 C はマーカーとして機能する単一の op です。 =begin original That's how Perl parsed the program, from top to bottom: =end original このようにして、Perl はプログラムを上から下まで構文解析しました: Program | Statement | = / \ / \ $a + / \ $b $c =begin original However, it's impossible to B the operations in this order: you have to find the values of C<$b> and C<$c> 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 C 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 C option to C: =end original しかし、この順序で操作を B<実行> することは不可能です: 例えば、C<$b> と C<$c> の値を見つけてから、それらを一緒に追加する 必要があります。 そのため、op 木を通るもう一つの糸は実行順序です: 各 op には、次に実行される op を指すフィールド C があるので、 これらのポインタに従って perl がどのようにコードを実行するかを 知ることができます。 C オプションを C に指定すると、この順序で木を走査できます: % perl -MO=Terse,exec -e '$a=$b+$c' 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 =begin original This probably makes more sense for a human: enter a block, start a statement. Get the values of C<$b> and C<$c>, and add them together. Find C<$a>, and assign one to the other. Then leave. =end original これはおそらく人間にとってより分かりやすいでしょう: ブロックにを入り、文を開始します。 C<$b> と C<$c> の値を取得し、それらを加算します。 C<$a> を検索し、一方をもう一方に代入します。 そして離れます。 =begin original The way Perl builds up these op trees in the parsing process can be unravelled by examining F, the YACC grammar. Let's take the piece we need to construct the tree for C<$a = $b + $c> =end original Perl が構文解析プロセスでこれらの op 木を構築する方法は、YACC 文法である F を調べることによって解明できます。 C<$a = $b + $c> の木を構築するために必要な部分を取り上げましょう: 1 term : term ASSIGNOP term 2 { $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); } 3 | term ADDOP term 4 { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } =begin original 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. Here, C, is provided when the tokeniser sees C<+> in your code. C is provided when C<=> is used for assigning. These are "terminal symbols", because you can't get any simpler than them. =end original BNF 文法を読むことに慣れていない人は、次のように動作します: ある種のものをトークナイザによって供給されます; それは通常大文字になります。 ここでは、C は、トークナイザがコード内で C<+> が検出したときに 提供されます。 C は、代入のために C<=> が使用されたときに提供されます。 これらは「終端記号」です; これ以上単純なものは得られないからです。 =begin original 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. C here is a non-terminal symbol, representing a single expression. =end original 上のスニペットの1 行目と3 行目の文法では、より複雑な形式を 構築する方法が説明されています。 これらの複合形式である「非終端記号」は、通常は小文字で配置されます。 ここで C は、単一の式を表す非終端記号です。 =begin original 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, C followed by C<=> followed by C makes a C, and C followed by C<+> followed by C can also make a C. =end original 文法は次の規則を与えます: 右側のすべてのものを順番に見れば、 コロンの左側のものを作ることができます。 これは「還元」(reduction)と呼ばれ、構文解析の目的は入力を完全に 還元することです。 還元を実行するにはいくつかの異なる方法があり、縦棒で区切られています: つまり、C の後に C<=> と C が続くと C を作成し、 C の後に C<+> と C が続いても C を作成できます。 =begin original So, if you see two terms with an C<=> or C<+>, 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 C<=>, you'll do the code in line 2. If you see C<+>, you'll do the code in line 4. It's this code which contributes to the op tree. =end original それで、二つの項の間に C<=> または C<+> がある場合、それらを一つの式に 変換できます。 これを行うときは、次の行のブロック内のコードを実行します: C<=> がある場合は 2 行目のコードを実行します。 C<+> がある場合は 4 行目のコードを実行します。 このコードが op 木に貢献しています。 | term ADDOP term { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } =begin original What this does is creates a new binary op, and feeds it a number of variables. The variables refer to the tokens: C<$1> is the first token in the input, C<$2> the second, and so on - think regular expression backreferences. C<$$> is the op returned from this reduction. So, we call C to create a new binary operator. The first parameter to C, a function in F, is the op type. It's an addition operator, so we want the type to be C. We could specify this directly, but it's right there as the second token in the input, so we use C<$2>. 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. =end original これにより、新しいバイナリ op が作成され、多数の変数が渡されます。 変数はトークンを参照します: C<$1> は入力の最初のトークン、C<$2> は 2 番目のトークン、という形です - 正規表現の後方参照を考えてみてください。 C<$$> はこの還元から返される op です。 そこで、C を呼び出して新しい二項演算子を作成します。 F にある関数である C の最初の引数は op 型です。 これは加算演算子なので、型が C になってほしいです。 これを直接指定することもできますが、これは入力の 2 番目のトークンとして すぐそこにあるので、C<$2> を使用します。 2 番目の引数は op のフラグです: 0 は「特別なものがない」ことを意味します。 次に追加すべきものは、スカラコンテキストでの式の左辺と右辺です。 =head1 STACKS (スタック) =begin original When perl executes something like C, 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. =end original perl が C のようなものを実行した場合、その結果をどのように 次の op に渡すのでしょうか? 答えは、スタックを使用することです。 Perl には、現在作業中のものを保存するためのスタックが数多くありますが、 ここでは最も重要な三つのスタックについて説明します。 =head2 Argument stack (引数スタック) =begin original Arguments are passed to PP code and returned from PP code using the argument stack, C. 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: =end original 引数は PP コードに渡され、引数スタック C を使用して PP コードから 返されます。 引数を処理する一般的な方法は、引数をスタックから取り出し、 必要に応じて処理した後、結果をスタックにプッシュします。 たとえば、余弦演算子は次のように動作します: NV value; value = POPn; value = Perl_cos(value); XPUSHn(value); =begin original We'll see a more tricky example of this when we consider Perl's macros below. C gives you the NV (floating point value) of the top SV on the stack: the C<$x> in C. Then we compute the cosine, and push the result back as an NV. The C in C 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 C macros at least guarantee safety. =end original 以下に示す Perl のマクロを考えると、もっと巧妙な例を見ることになります。 C はスタック上の最上位 SV の NV (浮動小数点値)を与えます: C の C<$x> です。 次にコサインを計算し、その結果を NV としてプッシュします。 C の C は、必要に応じてスタックを拡張する 必要があることを意味します - ここでは必要ありません; なぜなら、スタック上にもう一つの項目のためのスペースがあることが わかっているからです; なぜなら、一つを削除したばかりなのです! C マクロは少なくとも安全性を保証します。 =begin original Alternatively, you can fiddle with the stack directly: C gives you the first element in your portion of the stack, and C gives you the top SV/IV/NV/etc. on the stack. So, for instance, to do unary negation of an integer: =end original あるいは、スタックを直接操作することもできます: C は スタックのあなたの部分の最初の要素を与え、C はスタック上の最上位の SV/IV/NV などを与えます。 たとえば、整数の単項否定を行うには、次のようにします: SETi(-TOPi); =begin original Just set the integer value of the top stack entry to its negation. =end original 最上位スタックエントリの整数値をその否定に設定するだけです。 =begin original Argument stack manipulation in the core is exactly the same as it is in XSUBs - see L, L and L for a longer description of the macros used in stack manipulation. =end original コアでの引数スタック操作は、XSUBs とまったく同じです - スタック操作で 使用されるマクロのより長い説明については、 L、L、L を参照してください。 =head2 Mark stack (マークスタック) =begin original 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 C is implemented; see C in F: =end original 上で「スタックのあなたの部分」と言ったのは、PP コードが必ずしも スタック全体を自分自身に取得する必要はないからです: 関数が別の関数を呼び出す場合は、呼び出された関数を対象とした引数を 公開するだけで、(必ずしも)自分自身のデータを取得させるわけではありません。 これを行う方法は、各関数に公開される「仮想的な」スタックの最下位を 持つことです。 マークスタックは、各関数が使用できる引数スタック内の場所への ブックマークを保持します。 例えば、tie された変数を扱う場合(内部では "P" マジックのようなもの)、 Perl は tie された変数にアクセスするためにメソッドを呼び出す必要があります。 ただし、メソッドに公開される引数を、元の関数に公開される引数(store や fetch など)に分離する必要があります。 tie された C がどのように実装されるかを大まかに説明します; F の C を参照してください。 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; =begin original Let's examine the whole implementation, for practice: =end original 実践のために、実装全体を調べてみましょう: 1 PUSHMARK(SP); =begin original 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. =end original スタックポインタの現在の状態をマークスタックにプッシュします。 これは、引数スタックへの項目の追加が完了したときに、Perl が最近追加した 項目の数を知るためです。 2 EXTEND(SP,2); 3 PUSHs(SvTIED_obj((SV*)av, mg)); 4 PUSHs(val); =begin original We're going to add two more items onto the argument stack: when you have a tied array, the C subroutine receives the object and the value to be pushed, and that's exactly what we have here - the tied object, retrieved with C, and the value, the SV C. =end original 引数スタックにさらに二つの項目を追加します: tie された配列がある場合、C サブルーチンはオブジェクトと プッシュされる値を受け取ります; そしてこれがここで得られるものです - C で取得された tie されたオブジェクトと、 その値である SV C です。 5 PUTBACK; =begin original Next we tell Perl to update the global stack pointer from our internal variable: C only gave us a local copy, not a reference to the global. =end original 次に、内部変数からグローバルスタックポインタを更新するように Perl に指示します: C はローカルコピーだけを提供し、グローバルへの参照は提供しません。 6 ENTER; 7 call_method("PUSH", G_SCALAR|G_DISCARD); 8 LEAVE; =begin original C and C 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 C<{> and C<}> of a Perl block. =end original C と C はコードブロックをローカル化します - すべての変数が 整理されていること、ローカル化されたすべてのものが以前の値を返すことなどを 確認します。 これらは Perl ブロックの C<{> と C<}> と考えてください。 =begin original To actually do the magic method call, we have to call a subroutine in Perl space: C takes care of that, and it's described in L. We call the C method in scalar context, and we're going to discard its return value. The call_method() function removes the top element of the mark stack, so there is nothing for the caller to clean up. =end original マジックメソッド呼び出しを実際に行うためには、Perl 空間でサブルーチンを 呼び出す必要があります: C がこれを処理します; これについては L で説明しています。 C メソッドをスカラコンテキストで呼び出し、その戻り値を破棄します。 call_method() 関数はマークスタックの最上位要素を削除するため、 呼び出し側がクリーンアップするものはありません。 =head2 Save stack (保存スタック) =begin original C doesn't have a concept of local scope, so perl provides one. We've seen that C and C are used as scoping braces; the save stack implements the C equivalent of, for example: =end original C にはローカルスコープという概念がないので、perl が提供しています。 C と C がスコープを作る中かっことして 使用されていることを見てきました; 保存スタックは以下のような C に相当するものを実装しています: { local $foo = 42; ... } =begin original See L for how to use the save stack. =end original 保存スタックの使用方法については、 L を参照してください。 =head1 MILLIONS OF MACROS (大量のマクロ) =begin original 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, the code which implements the addition operator: =end original Perl ソースに関して気付くかも知れない一つのことは、Perl ソースには マクロが豊富に含まれているということです。 マクロが広く使われていることを理解するのが最も難しいとする人もいれば、 マクロが明快さを増すと考える人もいます。 例えば、加算演算子を実装するコードを例にとりましょう: 1 PP(pp_add) 2 { 3 dSP; dATARGET; tryAMAGICbin(add,opASSIGN); 4 { 5 dPOPTOPnnrl_ul; 6 SETn( left + right ); 7 RETURN; 8 } 9 } =begin original 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. Finally, it tries to see if the addition operation is overloaded; if so, the appropriate subroutine is called. =end original ここの各行(もちろん中かっこを除く)にはマクロが含まれています。 最初の行は、Perl が PP コードに期待する関数宣言を設定します。 3 行目は、引数スタックと操作の戻り値であるターゲットの変数宣言を設定します。 最後に、加算操作がオーバーロードされているかどうかを調べます; オーバーロードされている場合は、適切なサブルーチンが呼び出されます。 =begin original Line 5 is another variable declaration - all variable declarations start with C - which pops from the top of the argument stack two NVs (hence C) and puts them into the variables C and C, hence the C. These are the two operands to the addition operator. Next, we call C to set the NV of the return value to the result of adding the two values. This done, we return - the C macro makes sure that our return value is properly handled, and we pass the next operator to run back to the main run loop. =end original 5 行目はもう一つの変数宣言です - すべての変数宣言は C で始まります - これは引数スタックの先頭から二つの NV(つまり C)を取り出し、それらを 変数 C と C(つまり C)に入れます。 これらは加算演算子に対する二つのオペランドです。 次に、C を呼び出して、戻り値の NV を二つの値を加算した結果に 設定します。 これが終われば、返ります - C マクロは返り値が適切に処理されていることを確認し、 メインの実行ループに戻るために次の演算子を渡します。 =begin original Most of these macros are explained in L, and some of the more important ones are explained in L as well. Pay special attention to L for information on the C<[pad]THX_?> macros. =end original これらのマクロのほとんどは L で説明されていますし、 より重要なマクロのいくつかは L でも説明されています。 C<[pad]THX_?> マクロに関する情報については、 L に特に注意してください。 =head1 FURTHER READING =begin original For more information on the Perl internals, please see the documents listed at L. =end original Perl の内部に関するさらなる情報については、 L に挙げられている文書を 見てください。 =begin meta Translate: SHIRAKATA Kentaro Status: completed =end meta