==================== コーディングガイド ==================== .. contents:: .. This document describes coding requirements and conventions for .. working with the PyPy code base. Please read it carefully and .. ask back any questions you might have. The document does not talk .. very much about coding style issues. We mostly follow `PEP 8`_ though. .. If in doubt, follow the style that is already present in the code base. このドキュメントは、コーディングの要件と PyPy のコードベースで作業をする上での取り決めを説明します。 このドキュメントを注意深く読み、どんな疑問が合った場合でも読み返して下さい。 ドキュメントはコーディングスタイルの問題について多くは語りません。 おおよその場合 `PEP 8`_ にあわせて下さい。 疑わしい場合は、既に存在するコードベースのスタイルに合わせてください。 .. _`PEP 8`: http://www.python.org/dev/peps/pep-0008/ .. _`RPython`: .. Overview and motivation 概要と動機 ========== .. We are writing a Python interpreter in Python, using Python's well known .. ability to step behind the algorithmic problems as a language. At first glance, .. one might think this achieves nothing but a better understanding how the .. interpreter works. This alone would make it worth doing, but we have much .. larger goals. 私たちは Python インタプリタを Python で書いています。 Python を使用することは、アルゴリズム問題ではなく、言語そのものに言及できることはよく知られています。 ぱっと見、これは何の意味もないと思うかもしれませんが、インタプリタの仕組みを理解するためにはよいことです。 これだけで価値があります。しかし、私たちにはより大きな目標があります。 .. CPython vs. PyPy CPython 対 PyPy --------------- .. Compared to the CPython implementation, Python takes the role of the C .. Code. We rewrite the CPython interpreter in Python itself. We could .. also aim at writing a more flexible interpreter at C level but we .. want to use Python to give an alternative description of the interpreter. CPython の実装と比較すると、 Python は C コードの役割を持ちます。 我々は CPython インタプリタを Python それ自身で書きなおしています。 我々は C レベルでもより柔軟なインタプリタ目指せますが、インタプリタの代替として高級言語による実装を与えるために Python を使います。 .. XXX description の訳し方が若干微妙 .. The clear advantage is that such a description is shorter and simpler to .. read, and many implementation details vanish. The drawback of this approach is .. that this interpreter will be unbearably slow as long as it is run on top .. of CPython. 明確な利点は、このような高級言語による実装は短く、より単純で読みやすく、多くの実装の詳細がないことです。 このアプローチの欠点は、このインタプリタがとても遅く、 CPython のトップレベルが実行されるまでに時間がかかってしまうことです。 .. To get to a useful interpreter again, we need to translate our .. high-level description of Python to a lower level one. One rather .. straight-forward way is to do a whole program analysis of the PyPy .. interpreter and create a C source, again. There are many other ways, .. but let's stick with this somewhat canonical approach. 便利なインタプリタを再度手に入れるために、Python による高級な実装から低級なものに変換する必要があります。 もうひとつの直線コースは、 PyPy インタプリタのソースコード全体の解析と、 C のソースコードを再度作ることです。 他の道も様々ありますが、このやや標準的なアプローチにこだわってしてみましょう。 .. _`application-level`: .. _`interpreter-level`: .. Application-level and interpreter-level execution and objects アプリケーションレベルとインタプリタレベルの実行とオブジェクト -------------------------------------------------------------- .. Since Python is used for implementing all of our code base, there is a .. crucial distinction to be aware of: that between *interpreter-level* objects and .. *application-level* objects. The latter are the ones that you deal with .. when you write normal python programs. Interpreter-level code, however, .. cannot invoke operations nor access attributes from application-level .. objects. You will immediately recognize any interpreter level code in .. PyPy, because half the variable and object names start with a ``w_``, which .. indicates that they are `wrapped`_ application-level values. Python が我々の全てのコードベースの実装に使われて以降、 *インタプリタレベル* オブジェクトと *アプリケーションレベルオブジェクト* の間には注意するべき重要な区別があります。 通常の Python プログラムで書く上であなたが扱う文字です。 インタプリタレベルのコードは、アプリケーションレベルのオブジェクトのオペレーションを呼び出したり、また、属性にアクセスすることはできません。 あなたはPyPy のどんなインタプリタレベルのコードでもすぐにわかるでしょう、 半分の変数とオブジェクト名は ``w_`` という文字列で始まっているからです。 これは、変数やオブジェクトが `ラップされた`_ アプリケーションレベルのオブジェクトであることを示します。 .. Let's show the difference with a simple example. To sum the contents of .. two variables ``a`` and ``b``, one would write the simple application-level .. ``a+b`` -- in contrast, the equivalent interpreter-level code is .. ``space.add(w_a, w_b)``, where ``space`` is an instance of an object space, .. and ``w_a`` and ``w_b`` are typical names for the wrapped versions of the .. two variables. ここでは単純な例で違いを示します。 二つの変数 ``a`` と ``b`` の中身を足す、という処理はアプリケーションレベルでは単に ``a+b`` と書かれます。 対照的に、インタプリタレベルのコードは ``space.add(w_a, w_b)``` となります。 ``space`` はオブジェクトスペースのインスタンス、 ``w_a`` と ``w_b`` は二つの変数のラップされたバージョンの典型的な名前です。 .. It helps to remember how CPython deals with the same issue: interpreter .. level code, in CPython, is written in C and thus typical code for the .. addition is ``PyNumber_Add(p_a, p_b)`` where ``p_a`` and ``p_b`` are C .. variables of type ``PyObject*``. This is conceptually similar to how we write .. our interpreter-level code in Python. これは、CPython が同じ問題にどうやって対処しているかを思い出すことを救けてくれます。 CPython のインタプリタレベルのコードは C で書かれでいます。従って、典型的な加算処理のコードは ``PyNumber_Add(p_a, p_b)`` です。ここでは ``p_a`` と ``p_b`` は ``PyObject*`` 型の C の変数です。 これは、概念的には我々が Python でインタプリタレベルのコードを各方法に似ています。 .. Moreover, in PyPy we have to make a sharp distinction between .. interpreter- and application-level *exceptions*: application exceptions .. are always contained inside an instance of ``OperationError``. This .. makes it easy to distinguish failures (or bugs) in our interpreter-level code .. from failures appearing in a python application level program that we are .. interpreting. また、 PyPy ではインタプリタレベルとアプリケーションレベルの例外を明確に区別します。 アプリケーションの例外は常に ``OperationError`` クラスのインスタンスの中に格納されます。 これは、インタプリタで実行している Python のアプリケーション上で表示されるエラーから、インタプリタレベルのコードが失敗したのか(もしくはバグなのか)の区別を容易にします。 .. _`app-preferable`: .. Application level is often preferable アプリケーションレベルのコードはたまに理想的 -------------------------------------------- .. Application-level code is substantially higher-level, and therefore .. correspondingly easier to write and debug. For example, suppose we want .. to implement the ``update`` method of dict objects. Programming at .. application level, we can write an obvious, simple implementation, one .. that looks like an **executable definition** of ``update``, for .. example アプリケーションレベルのコードは、とても高級なので書いたりデバッグすることが簡単になっています。 例えば、辞書オブジェクトの ``update`` メソッドを実装しようとしているとします。 アプリケーションレベルでのプログラミングは、 ``update`` メソッドの **実行可能な定義** のように見えるようなとてもシンプルな実装を書けます。 例えば以下のようなものです:: def update(self, other): for k in other.keys(): self[k] = other[k] .. If we had to code only at interpreter level, we would have to code .. something much lower-level and involved, say something like もし、インタプリタレベルのコードのみを書くことになったら、多くの低レベルな何かのコードを書き、考慮する必要があります。 以下で述べるようにです。:: def update(space, w_self, w_other): w_keys = space.call_method(w_other, 'keys') w_iter = space.iter(w_keys) while True: try: w_key = space.next(w_iter) except OperationError, e: if not e.match(space, space.w_StopIteration): raise # re-raise other app-level exceptions break w_value = space.getitem(w_other, w_key) space.setitem(w_self, w_key, w_value) .. This interpreter-level implementation looks much more similar to the C .. source code. It is still more readable than its C counterpart because .. it doesn't contain memory management details and can use Python's native .. exception mechanism. このインタプリタレベルの実装は、 C のソースコードのそれに似ています。 ただし、メモリマネジメントや Python の例外機構を使えるため、 C で書いたそれよりもまだ読みやすいでしょう。 .. In any case, it should be obvious that the application-level implementation .. is definitely more readable, more elegant and more maintainable than the .. interpreter-level one (and indeed, dict.update is really implemented at .. applevel in PyPy). いかなるケースでも、アプリケーションレベルの実装の方がインタプリタレベルのそれよりも確実に読みやすく、エレガントで、メンテナンス性が高い事を明らかにする必要があります(そして実際に dict.update は PyPy においては本当のアプリケーションレベルで実装されています)。 .. In fact, in almost all parts of PyPy, you find application level code in .. the middle of interpreter-level code. Apart from some bootstrapping .. problems (application level functions need a certain initialization .. level of the object space before they can be executed), application .. level code is usually preferable. We have an abstraction (called the .. 'Gateway') which allows the caller of a function to remain ignorant of .. whether a particular function is implemented at application or .. interpreter level. 実際、 PyPy のほぼすべての部分において、アプリケーションレベルのコードがインタプリタレベルのコードの中に使われています。 いくつかのブートストラップ問題を置いておいて、 (アプリケーションレベルの機能は使えるようになる前に、オブジェクトスペースが特定の初期化レベルに達することが必要です)、アプリケーションレベルのコートは通常、望ましいものです。 特定の関数の実装がアプリケーションレベルかインタプリタレベルかを知らないまま関数の呼び出しを許可する ("ゲートウェイ"と呼ばれる) 抽象化機能を持っています。 .. Our runtime interpreter is "RPython" ランタイムインタプリタは "RPython" ---------------------------------- .. In order to make a C code generator feasible all code on interpreter level has .. to restrict itself to a subset of the Python language, and we adhere to some .. rules which make translation to lower level languages feasible. Code on .. application level can still use the full expressivity of Python. インタプリタレベルの全てのコードを実行可能な C コードを生成するジェネレータを作るには Python のサブセットとしてそれ自身を制限する必要があります。 そして、いくつかのルールに準拠して、実行可能な低レベル言語に変換します。 アプリケーションレベルのコードは、まだ Python の全ての表現を使えます。 .. Unlike source-to-source translations (like e.g. Starkiller_ or more recently .. ShedSkin_) we start .. translation from live python code objects which constitute our Python .. interpreter. When doing its work of interpreting bytecode our Python .. implementation must behave in a static way often referenced as .. "RPythonic". ソースからソースへの変換 (Starkiller_ もしくは最近では ShedSkin_ のような例があります) とは異なり、生きた Python コードオブジェクトから変換を開始し、 Python インタプリタを構成します。 我々の Python 実装は、バイトコート解釈作業の実行時に "RPythonic" として参照されることがあるような静的な方法で動作する必要があります .. _Starkiller: http://people.csail.mit.edu/jrb/Projects/starkiller.pdf .. _ShedSkin: http://shed-skin.blogspot.com/ .. However, when the PyPy interpreter is started as a Python program, it .. can use all of the Python language until it reaches a certain point in .. time, from which on everything that is being executed must be static. .. That is, during initialization our program is free to use the .. full dynamism of Python, including dynamic code generation. ただし、PyPy インタプリタが Python プログラムとして開始したとき、 Python 言語のすべてを使えるような特定の時点でのポイントに達するまでのすべての実行は静的である必要があります。 プログラムの初期化中は、動的なコード生成を含む Python の動的な処理が自由に使えます。 .. An example can be found in the current implementation which is quite .. elegant: For the definition of all the opcodes of the Python .. interpreter, the module ``dis`` is imported and used to initialize our .. bytecode interpreter. (See ``__initclass__`` in .. `pypy/interpreter/pyopcode.py`_). This .. saves us from adding extra modules to PyPy. The import code is run at .. startup time, and we are allowed to use the CPython builtin import .. function. 現行の実装に含まれるサンプルコードは非常にエレガントです。 Python インタプリタに含まれるすべてのオペコードの定義に使われる ``dis`` モジュールは、バイトコードインタプリタからインポートされ、使われています。 (`pypy/interpreter/pyopcode.py`_ にある ``__initclass__`` を見てください) このおかげで余分なモジュールを PyPy に追加することを抑えられています。 インポートしたコードはスタートアップ時に走り、 CPython ビルトインインポート関数を使うことを許可しています。 .. After the startup code is finished, all resulting objects, functions, .. code blocks etc. must adhere to certain runtime restrictions which we .. describe further below. Here is some background for why this is so: .. during translation, a whole program analysis ("type inference") is .. performed, which makes use of the restrictions defined in RPython. This .. enables the code generator to emit efficient machine level replacements .. for pure integer objects, for instance. スタートアップコードの終了後は、すべての結果のオブジェクト、関数、コードブロックなどは 下記にあるような特定のランタイムの制限に従う必要があります。 そのような制限がある理由とその背景について説明します。 変換とプログラム全体の解析 ("型インタフェイス") の実行中は、 RPython で定義された制限を利用します。 これは、純粋な整数型のオブジェクトやインスタンスのための効率的なマシンレベルコードに置き換えるコードジェネレータを有効にします。 RPython ======= .. RPython Definition RPython の定義 -------------- .. RPython is a restricted subset of Python that is amenable to static analysis. .. Although there are additions to the language and some things might surprisingly .. work, this is a rough list of restrictions that should be considered. Note .. that there are tons of special cased restrictions that you'll encounter .. as you go. The exact definition is "RPython is everything that our translation .. toolchain can accept" :) RPython は静的解析が可能なように制限された Python のサブセットです。 言語への追加があり、いくつかの要素が想定外の動作をする可能性があります。 これらは、その考慮するべき制限の大雑把なリストです。 注意としては、あなたが遭遇する制限には多くの特殊なケースがあることが挙げられます。 正確な定義としては、「RPython は我々の翻訳toolchainが受け入れられるものが全て」です :) .. _`wrapped object`: coding-guide.html#wrapping-rules .. Flow restrictions 制御フローの制限 ---------------- .. **variables** **変数** .. variables should contain values of at most one type as described in .. `Object restrictions`_ at each control flow point, that means for .. example that joining control paths using the same variable to .. contain both a string and a int must be avoided. It is allowed to .. mix None (basically with the role of a null pointer) with many other .. types: `wrapped objects`, class instances, lists, dicts, strings, etc. .. but *not* with int, floats or tuples. 変数は `オブジェクトの制限`_ によってそれぞれのコントロールフローポイントで解釈された一つの型の値を含む必要があります。 それが意味するところは、例えば、コントロールパスの接続時に、同じ変数に対して int と string の両方が使われることが回避されなければならないということです。 その他の多くの型と一緒に None を含めることは許可されています。(基本的には None は NULL ポインタとして使われます) 多くの型とはすなわち `wrapped objects`, クラスのインスタンス、リスト、辞書、文字列などです *が* 、int, float, tuple は含まれません。 .. **constants** **定数** .. all module globals are considered constants. Their binding must not .. be changed at run-time. Moreover, global (i.e. prebuilt) lists and .. dictionaries are supposed to be immutable: modifying e.g. a global .. list will give inconsistent results. However, global instances don't .. have this restriction, so if you need mutable global state, store it .. in the attributes of some prebuilt singleton instance. 全てのモジュールグローバル変数は定数として扱われます。その束縛を実行時に変更することはできません。 また、グローバルな (すなわち実行前に作られた) リストと辞書は不変なオブジェクトであるとして扱われます。 もし、グローバルなリストが変更された場合、一貫性のない結果をもたらすでしょう。 ただし、グローバルインスタンスはこの制限を持ちません。なので、もし変更可能なグローバルな状態を扱いたいのであれば、シングルトンインスタンスの属性としてストアしてあげればよいのです。 .. **control structures** **制御構造** .. all allowed, ``for`` loops restricted to builtin types, generators .. very restricted. 全て使えますが、 ``for`` ループはビルトインの型のみに制限され、ジェネレータはかなりの制限がかかっています。 **range** .. ``range`` and ``xrange`` are identical. ``range`` does not necessarily create an array, .. only if the result is modified. It is allowed everywhere and completely .. implemented. The only visible difference to CPython is the inaccessibility .. of the ``xrange`` fields start, stop and step. ``range`` と ``xrange`` は同一です。 ``range`` は、その結果が変更される場合を除いて必ずしも配列を作るわけではありません。 これは、どこでも使え、完全に実装されています。 CPython からの違いとして、唯一確認可能ものは、 ``xrange`` の start, stop, step フィールドにアクセスできないことです。 .. **definitions** **定義** .. run-time definition of classes or functions is not allowed. 実行時にクラスや関数を定義することはできません。 .. **generators** **ジェネレータ** .. generators are supported, but their exact scope is very limited. you can't .. merge two different generator in one control point. ジェネレータはサポートされますが、実際のスコープはとても制限されています。 別々のジェネレータを一つの制御点において混ぜて使用することはできません。 .. **exceptions** **例外** .. + fully supported .. + see below `Exception rules`_ for restrictions on exceptions raised by built-in operations + 完全にサポートしています + 下記 `例外のルール`_ で組み込み演算で送出される例外に関する制限を説明しています オブジェクトの制限 ------------------ .. We are using 以下の通りです .. **integer, float, boolean** **整数, 浮動少数, 真偽値** .. works. 使えます。 .. **strings** **文字列** .. a lot of, but not all string methods are supported and those that are .. supported, not necesarilly accept all arguments. Indexes can be .. negative. In case they are not, then you get slightly more efficient .. code if the translator can prove that they are non-negative. When .. slicing a string it is necessary to prove that the slice start and .. stop indexes are non-negative. There is no implicit str-to-unicode cast .. anywhere. 大体使えます。しかし、文字列のメソッド全てをサポートしているわけではないのと、必ずしも全ての引数を受け付けるとは限りません。 負値によるインデックスアクセスが可能です。もし、インデックスアクセスの値が非負であることをトランスレータが検出した場合は、わずかに効率的なコードを出力します。 文字列に対するスライス処理を行う場合は、開始と終了のインデックスが非負である必要があります。 文字列とユニコード文字列の暗黙の変換が行われることはありません。 .. **tuples** **タプル** .. no variable-length tuples; use them to store or return pairs or n-tuples of .. values. Each combination of types for elements and length constitute .. a separate and not mixable type. タプル変数の長さはありません。それらは ストアもしくはペアの返却, n要素のタプルの値として使われます。 型の組み合わせごとに別々の要素と長さを構成し、型を混ぜることはできません。 .. **lists** **リスト** .. lists are used as an allocated array. Lists are over-allocated, so list.append() .. is reasonably fast. However, if you use a fixed-size list, the code .. is more efficient. Annotator can figure out most of the time that your .. list is fixed-size, even when you use list comprehension. .. Negative or out-of-bound indexes are only allowed for the .. most common operations, as follows: リストは動的にメモリ領域を確保される配列として使われます。 リストは多めに確保されるため、 list.append() はそれなりに高速に動作します。 ただし、もしあなたが固定長のリストを使う場合は、コードはより効率的になります。 アノテータはほとんどの場合においてリストが固定長であるかどうかを把握できます。リスト内包表記を使った時であってもです。 負値か境界外のインデックスは、以下のほとんどのオペレーションで使えます。 .. - *indexing*: .. positive and negative indexes are allowed. Indexes are checked when requested .. by an IndexError exception clause. - *インデックスアクセス*: 正負両方のインデックスによるアクセスができます。インデックスはチェックされ、場合によっては IndexError 例外を送出します。 .. - *slicing*: .. the slice start must be within bounds. The stop doesn't need to, but it must .. not be smaller than the start. All negative indexes are disallowed, except for .. the [:-1] special case. No step. - *スライス*: スライスの開始インデックスはリストの範囲内になければいけません。終了インデックスは必要ありませんが、開始インデックスよりも小さい値ではいけません。 全ての負のインデックスは使えません、ただし、 [::-1] のような場合は例外的に使えます。 .. - *other operators*: .. ``+``, ``+=``, ``in``, ``*``, ``*=``, ``==``, ``!=`` work as expected. - *その他の演算子*: ``+``, ``+=``, ``in``, ``*``, ``*=``, ``==``, ``!=`` は予想のとおりに動きます。 .. - *methods*: .. append, index, insert, extend, reverse, pop. The index used in pop() follows .. the same rules as for *indexing* above. The index used in insert() must be within .. bounds and not negative. - *メソッド*: append, index, insert, extend, reverse, pop について。 pop() の呼び出しでインデックスを渡した場合は、 *インデックスアクセス* と同様のルールが適用されます。 insert() の呼び出しでインデックスを渡す場合は、境界内かつ非負の値でなければいけません。 .. **dicts** **辞書** .. dicts with a unique key type only, provided it is hashable. Custom .. hash functions and custom equality will not be honored. .. Use ``pypy.rlib.objectmodel.r_dict`` for custom hash functions. 辞書のキーはハッシュ化可能な一つの型しか使えません。独自のハッシュ関数や、独自の比較関数は使えません。 ``pypy.rlib.objectmodel.r_dict`` は独自のハッシュ関数を利用するために使えます。 .. **list comprehensions** **リスト内包表記** .. May be used to create allocated, initialized arrays. 割り当て済み、初期化済みの配列に使うことがあります。 .. **functions** **関数** .. + statically called functions may use defaults and a variable number of .. arguments (which may be passed as a list instead of a tuple, so write code .. that does not depend on it being a tuple). + 静的に呼び出される関数は、デフォルト引数と可変長の引数を使うことがあります。 (タプルの代わりにリストが渡されることがあり、タプルに依存しないコードが書きだされます) .. + dynamic dispatch enforces the use of signatures that are equal for all .. possible called function, or at least "compatible enough". This .. concerns mainly method calls, when the method is overridden or in any .. way given different definitions in different classes. It also concerns .. the less common case of explicitly manipulated function objects. .. Describing the exact compatibility rules is rather involved (but if you .. break them, you should get explicit errors from the rtyper and not .. obscure crashes.) + 動的ディスパッチは全ての呼び出される関数か、少なくとも「十分な互換性」を持つ関数と等しいシグネチャを使うことを強制します。 この懸念は主にメソッドがオーバライドされていたり、任意の方法で別のクラスの別の定義が与えられたときのメソッド呼び出しのものです。 関数オブジェクトを明示的に操作するという少ない共通のケースもまた懸念されます。 正確な互換性のルールはむしろ関係を記述しています。 (もしそれらが破れた場合、あなたは RTyper からの明示的なエラーを得、曖昧ではないクラッシュをするでしょう。) .. **builtin functions** **組み込み関数** .. A number of builtin functions can be used. The precise set can be .. found in `pypy/annotation/builtin.py`_ (see ``def builtin_xxx()``). .. Some builtin functions may be limited in what they support, though. .. ``int, float, str, ord, chr``... are available as simple conversion .. functions. Note that ``int, float, str``... have a special meaning as .. a type inside of isinstance only. いくつかの組み込み関数は使えます。正確には `pypy/annotation/builtin.py`_ に定義されているものがそうです。 (``def builtin_xxx()`` という定義を見てください) いくつかの組み込み関数はサポートしている範囲を制限されることがあります。 ``int, float, str, ord, chr``... これらは単純な変換関数として使えます。 ``int, float, str``... これらは isinstance() で使った時のみ内部型として特別な意味を持つことに注意してください。 .. **classes** **クラス** .. + methods and other class attributes do not change after startup + メソッドとその他のクラスの属性は実行後に変更できません .. + single inheritance is fully supported + 単一継承は完全にサポートしています .. + simple mixins work too, but the mixed in class needs a ``_mixin_ = True`` .. class attribute + 単純な mixin は機能しますが、 mixin される側のクラスには ``_mixin_ = True`` というクラス属性を付けなければいけません .. + classes are first-class objects too + クラスはもちろんファーストクラスオブジェクトです .. **objects** **オブジェクト** .. Normal rules apply. Special methods are not honoured, except ``__init__`` and .. ``__del__``. 通常のルールが適用されます。 ``__init__`` と ``__del__`` 以外の特殊メソッドは使えません。 .. This layout makes the number of types to take care about quite limited. 以上のように、いくつかの型に関して、かなりの制限があることを気をつける必要があります。 .. Integer Types 整数型 ------ .. While implementing the integer type, we stumbled over the problem that .. integers are quite in flux in CPython right now. Starting with Python 2.4, .. integers mutate into longs on overflow. In contrast, we need .. a way to perform wrap-around machine-sized arithmetic by default, while still .. being able to check for overflow when we need it explicitly. Moreover, we need .. a consistent behavior before and after translation. 整数型を実装する中で、現在の CPython の実装では、整数型はかなり流動的である、という問題に当たりました。 Python 2.4 以降では、整数型はオーバーフローが起こると長正数型に変異します。 対照的に、デフォルトでは、必要があると分かっている場合には、オーバーフローをチェックしている間にマシンのビットサイズに収まる範囲でのでの算術演算を実行する方法が必要です。 また、変換の前後で一貫性のある振る舞いが必要です。 .. We use normal integers for signed arithmetic. It means that before .. translation we get longs in case of overflow, and after translation we get a .. silent wrap-around. Whenever we need more control, we use the following .. helpers (which live the `pypy/rlib/rarithmetic.py`_): 通常、整数は符号付きの算術演算を使います。 それが意味するところは、変換前はオーバーフローが発生するケースで長整数型になり、変換後はラップアラウンドしないということです。 我々はいつでも制御が必要で、次のヘルパを使用します (`pypy/rlib/rarithmetic.py`_ ここに存在します): **ovfcheck()** .. This special function should only be used with a single arithmetic operation .. as its argument, e.g. ``z = ovfcheck(x+y)``. Its intended meaning is to .. perform the given operation in overflow-checking mode. この特殊関数は、単一の算術演算を引数として使われる必要があります。 ``z = ovfcheck(x+y)`` のように。 その目的は、引数で与えられた操作をオーバーフローチェックモードで実行するためにあります。 .. At run-time, in Python, the ovfcheck() function itself checks the result .. and raises OverflowError if it is a ``long``. But the code generators use .. ovfcheck() as a hint: they replace the whole ``ovfcheck(x+y)`` expression .. with a single overflow-checking addition in C. Python の実行時、 ovfcheck() 関数は自身の結果のチェックをして、もし結果が ``long`` であれば OverflowError を送出します。 しかし、コード生成器は ovfcheck() 関数をヒントとして使います。 コード生成器は、全ての ``ovfcheck(x+y)`` 式を C でのオーバーフロー検出の追加に置き換えます。 **intmask()** .. This function is used for wrap-around arithmetic. It returns the lower bits .. of its argument, masking away anything that doesn't fit in a C "signed long int". .. Its purpose is, in Python, to convert from a Python ``long`` that resulted from a .. previous operation back to a Python ``int``. The code generators ignore .. intmask() entirely, as they are doing wrap-around signed arithmetic all the time .. by default anyway. (We have no equivalent of the "int" versus "long int" .. distinction of C at the moment and assume "long ints" everywhere.) この関数はラップアラウンドする算術演算に使います。 この関数は引数の下位ビット以外をマスクして取り除き、返しますが、 C での "signed long int" にフィットするわけではありません。 その目的は、 Python を処理する上で、直前の演算結果の Python での ``long`` から Python の ``int`` に戻すための変換です。 コード生成器は intmask() を完全に無視し、とにかくラップアラウンドする符号付き演算を行うようにします。 (C での "int" と "long int" 相当の区別を持たず、現時点では "long ints" を前提としています。) **r_uint** .. In a few cases (e.g. hash table manipulation), we need machine-sized unsigned .. arithmetic. For these cases there is the r_uint class, which is a pure .. Python implementation of word-sized unsigned integers that silently wrap .. around. The purpose of this class (as opposed to helper functions as above) .. is consistent typing: both Python and the annotator will propagate r_uint .. instances in the program and interpret all the operations between them as .. unsigned. Instances of r_uint are special-cased by the code generators to .. use the appropriate low-level type and operations. .. Mixing of (signed) integers and r_uint in operations produces r_uint that .. means unsigned results. To convert back from r_uint to signed integers, use .. intmask(). いくつかのケース (例えばハッシュテーブルの操作など) でマシンサイズ依存の符号なし演算が必要な場面があります。 それらのケースのために r_uint クラス があります。勝手にラップアラウンドする word サイズの符号なし整数 の Pure Python 実装です。 このクラスの目的は (ヘルパ関数としての上記に反して) 一貫性のある型付けのためにあります。 Python とアノテータのどちらもプログラムの中で r_uint インスタンスを伝達し、全ての演算でそれらを符号なし整数として解釈するでしょう。 演算の中で(符号付き)整数と r_uint 混ぜると、結果は r_uint になり、結果が符号なし整数であることを意味します。 r_uint から通常の符号付き整数に戻すには intmask() を使います。 .. Exception rules 例外のルール ------------ .. Exceptions are by default not generated for simple cases.:: 例外はデフォルトでは単純なケースには生成されません:: #!/usr/bin/python lst = [1,2,3,4,5] item = lst[i] # このコードは範囲外アクセスをチェックしていない try: item = lst[i] except IndexError: # 文句を言われた .. Code with no exception handlers does not raise exceptions (after it has been .. translated, that is. When you run it on top of CPython, it may raise .. exceptions, of course). By supplying an exception handler, you ask for error .. checking. Without, you assure the system that the operation cannot fail. .. This rule does not apply to *function calls*: any called function is .. assumed to be allowed to raise any exception. 例外ハンドラのないコードは例外を送出しません (翻訳された後は。 CPython のトップレベルで実行する場合は、もちろん例外を送出する可能性があります) 例外ハンドラを提供することでエラーチェックをします。 エラーチェックなしには操作を失敗しないシステムを保証しません。 このルールは *関数呼び出し* には適用されません。 呼ばれる関数はあらゆる例外を送出すると仮定されます。 .. For example:: .. x = 5.1 .. x = x + 1.2 # not checked for float overflow .. try: .. x = x + 1.2 .. except OverflowError: .. # float result too big 例:: x = 5.1 x = x + 1.2 # 浮動小数点のオーバーフローはチェックされません try: x = x + 1.2 except OverflowError: # float result too big .. But .. z = some_function(x, y) # can raise any exception .. try: .. z = some_other_function(x, y) .. except IndexError: .. # only catches explicitly-raised IndexErrors in some_other_function() .. # other exceptions can be raised, too, and will not be caught here. ただし:: z = some_function(x, y) # どんな例外でも送出できます try: z = some_other_function(x, y) except IndexError: # some_other_function() の中で明示的に送出された IndexError のみキャッチします # 他の例外は送出でき、ここではキャッチされないでしょう。 .. The ovfcheck() function described above follows the same rule: in case of .. overflow, it explicitly raise OverflowError, which can be caught anywhere. ovfcheck() 関数は次のように上を述べたものと同様のルールです: オーバーフローが発生するケースでは、 明示的に OverflowError を送出し、どこでもキャッチできます。 .. Exceptions explicitly raised or re-raised will always be generated. 明示的に送出されたか、もしくは再送出された例外は常に生成されます。 .. PyPy is debuggable on top of CPython PyPy は CPython のトップレベルでデバッグできます ------------------------------------------------ .. PyPy has the advantage that it is runnable on standard .. CPython. That means, we can run all of PyPy with all exception .. handling enabled, so we might catch cases where we failed to .. adhere to our implicit assertions. PyPy は標準的な CPython で実行できるという利点があります。 それが意味することは、PyPy を全ての例外ハンドラを有効にして実行できるということです。 そのため、暗黙のアサーションに準拠してキャッチする可能性があります。 .. .. _`wrapping rules` .. _`ラッピングのルール`: .. _`ラップされた`: ラッピングルール ================ ラッピング ---------- .. PyPy is made of Python source code at two levels: there is on the one hand .. *application-level code* that looks like normal Python code, and that .. implements some functionalities as one would expect from Python code (e.g. one .. can give a pure Python implementation of some built-in functions like .. ``zip()``). There is also *interpreter-level code* for the functionalities .. that must more directly manipulate interpreter data and objects (e.g. the main .. loop of the interpreter, and the various object spaces). PyPy は 2つのレベルの Python ソースコードからできています。 片方は *アプリケーションレベルのコード* です。 これは Python コードからは期待通りの機能を果たすようものをいくつか実装していて、通常の Python コードのように見えます(例: ビルトイン関数の ``zip()`` と同じものの Pure Python の実装)。 もうひとつは *インタプリタレベルのコード* です。 これはインタプリタのデータとオブジェクトを直接操作する必要があるような機能です(例: インタプリタのメインループや様々なオブジェクトスペース)。 .. Application-level code doesn't see object spaces explicitly: it runs using an .. object space to support the objects it manipulates, but this is implicit. .. There is no need for particular conventions for application-level code. The .. sequel is only about interpreter-level code. (Ideally, no application-level .. variable should be called ``space`` or ``w_xxx`` to avoid confusion.) アプリケーションレベルのコードはオブジェクトスペースを明示的に参照することはありません。 オブジェクト操作のサポートのためにオブジェクトスペースを使って実行しますが、これは暗黙的に行われます。 アプリケーションレベルのコードでは特定の規則のための必要はありません。 続編についてはインタプリタレベルのコードのみです。(理想的には、混乱を避けるためにアプリケーションレベルのコードが ``space`` や ``w_xxx`` を呼び出す必要がないようにするべきです) .. XXX 下二行なんか変 .. The ``w_`` prefixes so lavishly used in the example above indicate, .. by PyPy coding convention, that we are dealing with *wrapped* (or *boxed*) objects, .. that is, interpreter-level objects which the object space constructs .. to implement corresponding application-level objects. Each object .. space supplies ``wrap``, ``unwrap``, ``int_w``, ``interpclass_w``, .. etc. operations that move between the two levels for objects of simple .. built-in types; each object space also implements other Python types .. with suitable interpreter-level classes with some amount of internal .. structure. 上記で示した例では ``w_`` というプレフィクスはとてもふんだんに使われています。 アプリケーションオブジェクトに対応したインタプリタレベルオブジェクトの実装のためにオブジェクトスペースを構築します。 そして、その実装は PyPy のコーディング規則によって、 *ラップされた* (もしくは *ボックス化された*) オブジェクトを使うことで対処しています。 オブジェクトスペースごとに ``wrap``, ``unwrap``, ``int_w``, ``interpclass_w`` などの単純なビルトイン型オブジェクトが二つのレベルの間を行き来するためのオペレーションを提供しています。 オブジェクトスペースごとに、いくつかの内部構造を持つ適切なインタプリタレベルのクラスなどの他の Python の型も実装しています。 .. For example, an application-level Python ``list`` .. is implemented by the `standard object space`_ as an .. instance of ``W_ListObject``, which has an instance attribute .. ``wrappeditems`` (an interpreter-level list which contains the .. application-level list's items as wrapped objects). .. The rules are described in more details below. 例えば、アプリケーションレベルの Python の ``list`` は `標準オブジェクトスペース`_ では ``wrappeditems`` という属性を持った ``W_ListObject`` のインスタンス (ラップされたオブジェクトとしてアプリケーションレベルのリストのアイテムを含むインタプリタレベルのリスト) として実装されています。 このルールの詳細は下記で説明します。 .. Naming conventions 名前付の規則 ------------ .. * ``space``: the object space is only visible at .. interpreter-level code, where it is by convention passed around by the name .. ``space``. * ``スペース``: オブジェクトスペースはインタプリタレベルのコードにおいてのみ見えます。これは ``space`` という名前にる受け渡しが行われることになっています。 .. * ``w_xxx``: any object seen by application-level code is an .. object explicitly managed by the object space. From the .. interpreter-level point of view, this is called a *wrapped* .. object. The ``w_`` prefix is used for any type of .. application-level object. * ``w_xxx``: アプリケーションレベルコードから見えるどんなオブジェクトであっても、オブジェクトスペースによって明示的に管理されます。 インタプリタレベルの観点から、これは *ラップされた* オブジェクトと呼ばれます。 ``w_`` のプリフィクスはどんなタイプのアプリケーションレベルのオブジェクトに対しても使われます。 .. * ``xxx_w``: an interpreter-level container for wrapped .. objects, for example a list or a dict containing wrapped .. objects. Not to be confused with a wrapped object that .. would be a list or a dict: these are normal wrapped objects, .. so they use the ``w_`` prefix. * ``xxx_w``: ラップされたオブジェクトのためのインタプリタレベルのコンテナです。list や dict などがラップされたオブジェクトの例です。list や dict とラップされたオブジェクトを混同しないようにしてください。それらは通常のラップされたオブジェクトで、 ``w_`` のプリフィクスが使われています。 .. Operations on ``w_xxx`` ``w_xxx`` の操作 ---------------- .. The core bytecode interpreter considers wrapped objects as black boxes. .. It is not allowed to inspect them directly. The allowed .. operations are all implemented on the object space: they are .. called ``space.xxx()``, where ``xxx`` is a standard operation .. name (``add``, ``getattr``, ``call``, ``eq``...). They are documented in the .. `object space document`_. コアのバイトコードインタプリタはラップされたオブジェクトをブラックボックスとして扱います。 ブラックボックスの中を直接検査することは許されていません。許可された操作は全てオブジェクトスペースに実装されています。 それらは ``space.xxx()``` と呼ばれます。 ``xxx`` は標準的な操作の名前です( ``add``, ``getattr``, ``call``, ``eq`` ...)。 オペレーションは `オブジェクトスペースのドキュメント`_ に記載されています。 .. A short warning: **don't do** ``w_x == w_y`` or ``w_x is w_y``! .. rationale for this rule is that there is no reason that two .. wrappers are related in any way even if they contain what .. looks like the same object at application-level. To check .. for equality, use ``space.is_true(space.eq(w_x, w_y))`` or .. even better the short-cut ``space.eq_w(w_x, w_y)`` returning .. directly a interpreter-level bool. To check for identity, .. use ``space.is_true(space.is_(w_x, w_y))`` or better .. ``space.is_w(w_x, w_y)``. **don't do** ``w_x == w_y`` or ``w_x is w_y`` という短い警告がでます! 上記ルールのが存在するため、たとえアプリケーションレベルで同じオブジェクトを含むとしても、二つのラップされたオブジェクトが関連している理由にはなりません。 同値性をチェックするには、 ``space.is_true(space.eq(w_x, w_y))`` もしくはよりよいショートカットである ``space.eq_w(w_x, w_y)`` が返すインタプリタレベルのブール値を使います。 同一性をチェックするには ``space.is_true(space.is_(w_x, w_y))`` もしくはより短い ``space.is_w(w_x, w_y)`` を使います。 .. _`オブジェクトスペースのドキュメント`: objspace.html#interface .. _`アプリケーションレベルの例外`: .. Application-level exceptions アプリケーションレベルの例外 ---------------------------- .. Interpreter-level code can use exceptions freely. However, .. all application-level exceptions are represented as an .. ``OperationError`` at interpreter-level. In other words, all .. exceptions that are potentially visible at application-level .. are internally an ``OperationError``. This is the case of all .. errors reported by the object space operations .. (``space.add()`` etc.). インタプリタレベルのコードは自由に例外を使えます。 ただし、全てのアプリケーションレベルの例外はインタプリタレベルでは ``OperationError`` として扱われます。 別の言い方をすると、アプリケーショレベルで発生する可能性のある全ての例外は、内部的には ``OperationError`` です。 オブジェクトスペースの操作によって報告される全てのエラーがこのように扱われます。 .. To raise an application-level exception アプリケーションレベルの例外を発生させる:: raise OperationError(space.w_XxxError, space.wrap("message")) .. To catch a specific application-level exception 特定のアプリケーションレベルの例外をキャッチする:: try: ... except OperationError, e: if not e.match(space, space.w_XxxError): raise ... .. This construct catches all application-level exceptions, so we .. have to match it against the particular ``w_XxxError`` we are .. interested in and re-raise other exceptions. The exception .. instance ``e`` holds two attributes that you can inspect: .. ``e.w_type`` and ``e.w_value``. Do not use ``e.w_type`` to .. match an exception, as this will miss exceptions that are .. instances of subclasses. これは、全てのアプリケーションレベルの例外をキャッチするようにしています。 そして、再度特定の処理したい例外とマッチするかどうかをチェックし ``w_XxxError`` 、そうでなければ再度例外を送出しなければいけません。 例外のインスタンス ``e`` は ``e.w_type`` と ``e.w_value`` という名前でアクセスできる二つの属性を持ちます。 ``e.w_type`` を例外のマッチに使わないでください。この方法だと、処理対象の例外のサブクラスのインスタンスが送出された場合にマッチに失敗してしまいます。 .. _`モジュール`: .. Modules in PyPy PyPy におけるモジュール ======================= .. Modules visible from application programs are imported from .. interpreter or application level files. PyPy reuses almost all python .. modules of CPython's standard library, currently from version 2.7.1. We .. sometimes need to `modify modules`_ and - more often - regression tests .. because they rely on implementation details of CPython. アプリケーションプログラムから見えるモジュールは、インタプリタからインポートされたものかアプリケーションレベルのファイルです。 PyPy は CPython 標準ライブラリの殆ど全てのモジュールを再利用します。現在はバージョン 2.7.1 から使っています。 時々 `変更したモジュール`_ と - 多くの - 回帰テストが必要になります。それらは CPython の実装の詳細に依存しているためです。 .. If we don't just modify an original CPython module but need to rewrite .. it from scratch we put it into `lib_pypy/`_ as a pure application level .. module. オリジナルの CPython モジュールの変更にとどまらず、フルスクラッチで書き直した場合は、 `lib_pypy/`_ が実際のアプリケーションレベルのモジュールです。 .. When we need access to interpreter-level objects we put the module into .. `pypy/module`_. Such modules use a `mixed module mechanism`_ .. which makes it convenient to use both interpreter- and application-level parts .. for the implementation. Note that there is no extra facility for .. pure-interpreter level modules, you just write a mixed module and leave the .. application-level part empty. インタプリタレベルのオブジェクトへのアクセスが必要なときは、モジュールを `pypy/module`_ に置いています。 ここにあるモジュールは `混合モジュール機構`_ を使用しています。 これは、インタプリタレベルとアプリケーションレベルの両方のパーツを使って実装する際に便利です。 純粋なインタプリタレベルのモジュールのための余分な機能はありません。 混合モジュールを書くだけで、アプリケーションレベルの部分はありません。 .. Determining the location of a module implementation モジュールを実装する場所を決定する ---------------------------------- .. You can interactively find out where a module comes from, when running py.py. .. here are examples for the possible locations py.py の実行中に、モジュールがどこから来たものなのかを対話的に見つけられます:: >>>> import sys >>>> sys.__file__ '/home/hpk/pypy-dist/pypy/module/sys' >>>> import cPickle >>>> cPickle.__file__ '/home/hpk/pypy-dist/lib_pypy/cPickle..py' >>>> import opcode >>>> opcode.__file__ '/home/hpk/pypy-dist/lib-python/modified-2.7/opcode.py' >>>> import os >>>> os.__file__ '/home/hpk/pypy-dist/lib-python/2.7/os.py' >>>> .. Module directories / Import order モジュールディレクトリ / インポート順 ------------------------------------- .. Here is the order in which PyPy looks up Python modules: ここでは、PyPy が Python モジュールを探す順番について話します: *pypy/modules* .. mixed interpreter/app-level builtin modules, such as .. the ``sys`` and ``__builtin__`` module. インタプリタ/アプリケーションレベルが混合された ``sys`` や ``__builtin__`` などの組み込みモジュールです。 *PYTHONPATH の中身* .. lookup application level modules in each of the ``:`` separated .. list of directories, specified in the ``PYTHONPATH`` environment .. variable. ``PYTHONPATH`` 環境変数で指定された ``:`` で区切ったディレクトリのリストで、それぞれのディレクトリからアプリケーションレベルモジュールを探します。 *lib_pypy/* .. contains pure Python reimplementation of modules. Python のみで再実装されたモジュールがあります。 *lib-python/modified-2.7/* .. The files and tests that we have modified from the CPython library. CPython から書き換えなければならなかったファイルとテストです。 *lib-python/2.7/* .. The unmodified CPython library. **Never ever check anything in there**. 変更していない CPython ライブラリです。 **ここにあるものはチェックしていません** (**Never ever check anything in there** って合ってる?) .. _`変更したモジュール`: .. Modifying a CPython library module or regression test CPython 標準モジュールと回帰テストの変更 ---------------------------------------- .. Although PyPy is very compatible with CPython we sometimes need .. to change modules contained in our copy of the standard library, .. often due to the fact that PyPy works with all new-style classes .. by default and CPython has a number of places where it relies .. on some classes being old-style. PyPy は CPython とても互換性がありますが、時々コピーした標準ライブラリを変更する必要があります。 多くの場合、 PyPy はデフォルトでは全て新スタイルクラスとして動作しますが、いくつかの場所で CPython は旧スタイルクラスの挙動に依存しているために発生します。 .. If you want to change a module or test contained in ``lib-python/2.7`` .. then make sure that you copy the file to our ``lib-python/modified-2.7`` .. directory first. In mercurial commandline terms this reads もし ``lib-python/2.7`` に含まれるモジュールとテストを変更する場合は、まず ``lib-python/modified-2.7`` ディレクトリにコピーしてください。 Mercurial のコマンドラインでは以下のコマンドで行います:: $ hg cp lib-python/2.7/somemodule.py lib-python/modified-2.7/ .. and subsequently you edit and commit .. ``lib-python/modified-2.7/somemodule.py``. This copying operation is .. important because it keeps the original CPython tree clean and makes it .. obvious what we had to change. その後、 ``lib-python/modified-2.7/somemodule.py`` を編集してコミットします。 オリジナルの CPython ツリーをクリーンに保ち、何を変更したかを明確にするために、このコピーの操作は重要です。 .. _`混合モジュール機構`: .. _`混合モジュール`: .. Implementing a mixed interpreter/application level Module インタプリタ/アプリケーションレベルを混合したモジュールの実装 ------------------------------------------------------------- .. If a module needs to access PyPy's interpreter level .. then it is implemented as a mixed module. モジュールが PyPy のインタプリタレベルにアクセスする必要がある場合、混合モジュールとして実装します。 .. Mixed modules are directories in `pypy/module`_ with an `__init__.py` .. file containing specifications where each name in a module comes from. .. Only specified names will be exported to a Mixed Module's applevel .. namespace. 混合モジュールは `pypy/module`_ にあるディレクトリで、 `__init__.py` を含まなければいけません。 指定した名前のみ混合モジュールの名前空間としてエクスポートされます。 .. Sometimes it is necessary to really write some functions in C (or .. whatever target language). See `rffi`_ and `external functions .. documentation`_ for details. The latter approach is cumbersome and .. being phased out and former has currently quite a few rough edges. 混合モジュールは、時々いくつかの関数を C (もしくはターゲットの言語)で書くために必要です。 詳細は `rffi`_ と `外部関数のドキュメント`_ を見てください。 後者のアプローチは面倒で、段階的に廃止され、今は少しのエッジのみ残っています。 .. _`rffi`: rffi.html .. _`外部関数のドキュメント`: translation.html#extfunccalls .. application level definitions アプリケーションレベルの定義 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. Application level specifications are found in the `appleveldefs` .. dictionary found in ``__init__.py`` files of directories in ``pypy/module``. .. For example, in `pypy/module/__builtin__/__init__.py`_ you find the following .. entry specifying where ``__builtin__.locals`` comes from アプリケーションレベルの定義は ``pypy/module`` にあるディレクトリの中の ``__init__.py`` ファイルにある ``appleveldefs`` です。 例えば、 `pypy/module/__builtin__/__init__.py`_ の中に以下のような ``__builtin__.locals`` の指定があります:: ... 'locals' : 'app_inspect.locals', ... .. The ``app_`` prefix indicates that the submodule ``app_inspect`` is .. interpreted at application level and the wrapped function value for ``locals`` .. will be extracted accordingly. ``app_`` プレフィクスは ``app_inspect`` サブモジュールとして解釈され、アプリケーションレベルでラップされた ``locals`` 関数はそれに従って抽出されます。 .. interpreter level definitions インタプリタレベルの定義 ~~~~~~~~~~~~~~~~~~~~~~~~ .. Interpreter level specifications are found in the ``interpleveldefs`` .. dictionary found in ``__init__.py`` files of directories in ``pypy/module``. .. For example, in `pypy/module/__builtin__/__init__.py`_ the following .. entry specifies where ``__builtin__.len`` comes from インタプリタレベルの定義は ``pypy/module`` にあるディレクトリの中の ``__init__.py`` ファイルにある ``interpleveldefs`` です。 例えば、 `pypy/module/__builtin__/__init__.py`_ の中に以下のような ``__builtin__.len`` の定義があります:: ... 'len' : 'operation.len', ... .. The ``operation`` submodule lives at interpreter level and ``len`` .. is expected to be exposable to application level. Here is .. the definition for ``operation.len()`` ``operation`` サブモジュールはインタプリタレベルのもので、 ``len`` はアプリケーションレベルにエクスポートできると予想されます。これは、 ``operation.len()`` の定義です:: def len(space, w_obj): "len(object) -> integer\n\nReturn the number of items of a sequence or mapping." return space.len(w_obj) .. Exposed interpreter level functions usually take a ``space`` argument .. and some wrapped values (see `wrapping rules`_) . 公開されるインタプリタレベル関数は、通常 ``space`` といくつかのラップされた値を引数として受け取ります。 (`ラッピングのルール`_ 参照) .. You can also use a convenient shortcut in ``interpleveldefs`` dictionaries: .. namely an expression in parentheses to specify an interpreter level .. expression directly (instead of pulling it indirectly from a file) ``interpleveldefs`` 辞書にある便利なショートカットも使えます。 すなわち、括弧の中では(ファイルから直接取ってくる代わりに)直接インタプリタレベルの式を書けます:: ... 'None' : '(space.w_None)', 'False' : '(space.w_False)', ... .. The interpreter level expression has a ``space`` binding when .. it is executed. インタプリタレベルの式は実行する際に ``space`` を束縛します。 .. Adding an entry under pypy/module (e.g. mymodule) entails automatic .. creation of a new config option (such as --withmod-mymodule and .. --withoutmod-mymodule (the later being the default)) for py.py and .. translate.py. pypy/module にエントリを追加する (例えば mymodule など) と、自動的に py.py と translate.py に新しいコンフィグオブションが作られ (--withmod-mymod と --withoutmod-mymodule のようなものです (デフォルトは後者)) ます。 .. Testing modules in ``lib_pypy/`` ``lib_pypy/`` にあるモジュールのテスト -------------------------------------- .. You can go to the `lib_pypy/pypy_test/`_ directory and invoke the testing tool .. ("py.test" or "python ../../pypy/test_all.py") to run tests against the .. lib_pypy hierarchy. Note, that tests in `lib_pypy/pypy_test/`_ are allowed .. and encouraged to let their tests run at interpreter level although .. `lib_pypy/`_ modules eventually live at PyPy's application level. .. This allows us to quickly test our python-coded reimplementations .. against CPython. `lib_pypy/pypy_test/`_ ディレクトリに移動して、 lib_pypy ディレクトリツリーに対するテストを走らせるためにテストツールを実行できます。("py.test" か "python ../../pypy/test_all.py" などです) 註 `lib_pypy/pypy_test/`_ はそれらのテストをインタプリタレベルで走らせることが許可され、推奨されていますが、 `lib_pypy/`_ のモジュール群は最終的に PyPy のアプリケーションレベルで動きます。 これにより、CPython に比べて私たちの Python コードでの再実装の素早いテストが可能になります。 .. Testing modules in ``pypy/module`` ``pypy/module`` にあるモジュールのテスト ---------------------------------------- .. Simply change to ``pypy/module`` or to a subdirectory and `run the .. tests as usual`_. ``pypy/module`` とそのサブディレクトリに変更を加えた場合は、単純に `いつものテストを実行します`_ 。 .. Testing modules in ``lib-python`` ``lib-python`` にあるモジュールのテスト --------------------------------------- .. In order to let CPython's regression tests run against PyPy .. you can switch to the `lib-python/`_ directory and run .. the testing tool in order to start compliance tests. .. (XXX check windows compatibility for producing test reports). CPython の回帰テストを PyPy に対して実行するために、 `lib-python/`_ ディレクトリに切り替え、互換性テストのためのテストツールを実行します。(XXX テストレポート生成のための Windows の互換性の検査) .. Naming conventions and directory layout 命名規則とディレクトリ構成 ========================== .. Directory and File Naming ディレクトリとファイルの命名 ---------------------------- .. - directories/modules/namespaces are always **lowercase** - ディレクトリ/モジュール/名前空間はすべて **小文字** .. - never use plural names in directory and file names - ディレクトリとファイルの名前に複数形は使わない .. - ``__init__.py`` is usually empty except for .. ``pypy/objspace/*`` and ``pypy/module/*/__init__.py``. - ``__init__.py`` は通常空だが、 ``pypy/objspace/\*`` と ``pypy/module/\*/__init__.py`` は例外 .. - don't use more than 4 directory nesting levels - 四階層以上のディレクトリ構成を作らない .. - keep filenames concise and completion-friendly. - ファイル名簡潔で容易にわかるようにする .. Naming of python objects Python オブジェクトの命名 ------------------------- .. - class names are **CamelCase** - クラス名は **CamelCase** (キャメルケース/ラクダ記法) .. - functions/methods are lowercase and ``_`` separated - 関数名/メソッド名は小文字を ``_`` で区切ったもの (snake case/スネークケース) .. - objectspace classes are spelled ``XyzObjSpace``. e.g. .. - StdObjSpace .. - FlowObjSpace - オブジェクトスペースのクラスは ``XyzObjSpace`` のように綴る。 例: - StdObjSpace - FlowObjSpace .. - at interpreter level and in ObjSpace all boxed values .. have a leading ``w_`` to indicate "wrapped values". This .. includes w_self. Don't use ``w_`` in application level .. python only code. - インタプリタレベルと ObjSpace に含まれる全てのボックス化された値は、"ラップされた値" を示す ``w_`` で始まる これには w_self も含まれる。 ``w_`` をアプリケーションレベルの Python でのみ使われるコードに使ってはいけない。 .. Committing & Branching to the repository リポジトリのコミットとブランチ ------------------------------ .. - write good log messages because several people .. are reading the diffs. - 何人かは diff を読んでいるので分かりやすいコミットログメッセージを書くこと。 .. - What was previously called ``trunk`` is called the ``default`` branch in .. mercurial. Branches in mercurial are always pushed together with the rest .. of the repository. To create a ``try1`` branch (assuming that a branch named .. ``try1`` doesn't already exists) you should do .. hg branch try1 .. The branch will be recorded in the repository only after a commit. To switch .. back to the default branch .. hg update default .. For further details use the help or refer to the `official wiki`_ .. hg help branch - 以前は ``trunk`` と呼ばれていたものは Mercurial では ``default`` ブランチと呼ばれる。 Mercurial のブランチはいつもリポジトリの他の部分と一緒に push される (``try1`` というブランチが存在しないと仮定すると) ``try1`` というブランチを作るには以下のようにする:: hg branch try1 コミットするとブランチはリポジトリに保存される。 default ブランチに戻るには以下の操作を行う:: hg update default さらに詳細を知りたい場合は help を使うか `オフィシャル wiki`_ を参照する .. _`オフィシャル wiki`: http://mercurial.selenic.com/wiki/Branch .. _`開発トラッカーを使う`: .. Using the development bug/feature tracker 開発のバグ/機能要望トラッカーを使う =================================== .. We have a `development tracker`_, based on Richard Jones' .. `roundup`_ application. You can file bugs, .. feature requests or see what's going on .. for the next milestone, both from an E-Mail and from a .. web interface. Richard Jones の `roundup`_ というアプリケーションをベースにした `開発トラッカー`_ を運用しています。 バグや機能要望を登録したり、次のマイルストーンのためにになにが行われているかを電子メールと Web インタフェイスから参照できます。 .. _`開発トラッカー`: https://codespeak.net/issue/pypy-dev/ .. use your codespeak login or register codespeak へのログインと登録 ---------------------------- .. If you have an existing codespeak account, you can use it to login within the .. tracker. Else, you can `register with the tracker`_ easily. codespeak のアカウントを持っていれば、トラッカーへのログインに使用できます。 もし持っていなければ簡単に `トラッカーを使って登録`_ できます。 .. _`トラッカーを使って登録`: https://codespeak.net/issue/pypy-dev/user?@template=register .. _`roundup`: http://roundup.sourceforge.net/ .. _`testing in PyPy`: .. _`test-design`: .. Testing in PyPy PyPy のテスト ============= .. Our tests are based on the `py.test`_ tool which lets you write .. unittests without boilerplate. All tests of modules .. in a directory usually reside in a subdirectory **test**. There are .. basically two types of unit tests: テストは、定型句なしに unittest が書ける `py.test`_ ツールをベースにしています。 ディレクトリに含まれる全てのモジュールのテストは、通常 **test** というサブディレクトリに存在します。 そこには基本的な二つのタイプの単体テストがあります。 .. - **Interpreter Level tests**. They run at the same level as PyPy's .. interpreter. - **インタプリタレベルのテスト**: PyPy のインタプリタと同じレベルで実行されます。 .. - **Application Level tests**. They run at application level which means .. that they look like straight python code but they are interpreted by PyPy. - **アプリケーションレベルのテスト**: アプリケーションレベルで実行されます。ただの Python コードのように見えますが、 PyPy によって解釈・実行されます。 .. _`標準オブジェクトスペース`: objspace.html#standard-object-space .. _`オブジェクトスペース`: objspace.html .. _`py.test`: http://pytest.org/ .. Interpreter level tests インタプリタレベルのテスト -------------------------- .. You can write test functions and methods like this .. def test_something(space): .. # use space ... .. class TestSomething(object): .. def test_some(self): .. # use 'self.space' here テスト関数は以下のように書きます:: def test_something(space): # space を使ったテスト ... class TestSomething(object): def test_some(self): # self.space を使ったテスト .. Note that the prefix `test` for test functions and `Test` for test .. classes is mandatory. In both cases you can import Python modules at .. module global level and use plain 'assert' statements thanks to the .. usage of the `py.test`_ tool. テストに使う関数の名前の `test` プレフィクスと、テストに使うクラスの名前に `Test` が含まれていることは必須です。 どちらのケースでも Python モジュールはモジュールグローバルレベルでインポートでき、普通の 'assert' 文は `py.test`_ ツールのおかげで使えます。 .. Application Level tests アプリケーションレベルのテスト ------------------------------ .. For testing the conformance and well-behavedness of PyPy it .. is often sufficient to write "normal" application-level .. Python code that doesn't need to be aware of any particular .. coding style or restrictions. If we have a choice we often .. use application level tests which usually look like this .. def app_test_something(): .. # application level test code .. class AppTestSomething(object): .. def test_this(self): .. # application level test code PyPy の適合性と振る舞いの適切さのテストのためには、特定のコーディングスタイルや制限に注意する必要のない "普通の" アプリケーションレベルの Python コードを書けば、多くの場合は十分です。 アプリケーションレベルのテストを選択するなら、通常は以下のようなものになります:: def app_test_something(): # アプリケーションレベルのテストコード class AppTestSomething(object): def test_this(self): # アプリケーションレベルのテストコード .. These application level test functions will run on top .. of PyPy, i.e. they have no access to interpreter details. .. You cannot use imported modules from global level because .. they are imported at interpreter-level while you test code .. runs at application level. If you need to use modules .. you have to import them within the test function. それらのアプリケーションレベルのテスト関数は、 PyPy のトップレベルで実行されます。 すなわち、インタプリタレベルの詳細にアクセスできないということです。 グローバルレベルでインポートしたモジュールは使えません。 それらのモジュールはインタプリタレベルでインポートされたもので、テストコードはアプリケーションレベルで実行されるためです。 モジュールを使う場合は、テスト関数の中でインポートしてください。 .. Another possibility to pass in data into the AppTest is to use .. the ``setup_class`` method of the AppTest. All wrapped objects that are .. attached to the class there and start with ``w_`` can be accessed .. via self (but without the ``w_``) in the actual test method. An example .. class AppTestErrno(object): .. def setup_class(cls): .. cls.w_d = cls.space.wrap({"a": 1, "b", 2}) .. def test_dict(self): .. assert self.d["a"] == 1 .. assert self.d["b"] == 2 AppTest の中にデータを受け渡す別の可能性は、 AppTest クラスの ``setup_class`` メソッドを使うことです。 ``w_`` で始まる全てのラップされたオブジェクトは、self を介して (``w_`` の前置なしで) 実際のテストメソッドの中からアクセスできます。 例:: class AppTestErrno(object): def setup_class(cls): cls.w_d = cls.space.wrap({"a": 1, "b", 2}) def test_dict(self): assert self.d["a"] == 1 assert self.d["b"] == 2 .. _`いつものテストを実行します`: .. Command line tool test_all コマンドラインツール: test_all ------------------------------ .. You can run almost all of PyPy's tests by invoking .. python test_all.py file_or_directory PyPy のほとんどすべてのテストを呼び出し、実行できます:: python test_all.py file_or_directory which is a synonym for the general `py.test`_ utility located in the ``py/bin/`` directory. For switches to modify test execution pass the ``-h`` option. これは ``py/bin/`` ディレクトリにある `py.test` ユーティリティの別名です。 ``-h`` オプションを渡すことでテストの実行を切り替えます。 カバレッジのレポート -------------------- .. In order to get coverage reports the `pytest-cov`_ plugin is included. .. it adds some extra requirements ( coverage_ and `cov-core`_ ) .. and can once they are installed coverage testing can be invoked via .. python test_all.py --cov file_or_direcory_to_cover file_or_directory カバレッジポートを取得するために、 `pytest-cov`_ プラグインが含まれています。 いくつかの追加モジュール (`coverage`_ と `cov-core`_) と、 カバレッジテストを一度にインストールするには以下のコマンドを実行します:: python test_all.py --cov file_or_direcory_to_cover file_or_directory .. _`pytest-cov`: http://pypi.python.org/pypi/pytest-cov .. _`coverage`: http://pypi.python.org/pypi/coverage .. _`cov-core`: http://pypi.python.org/pypi/cov-core .. Test conventions 規則のテスト ------------ .. - adding features requires adding appropriate tests. (It often even .. makes sense to first write the tests so that you are sure that they .. actually can fail.) - 機能を追加するためには、適切なテストを追加する必要があります。 (失敗できるように最初にテストを書くことは、多くの場合理に適っています。) .. - All over the pypy source code there are test/ directories .. which contain unit tests. Such scripts can usually be executed .. directly or are collectively run by pypy/test_all.py - 全ての PyPy のソースコードのには、単体テストが含まれる test/ ディレクトリがあります。 このようなスクリプトは通常直接実行できるか pypy/test_all.py の実行によって実行されます。 .. _`change documentation and website`: .. Changing documentation and website ドキュメントとウェブサイトの変更 ================================ .. documentation/website files in your local checkout ドキュメント/ウェブサイトのファイルはローカルリポジトリに含まれます ------------------------------------------------------------------- .. Most of the PyPy's documentation is kept in `pypy/doc`. .. You can simply edit or add '.rst' files which contain ReST-markuped .. files. Here is a `ReST quickstart`_ but you can also just look .. at the existing documentation and see how things work. ほとんどの PyPy のドキュメントは `pypy/doc` にあります。 単純に ReST でマークアップされた '.rst' ファイルを編集したり追加したりできます。 ここは `ReST クイックスタート`_ ですが、単に既に存在するドキュメントを見て、どのように動いているかを見られます。 .. _`ReST クイックスタート`: http://docutils.sourceforge.net/docs/user/rst/quickref.html .. Note that the web site of http://pypy.org/ is maintained separately. .. For now it is in the repository https://bitbucket.org/pypy/pypy.org http://pypy.org/ のウェブサイトは個別に管理されています。 今は https://bitbucket.org/pypy/pypy.org のリポジトリに存在します。 .. Automatically test documentation/website changes ドキュメント/ウェブサイトの変更の自動テスト ------------------------------------------- .. _`sphinx home page`: .. _`sphinx`: http://sphinx.pocoo.org/ .. We automatically check referential integrity and ReST-conformance. In order to .. run the tests you need sphinx_ installed. Then go to the local checkout .. of the documentation directory and run the Makefile .. cd pypy/doc .. make html 自動で参照の整合性と ReST の適合性のテストをしています。 テストの実行のためには `sphinx`_ のインストールが必要です。 インストール後、ローカルにチェックアウトしたリポジトリのドキュメントディレクトリにに移動し、 Makefile を走らせます:: cd pypy/doc make html .. If you see no failures chances are high that your modifications at least .. don't produce ReST-errors or wrong local references. Now you will have `.html` .. files in the documentation directory which you can point your browser to! 変更した後にエラーメッセージが出ていない場合、少なくとも ReST のエラーなないことと無効なローカル参照がないという可能性が高いです。 ドキュメントディレクトリに `.html` ファイルがありブラウザで開けます。 .. Additionally, if you also want to check for remote references inside .. the documentation issue .. make linkcheck さらに、 ドキュメント中の外部リファレンスをチェックしたいのであれば:: make linkcheck .. which will check that remote URLs are reachable. とすることで外部の URL が生きているかのチェックができます。 .. include:: _ref.txt