[pypy-svn] rev 913 - pypy/trunk/doc/objspacedoc

anna at codespeak.net anna at codespeak.net
Sun Jun 22 12:30:19 CEST 2003


Author: anna
Date: Sun Jun 22 12:30:19 2003
New Revision: 913

Added:
   pypy/trunk/doc/objspacedoc/
   pypy/trunk/doc/objspacedoc/AbObSp.txt
   pypy/trunk/doc/objspacedoc/AnnotateObSp.txt
   pypy/trunk/doc/objspacedoc/MultiMeth.txt
   pypy/trunk/doc/objspacedoc/ObSpIntfc.txt
   pypy/trunk/doc/objspacedoc/ObjSpc.txt
   pypy/trunk/doc/objspacedoc/RestrictedPython.txt
   pypy/trunk/doc/objspacedoc/StObSp.txt
   pypy/trunk/doc/objspacedoc/TrivObSp.txt
Log:
adding directory

Added: pypy/trunk/doc/objspacedoc/AbObSp.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/doc/objspacedoc/AbObSp.txt	Sun Jun 22 12:30:19 2003
@@ -0,0 +1,16 @@
+=======================
+AbstractObjectSpace
+=======================
+
+User History
+------------------------
+
+This is an example of abstract interpretation, i.e. following the bytecode instructions of a program like an interpreter does but with abstract objects instead of concrete ones. Remember that in PyPy this is done by using alternate object spaces with the same interpreter main loop.
+
+The most abstract object space is the one manipulating the most abstract objects that you could imagine: they are all equivalent, because we have abstracted away any information about the object. There is actually only one of them left, and we can call it "the object". In Python terms, our AbstractObjectSpace uses None for all its wrapped objects. Any operation between wrapped objects gives None again as the wrapped result -- there is nothing else it could give anyway. So when you have said that the add method of AbstractObjectSpace takes None and None and returns None you have said everything.
+
+The point of such an object space is for example to check the bytecode. The interpreter will really run your bytecode, just with completely abstract arguments. If there is no problem then you are sure that the bytecode is valid. You could also record, during this abstract interpretation, how much the stack ever grows; that would give you a fool-proof method of computing the co_stacksize argument of a code object which might be useful for the PyPy compiler. (There are subtleties which I won't describe here, but that's the basic idea.)
+
+Typically, however, abstract object spaces are a (little) bit less abstract, still maintaining a minimal amount of information about the objects. For example, a wrapped object could be represented by its type. You then define the object space's add to return int when the two arguments are int and int. That way, you abstractedly call a function with the input argument's types and what the interpreter will do is a type inference. (Here also there are subtle problems, even besides the remark that integer operations can overflow and actually return longs in a real Python implementation.)
+
+As an example of more abstract object spaces you have the ones with finite domain, i.e. with a finite number of different possible wrapped objects. For example, you can use True and False as wrapped values to denote the fact that the object is, respectively, a non-negative integer or anything else. In this way you are doing another kind of type inference that just tells you which variables will only ever contain non-negative integers.

Added: pypy/trunk/doc/objspacedoc/AnnotateObSp.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/doc/objspacedoc/AnnotateObSp.txt	Sun Jun 22 12:30:19 2003
@@ -0,0 +1,29 @@
+=========================
+Annotated Object Space
+=========================
+
+was TranslateObjectSpace
+-------------------------
+This has been renamed and is currently being re-written. Old information follows:
+
+User History
+------------------
+
+This is an example of an ObjectSpace that differs a lot from StandardObjectSpace_.
+
+At some point in the near future we will have to design a translator from all the RestrictedPython_ code we have into C code. This is the sine qua non condition for our work to be actually usable. Quite unexpectedly, the major piece of the translator is itself an object space, the TranslateObjectSpace. Its goal is to run any RestrictedPython code and produce C code in the background as it does so.
+
+More specifically, we take our PyPy interpreter with the TranslateObjectSpace instead of the StandardObjectSpace, and run that, asking it to interpret some RestrictedPython bytecode. The idea is that a wrapped object is now the name of a variable in the C program we are emitting:
+
+The TranslateObjectSpace's add method takes two such variable names x and y, and emits the C code z=x+y;, where z is a new variable name which is returned as the result of add. So when the interpreter goes along the bytecode, the TranslateObjectSpace will create variable names and emit C code that does just the same thing as the bytecode.
+
+The above description is what would occur if RestrictedPython only had integer data types. We must actually make the wrapped objects a bit more elaborate to also record, besides the C variable name, its basic type. This can be easy, like prefixing the variable name with a type character; for example, add would behave as above if the variable names begin with ``i_`` but differently if they begin with the prefix denoting floats or lists, say.
+
+Once you grasp the idea that this process can actually easily translate any RestrictedPython to C, and if you remember that the interpreter main loop itself is written in RestrictedPython, then you shouldn't be surprised if I say that all we have to do next is run the interpreter to interpret itself (and thus translate itself to C)!
+
+This is again a rough sketch, but it shows why I expect translating RestrictedPython to C to be easy. The RestrictedPython is precisely restricted in such a way that makes the above process work, e.g. we only ever use well-known types and operations that are easy to convert to an efficient C equivalent. (For example, if lists are translated to C arrays, I'm sure Christian would insist on not using '+' between lists in RestrictedPython but rather '+=', which has a more direct translation as realloc() -- although by now he might be convinced that supporting '+' as a bonus isn't going to be any difficult anyway :-) )
+
+------------------------------
+
+.. _StandardObjectSpace: StObSp.html
+.. _RestrictedPython: RestrictedPython.html

Added: pypy/trunk/doc/objspacedoc/MultiMeth.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/doc/objspacedoc/MultiMeth.txt	Sun Jun 22 12:30:19 2003
@@ -0,0 +1,143 @@
+========================
+PyPython MultiMethod
+========================
+
+Notes on Multimethods
+------------------------
+
+Interpreter-level classes correspond to implementations of application-level
+types. Several implementations can be given for the same type (e.g. several
+ways to code strings or dictionaries), and conversely the same implementation
+can cover several types (e.g. all instances of user-defined types currently
+share the same implementation).
+
+The hierarchy among the classes used for the implementations is convenient
+for implementation purposes. It is not related to any application-level type
+hierarchy.
+
+Dispatch
+-------------------
+
+Multimethods dispatch by looking in a set of registered functions. Each
+registered function has a signature, which defines which object implementation
+classes are accepted at the corresponding argument position.
+
+The name 'W_ANY' is a synonym for 'W_Object' (currently, possibly 'object'
+later). As it accepts anything, it is the only way to guarantee that the
+registered function will be called with exactly the same object as was
+passed originally. ATTENTION: in all other cases the argument received by
+the function may have been converted in some way. It must thus not be
+considered to be 'id'entical to the original argument. For example it should
+not be stored in a data structure, nor be queried for type, nor be used for
+another multimethod dispatch -- the only thing you should do is read and
+write its internal data.
+
+For example, 'getattr(obj, attr)' is implemented with a ``W_StringObject`` second
+argument when all it needs is just the name of the attr, and with a W_ANY
+when the 'attr' object could be used as a key in ``obj.__dict__``.
+
+
+Delegation
+---------------
+
+Delegation is a transparent convertion mechanism between object
+implementations. The convertion can give a result of a different type
+(e.g. int -> float) or of the same type (e.g. W_VeryLongString -> str).
+There is a global table of delegators. We should not rely on the delegators
+to be tried in any particlar order, or at all (e.g. the int -> float delegator
+could be ignored when we know that no registered function will accept a float
+anyway).
+
+Delegation is also used to emulate inheritance between built-in types
+(e.g. bool -> int). This is done by delegation because there is no reason
+that a particular implementation of a sub-type can be trivially typecast
+to some other particular implementation of the parent type; the process might
+require some work.
+
+
+Types
+---------
+
+Types are implemented by the class W_TypeObject. This is where inheritance
+and the Method Resolution Order are defined, and where attribute look-ups
+are done.
+
+Instances of user-defined types are implementated as W_UserObjects.
+A user-defined type can inherit from built-in types (maybe more than one,
+although this is incompatible with CPython). The W_UserObject delegator
+converts the object into any of these "parent objects" if needed. This is
+how user-defined types appear to inherit all built-in operator
+implementations.
+
+Delegators should be able to invoke user code; this would let us
+implement special methods like __int__() by calling them within a
+W_UserObject -> int delegator.
+
+Specifics of multimethods
+---------------------------
+
+Multimethods dispatch more-specific-first, left-to-right (i.e. if there is
+an exact match for the first argument it will always be tried first).
+
+Delegators are automatically chained (i.e. A -> B and B -> C would be
+combined to allow for A -> C delegation).
+
+Delegators do not publish the class of the converted object in advance,
+so that the W_UserObject delegator can potentially produce any other
+built-in implementation. This means chaining and chain loop detection cannot
+be done statically (at least without help from an analysis tool like the
+translator-to-C). To break loops, we can assume (unless a particular need
+arises) that delegators are looping when they return an object of an
+already-seen class.
+
+Registration
+--------------------
+
+The register() method of multimethods adds a function to its database of
+functions, with the given signature. A function that raises
+!FailedToImplement causes the next match to be tried.
+
+'delegate' is the special unary multimethod that should try to convert
+its argument to something else. For greater control, it can also return
+a list of 2-tuples (class, object), or an empty list for failure to convert
+the argument to anything. All delegators will potentially be tried, and
+recursively on each other's results to do chaining.
+
+A priority ordering between delegators is used. See ``objspace.PRIORITY_*``.
+
+
+Translation
+-----------------------
+
+The code in multimethod.py is not supposed to be read by the
+translator-to-C. Special optimized code will be generated instead
+(typically some kind of precomputed dispatch tables).
+
+Delegation is special-cased too. Most delegators will be found
+to return an object of a statically known class, which means that
+most of the chaining and loop detection can be done in advance.
+
+
+Multimethod slicing
+------------------------
+
+Multimethods are visible to user code as (bound or unbound) methods
+defined for the corresponding types. (At some point built-in functions
+like len() and the operator.xxx() should really directly map to the
+multimethods themselves, too.)
+
+To build a method from a multimethod (e.g. as in 'l.append' or
+'int.__add__'), the result is actually a "slice" of the whole
+multimethod, i.e. a sub-multimethod in which the registration table has
+been trimmed down. (Delegation mechanisms are not restricted for sliced
+multimethods.)
+
+Say that C is the class the new method is attached to (in the above
+examples, respectively, C=type(l) and C=int). The restriction is
+based on the registered class of the first argument ('self' for the
+new method) in the signature. If this class corresponds to a fixed
+type (as advertized by 'statictype'), and this fixed type is C or a
+superclass of C, then we keep it.
+
+Some multimethods can also be sliced along their second argument,
+e.g. for __radd__().

Added: pypy/trunk/doc/objspacedoc/ObSpIntfc.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/doc/objspacedoc/ObSpIntfc.txt	Sun Jun 22 12:30:19 2003
@@ -0,0 +1,111 @@
+================================
+PyPython ObjectSpaceInterface
+================================
+
+Note this is only a draft version of the ObjectSpace_ interface. The reality of the interface depends on the particular implementation you are using. Consult the code for details.
+
+class ObjSpace
+=================
+
+Data Members
+-----------------
+
++ ObjSpace.MethodTable:
+   List of tuples (method name, symbol, number of arguments) for the regular part of the interface. (Tuples are interpreter level.)
+
++ self.w_builtins
++ self.w_modules
++ self.appfile_helpers
++ self.w_None: The ObjectSpace's None
++ self.w_True: The ObjectSpace's True
++ self.w_False: The ObjectSpace's False
+
+Administrative Functions
+----------------------------
+
+**initialize():**
+  Function which initializes w_builtins and the other w_constants.
+
+**getexecutioncontext():**
+  Return current active execution context.
+
+**gethelper(applicationfile):**
+  Get helper for applicationfile.
+
+Operations on Objects in ObjectSpace
+-----------------------------------------
+
+These functions both take and return "wrapped" objects.
+
+*The following functions implement the same operations as those in CPython:*
+
+``id, type, issubtype, iter, repr, str, len, hash,``
+
+``getattr, setattr, delattr, getitem, setitem, delitem,``
+
+``pos, neg, not_, abs, invert, add, sub, mul, truediv, floordiv, div, mod, divmod, pow, lshift, rshift, and_, or_, xor,``
+
+``lt, le, eq, ne, gt, ge, contains,``
+
+``inplace_add, inplace_sub, inplace_mul, inplace_truediv, inplace_floordiv, inplace_div, inplace_mod, inplace_pow, inplace_lshift, inplace_rshift, inplace_and, inplace_or, inplace_xor``
+
+**next(w):**
+  Call the next function for iterator w.
+
+**call(callable, args, kwds):**
+  Call a function with the given args and keywords.
+
+**is_(w_x, w_y):**
+  Implements 'w_x is w_y'.
+
+**exception_match(w_exc_type, w_check_class):**
+  Checks if the given exception type matches 'w_check_class'. Used in matching the actual exception raised with the list of those to catch in an except clause. Returns a bool.
+
+Creation of Application Level objects
+---------------------------------------
+
+**wrap(x):**
+  Return ObjectSpace equivalent of x.
+
+**newbool(b):**
+  Creates a Bool Object from an interpreter level object.
+
+**newtuple([..]):**
+  Take an interpreter level list of wrapped objects.
+
+**newlist([..]):**
+  Takes an interpreter level list of wrapped objects.
+
+**newdict([..]):**
+  Takes an interpreter level list of interpreter level pairs of wrapped key:wrapped value entries.
+
+**newslice(w_start, w_end, w_step):**
+  Makes a new slice object.
+
+**newfunction(w_code, w_globals, w_defaultarguments, w_closure=None):**
+  Creates a new function object.
+
+**newstring(asciilist):**
+  Creates a string from a list of integers.
+
+**newmodule(w_name):**
+  Creates a new module with a given name.
+
+Conversions from Application Level to Interpreter Level
+----------------------------------------------------------
+
+**unwrap(w_x):**
+  Return Interpreter Level equivalent of w_x
+
+**is_true(w_x):**
+  Return a interpreter level bool (True or False).
+
+**unpackiterable(w_iterable, expected_length=None):**
+  Unpack an iterable object into a real (interpreter level) list. Raise a real ValueError if the expected_length is wrong.
+
+**unpacktuple(w_tuple, expected_length=None):**
+  Same as unpackiterable(), but only for tuples.
+
+---------------------------
+
+.. _ObjectSpace: ObjSpcDoc.html

Added: pypy/trunk/doc/objspacedoc/ObjSpc.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/doc/objspacedoc/ObjSpc.txt	Sun Jun 22 12:30:19 2003
@@ -0,0 +1,39 @@
+=====================
+PyPython ObjectSpace
+=====================
+
+See ObjectSpaceInterface_ for a draft version of the interface specification to ObjectSpace objects.
+------------------------------------------------------------------------------------------------------
+
+In a Python-like language, a running interpreter has three main parts:
+
++ the compiler, which represents the static optimization of the source code into an intermediate format, the bytecode;
++ the object library, implementing the various types of objects and their semantics;
++ the main loop, which suffles data around and calls the operations defined in the object library according to the bytecode.
+
+The main loop generally assumes little about the semantics of the objects: they are essentially black boxes (PyObject pointers). The interpreter stack and the variables only contain such black boxes. Every operation is done via calls to the object library, like PyNumber_Add().
+
+In PyPy, the three parts are clearly separated and can be replaced independently. I will discuss below the reasons I think it is very useful to have, in particular, the object library be replaced. We call object space such an object library. The standard object space is the object space that works just like Python's, that is, the object space whose black boxes are real Python objects that work as expected. We will call wrapped objects the black boxes of an object space. 
+
+Here are four examples of object spaces:
+
+- TrivialObjectSpace_
+- StandardObjectSpace_
+- AbstractObjectSpace_
+- TranslateObjectSpace_
+
+(We should also talk about turning the compiler and the main loop into explicit concepts, as Rocco discussed in pypy-dev.)
+
+I believe that the above examples should give a hint at why we might really want object spaces that behave differently: this is called abstact interpretation in the litterature. But there are also more funny ways to use object spaces, for example:
+
++ running with several object spaces at once, to clearly separate the data into domains
++ proxy object spaces, which forward all requests over a network to a "Python object server"
++ and more... there have been numerous ideas in pypy-dev.
+
+------------
+
+.. _ObjectSpaceInterface: ObSpIntfc.html
+.. _TrivialObjectSpace: TrivObSp.html
+.. _StandardObjectSpace: StObSp.html
+.. _AbstractObjectSpace: AbObSp.html
+.. _TranslateObjectSpace: TranObSp.html

Added: pypy/trunk/doc/objspacedoc/RestrictedPython.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/doc/objspacedoc/RestrictedPython.txt	Sun Jun 22 12:30:19 2003
@@ -0,0 +1,147 @@
+==================
+Restricted Python
+==================
+
+We are writing a Python interpreter in Python, using Python's well known ability to step behind the algorithmic problems as language. At first glance, one might think this achives nothing but a better understanding for everbody how the interpreter works. This alone would make it worth doing, but we have much larger goals. 
+
+
+CPython vs. PyPy
+-------------------
+
+Compared to the CPython implementation, Python takes the role of the C Code. So actually, we descibe something by Python, which has been coded in C already, with all the restrictions that are implied by C. We are not trying to make the structures of the CPython interpreter more flexible by rewriting things in C, but we want to use Python to give an alternative description of the interpreter.
+
+The clear advantage is that this description is probably shorter and simpler to read, and many implementation details vanish. The drawback of this approach is that this interpreter will be unbearably slow.
+
+To get to a useful interpreter again, we need to apply some mappings to the implementation, later. One rather straight-forward 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 the easiest approach, first.
+
+In order to make a C code generator simple, we resrict ourselves to a subset of the Python language, and we adhere to some rules, which make code generation obvious and easy.
+
+
+Restricted Python is Runtime Python
+-------------------------------------
+
+Restricted Python describes a runnable Python interpreter implementation. This is a quite static object that can be suitably described by RPython. But the restrictions do not apply during the startup phase.
+
+
+PyPy Bootstrap
+-------------------
+
+When the PyPy interpreter is started as a CPython program, it can use all of CPython for a while, until it reaches runtime. That is, all executable code will be executed using the full power of Python.
+
+An example can be found in the implementation, which is quite elegant: For the definition of all the opcodes of the Python interpreter, the module dis is imported and used. 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.
+
+When the startup code is done, all resulting objects, functions, code blocks etc. must adhere to the runtime restrictions. All initialized modules are written out in a persistent manner. Our current idea is to emit a huge C source file which contains everything created so far. During this process, a whole program analysis is performed, which makes use of the restrictions defined in RPython. This enables the code generator to emit efficient replacements for pure integer objects, for instance.
+
+
+RPython Definition
+--------------------
+
+It might make sense to define a sublanguage of Python called RPython, with the restrictions depicted below. This is an evolving topic, and we're just collecting things which come up during trying to code the interpreter, so this is no language at all, but an arbitrary set of rules, which are about to be changed all day.
+
+
+Object restrictions
+-------------------------
+
+We are using
+
+**variables**
+  the same variable in the same context can receive values of different types, at a possible overhead cost. For example, a variable that can contain a wrapped object or None is efficiently implemented as a PyObject* pointer that can be NULL, but a variable that can contain either an integer or a float must be implemented as a union with a type tag in C.
+
+**constants**
+  all module globals are considered constants.
+
+**integer, float, string, boolean**
+  avoid string methods and complex operations like slicing with a step
+
+**tuples**
+  no variable-length tuples; use them to store or return pairs or n-tuples of values
+
+**lists**
+  lists are used as an allocated array; list.append() does naive resizing, so as far as possible use list comprehensions (see below)
+
+**dicts**
+  no dicts
+
+**control structures**
+  all allowed
+
+**list comprehensions**
+  may be used to create allocated, initialized array. the array size must be computable in advance, which implies that we don't allow an if clause.
+
+**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 use of very simple signatures, equal for all functions to be called in that context. At the moment, this occours in the opcode dispatch, only.
+
+**builtin functions**
+  A few builtin functions will be used, while this set is not defined completely, yet. Some builtin functions are special forms:
+
+**range**
+  does not create an array. It is only allowed in for loops. The step argument must be a constant.
+
+**len**
++  may be used with basic types that have a length. But len is a special form that is recognized by the compiler.
++  If a certain structure is never touched by len, the compiler might save the length field from the underlying structure.
+
+``int, float, ord, chr``... are available as simple convertion functions.
+``int, float, str``... have a special meaning as a type inside of isinstance only.
+
+**classes**
++ methods do not change after startup
++ methods are never hidden by attributes
++ inheritance is supported
++ classes are first-class objects too
+
+**exceptions**
++ fully supported
++ see below for restrictions on exceptions raised by built-in operations
+
+**objects**
+  wrapped objects are borrowed from the object space. Just like in CPython, code that needs e.g. a dictionary can use a wrapped dict and the object space operations on it.
+
+This layout makes the number of types to take care about quite limited.
+
+
+Example: Integer Types
+-------------------------
+
+While implementing the integer type, I (Chris) stumbled over the problem, that integers are quite in flux in CPython right now. Depending on the version, integers either raise an overflow exception or mutate into longs on overflow. Also, shifting right now truncates (upto 2.3) but is going to extend to longs as well. In order to enable us to run the restricted Python stuff in CPython, I needed to use a derived class r_int(int), which always behaves the same: Never leaving its domain, but always staying an integer.
+
+The r_int type is implemented in a pervasive way: Every operation that involves an r_int creates an r_int as the result. Therefore, the implementation is not cluttered with special type casts. Just the initial value of an emulated integer's intval field is initialized by obj.intval = r_int(val) . This way, the r_int type propagates itself through all operations without extra effort of the programmer.
+
+This concept looks promising, and since we will need unsigned integers which do not overflow as well, I also created r_uint. It is always a word-sized unsigned integer and never overflows. This will be a building block for things like computing hash values, where wrap-around effects are intended and should be easily coded without lots of explicit mask shuffling. 
+
+Now I think to extend this even more and build a full set of primitive types, which are intended to
+
++ define the semantics of the primitive type
++ give a working implementation for unrestricted Python
+
+These primitive types can later easily be augmented with methods to emit C code instead of executing. I guess this would be implemented in an extra ObjectSpace.
+
+
+Exception rules
+---------------------
+
+Exceptions are by default not generated for simple cases.::
+
+
+    #!/usr/bin/python
+
+        x = 5
+        x = x + 1    # this code is not checked for overflow
+
+        try:
+            x = x + y
+        except OverflowError:
+            # implement using longs
+
+
+Code with no exception handlers does not raise exceptions. By supplying an exception handler, you ask for error checking. Without, you assure the system that the operation cannot overflow.
+
+Exceptions explicitly raised will always be generated.
+
+
+Testing
+------------
+
+Besides extra tests which have to be written, 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.

Added: pypy/trunk/doc/objspacedoc/StObSp.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/doc/objspacedoc/StObSp.txt	Sun Jun 22 12:30:19 2003
@@ -0,0 +1,26 @@
+=========================
+StandardObjectSpace
+=========================
+
+User History
+---------------
+
+The StandardObjectSpace is the direct equivalent of CPython's object library (the "Objects/" subdirectory in the distribution). It is an implementation of the common Python types in a lower-level language.
+
+The StandardObjectSpace defines an abstract parent class, W_Object, and a bunch of subclasses like W_IntObject, W_ListObject, and so on. A wrapped object (a "black box" for the interpreter main loop) is thus an instance of one of these classes. When the main loop invokes an operation, say the addition, between two wrapped objects w1 and w2, the StandardObjectSpace does some internal dispatching (similar to "Object/ abstract.c" in CPython) and invokes a method of the proper W_XyzObject class that can do the operation. The operation itself is done with the primitives allowed by RestrictedPython. The result is constructed as a wrapped object again. For example, compare the following implementation of integer addition with the function "int_add()" in "Object/intobject.c": ::
+
+    def int_int_add(space, w_int1, w_int2):
+        x = w_int1.intval
+        y = w_int2.intval
+        try:
+            z = x + y
+        except OverflowError:
+            raise FailedToImplement(space.w_OverflowError,
+                                    space.wrap("integer addition"))
+        return W_IntObject(z)
+
+Why such a burden just for integer objects? Why did we have to wrap them into W_IntObject instances? For them it seems it would have been sufficient just to use plain Python integers. But this argumentation fails just like it fails for more complex kind of objects. Wrapping them just like everything else is the cleanest solution. You could introduce case testing wherever you use a wrapped object, to know if it is a plain integer or an instance of (a subclass of) W_Object. But that makes the whole program more complicated. The equivalent in CPython would be to use PyObject* pointers all around except when the object is an integer (after all, integers are directly available in C too). You could represent small integers as odd-valuated pointers. But it puts extra burden on the whole C code, so the CPython team avoided it.
+
+In our case it is a later optimization that we could make. We just don't want to make it now (and certainly not hard-coded at this level -- it could be introduced by the C translators that we will eventually write). So in summary: wrapping integers as instances is the simple path, while using plain integers instead is the complex path, not the other way around.
+
+Note that the current StandardObjectSpace implementation uses MultiMethod dispatch instead of the complex rules of "Object/abstract.c". I think that this can be translated to a different low-level dispatch implementation that would be binary compatible with CPython's (basically the PyTypeObject structure and its function pointers). If compatibility is not required it will be more straightforwardly converted into some efficient multimethod code.

Added: pypy/trunk/doc/objspacedoc/TrivObSp.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/doc/objspacedoc/TrivObSp.txt	Sun Jun 22 12:30:19 2003
@@ -0,0 +1,20 @@
+=================================
+PyPython TrivialObjectSpace
+=================================
+
+User History
+----------------
+
+The easiest way to implement an ObjectSpace is to represent a Python object with itself.
+
+A PyPy interpreter using the TrivialObjectSpace is an interpreter with its own main loop (written in Python), but this main loop manipulates real Python objects and all operations are done directly on the Python objects. For example, "1" really means "1" and when the interpreter encounters the BINARY_ADD bytecode instructions the TrivialObjectSpace will just add two real Python objects together using Python's "+". The same for lists, dictionaries, classes... We just use Python's own.
+
+Of course you cannot do this if the goal is to write PyPy in such a way that it doesn't rely on a real underlying Python implementation like CPython. Still, it works, and it has its own uses, like testing our interpreter, or even interpreting a different kind of bytecode -- for example, it could probably be used to emulate generators in any Python version. (That would be quite slow, however.)
+
+(This is already done; it is funny to watch "dis.dis" disassembling itself painfully slowly :-) )
+
+See StandardObjectSpace_ for the rest of the story.
+
+-------------------------------------------------------------------
+
+.. _StandardObjectSpace: StObSp.html
\ No newline at end of file


More information about the Pypy-commit mailing list