.. original ============================= PyPy - The RPython Toolchain ============================= ========================== PyPy - RPython toolchain ========================== .. contents:: .. original This document describes the toolchain that we have developed to analyze and "compile" RPython_ programs (like PyPy itself) to various target platforms. この文書は我々が開発した toolchain について記述しており, それは (PyPy のような) RPython_ プログラムを様々なプラットフォームを対象に解析し「コンパイル」するものです. .. _RPython: coding-guide.html#restricted-python .. original It consists of three broad sections: a slightly simplified overview, a brief introduction to each of the major components of our toolchain and then a more comprehensive section describing how the pieces fit together. If you are reading this document for the first time, the Overview_ is likely to be most useful, if you are trying to refresh your PyPy memory then the `How It Fits Together`_ is probably what you want. 文書は3つの節からなります: やや簡潔な overview, toolchain の主要な部品の簡単な入門, それらがどう組み合わされるかについてのより包括的な記述. この文書を初めて読む場合は, Overview_ が最も役に立つでしょう. 再度 PyPy のことを思い出そうとして読んでいる場合は, `どう連携するか`_ がおそらく求めているものでしょう. Overview ======== .. original The job of the translation toolchain is to translate RPython_ programs into an efficient version of that program for one of various target platforms, generally one that is considerably lower-level than Python. It divides this task into several steps, and the purpose of this document is to introduce them. 翻訳 toolchain の仕事は RPython_ プログラムを対象とする様々なプラットフォームの1つに対して効率的な形に翻訳することです. 一般的に Python よりも低レベルな形になります. その翻訳ではこの仕事をいくつかの段階に分けますが, この文書はそれを説明するのが目的です. .. original As of the 1.2 release, RPython_ programs can be translated into the following languages/platforms: C/POSIX, CLI/.NET and Java/JVM. リリース 1.2 では, RPython_ プログラムは C/POSIX, CLI/.NET, Java/JVM という言語/プラットフォームで動く形に翻訳できます. .. _`application-level`: coding-guide.html#application-level .. _`interpreter-level`: coding-guide.html#interpreter-level .. original The choice of the target platform affects the process somewhat, but to start with we describe the process of translating an RPython_ program into C (which is the default and original target). 対象プラットフォームの選択は処理に多少の違いを生みますが, (デフォルトの, そしてオリジナルの対象である) C への RPython_ プログラムの翻訳処理の描写から始めます. .. _`initialization time`: .. original The RPython translation toolchain never sees Python source code or syntax trees, but rather starts with the *code objects* that define the behaviour of the function objects one gives it as input. The `bytecode evaluator`_ and the `Flow Object Space`_ work through these code objects using `abstract interpretation`_ to produce a control flow graph (one per function): yet another representation of the source program, but one which is suitable for applying type inference and translation techniques and which is the fundamental data structure most of the translation steps operate on. RPython の翻訳 toolchain は Python のソースコードや構文木を見ませんが, 入力として与えられる関数オブジェクトの動作の定義である *code object* から処理を始めます. `bytecode evaluator`_ や `Flow Object Space`_ はこれら code object に対し 抽象解釈 (`abstract interpretation`_) を行い control flow graph を (1関数につき1つ) 生成します: 元となるプログラムの別の表現 (意味論) もありますが, 型推論の適用や翻訳技法にはこれが向いている上に, 多くの翻訳段階を実行する上での基本的なデータ構造なのです. .. original It is helpful to consider translation as being made up of the following steps (see also the figure below): 翻訳が次の段階から成っていると考えると理解しやすいでしょう (下の図も見てください): .. original 1. The complete program is imported, at which time arbitrary run-time initialization can be performed. Once this is done, the program must be present in memory as a form that is "static enough" in the sense of RPython_. 1. プログラム全体が読み込まれた時点で, 任意の実行時の初期化処理が行えます. この処理が終わると RPython_ の意味で "十分に静的" な形でメモリ上に存在していなくてはなりません. .. original 2. The Annotator_ performs a global analysis starting from an specified entry point to deduce type and other information about what each variable can contain at run-time, building flow graphs using the `Flow Object Space`_ as it encounters them. 2. Annotator_ はある特定のエントリポイントから大域解析を開始し, 型とそれぞれの変数が実行時にどんな値を格納し得るかの情報を演繹していきます. それと同時に `Flow Object Space`_ を使って flow graph を構築していきます. .. original 3. The `RPython Typer`_ (or RTyper) uses the high-level information inferred by the Annotator to turn the operations in the control flow graphs into low-level operations. 3. `RPython Typer`_ (もしくは RTyper) は Annotator が推論して得た高レベルの情報を使い, control flow graph 上の演算を低レベルの演算に変換していきます. .. original 4. After RTyping there are two, rather different, `optional transformations`_ which can be applied -- the "backend optimizations" which are intended to make the resulting program go faster, and the "stackless transform" which transforms the program into a form of continuation passing style which allows the implementation of coroutines and other forms of non-standard control flow. 4. RTyping の次には2つのやや異なる処理 `optional transformations`_ が適用できます. "backend optimizations" は出力プログラムをより高速にするための処理です. "stackless transform" はプログラムを継続渡しスタイルに変換します. この変換によりコルーチンの実装やその他の標準的ではない control flow の実装が可能になります. .. original 5. The next step is `preparing the graphs for source generation`_, which involves computing the names that the various functions and types in the program will have in the final source and applying transformations which insert explicit exception handling and memory management operations. 5. 次の段階は `preparing the graphs for source generation`_ (ソース生成のためのグラフの準備) です. この段階は, プログラム中の様々な関数や型が最終的にどんな名前になるのかの計算と明示的な例外とメモリ管理操作を挿入する変換に関わります. .. original 6. The `C backend`_ (colloquially known as "GenC") produces a number of C source files (as noted above, we are ignoring the other backends for now). 6. `C backend`_ 処理 (所謂 "GenC") は C のソースファイルを生成します. (上で書いたように, 今は他の backend は無視しておきます.) .. original 7. These source files are compiled to produce an executable. 7. これらのソースファイルがコンパイルされ実行ファイルが作成されます. .. original (although these steps are not quite as distinct as you might think from this presentation). (ここでの表現から想像するものと, 実際の処理はそう違いません.) .. original There is an `interactive interface`_ called `pypy/bin/translatorshell.py`_ to the translation process which allows you to interactively work through these stages. `pypy/bin/translatorshell.py`_ という翻訳過程へのインターフェース `interactive interface`_ があり, 処理を段階を追いながら対話的に実行していけます. .. original The following figure gives a simplified overview (`PDF color version`_): 次の図は簡略化された全体図です (`PDF color version`_): .. image:: image/translation-greyscale-small.png .. _`PDF color version`: image/translation.pdf .. _`bytecode evaluator`: interpreter.html .. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation .. _`Flow Object Space`: objspace.html#the-flow-object-space .. _`interactive interface`: getting-started-dev.html#try-out-the-translator .. _`flow model`: .. _`control flow graphs`: .. original The Flow Model ============== flow モデル =========== .. original The `Flow Object Space`_ is described in the `document describing object spaces`_. Here we describe the data structures produced by it, which are the basic data structures of the translation process. `Flow Object Space`_ の解説は `document describing object spaces`_ にあります. ここでは, それから生成される翻訳過程の基本的なデータ構造について説明します. .. original All these types are defined in `pypy/objspace/flow/model.py`_ (which is a rather important module in the PyPy source base, to reinforce the point). 全ての型は `pypy/objspace/flow/model.py`_ に定義してあります. これは PyPy のソースコードの中でその特徴を強調するのに比較的重要なモジュールです. .. original The flow graph of a function is represented by the class ``FunctionGraph``. It contains a reference to a collection of ``Block``\ s connected by ``Link``\ s. 関数の flow graph は ``FunctionGraph`` クラスで表現されます. これには ``Link`` で結合された ``Block`` の集まりへの参照が入っています. .. original A ``Block`` contains a list of ``SpaceOperation``\ s. Each ``SpaceOperation`` has an ``opname`` and a list of ``args`` and ``result``, which are either ``Variable``\ s or ``Constant``\ s. ``Block`` は ``SpaceOperation`` のリストを持っています. それぞれの ``SpaceOperation`` は ``opname``, ``args`` リスト, ``result`` を持っていて, ``args`` の要素と ``result`` は ``Variable`` であるか ``Constant`` であるかです. .. original We have an extremely useful PyGame viewer, which allows you to visually inspect the graphs at various stages of the translation process (very useful to try to work out why things are breaking). It looks like this: 圧倒的に便利な PyGame viewer というツールがあり, 翻訳過程の様々な段階のグラフの様子を覗くことができます. (なんで上手く行かないのかを調べるのに非常に便利です.) 見た目は次のような感じです: .. image:: image/bpnn_update.png .. original It is recommended to play with ``python bin/translatorshell.py`` on a few examples to get an idea of the structure of flow graphs. The following describes the types and their attributes in some detail: flow graph の構造について理解するために, いくつかの例に ``python bin/translatorshell.py`` を使用して遊んでみることをおすすめします. 以下では型とその属性について少し詳しく記述してあります: .. original ``FunctionGraph`` A container for one graph (corresponding to one function). :startblock: the first block. It is where the control goes when the function is called. The input arguments of the startblock are the function's arguments. If the function takes a ``*args`` argument, the ``args`` tuple is given as the last input argument of the startblock. :returnblock: the (unique) block that performs a function return. It is empty, not actually containing any ``return`` operation; the return is implicit. The returned value is the unique input variable of the returnblock. :exceptblock: the (unique) block that raises an exception out of the function. The two input variables are the exception class and the exception value, respectively. (No other block will actually link to the exceptblock if the function does not explicitely raise exceptions.) ``FunctionGraph`` グラフ1つを格納するのためのコンテナ (1つの関数に対応します). :startblock: 最初のブロック. 関数が呼ばれたときに処理が移っていく箇所です. startblock の入力引数は関数の引数です. 関数が ``*args`` 引数を受け取る場合は, ``args`` タプルが startblock の最後の入力として渡されます. :returnblock: 関数の return に相当する (唯一の) ブロック. このブロックは空で実際の ``return`` 操作を含んではいません; return 操作は暗黙的なものです. 返り値は returnblock 唯一の入力引数です. :exceptblock: 例外を関数の外部へ送出する (唯一の) ブロック. 2つの入力変数があり, それぞれ例外クラスと例外値です. (関数が明示的に例外を送出しない場合, 実際には他のブロックは exceptblock へ接続しません.) .. original ``Block`` A basic block, containing a list of operations and ending in jumps to other basic blocks. All the values that are "live" during the execution of the block are stored in Variables. Each basic block uses its own distinct Variables. :inputargs: list of fresh, distinct Variables that represent all the values that can enter this block from any of the previous blocks. :operations: list of SpaceOperations. :exitswitch: see below :exits: list of Links representing possible jumps from the end of this basic block to the beginning of other basic blocks. Each Block ends in one of the following ways: * unconditional jump: exitswitch is None, exits contains a single Link. * conditional jump: exitswitch is one of the Variables that appear in the Block, and exits contains one or more Links (usually 2). Each Link's exitcase gives a concrete value. This is the equivalent of a "switch": the control follows the Link whose exitcase matches the run-time value of the exitswitch Variable. It is a run-time error if the Variable doesn't match any exitcase. * exception catching: exitswitch is ``Constant(last_exception)``. The first Link has exitcase set to None and represents the non-exceptional path. The next Links have exitcase set to a subclass of Exception, and are taken when the *last* operation of the basic block raises a matching exception. (Thus the basic block must not be empty, and only the last operation is protected by the handler.) * return or except: the returnblock and the exceptblock have operations set to an empty tuple, exitswitch to None, and exits empty. ``Block`` 基本ブロック. 処理のリストと, 処理の終了後にジャンプしていく他の基本ブロックのリストを持ちます. このブロックの実行中に "生きている" 値は全て Variable に保持されています. ブロックはそれぞれ自身の異なる Variable を持っています. :inputargs: どの変数とも異なる Variable のリスト. 任意の直前のブロックから来る全ての値を表しています. :operations: SpaceOperations のリスト. :exitswitch: 下記を参照のこと. :exits: Link のリスト. この基本ブロックから他の基本ブロックへの取り得るジャンプを表しています. それぞれの Block は次のうち, ある 1 つの終了の仕方をします: * 無条件ジャンプ: exitswitch が None で, exits に 1 つの Link しかない場合. * 条件付きジャンプ: exitswitch が Block に現れる Variable のうちの 1 つであり, exits が 1 つ以上 (たいてい 2 つ) の Link を含んでいる場合. それぞれの Link の exitcase が具体的な値です. これは "switch" と等価です: 実行時の exitswitch の Variable の値と一致する exitcase を持つ Link に従って処理は進んでいきます. Variable がどの exitcase とも一致しない場合は実行時エラーとなります. * 例外捕捉: exitswitch が ``Constant(last_exception)`` である場合. 先頭にある Link の exitcase は None になっており, 例外的でない処理の道を表しています. それに続く Link の exitcase は Exception の子クラスになっており, 基本ブロックの *最後の* 処理が例外を送出した場合に, 対応する例外が選択されます. (従って基本ブロックは空であってはならず, 最後の処理だけが handler から保護されています.) * 復帰または例外: returnblock と exceptblock の operations が空タプル, exitswitch が None, exits が None である場合. .. original ``Link`` A link from one basic block to another. :prevblock: the Block that this Link is an exit of. :target: the target Block to which this Link points to. :args: a list of Variables and Constants, of the same size as the target Block's inputargs, which gives all the values passed into the next block. (Note that each Variable used in the prevblock may appear zero, one or more times in the ``args`` list.) :exitcase: see above. :last_exception: None or a Variable; see below. :last_exc_value: None or a Variable; see below. Note that ``args`` uses Variables from the prevblock, which are matched to the target block's ``inputargs`` by position, as in a tuple assignment or function call would do. If the link is an exception-catching one, the ``last_exception`` and ``last_exc_value`` are set to two fresh Variables that are considered to be created when the link is entered; at run-time, they will hold the exception class and value, respectively. These two new variables can only be used in the same link's ``args`` list, to be passed to the next block (as usual, they may actually not appear at all, or appear several times in ``args``). ``Link`` 基本ブロックから他の基本ブロックへの結線です. :prevblock: 出口がこの Link に繋がっている Block. :target: この Link が指す対象の Block. :args: 対象 Block の inputargs と同じサイズの Variable と Constant からなるリスト. このリストが次のブロックへ値を渡していきます. (prevblock で使われた各 Variable は ``args`` リストの中に, 0 回, 1 回もしくはそれ以上の回数出現し得ることに注意してください. ) :exitcase: 上記を参照のこと. :last_exception: None または Variable; 下記を参照のこと. :last_exc_value: None または Variable; 下記を参照のこと. ``args`` は prevblock の Variable を使っていますが, タプル代入 (多重割り当て) や関数呼び出し (のときの引数) のように対象ブロックの ``inputargs`` と対応付けられます. リンクが例外捕捉のものだった場合, ``last_exception`` と ``last_exc_value`` には処理がリンクに入ったときに作られる既存のどれとも異なる Variable がそれぞれ設定されています; 実行時には例外クラスとその値がそれぞれ入っています. それら 2 つの新しい変数は同じリンクの ``args`` リストの中でのみ使われ, 次のブロックへ受け渡されていきます (通常は, ``args`` の中に全く現れなかったり数回現れたりします). .. original ``SpaceOperation`` A recorded (or otherwise generated) basic operation. :opname: the name of the operation. The Flow Space produces only operations from the list in ``pypy.interpreter.baseobjspace``, but later the names can be changed arbitrarily. :args: list of arguments. Each one is a Constant or a Variable seen previously in the basic block. :result: a *new* Variable into which the result is to be stored. Note that operations usually cannot implicitly raise exceptions at run-time; so for example, code generators can assume that a ``getitem`` operation on a list is safe and can be performed without bound checking. The exceptions to this rule are: (1) if the operation is the last in the block, which ends with ``exitswitch == Constant(last_exception)``, then the implicit exceptions must be checked for, generated, and caught appropriately; (2) calls to other functions, as per ``simple_call`` or ``call_args``, can always raise whatever the called function can raise --- and such exceptions must be passed through to the parent unless they are caught as above. ``SpaceOperation`` 登録された (もしくは生成された) 基本演算です. :opname: 演算の名前. Flow Space は ``pypy.interpreter.baseobjspace`` のリストにある演算しか生成しませんが, その名前は後で任意の名前に変更できます. :args: 引数のリスト. 個々の要素は基本ブロックのところで見た Constant か Variable です. :result: 結果が格納される *新しい* Variable. 通常演算は, 実行時に暗黙的に例外を送出できないことに注意してください. なので例えば, リストの ``getitem`` 演算は安全であり境界判定をせずに実行できる, とコード生成器が仮定してしまうことも有り得ます. この規則の例外は: (1) もしその演算が ``exitswitch == Constant(last_exception)`` で終わるブロックの最後に現れた場合, 明示されていない例外をチェックし, 生成し, 適切に捕捉しなければいけません; (2) ``simple_call`` や ``call_args`` を通じた他の関数の呼び出しは, その関数が送出し得るどんな例外も常に送出する可能性があります --- そしてそのような例外は前出のように捕捉されない限り, そのまま呼び出し元に渡さなければなりません. .. original ``Variable`` A placeholder for a run-time value. There is mostly debugging stuff here. :name: it is good style to use the Variable object itself instead of its ``name`` attribute to reference a value, although the ``name`` is guaranteed unique. ``Variable`` 実行時の値のプレースホルダー. 主にデバッグ用のものです. :name: ``name`` の一意性が保証されているとしても, 値を参照するのに ``name`` 属性ではなく Variable オブジェクトそのものを使うのは良い手法です. .. original ``Constant`` A constant value used as argument to a SpaceOperation, or as value to pass across a Link to initialize an input Variable in the target Block. :value: the concrete value represented by this Constant. :key: a hashable object representing the value. A Constant can occasionally store a mutable Python object. It represents a static, pre-initialized, read-only version of that object. The flow graph should not attempt to actually mutate such Constants. ``Constant`` SpaceOperation の引数や, ある Link の対象ブロックにおける入力 Variable を初期化するために渡す値として使う定数. :value: この Constant によって表現されている具体値 :key: この値を表すハッシュ化可能なオブジェクト Constant は変更可能な Python オブジェクトを格納することも可能です. これはそのオブジェクトの, 静的で初期化済みの読み取り専用版を表しています. flow graph はそのような Constant を実際に変更しようとすべきではありません. .. _`document describing object spaces`: objspace.html .. _Annotator: .. original The Annotation Pass =================== 注釈渡し ======== .. original We describe briefly below how a control flow graph can be "annotated" to discover the types of the objects. This annotation pass is a form of type inference. It operates on the control flow graphs built by the Flow Object Space. 以下で, どのように control flow graph に "注釈" が付けられ, オブジェクトの型を知ることができるかについて簡単に説明します. この注釈渡しは型推論の一形式であり, Flow Object Space によって組み立てられる control flow graph に作用します. .. original For a more comprehensive description of the annotation process, see the corresponding section of our `EU report about translation`_. より包括的な注釈処理の解説は, `EU report about translation`_ の対応する節を参照してください. .. original The major goal of the annotator is to "annotate" each variable that appears in a flow graph. An "annotation" describes all the possible Python objects that this variable could contain at run-time, based on a whole-program analysis of all the flow graphs -- one per function. Annotator の主な目的は flow graph に現れる変数にそれぞれ "注釈を付ける" ことです. "注釈" はプログラム全体の全ての -- 1つの関数につき1つの -- flow graph の解析結果に基づき, 変数が実行時に格納し得る全ての Python オブジェクトを記述します. .. original An "annotation" is an instance of a subclass of ``SomeObject``. Each subclass that represents a specific family of objects. "注釈" は ``SomeObject`` の子クラスのインスタンスです. それぞれの子クラスはオブジェクトの特定の族を表現しています. .. original Here is an overview (see ``pypy/annotation/model/``): 以下が概要です (``pypy/annotation/model/`` も参照してください): .. original * ``SomeObject`` is the base class. An instance of ``SomeObject()`` represents any Python object, and as such usually means that the input program was not fully RPython. * ``SomeInteger()`` represents any integer. ``SomeInteger(nonneg=True)`` represent a non-negative integer (``>=0``). * ``SomeString()`` represents any string; ``SomeChar()`` a string of length 1. * ``SomeTuple([s1,s2,..,sn])`` represents a tuple of length ``n``. The elements in this tuple are themselves constrained by the given list of annotations. For example, ``SomeTuple([SomeInteger(), SomeString()])`` represents a tuple with two items: an integer and a string. * ``SomeObject`` は基底クラスです. ``SomeObject()`` のインスタンスは任意の Python オブジェクトを表現していて, たいていは入力プログラムが全てが RPython でないことを意味しています. * ``SomeInteger()`` は任意の整数を表現します. ``SomeInteger(nonneg=True)`` は非負整数 (``>=0``) を表しています. * ``SomeString()`` は任意の文字列を表現します. ``SomeChar()`` は長さが 1 の文字列です. * ``SomeTuple([s1,s2,...,sn])`` は長さ ``n`` のタプルを表現します. タプルの要素は与えられた注釈のリストによって制限されています. 例えば, ``SomeTuple([SomeInteger(), SomeString()])`` は 2 つの要素: 整数と文字列, を持つタプルを表現しています. .. original The result of the annotation pass is essentially a large dictionary mapping ``Variable``\ s to annotations. 注釈渡しの結果得られるものは本質的には ``Variable`` から注釈への巨大な辞書です. .. original All the ``SomeXxx`` instances are immutable. If the annotator needs to revise its belief about what a Variable can contain, it does so creating a new annotation, not mutating the existing one. 全ての ``SomeXXX`` インスタンスは変更不可能です. Annotator がある変数に対し何を格納し得るかの考えを改める必要がある場合には, 新しい注釈を作り, 既存のものは変更しません. .. original Mutable Values and Containers ------------------------------ 変更可能な値とコンテナ ---------------------- .. original Mutable objects need special treatment during annotation, because the annotation of contained values needs to be possibly updated to account for mutation operations, and consequently the annotation information reflown through the relevant parts of the flow the graphs. .. memo s/the flow the graphs/the flow graphs/ 変更可能なオブジェクトは注釈付けでは特別な扱いをする必要があります. というのは, 格納されている値の注釈は変更操作のために更新する必要があり, 従ってその注釈の情報は flow graph の関係する部分に伝わらなければなりません. .. original * ``SomeList`` stands for a list of homogeneous type (i.e. all the elements of the list are represented by a single common ``SomeXxx`` annotation). * ``SomeDict`` stands for a homogeneous dictionary (i.e. all keys have the same ``SomeXxx`` annotation, and so have all values). * ``SomeList`` は均質な型のリストを表しています. (つまり, リストの全ての要素は単一の注釈 ``SomeXxx`` が付けられています.) * ``SomeDict`` は均質な辞書を表しています. (つまり, 全てのキーは同じ注釈 ``SomeXxx`` を持ち, 値に関しても同様です.) .. original User-defined Classes and Instances ----------------------------------- ユーザ定義クラス, インスタンス ------------------------------ .. original ``SomeInstance`` stands for an instance of the given class or any subclass of it. For each user-defined class seen by the annotator, we maintain a ClassDef (``pypy.annotation.classdef``) describing the attributes of the instances of the class; essentially, a ClassDef gives the set of all class-level and instance-level attributes, and for each one, a corresponding ``SomeXxx`` annotation. ``SomeInstance`` は与えられたクラスやその任意の子クラスのインスタンスを表現しています. Annotator が見ているユーザ定義クラスそれぞれに対し, そのクラスのインスタンスが持つ属性を表現する ClassDef (``pypy.annotation.classdef``) を用意しています; 本質的に ClassDef は全てのクラスレベルとインスタンスレベルの属性の集合と, それらに対応する注釈 ``SomeXxx`` を与えます. .. original Instance-level attributes are discovered progressively as the annotation progresses. Assignments like:: inst.attr = value update the ClassDef of the given instance to record that the given attribute exists and can be as general as the given value. インスタンスレベルの属性は, 注釈処理が進むのに従って漸進的に発見されていきます. 次のような代入:: inst.attr = value は ClassDef を更新し, その属性が存在し, 代入したその値まで一般化できることを記録します. .. original For every attribute, the ClassDef also records all the positions where the attribute is *read*. If, at some later time, we discover an assignment that forces the annotation about the attribute to be generalized, then all the places that read the attribute so far are marked as invalid and the annotator will restart its analysis from there. 全ての属性について ClassDef はその属性が *読まれる* 全ての位置も記録しています. しばらく進んでから, その属性の注釈を一般化しなければならない代入に出会った場合は, それまでに属性を読み取っている全ての場所は無効と印を付けられ, Annotator はそこから解析をやり直します. .. original The distinction between instance-level and class-level attributes is thin; class-level attributes are essentially considered as initial values for instance-level attributes. Methods are not special in this respect, except that they are bound to the instance (i.e. ``self = SomeInstance(cls)``) when considered as the initial value for the instance. インスタンスレベルの属性とクラスレベルの属性の違いはわずかです; クラスレベルの属性は本質的にはインスタンスレベルの属性の初期値と考えらることができます. メソッドをインスタンスの初期値と看做すとすると, メソッドがインスタンス (例えば ``self = SomeInstance(cls)``) に結び付けられている点を除けば, メソッドは特別なものではありません. .. original The inheritance rules are as follows: the union of two ``SomeInstance`` annotations is the ``SomeInstance`` of the most precise common base class. If an attribute is considered (i.e. read or written) through a ``SomeInstance`` of a parent class, then we assume that all subclasses also have the same attribute, and that the same annotation applies to them all (so code like ``return self.x`` in a method of a parent class forces the parent class and all its subclasses to have an attribute ``x``, whose annotation is general enough to contain all the values that all the subclasses might want to store in ``x``). However, distinct subclasses can have attributes of the same names with different, unrelated annotations if they are not used in a general way through the parent class. 継承の規則は以下の通りです: 2 つの ``SomeInstance`` 注釈の併合は, 最も具体的な共通の祖先クラスの ``SomeInstance`` です. 親クラスの ``SomeInstance`` を通して属性が使われた (読み取り, もしくは書き込みされた) 場合, 全ての子クラスも同じ属性を持ち同じ注釈がそれら全てに適用されると考えます (なので, 親クラスのメソッドに ``return self.x`` のようなコードがあると, その親クラスと全ての子クラスが属性 ``x`` を持つように強制され, 全ての子クラスがその ``x`` に格納する可能性のある値全てを含む十分一般化された注釈が付けられます). しかし, 親クラスを通した普通の方法ではない方法で使われた場合, 子クラスは同じ名前の属性で異なった無関係の注釈を持つことができます. .. _`RPython typer`: .. original The RPython Typer ================= RPython 型付け器 ================ https://bitbucket.org/pypy/pypy/src/default/pypy/rpython/ .. original The RTyper is the first place where the choice of backend makes a difference; as outlined above we are assuming that ANSI C is the target. RTyper はバックエンドの選択にごとに処理が異なる初めての場所です; 上で説明した概要は ANSI C を対象と仮定しています. .. original The RPython Typer is the bridge between the Annotator_ and the code generator. The information computed by the annotator is high-level, in the sense that it describe RPython types like lists or instances of user-defined classes. RPython 型付け器は Annotator_ とコード生成器の橋渡しをします. Annotator が計算した情報は, リストやユーザ定義クラスのインスタンスのような RPython の型について記述してあるという意味で高レベルな情報です. .. original To emit code we need to represent these high-level annotations in the low-level model of the target language; for C, this means structures and pointers and arrays. The Typer both determines the appropriate low-level type for each annotation and replaces each high-level operation in the control flow graphs with one or a few low-level operations. Just like low-level types, there is only a fairly restricted set of low-level operations, along the lines of reading or writing from or to a field of a structure. これら高レベルな注釈を対象言語の低レベルなモデルで表現するのに必要なコードを出力すること; 低レベルなモデルとは C では構造体, ポインタ, 配列を意味します. 型付け器はそれぞれの注釈に対する適切な低レベルの型を決定し, control flow graph の高レベルな演算を 1 つもしくはいくつかの低レベルの演算に置き換えます. 低レベルの型と同じように, 構造体のフィールドの読み取りおよび書き込みの行に沿って、低レベルの演算のいくらか制限された集合があります. .. original In theory, this step is optional; a code generator might be able to read directly the high-level types. Our experience, however, suggests that this is very unlikely to be practical. "Compiling" high-level types into low-level ones is rather more messy than one would expect and this was the motivation for making this step explicit and isolated in a single place. After RTyping, the graphs only contain operations that already live on the level of the target language, which makes the job of the code generators much simpler. 理論的には, この処理段階はオプションです; コード生成器は直接高レベルな型を読めても構いません. しかし我々の経験上, これはあまり実践的ではないことを申し上げておきます. 高レベルな型を低レベルな型に "コンパイルする" ことは想像するよりも煩雑で, それがこの処理段階を明示的に1つの段階として分離する動機です. RTyping が終わったら, graph は対象言語のレベルにある演算しか含んでいない状態になり, これによってコード生成作業を非常に単純化されます.. .. original For more detailed information, see the `documentation for the RTyper`_. もっと詳細な情報は `RTyper のドキュメント`_ を参照してください. .. original .. _`documentation for the RTyper`: rtyper.html .. _`RTyper のドキュメント`: rtyper.html .. original Example: Integer operations --------------------------- 例: 整数演算 ------------ .. original Integer operations are make an easy example. Assume a graph containing the following operation:: v3 = add(v1, v2) annotated:: v1 -> SomeInteger() v2 -> SomeInteger() v3 -> SomeInteger() then obviously we want to type it and replace it with:: v3 = int_add(v1, v2) where -- in C notation -- all three variables v1, v2 and v3 are typed ``int``. This is done by attaching an attribute ``concretetype`` to v1, v2 and v3 (which might be instances of Variable or possibly Constant). In our model, this ``concretetype`` is ``pypy.rpython.lltypesystem.lltype.Signed``. Of course, the purpose of replacing the operation called ``add`` with ``int_add`` is that code generators no longer have to worry about what kind of addition (or concatenation maybe?) it means. 整数演算は簡単な例になります. graph が次のような演算を含んでいるとします:: v3 = add(v1, v2) このように注釈付けされるとします:: v1 -> SomeInteger() v2 -> SomeInteger() v3 -> SomeInteger() すると明らかに次のように型付けをして置換したくなります:: v3 = int_add(v1, v2) -- C の記法で書くと -- 3つの変数 v1, v2, v3 は全て ``int`` と型が付けられています. これは ``concretetype`` 属性を (Variable もしくは Constant のインスタンスである) v1, v2, v3 に与えることで実現されます. 我々のモデルでは, この ``concretetype`` は ``pypy.rpython.lltypesystem.lltype.Signed`` です. 当然, ``add`` という演算を ``int_add`` という演算に置き換える目的は, コード生成器は, この演算がどの種類の加算 (もしくは文字列結合?) を意味しているのかをこれ以上心配したくないからです. .. _`optional transformations`: .. original The Optional Transformations ============================ オプションの変形 ================ .. original Between RTyping and C source generation there are two optional transforms: the "backend optimizations" and the "stackless transform". See also `D07.1 Massive Parallelism and Translation Aspects`_ for further details. RTyping と C ソースコード生成の間に 2 つのオプションの変形処理があります: "backend optimizations" と "stackless transform" です. より詳しい情報は `D07.1 Massive Parallelism and Translation Aspects`_ を参照してください. .. _`Technical report`: .. _`D07.1 Massive Parallelism and Translation Aspects`: https://bitbucket.org/pypy/extradoc/raw/ee3059291497/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-2007-02-28.pdf Backend Optimizations --------------------- .. original The point of the backend optimizations are to make the compiled program run faster. Compared to many parts of the PyPy translator, which are very unlike a traditional compiler, most of these will be fairly familiar to people who know how compilers work. backend optimizations のポイントはコンパイルされたプログラムがより高速に実行されることです. 伝統的なコンパイラとは大きく異なる PyPy 翻訳機のほとんどの部分と比較して, この最適化はコンパイラがどのように働くかを知ってる人にはそこそこ馴染み深いものでしょう. 関数インライン化 ++++++++++++++++ .. original To reduce the overhead of the many function calls that occur when running the PyPy interpreter we implemented function inlining. This is an optimization which takes a flow graph and a callsite and inserts a copy of the flow graph into the graph of the calling function, renaming occurring variables as appropriate. This leads to problems if the original function was surrounded by a ``try: ... except: ...`` guard. In this case inlining is not always possible. If the called function is not directly raising an exception (but an exception is potentially raised by further called functions) inlining is safe, though. PyPy インタプリタを実行しているときに起こる関数呼び出しのオーバーヘッドを減らすために, 我々は関数インライン化を実装しました. これは flow graph と呼び出し箇所に対して, 変数を適切に変更しながら呼び出されている関数の flow graph を呼び出し側の flow graph に埋め込む最適化です. これはインライン化する前の関数が ``try: ... except: ...`` で囲われている場合に問題を引き起こします. このケースでは, インライン化は常にできるとは限りません. もっとも呼び出される関数が直接例外を送出しない (が, それ以降に呼び出される関数から例外が送出される可能性はある) 場合は, インライン化は安全です. .. original In addition we also implemented heuristics which function to inline where. For this purpose we assign every function a "size". This size should roughly correspond to the increase in code-size which is to be expected should the function be inlined somewhere. This estimate is the sum of two numbers: for one every operations is assigned a specific weight, the default being a weight of one. Some operations are considered to be more effort than others, e.g. memory allocation and calls; others are considered to be no effort at all (casts...). The size estimate is for one the sum of the weights of all operations occurring in the graph. This is called the "static instruction count". The other part of the size estimate of a graph is the "median execution cost". This is again the sum of the weight of all operations in the graph, but this time weighted with a guess how often the operation is executed. To arrive at this guess we assume that at every branch we take both paths equally often, except for branches that are the end of loops, where the jump back to the end of the loop is considered more likely. This leads to a system of equations which can be solved to get approximate weights for all operations. 加えて言うと, どの関数をどこでインライン化するかの発見的手法を実装しました. この目的のために全ての関数に "size" (大きさ) という概念を追加しました. 大きさは大雑把には, ある場所に関数をインライン化したときのコードサイズの増加に対応します. これは 2 つの数字の和で評価されます: 1 つ目は全ての演算にある特定の重み (デフォルトは 1) を割り当てます. ある演算, 例えばメモリ割り当てや呼び出しなどは, 他の演算よりもコストが掛かると看做されます; 他のもの (キャスト...) は全くコストが掛からないと看做されます. 大きさの評価は 1 つは graph に現れる全ての演算の重みの合計です. これは "static instruction count" (静的インストラクション数) と呼ばれます. graph の大きさの評価のもう 1 つの要素は "median execution cost" (実行コストの中央値) です. これも graph の全ての演算の重みの和ですが, これはその演算がどのくらい頻繁に呼ばれるかを推測した値の分の重みが掛けられています. この推測を行うために, 我々は全ての条件分岐は同じ頻度で両方の分岐を通るという仮定を置いています. ただし例外として, ループの末尾の条件分岐はループを抜けるよりもループの先頭に戻る方が多いと看做しています. これによって等式系 (連立方程式) が導き出され, これを解くことで全ての演算のおおよその重みを得ることができます. .. original After the size estimate for all function has been determined, functions are being inlined into their callsites, starting from the smallest functions. Every time a function is being inlined into another function, the size of the outer function is recalculated. This is done until the remaining functions all have a size greater than a predefined limit. 全ての関数の大きさの評価が確定した後に, 最も小さい関数から順に呼び出し箇所へインライン化されていきます. 関数が他の関数の中へインライン化されていくたびに, 外側の関数の大きさが再計算されます. この処理は残っている全ての関数が事前に決めた値より大きくなるまで続けられます. .. original Malloc Removal ++++++++++++++ malloc 除去 +++++++++++ .. original Since RPython is a garbage collected language there is a lot of heap memory allocation going on all the time, which would either not occur at all in a more traditional explicitely managed language or results in an object which dies at a time known in advance and can thus be explicitely deallocated. For example a loop of the following form:: for i in range(n): ... which simply iterates over all numbers from 0 to n - 1 is equivalent to the following in Python:: l = range(n) iterator = iter(l) try: while 1: i = iterator.next() ... except StopIteration: pass Which means that three memory allocations are executed: The range object, the iterator for the range object and the StopIteration instance, which ends the loop. RPython は GC (garbage collection) 付きの言語なので, 常にヒープメモリの割り当てが行われています. これは伝統的な開発者が明示的に管理を行う言語では全く起きないか, 前持って分かっているタイミングで死に, 従って暗黙的に (訳注: 原文では explicitely とあるが implicitly の間違いか?) 解放されるオブジェクトという仕組みが作られたりします. 例えば以下のような形のループを考えてみます:: for i in range(n): ... これは単純に 0 から n - 1 までの全ての整数を順に繰り返すループで, 以下の Python スクリプトと同等です:: l = range(n) iterator = iter(l) try: while 1: i = iterator.next() ... except StopIteration: pass これから 3 回メモリ割り当てが行われていることが分かります: range オブジェクト, range オブジェクトのイテレータ, ループを終了させる StopIteration インスタンスです. .. original After a small bit of inlining all these three objects are never even passed as arguments to another function and are also not stored into a globally reachable position. In such a situation the object can be removed (since it would die anyway after the function returns) and can be replaced by its contained values. 少々のインライン化を行ってみると, これら 3 つのオブジェクトは他の関数に引数として渡されることも グローバルにアクセスできる場所に格納されることもありません. このような状況では (関数が終了したときにどちらにせよ死ぬので) オブジェクトは除去でき, オブジェクトが格納している値に置き換えることができます. .. original This pattern (an allocated object never leaves the current function and thus dies after the function returns) occurs quite often, especially after some inlining has happened. Therefore we implemented an optimization which "explodes" objects and thus saves one allocation in this simple (but quite common) situation. この (作成したオブジェクトが現在の関数の外に出ることが無く, 関数が終了すると死ぬ) パターンは非常に頻繁に起き, 特にインライン化をした後に起きやすいです. それ故, オブジェクトを "爆破" し, この単純 (かつ頻度の高い) 状況でのメモリ割り当てを 1 つ節約する最適化を実装しました. .. original Escape Analysis and Stack Allocation ++++++++++++++++++++++++++++++++++++ エスケープ解析とスタック内メモリ割り当て ++++++++++++++++++++++++++++++++++++++++ .. original Another technique to reduce the memory allocation penalty is to use stack allocation for objects that can be proved not to life longer than the stack frame they have been allocated in. This proved not to really gain us any speed, so over time it was removed again. もう 1 つのメモリ割り当てのコストを減らす技術は, メモリ割り当てがなされたスタックフレームの中でしか生存しないことが証明されたオブジェクトに対し スタック上でメモリ割り当てを行ってしまうことです. これは現実には速度には寄与しないことが分かったので, 徐々に取り除かれました. The Stackless Transform ----------------------- .. original The stackless transform converts functions into a form that knows how to save the execution point and active variables into a heap structure and resume execution at that point. This was used to implement coroutines as an RPython-level feature, which in turn are used to implement coroutines, greenlets and tasklets as an application level feature for the Standard Interpreter. stackless transform は関数を, 実行箇所と生きている変数をヒープに保存し, その箇所から実行を再開することのできる形式に変換します. これは RPython レベルの機能として coroutine を実装するために使われ, さらに coroutine, greenlet, tasklet を標準インタプリタのアプリケーションレベルの機能として実装するのに使われています. .. original The stackless transformation has been deprecated and is no longer available in trunk. It has been replaced with continulets_. stackless transformation は廃止予定となっていて, 今後は trunk では利用できなくなっています. これは既に continulets_ に置き換えられています. .. _continulets: stackless.html .. _`preparing the graphs for source generation`: .. original Preparation for Source Generation ================================= ソース生成の準備 ================ .. original This, perhaps slightly vaguely named, stage is the most recent to appear as a separate step. Its job is to make the final implementation decisions before source generation -- experience has shown that you really don't want to be doing *any* thinking at the same time as actually generating source code. For the C backend, this step does three things: - inserts explicit exception handling, - inserts explicit memory management operations, - decides on the names functions and types will have in the final source (this mapping of objects to names is sometimes referred to as the "low-level database"). このステージは, やや漠然とした名前かもしれませんが, 最近個別の処理段階として分離されました. ここでの仕事はソース生成の前の最後の実装の判断を行います -- 実際のソースコード生成と同時に *どんなことでも* 考えることはしたくないと, 経験的に思うはずです. C backend では, この処理段階は 3 つのことを行います: - 明示的な例外処理を挿入し, - 明示的なメモリ管理操作を挿入し, - 関数や型が最終的なソースでどんな名前になるかを決定します (このオブジェクトから名前への対応付けは, "low-level database" として何度か参照されます). .. original Making Exception Handling Explicit ---------------------------------- 例外処理の明示化 ---------------- .. original RPython code is free to use exceptions in much the same way as unrestricted Python, but the final result is a C program, and C has no concept of exceptions. The exception transformer implements exception handling in a similar way to CPython: exceptions are indicated by special return values and the current exception is stored in a global data structure. RPython のコードは制限の無い Python と同じ方法で自由に例外が使えますが, 最終的な成果物は C プログラムであり, C には例外の考え方がありません. 例外変換器は CPython と似た方法で例外処理を実装します: 例外は特殊な返り値として表現され, 現在の例外はグローバルなデータ構造に格納されます. .. original In a sense the input to the exception transformer is a program in terms of the lltypesystem_ with exceptions and the output is a program in terms of the bare lltypesystem. ある意味では例外変換器への入力は例外付き lltypesystem_ のプログラムであり, 出力は生の lltypesystem のプログラムです. .. _lltypesystem: glossary.html#lltypesystem .. original Memory Management Details ------------------------- メモリ管理の詳細 ---------------- .. original As well as featuring exceptions, RPython is a garbage collected language; again, C is not. To square this circle, decisions about memory management must be made. In keeping with PyPy's approach to flexibility, there is freedom to change how to do it. There are three approaches implemented today: - reference counting (deprecated, too slow) - using the `Boehm-Demers-Weiser conservative garbage collector`_ - using one of our custom `exact GCs implemented in RPython`_ RPython は例外を特徴として持つ言語ですが, GC を持つ言語でもあります; そしてやはり C はそうではありません. この丸をなんとか四角にするために, メモリ管理に関する判断をしなければなりません. PyPy の柔軟さを保つために, その手法は自由に変更できます. 今日では 3 つの実装があります: - 参照カウント (廃止予定, 非常に遅い) - `Boehm-Demers-Weiser conservative garbage collector`_ を使う - 我々独自の `exact GCs implemented in RPython`_ を使う .. _`Boehm-Demers-Weiser conservative garbage collector`: http://www.hpl.hp.com/personal/Hans_Boehm/gc/ .. _`exact GCs implemented in RPython`: garbage_collection.html .. original Almost all application-level Python code allocates objects at a very fast rate; this means that the memory management implementation is critical to the performance of the PyPy interpreter. ほとんど全てのアプリケーションレベルの Python コードは非常に高い割合でオブジェクト割り当てを行っています; これはメモリ管理の実装は PyPy インタプリタのパフォーマンスに重大な影響があることを意味します. .. original You can choose which garbage collection strategy to use with :config:`translation.gc`. どの GC 戦略を使うは :config:`translation.gc` で選べます. .. _C: .. _GenC: .. _`c backend`: The C Back-End ============== https://bitbucket.org/pypy/pypy/src/default/pypy/translator/c/ .. original GenC is usually the most actively maintained backend -- everyone working on PyPy has a C compiler, for one thing -- and is usually where new features are implemented first. GenC は最も活発に保守されている backend であり -- 1 つには, PyPy を開発している人は皆 C コンパイラを持っていることがあります --, たいていの新しい機能が最初に実装されます. .. _`EU report about translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf .. original A Historical Note ================= 歴史についてのメモ ================== .. original As this document has shown, the translation step is divided into more steps than one might at first expect. It is certainly divided into more steps than we expected when the project started; the very first version of GenC operated on the high-level flow graphs and the output of the annotator, and even the concept of the RTyper didn't exist yet. More recently, the fact that preparing the graphs for source generation ("databasing") and actually generating the source are best considered separately has become clear. このドキュメントを読めば分かるように, 最初は 1 つだと思われていた翻訳の処理段階が分割されています. プロジェクトが開始したときの予想よりも確実に多くの処理段階に分割されています; 本当に最初のバージョンの GenC は高レベルな flow graph と Annotator の出力結果を処理していましたし, RTyper の概念はまだ存在すらしていませんでした. もっと最近では, ソース生成のためにグラフを前処理する ("databasing") 段階と 実際にソース生成する段階を分けるのが最も良い, という事実がはっきりしました. .. original Other backends ============== 他の backend ============ .. original Use the :config:`translation.backend` option to choose which backend to use. :config:`translation.backend` オプションを使ってどの backend を使うかを選べます. .. original The Object-Oriented Backends ---------------------------- オブジェクト指向 backend ------------------------ .. original The Object-Oriented backends target platforms that are less C-like and support classes, instance etc. If such a platform is targeted, the `OO type system` is used while rtyping. Of the OO backends, both gencli and genjava can translate the full Python interpreter. オブジェクト指向 backend は, C とは異なりクラスやインスタンスなどをサポートするプラットフォームを対象としています. このようなプラットフォームを対象とした場合は, RTyping の処理で `OO type system` が使われます. OO backend の gencli も genjava も Python インタプリタ全体を翻訳できます. .. _`oo type system`: rtyper.html#oo-type .. mention that pretty much all these backends are done by volunteers? GenCLI ++++++ .. original GenCLI_ targets the `Common Language Infrastructure`_, the most famous implementations of which are Microsoft's `.NET`_ and Mono_. GenCLI_ は Microsoft の `.NET`_ と Mono_ の最も有名な実装である `Common Language Infrastructure`_ を対象としています. .. original It is the most advanced of the object oriented backends -- it can compile the PyPy interpreter as well as our two standard benchmarks, RPyStone (CPython's PyStone benchmark modified slightly to be RPython) and a RPython version of the common Richards benchmark. これはオブジェクト指向 backend の中で最も開発が進んでいます -- 標準的なベンチマークである RPyStone (CPython の PyStone ベンチマークを RPython 用に少し改造したもの) や 有名な Rechards のベンチマークの RPython 版にに加えて PyPy インタプリタもコンパイルできます. .. original It is almost entirely the work of Antonio Cuni, who started this backend as part of his `Master's thesis`_, the Google's Summer of Code 2006 program and the Summer of PyPy program. これはほぼ全て `Master's thesis`_ (修士論文のテーマ), Google の Summer of Code 2006 プログラムおよび Summer of PyPy プログラムの一部として, この backend の開発を始めた Antonio Cuni の働きによるものです. .. _`Common Language Infrastructure`: http://www.ecma-international.org/publications/standards/Ecma-335.htm .. _`.NET`: http://www.microsoft.com/net/ .. _Mono: http://www.mono-project.com/ .. _`Master's thesis`: http://buildbot.pypy.org/misc/Implementing%20Python%20in%20.NET.pdf .. _GenCLI: cli-backend.html GenJVM ++++++ .. original GenJVM targets the Java Virtual Machine: it translates RPython programs directly into Java bytecode, similarly to what GenCLI does. GenJVM は Java 仮想マシンを対象にしています: GenCLI が行っているように RPython プログラムを直接 Java バイトコードに変換します. .. original So far it is the second most mature high level backend after GenCLI: it still can't translate the full Standard Interpreter, but after the Leysin sprint we were able to compile and run the rpytstone and richards benchmarks. 現在のところ GenCLI に続いて 2 番目に成熟している高レベルな backend です: まだ標準インタプリタ全体をコンパイルすることはできませんが, Leysin sprint において RPyStone (訳注: 原文の rpytstone はおそらく typo) と Richards ベンチマークはコンパイルし, 実行することができるようになりました. .. original GenJVM is almost entirely the work of Niko Matsakis, who worked on it also as part of the Summer of PyPy program. GenJVM はほぼ全て, Summer of PyPy プログラムの一部として取り組んだ Niko Matsakis の働きによるものです. .. _extfunccalls: .. original External Function Calls ======================= 外部関数呼び出し ================ .. original The external function call approach is described in `rffi`_ documentation. 外部関数呼び出しへのアプローチについては `rffi`_ ドキュメントで解説されています. .. _`rffi`: rffi.html .. original How It Fits Together ==================== どう連携するか ============== .. original As should be clear by now, the translation toolchain of PyPy is a flexible and complicated beast, formed from many separate components. ここまでで明らかになったように, PyPy の translation toolchain は多くのコンポーネントが形成する柔軟性に富む複雑な獣です. .. original The following image summarizes the various parts of the toolchain as of the 0.9 release, with the default translation to C highlighted: 次の画像は 0.9 リリースの toolchain の様々な部品をまとめたもので, C へのデフォルトの翻訳処理に色が付けてあります: .. image:: image/pypy-translation-0.9.png :align: center .. original A detail that has not yet been emphasized is the interaction of the various components. It makes for a nice presentation to say that after the annotator has finished the RTyper processes the graphs and then the exception handling is made explicit and so on, but it's not entirely true. For example, the RTyper inserts calls to many `low-level helpers`_ which must first be annotated, and the GC transformer can use inlining (one of the `backend optimizations`_) of some of its small helper functions to improve performance. The following picture attempts to summarize the components involved in performing each step of the default translation process: ここまで強調されていなかった詳細部分は様々なコンポーネントの相互作用です. この図では Annotator が終わったら RTyper が graph の処理を行い, 次に例外処理が明示化され, などなど, ということが分かりやすくなっていますが, これは本当に正しいというわけではありません. 例えば, RTyper はまず注釈付けされなくてはならない多くの `low-level helpers`_ を呼んでいますし, GC 変換器はパフォーマンスを改善するために, そのヘルパー関数のインライン化 (これは `backend optimizations`_ の 1 つ) を使えます. 次の画像はデフォルトの翻訳過程のそれぞれの処理段階に関わるコンポーネントをまとめた図です: .. image:: image/translation-detail-0.9.png :align: center .. _`low-level helpers`: glossary.html#low-level-helper .. original A component not mentioned before is the "MixLevelAnnotator"; it provides a convenient interface for a "late" (after RTyping) translation step to declare that it needs to be able to call each of a collection of functions (which may refer to each other in a mutually recursive fashion) and annotate and rtype them all at once. まだ言及していないコンポーネントは "MixLevelAnnotator" です; これは (RTyping より) "後の" 翻訳段階が (お互いに参照し合う相互再帰のような形になっているかもしれない) 関数群のそれぞれ関数の呼び出し, 注釈付け, 型付け (RTyping) をいっぺんにできる必要がある, と宣言するための便利なインターフェースを提供します. .. include:: _ref.txt