[pypy-svn] rev 2675 - pypy/trunk/doc
alex at codespeak.net
alex at codespeak.net
Mon Dec 22 16:43:37 CET 2003
Author: alex
Date: Mon Dec 22 16:43:36 2003
New Revision: 2675
Modified:
pypy/trunk/doc/architecture.txt
Log:
several more minor edits (typo fixes &c).
Modified: pypy/trunk/doc/architecture.txt
==============================================================================
--- pypy/trunk/doc/architecture.txt (original)
+++ pypy/trunk/doc/architecture.txt Mon Dec 22 16:43:36 2003
@@ -6,8 +6,8 @@
basic architecture remains rather simple and unchanged: a plain
*interpreter* reads and dispatches *bytecodes*, shuffling objects around
on the stack and between namespaces of which it knows almost nothing.
-For any operation on an object, the interpreter delegates to an
-so-called "Object Space", which performs modifications, creation and
+For any operation on an object, the interpreter delegates to a so-called
+"Object Space", which performs creation, modification, access, and
destruction of objects. Such objects are often refered to as
*application-level objects*, because they are the objects you naturally
work with from a python program.
@@ -15,7 +15,7 @@
The Interpreter
===============
-The interpreter handles python code objects. The interpreter can built
+The interpreter handles python code objects. The interpreter can build
code objects from Python sources, when needed, by invoking Python's
builtin compiler (we also have a way of constructing those code objects
from python code only, but we have not integrated it yet). Code objects
@@ -89,11 +89,12 @@
intimpl)`` and ``add(floatimpl, floatimpl)``, *register* with that one
``add`` multimethod.
-When in our application program we have the expression ``2+3``, the
-interpreter creates an application-level object containing the value
-``2`` and one containing the value ``3``. We talk about them as
-``W_Int(2)`` and ``W_Int(3)`` respectively. The interpreter then calls
-the Standard Object Space with ``add(W_Int(2), W_Int(3))``.
+When we have the expression ``2+3`` in our application program, the
+interpreter creates an application-level object containing ("wrapping")
+the value ``2`` and another one containing the value ``3``. We talk
+about them as ``W_Int(2)`` and ``W_Int(3)`` respectively. The
+interpreter then calls the Standard Object Space with ``add(W_Int(2),
+W_Int(3))``.
The Object Space then examines the objects passed in, and delegates
directly to the ``add(intimpl, intimpl)`` function: since this is a
@@ -136,28 +137,29 @@
our interpreter-level code in Python.
Moreover, in PyPy we have to make a sharp distinction between
-interpreter and application level *exceptions*: application exceptions
+interpreter- and application-level *exceptions*: application exceptions
are always contained inside an instance of ``OperationError``. This
makes it easy to distinguish failures in our interpreter-level code from
-those appearing in a python application level program that we are
+failures appearing in a python application level program that we are
interpreting.
Application level is often preferable
-------------------------------------
-Application-level code is much higher-level, and therefore easier to
-write and debug. For example, suppose we want to implement the
-``update`` method of dict objects. Programming at the application
-level, we can write the obvious, simple implementation, one that looks
-like an **executable definition** of ``update``, for example::
+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::
def update(self, other):
for k in other.keys():
self[k] = other[k]
-If we had to code only at the interpreter level, we would have to
-code something much lower-level and involved, say something like::
+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')
@@ -188,15 +190,15 @@
The ``w_`` prefixes so lavishly used in the previous example indicate,
by PyPy coding convention, that we are dealing with *wrapped* objects,
-that is, objects constructed by the object space at interpreter level to
+that is, interpreter-level objects which the object space constructs to
implement corresponding application-level objects. Each object space
supplies ``wrap`` and ``unwrap`` operations that move between the two
-levels for objects of simple built-in types; other Python types are
-implemented by interpreter-level classes with some amount of internal
-structure.
+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.
For example, an application-level Python ``list`` is implemented as an
-instance of ``W_ListObject```, which has an instance attribute
+instance of ``W_ListObject``, which has an instance attribute
``ob_item`` (an interpreter-level list which contains the
application-level list's items as wrapped objects) and another attribute
``ob_size`` which records the application-level list's length (we want
@@ -210,45 +212,45 @@
RPython, the Flow Object Space and translation
==============================================
-One of PyPy's longer-term objectives is to enable translation of our
+One of PyPy's -term objectives is to enable translation of our
interpreter and standard object space into a lower-level language. In
order for our translation and type inference mechanisms to work
effectively, we need to restrict the dynamism of our interpreter-level
Python code at some point. However, in the start-up phase, we are
-completly free to use all kind of nice python constructs. including
-metaclasses and execution of dynamically constructed strings. When the
-initialization phase (mainly, the function ``objspace.initialize()``)
-finishes, however, all code objects involved need to adhere to a
-(non-formally defined) more static subset of Python: Restricted Python,
-also known as 'RPython'.
+completly free to use all kind of nice python constructs, including
+metaclasses and execution of dynamically constructed strings. However,
+when the initialization phase (mainly, the function
+``objspace.initialize()``) finishes, all code objects involved need to
+adhere to a (non-formally defined) more static subset of Python:
+Restricted Python, also known as 'RPython'.
-The Flow Object Space will then, with the help of our plain interpreter,
-work through those initialized "RPython" code objects. The result of
+The Flow Object Space then, with the help of our plain interpreter,
+works through those initialized "RPython" code objects. The result of
this *abstract interpretation* is a flow graph: yet another
representation of a python program, but one which is suitable for
applying translation and type inference techniques. The nodes of the
-graphs are basic blocks consisting of Object Space operations, flowing
-of values and an exitswitch to one, two or multiple links which connect
-it to other basic blocks.
-
-The flow graphs are fed as input to the Annotator. The Annotator, given
-entry point types, infers the types of values that flow through the
-program variables. Here, one of the informal definitions of RPython
-comes into play: RPython code is restricted in a way that the translator
-can still compile low-level typed code. How much dynamism we allow in
-RPython depends, and is restricted by, the Flow Object Space and the
-Annotator implementation. The more we can improve this translation
-phase, the more dynamism we can allow. In some cases, however, it will
-probably be more feasible and practical to just get rid of some of the
-dynamism we use in our interpreter level code. It is mainly because of
-this trade-off situation that we don't currently try to formally define
-'RPython'.
+graph are basic blocks consisting of Object Space operations, flowing
+of values, and an exitswitch to one, two or multiple links which connect
+each basic block to other basic blocks.
+
+The flow graphs are fed as input into the Annotator. The Annotator,
+given entry point types, infers the types of values that flow through
+the program variables. Here, one of the informal definitions of RPython
+comes into play: RPython code is restricted in such a way that the
+translator is able to compile low-level **typed** code. How much
+dynamism we allow in RPython depends, and is restricted by, the Flow
+Object Space and the Annotator implementation. The more we can improve
+this translation phase, the more dynamism we can allow. In some cases,
+however, it will probably be more feasible and practical to just get rid
+of some of the dynamism we use in our interpreter level code. It is
+mainly because of this trade-off situation that we don't currently try
+to formally define 'RPython'.
The actual low-level code (and, in fact, also other high-level code) is
emitted by "visiting" the type-annotated flow graph. Currently, we have
a Pyrex-producing backend, and a Lisp-producing backend. We use (a
slightly hacked version of) Pyrex to generate C libraries. Since Pyrex
-also accepts plain non-typed python code. we can test translation even
+also accepts plain non-typed python code, we can test translation even
though type annotation is not complete.
Trace Object Space
@@ -265,8 +267,8 @@
There are certainly many more possibly useful Object Space ideas, such
as a ProxySpace that connects to a remote machine where the actual
operations are performed. At the other end, we wouldn't need to change
-object spaces at all if we want to extend or modify the interpreter,
-e.g. by adding or removing some bytecodes. Thus, the interpreter and
+object spaces at all in order to extend or modify the interpreter, e.g.
+by adding or removing some bytecodes. Thus, the interpreter and
object-space cooperation nicely splits the python runtime into two
reasonably-independent halves, cooperating along a reasonably narrow
interface, and suitable for multiple separate implementations.
More information about the Pypy-commit
mailing list