[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