Alex Gaynor avatar Alex Gaynor committed 1646d57

remove dump, thunk, and trace objspaces which were unused

Comments (0)

Files changed (26)

demo/fibonacci.py

-"""
-Thunk (a.k.a. lazy objects) in PyPy.
-To run on top of the thunk object space with the following command-line:
-
-    py.py -o thunk fibonacci.py
-
-This is a typical Functional Programming Languages demo, computing the
-Fibonacci sequence by using an infinite lazy linked list.
-"""
-
-try:
-    from __pypy__ import thunk    # only available in 'py.py -o thunk'
-except ImportError:
-    print __doc__
-    raise SystemExit(2)
-
-# ____________________________________________________________
-
-
-class ListNode:
-    def __init__(self, head, tail):
-        self.head = head   # the first element of the list
-        self.tail = tail   # the sublist of all remaining elements
-
-
-def add_lists(list1, list2):
-    """Compute the linked-list equivalent of the Python expression
-          [a+b for (a,b) in zip(list1,list2)]
-    """
-    return ListNode(list1.head + list2.head,
-                    thunk(add_lists, list1.tail, list2.tail))
-
-
-# 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
-Fibonacci = ListNode(1, ListNode(1, None))
-Fibonacci.tail.tail = thunk(add_lists, Fibonacci, Fibonacci.tail)
-
-
-if __name__ == '__main__':
-    node = Fibonacci
-    while True:
-        print node.head
-        node = node.tail

demo/fibonacci2.py

-"""
-Lazy functions in PyPy.
-To run on top of the thunk object space with the following command-line:
-
-    py.py -o thunk fibonacci2.py
-
-This is a typical Functional Programming Languages demo, computing the
-Fibonacci sequence as nested 2-tuples.
-"""
-
-import pprint
-
-try:
-    from __pypy__ import lazy
-except ImportError:
-    print __doc__
-    raise SystemExit(2)
-
-
-@lazy
-def fibo(a, b):
-    return (a, fibo(b, a + b))
-
-
-fibonacci = fibo(1, 1)
-
-pprint.pprint(fibonacci, depth=10)

demo/sharedref.py

-"""
-   This is an example usage of the 'thunk' object space of PyPy.
-   It implements transparent distributed object manipulation.
-
-   Start a server on a local port, say port 8888, with:
-
-       $ py.py -o thunk sharedref.py 8888
-       Waiting for connection on port 8888
-
-   Then start and connect a client from the same or another machine:
-
-       $ py.py -o thunk sharedref.py ip_or_name:8888
-       Connecting to ('...', 8888)
-       Ok
-       >>> l = [1,2,3]
-       >>> chan.send(l)    # send the list to the server over the connexion
-
-   On the server-side:
-
-       Connected from ('...', 1046)
-       >>> l = chan.recv()    # receive the list sent above
-       >>> l
-       [1, 2, 3]
-       >>> l.append(4)
-
-   Back on the client-side:
-
-       >>> l
-       [1, 2, 3, 4]
-
-   The list behaves like a single distributed object, which both sides can
-   modify and access without needing further explicit synchronization.
-   There is no difference between who was the original sender or receiver of
-   the object, nor between which side was originally 'server' or 'client'.
-"""
-
-import sys, marshal
-from __pypy__ import thunk, become
-from socket import *
-from select import select
-
-
-class Channel:
-
-    def __init__(self, s, serverside):
-        # invariants: a shared object 'obj' is
-        #  - either remote, and a thunk, and not a value in self.cache
-        #  - or local (or at least on "our" side of this Channel), and
-        #    then it has a corresponding key in self.cache
-        self.s = s
-        self.cache = {}
-        self.inputfifo = []
-        self.count = int(not serverside)
-
-##    def _check(self, obj):
-##        print '%s: cache=%r' % (self, self.cache.keys()),
-##        if is_thunk(obj):
-##            print 'THUNK'
-##        else:
-##            print obj
-
-    def sendraw(self, obj):
-        data = marshal.dumps(obj)
-        hdr = str(len(data))
-        hdr = '0'*(10-len(hdr)) + hdr
-        self.s.sendall(hdr + data)
-
-    def _readbytes(self, count):
-        data = ''
-        while len(data) < count:
-            t = self.s.recv(count - len(data))
-            if not t:
-                raise EOFError
-            data += t
-        return data
-
-    def recvraw(self):
-        datasize = int(self._readbytes(10))
-        data = self._readbytes(datasize)
-        return marshal.loads(data)
-
-    def send(self, obj, n=None):
-        #print 'send', n,; self._check(obj)
-        if n is None:
-            n = self.count
-            self.count += 2
-            data = (n, obj, None)
-        else:
-            data = (n, obj)
-        self.sendraw(data)
-        become(obj, thunk(self._resume, n))
-        #print 'done', n,; self._check(obj)
-
-    def recv(self):
-        obj = self.inputfifo.pop(0)
-        #print 'recv',; self._check(obj)
-        return obj
-
-    def _resume(self, n):
-        #print 'resume', n,; sys.stdout.flush()
-        assert n not in self.cache
-        self.sendraw((n,))
-        while n not in self.cache:
-            self.handle_once()
-        obj = self.cache[n]
-        #self._check(obj)
-        return obj
-
-    def handle_once(self):
-        input = self.recvraw()
-        if len(input) > 1:
-            obj = input[1]
-            self.cache[input[0]] = obj
-            if len(input) > 2:
-                self.inputfifo.append(obj)
-        else:
-            n = input[0]
-            obj = self.cache[n]
-            self.send(obj, n)
-            del self.cache[n]
-
-
-def mainloop(channels):
-    stdin = sys.stdin.fileno()
-    sockfd = [chan.s.fileno() for chan in channels]
-    while True:
-        sys.stdout.write('>>> ')
-        sys.stdout.flush()
-        while True:
-            iwtd, owtd, ewtd = select([stdin] + sockfd, [], [stdin])
-            if stdin in iwtd or stdin in ewtd: break
-            for chan in channels:
-                if chan.s.fileno() in iwtd:
-                    chan.handle_once()
-        code = raw_input()
-        if not code: break
-        try:
-            co = compile(code, '<input>', 'single')
-            exec co in globals()
-        except Exception, e:
-            print e.__class__.__name__, str(e)
-
-
-def server(port):
-    s = socket(AF_INET, SOCK_STREAM)
-    s.bind(('', port))
-    s.listen(1)
-    print 'Waiting for connection on port', port
-    s, addr = s.accept()
-    print 'Connected from', addr
-    return Channel(s, True)
-
-def client(addr):
-    s = socket(AF_INET, SOCK_STREAM)
-    print 'Connecting to', addr
-    s.connect(addr)
-    print 'Ok'
-    return Channel(s, False)
-
-
-if __name__ == '__main__':
-    try:
-        thunk, become    # only available in 'py.py -o thunk'
-    except NameError:
-        print __doc__
-        raise SystemExit(2)
-
-    channels = []
-    for a in sys.argv[1:]:
-        try:
-            port = int(a)
-        except ValueError:
-            host, port = a.split(':')
-            port = int(port)
-            chan = client((host, port))
-        else:
-            chan = server(port)
-        channels.append(chan)
-
-    try:
-        mainloop(channels)
-    finally:
-        for channel in channels:
-                channel.s.close()

pypy/config/pypyoption.py

 
 
 pypy_optiondescription = OptionDescription("objspace", "Object Space Options", [
-    ChoiceOption("name", "Object Space name",
-                 ["std", "flow", "thunk", "dump"],
-                 "std",
-                 cmdline='--objspace -o'),
-
     OptionDescription("opcodes", "opcodes to enable in the interpreter", [
         BoolOption("CALL_METHOD", "emit a special bytecode for expr.name()",
                    default=False),

pypy/config/test/test_config.py

 def make_description():
     gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
     gcdummy = BoolOption('dummy', 'dummy', default=False)
-    objspaceoption = ChoiceOption('objspace', 'Object space',
-                                ['std', 'thunk'], 'std')
     booloption = BoolOption('bool', 'Test boolean option', default=True)
     intoption = IntOption('int', 'Test int option', default=0)
     floatoption = FloatOption('float', 'Test float option', default=2.3)
                                       requires=[('gc.name', 'framework')])
     
     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
-    descr = OptionDescription('pypy', '', [gcgroup, booloption, objspaceoption,
+    descr = OptionDescription('pypy', '', [gcgroup, booloption,
                                            wantref_option, stroption,
                                            wantframework_option,
                                            intoption])
 def test_base_config():
     descr = make_description()
     config = Config(descr, bool=False)
-    
+
     assert config.gc.name == 'ref'
     config.gc.name = 'framework'
     assert config.gc.name == 'framework'
     assert getattr(config, "gc.name") == 'framework'
 
-    assert config.objspace == 'std'
-    config.objspace = 'thunk'
-    assert config.objspace == 'thunk'
-    
     assert config.gc.float == 2.3
     assert config.int == 0
     config.gc.float = 3.4
     config.str = "def"
     assert config.str == "def"
 
-    py.test.raises(ConfigError, 'config.objspace = "foo"')
     py.test.raises(ConfigError, 'config.gc.name = "foo"')
     py.test.raises(AttributeError, 'config.gc.foo = "bar"')
     py.test.raises(ConfigError, 'config.bool = 123')

pypy/config/test/test_parse.py

     assert (parse_info("                          objspace.allworkingmodules: True\n"
                        "                    objspace.disable_call_speedhacks: False\n"
                        "                                 objspace.extmodules: None\n"
-                       "                                       objspace.name: std\n"
                        "                        objspace.std.prebuiltintfrom: -5\n")
             == {
         'objspace.allworkingmodules': True,
         'objspace.disable_call_speedhacks': False,
         'objspace.extmodules': None,
-        'objspace.name': 'std',
         'objspace.std.prebuiltintfrom': -5,
         })

pypy/doc/__pypy__-module.rst

    It works like a simplified array of characters (actually, depending on the
    configuration the ``array`` module internally uses this).
 
-Thunk Object Space Functionality
-================================
-
-When the thunk object space is used (choose with :config:`objspace.name`),
-the following functions are put into ``__pypy__``:
-
- - ``thunk``
- - ``is_thunk``
- - ``become``
- - ``lazy``
-
-Those are all described in the `interface section of the thunk object space
-docs`_.
-
-For explanations and examples see the `thunk object space docs`_.
-
-.. _`thunk object space docs`: objspace-proxies.html#thunk
-.. _`interface section of the thunk object space docs`: objspace-proxies.html#thunk-interface
-
-
 Transparent Proxy Functionality
 ===============================
 

pypy/doc/_ref.txt

 .. _`pypy/module/__builtin__/__init__.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/__builtin__/__init__.py
 .. _`pypy/objspace`:
 .. _`pypy/objspace/`: https://bitbucket.org/pypy/pypy/src/default/pypy/objspace/
-.. _`pypy/objspace/dump.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/objspace/dump.py
 .. _`pypy/objspace/flow`:
 .. _`pypy/objspace/flow/`: https://bitbucket.org/pypy/pypy/src/default/pypy/objspace/flow/
 .. _`pypy/objspace/flow/model.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/objspace/flow/model.py
 .. _`pypy/objspace/std/transparent.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/objspace/std/transparent.py
 .. _`pypy/objspace/std/tupleobject.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/objspace/std/tupleobject.py
 .. _`pypy/objspace/std/tupletype.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/objspace/std/tupletype.py
-.. _`pypy/objspace/thunk.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/objspace/thunk.py
-.. _`pypy/objspace/trace.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/objspace/trace.py
 .. _`pypy/rlib`:
 .. _`pypy/rlib/`: https://bitbucket.org/pypy/pypy/src/default/pypy/rlib/
 .. _`pypy/rlib/listsort.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rlib/listsort.py

pypy/doc/config/objspace.name.txt

-Determine which `Object Space`_ to use. The `Standard Object Space`_ gives the
-normal Python semantics, the others are `Object Space Proxies`_ giving
-additional features (except the Flow Object Space which is not intended
-for normal usage):
-
-  * thunk_: The thunk object space adds lazy evaluation to PyPy.
-  * dump_:  Using this object spaces results in the dumpimp of all operations
-    to a log.
-
-.. _`Object Space`: ../objspace.html
-.. _`Object Space Proxies`: ../objspace-proxies.html
-.. _`Standard Object Space`: ../objspace.html#standard-object-space
-.. _thunk: ../objspace-proxies.html#thunk
-.. _dump: ../objspace-proxies.html#dump

pypy/doc/getting-started-dev.rst

    and grammar files that allow it to parse the syntax of various Python
    versions. Once the grammar has been processed, the parser can be
    translated by the above machinery into efficient code.
- 
+
 *  `pypy/interpreter/astcompiler`_ contains the compiler.  This
    contains a modified version of the compiler package from CPython
    that fixes some bugs and is translatable.
    ``xxxobject.py`` contain respectively the definition of the type and its
    (default) implementation.
 
-*  `pypy/objspace`_ contains a few other object spaces: the `pypy/objspace/thunk.py`_,
-   `pypy/objspace/trace.py`_ and `pypy/objspace/flow`_ object spaces.  The latter is a relatively short piece
-   of code that builds the control flow graphs when the bytecode interpreter
-   runs in it.
-
 *  `pypy/translator`_ contains the code analysis and generation stuff.
    Start reading from translator.py, from which it should be easy to follow
    the pieces of code involved in the various translation phases.

pypy/doc/getting-started-python.rst

 
 .. _`configuration sections`: config/index.html
 
-.. _`translate PyPy with the thunk object space`:
-
 Translating with non-standard options
 ++++++++++++++++++++++++++++++++++++++++
 

pypy/doc/index.rst

 
 `pypy/objspace/`_                  `object space`_ implementations
 
-`pypy/objspace/trace.py`_          the `trace object space`_ monitoring bytecode and space operations
-
-`pypy/objspace/dump.py`_           the dump object space saves a large, searchable log file
-                                   with all operations
-
-`pypy/objspace/thunk.py`_          the `thunk object space`_, providing unique object features 
-
 `pypy/objspace/flow/`_             the FlowObjSpace_ implementing `abstract interpretation`_
 
 `pypy/objspace/std/`_              the StdObjSpace_ implementing CPython's objects and types
 .. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf
 .. _`object space`: objspace.html
 .. _FlowObjSpace: objspace.html#the-flow-object-space 
-.. _`trace object space`: objspace.html#the-trace-object-space 
-.. _`thunk object space`: objspace-proxies.html#thunk
 .. _`transparent proxies`: objspace-proxies.html#tproxy
 .. _`Differences between PyPy and CPython`: cpython_differences.html
 .. _`What PyPy can do for your objects`: objspace-proxies.html

pypy/doc/objspace-proxies.rst

 
 Here is what we have implemented so far, in historical order:
 
-* *Thunk Object Space*: lazily computed objects, computing only when an
-  operation is performed on them; lazy functions, computing their result
-  only if and when needed; and a way to globally replace an object with
-  another.
-
 * *Dump Object Space*: dumps all operations performed on all the objects
   into a large log file.  For debugging your applications.
 
 * *Transparent Proxies Extension*: adds new proxy objects to
-  the Standard Object Space that enable applications to 
-  control operations on application and builtin objects, 
-  e.g lists, dictionaries, tracebacks. 
-
-Which object space to use can be chosen with the :config:`objspace.name`
-option.
+  the Standard Object Space that enable applications to
+  control operations on application and builtin objects,
+  e.g lists, dictionaries, tracebacks.
 
 .. _`Object Space`: objspace.html
-
-.. _thunk:
-
-The Thunk Object Space
-======================
-
-This small object space, meant as a nice example, wraps another object
-space (e.g. the standard one) and adds two capabilities: lazily computed
-objects, computed only when an operation is performed on them, and
-"become", a more obscure feature which allows to completely and globally
-replaces an object with another.
-
-Example usage of lazily computed objects::
-
-    $ py.py -o thunk
-    >>>> from __pypy__ import thunk
-    >>>> def f():
-    ....    print 'computing...'
-    ....    return 6*7
-    ....
-    >>>> x = thunk(f)
-    >>>> x
-    computing...
-    42
-    >>>> x
-    42
-    >>>> y = thunk(f)
-    >>>> type(y)
-    computing...
-    <type 'int'>
-
-Example of how one object can be instantly and globally replaced with
-another::
-
-    $ py.py -o thunk
-    >>>> from __pypy__ import become
-    >>>> x = object()
-    >>>> lst = [1, 2, x, 4]
-    >>>> become(x, 3)
-    >>>> lst
-    [1, 2, 3, 4]
-
-There is also a decorator for functions whose result can be computed
-lazily (the function appears to return a result, but it is not really
-invoked before the result is used, if at all)::
-
-    $ py.py -o thunk
-    >>>> from __pypy__ import lazy
-    >>>> @lazy
-    .... def f(x):
-    ....    print 'computing...'
-    ....    return x * 100
-    ....
-    >>>> lst = [f(i) for i in range(10)]
-    >>>> del lst[1:9]
-    >>>> lst
-    computing...
-    computing...
-    [0, 900]
-
-Implementation
---------------
-
-The implementation is short (see `pypy/objspace/thunk.py`_).  For the
-purpose of ``become()``, it adds an internal field `w_thunkalias` to
-each object, which is either None (in the common case) or a reference to
-the object that this object was replaced with.  When any space operation
-is invoked, the chain of ``w_thunkalias`` references is followed and the
-underlying object space really operates on the new objects instead of
-the old ones.
-
-For the laziness part, the function ``thunk()`` returns an instance of a
-new internal class ``W_Thunk`` which stores the user-supplied callable
-and arguments.  When a space operation follows the ``w_thunkalias``
-chains of objects, it special-cases ``W_Thunk``: it invokes the stored
-callable if necessary to compute the real value and then stores it in
-the ``w_thunkalias`` field of the ``W_Thunk``.  This has the effect of
-replacing the latter with the real value.
-
-.. _thunk-interface:
-
-Interface
----------
-
-In a PyPy running with (or translated with) the Thunk Object Space,
-the ``__pypy__`` module exposes the following interface:
-
- * ``thunk(f, *args, **kwargs)``: returns something that behaves like the result
-   of the call ``f(*args, **kwargs)`` but the call is done lazily.
-
- * ``is_thunk(obj)``: return True if ``obj`` is a thunk that is not computed
-   yet.
-
- * ``become(obj1, obj2)``: globally replace ``obj1`` with ``obj2``.
-
- * ``lazy(callable)``: should be used as a function decorator - the decorated
-   function behaves lazily: all calls to it return a thunk object.
-
-
-.. _dump:
-
-The Dump Object Space
-=====================
-
-When PyPy is run with (or translated with) the *Dump Object Space*, all
-operations between objects are dumped to a file called
-``pypy-space-dump``.  This should give a powerful way to debug
-applications, but so far the dump can only be inspected in a text
-editor; better browsing tools are needed before it becomes really useful.
-
-Try::
-
-    $ py.py -o dump
-    >>>> 2+3
-    5
-    >>>> (exit py.py here)
-    $ more pypy-space-dump
-
-On my machine the ``add`` between 2 and 3 starts at line 3152 (!)  and
-returns at line 3164.  All the rest is start-up, printing, and shutdown.
-
-
 .. _tproxy:
 
 Transparent Proxies
 ================================
 
-PyPy's Transparent Proxies allow routing of operations on objects 
+PyPy's Transparent Proxies allow routing of operations on objects
 to a callable.  Application level code can customize objects without
 interfering with the type system - ``type(proxied_list) is list`` holds true
 when 'proxied_list' is a proxied built-in list - while
 giving you full control on all operations that are performed on the
 ``proxied_list``.
 
-See [D12.1]_ for more context, motivation and usage of transparent proxies. 
+See [D12.1]_ for more context, motivation and usage of transparent proxies.
 
-Example of the core mechanism 
+Example of the core mechanism
 -------------------------------------------
 
-The following example proxies a list and will 
-return ``42`` on any add operation to the list:: 
+The following example proxies a list and will
+return ``42`` on any add operation to the list::
 
-   $ py.py --objspace-std-withtproxy 
+   $ py.py --objspace-std-withtproxy
    >>>> from __pypy__ import tproxy
    >>>> def f(operation, *args, **kwargs):
    >>>>    if operation == '__add__':
 
    history = []
    def recorder(operation):
-       history.append(operation) 
+       history.append(operation)
        return operation.delegate()
 
-   >>>> l = make_proxy(recorder, obj=[])    
+   >>>> l = make_proxy(recorder, obj=[])
    >>>> type(l)
    list
    >>>> l.append(3)
    1
    >>>> len(history)
    2
-   
+
 ``make_proxy(recorder, obj=[])`` creates a transparent list
-proxy where we can delegate operations to in the ``recorder`` function. 
-Calling ``type(l)`` does not lead to any operation being executed at all. 
+proxy where we can delegate operations to in the ``recorder`` function.
+Calling ``type(l)`` does not lead to any operation being executed at all.
 
 Note that ``append`` shows up as ``__getattribute__`` and that ``type(lst)``
 does not show up at all - the type is the only aspect of the instance which
 the controller cannot change.
 
-.. _`transparent proxy builtins`: 
+.. _`transparent proxy builtins`:
 
 Transparent Proxy PyPy builtins and support
 -----------------------------------------------------------
 
-If you are using the `--objspace-std-withtproxy`_ option 
-the `__pypy__`_ module provides the following builtins: 
+If you are using the `--objspace-std-withtproxy`_ option
+the `__pypy__`_ module provides the following builtins:
 
-* ``tproxy(type, controller)``: returns a proxy object 
-  representing the given type and forwarding all operations 
+* ``tproxy(type, controller)``: returns a proxy object
+  representing the given type and forwarding all operations
   on this type to the controller.  On each such operation
-  ``controller(opname, *args, **kwargs)`` is invoked. 
+  ``controller(opname, *args, **kwargs)`` is invoked.
 
-* ``get_tproxy_controller(obj)``:  returns the responsible 
+* ``get_tproxy_controller(obj)``:  returns the responsible
   controller for a given object.  For non-proxied objects
-  ``None`` is returned.  
+  ``None`` is returned.
 
-.. _`__pypy__`:  __pypy__-module.html 
+.. _`__pypy__`:  __pypy__-module.html
 .. _`--objspace-std-withtproxy`: config/objspace.std.withtproxy.html
 
-.. _tputil: 
+.. _tputil:
 
-tputil helper module 
+tputil helper module
 ----------------------------
 
-The `lib_pypy/tputil.py`_ module provides: 
+The `lib_pypy/tputil.py`_ module provides:
 
-* ``make_proxy(controller, type, obj)``: function which 
-  creates a transparent proxy controlled by the given 
-  'controller' callable.  The proxy will appear 
-  as a completely regular instance of the given 
-  type but all operations on it are send to the 
+* ``make_proxy(controller, type, obj)``: function which
+  creates a transparent proxy controlled by the given
+  'controller' callable.  The proxy will appear
+  as a completely regular instance of the given
+  type but all operations on it are send to the
   specified controller - which receives a
-  ProxyOperation instance on each such operation.  
-  A non-specified type will default to type(obj) if 
-  `obj` was specified. 
+  ProxyOperation instance on each such operation.
+  A non-specified type will default to type(obj) if
+  `obj` was specified.
 
-  ProxyOperation instances have the following attributes: 
+  ProxyOperation instances have the following attributes:
 
-    `proxyobj`: the transparent proxy object of this operation. 
+    `proxyobj`: the transparent proxy object of this operation.
 
-    `opname`: the operation name of this operation 
+    `opname`: the operation name of this operation
 
-    `args`: positional arguments for this operation 
+    `args`: positional arguments for this operation
 
-    `kwargs`: keyword arguments for this operation 
+    `kwargs`: keyword arguments for this operation
 
     `obj`: (if provided to `make_proxy`): a concrete object
 
-  If you have specified a concrete object instance `obj` 
-  to your `make_proxy` invocation, you may call 
-  ``proxyoperation.delegate()`` to delegate the operation 
-  to this object instance. 
+  If you have specified a concrete object instance `obj`
+  to your `make_proxy` invocation, you may call
+  ``proxyoperation.delegate()`` to delegate the operation
+  to this object instance.
 
 Further points of interest
 ---------------------------
   SQL object mapper which looks like a real object)
 
 * Access to external data structures, such as other languages, as normal
-  objects (of course some operations could raise exceptions, but 
+  objects (of course some operations could raise exceptions, but
   since they are purely done on application level, that is not real problem)
 
 Implementation Notes
 
 PyPy's standard object space allows to internally have multiple
 implementations of a type and change the implementation at run
-time while application level code consistently sees the exact 
-same type and object.  Multiple performance optimizations using 
+time while application level code consistently sees the exact
+same type and object.  Multiple performance optimizations using
 this features are already implemented: see the document
 about `alternative object implementations`_. Transparent
-Proxies use the architecture to provide control back 
-to application level code. 
+Proxies use the architecture to provide control back
+to application level code.
 
 Transparent proxies are implemented on top of the `standard object
 space`_, in `pypy/objspace/std/proxy_helpers.py`_, `pypy/objspace/std/proxyobject.py`_ and

pypy/doc/objspace.rst

 .. contents::
 
 
-.. _`objectspace`: 
-.. _`Object Space`: 
+.. _`objectspace`:
+.. _`Object Space`:
 
 Introduction
 ================
 The most important one is ``is_true()``, which returns a boolean
 interpreter-level value.  This is necessary to implement, for example,
 if-statements (or rather, to be pedantic, to implement the
-conditional-branching bytecodes into which if-statements get compiled). 
+conditional-branching bytecodes into which if-statements get compiled).
 
 We have many working object spaces which can be plugged into
 the bytecode interpreter:
 
-- The *Standard Object Space* is a complete implementation 
+- The *Standard Object Space* is a complete implementation
   of the various built-in types and objects of Python.  The Standard Object
   Space, together with the bytecode interpreter, is the foundation of our Python
   implementation.  Internally, it is a set of `interpreter-level`_ classes
   Space provides the equivalent of the C structures ``PyIntObject``,
   ``PyListObject``, etc.
 
-- the *Trace Object Space* wraps e.g. the standard 
-  object space in order to trace the execution of bytecodes, 
-  frames and object space operations.
-
 - various `Object Space proxies`_ wrap another object space (e.g. the standard
   one) and adds new capabilities, like lazily computed objects (computed only
   when an operation is performed on them), security-checking objects,
   distributed objects living on several machines, etc.
 
 - the *Flow Object Space* transforms a Python program into a
-  flow-graph representation, by recording all operations that the bytecode 
+  flow-graph representation, by recording all operations that the bytecode
   interpreter would like to perform when it is shown the given Python
   program.  This technique is explained `in another document`_.
 
 The sources of PyPy contain the various object spaces in the directory
 `pypy/objspace/`_.
 
-To choose which object space to use, use the :config:`objspace.name` option.
-
 .. _`application-level`: coding-guide.html#application-level
 .. _`interpreter-level`: coding-guide.html#interpreter-level
 .. _`in another document`: translation.html
 
 ``interpclass_w(w_x):``
   If w_x is a wrapped instance of an bytecode interpreter class -- for example
-  Function, Frame, Cell, etc. -- return it unwrapped.  Otherwise return None. 
+  Function, Frame, Cell, etc. -- return it unwrapped.  Otherwise return None.
 
 
 Data Members
    non-wrapped objects).
 
 
-.. _`standard object space`: 
+.. _`standard object space`:
 
 The Standard Object Space
 =========================
 operation. The operation itself is done with the primitives allowed by
 RPython. 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": :: 
+function "int_add()" in "Object/intobject.c": ::
 
     def add__Int_Int(space, w_int1, w_int2):
         x = w_int1.intval
 ``add__Long_Long`` and there is no ``add__Int_Long``), which leads to
 ``6L.__radd__(5)`` being called, as in CPython.
 
-
-The Trace Object Space
-======================
-
-The Trace Object Space was first written at the Amsterdam sprint.  The ease
-with which the Trace Object Space was implemented in `pypy/objspace/trace.py`_
-underlines the power of the Object Space abstraction.  Effectively it is a
-simple proxy object space.  It has gone through various refactors to reach its
-original objective, which was to show how bytecode in code objects ultimately
-performs computation via an object space.
-
-This space will intercept space operations in realtime and as a side effect
-will memorize them.  It also traces frame creation, deletion and bytecode
-execution.  Its implementation delegates to another object space - usually the
-standard object space - in order to carry out the operations.
-
-The pretty printing aims to be a graphical way of introducing programmers, and
-especially ones familiar with CPython, to how PyPy works from a bytecode and
-frames perspective.  As a result one can grasp an intuitive idea of how
-`Abstract Interpretation`_ records via tracing all execution paths of the
-individual operations if one removes the bytecode out of the equation.  This is
-the purpose of the `Flow Object Space`_.
-
-Another educational use of Trace Object Space is that it allows a Python user
-who has little understanding of how the interpreter works, a rapid way of
-understanding what bytecodes are and what an object space is.  When a statement
-or expression is typed on the command line, one can see what is happening
-behind the scenes.  This will hopefully give users a better mental framework
-when they are writing code.
-
-To make use of the tracing facilities you can at runtime switch
-your interactive session to tracing mode by typing:: 
-
-    >>> __pytrace__ = 1 
-
-Note that tracing mode will not show or record all space operations 
-by default to avoid presenting too much information.  Only non-helper 
-operations are usually shown.   
-
-A quick introduction on how to use the trace object space can be `found here`_.
-A number of options for configuration is here in `pypy/tool/traceconfig.py`_.
-
-
-.. _`found here` : getting-started-dev.html#tracing-bytecode-and-operations-on-objects
-.. _`Abstract Interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation
-
 .. _`Flow Object Space`:
 
 The Flow Object Space
 For example, if the placeholder ``v1`` is given as the argument to the above
 function, the bytecode interpreter will call ``v2 = space.mul(space.wrap(3),
 v1)`` and then ``v3 = space.add(v2, space.wrap(2))`` and return ``v3`` as the
-result.  During these calls the FlowObjSpace will record a basic block:: 
+result.  During these calls the FlowObjSpace will record a basic block::
 
   Block(v1):     # input argument
     v2 = mul(Constant(3), v1)
   situation, we interrupt the bytecode interpreter and we make a link from the
   end of the current block back to the previous block, thus closing the loop
   in the flow graph as well.  (Note that this occurs only when an operation is
-  about to be recorded, which allows some amount of constant-folding.) 
+  about to be recorded, which allows some amount of constant-folding.)
 
 * If the bytecode interpreter calls ``is_true()``, the FlowObjSpace doesn't
   generally know if the answer should be True or False, so it puts a
   fooled into thinking that ``is_true()`` first returns False (and the
   subsequent operations are recorded in the first successor block), and later
   the *same* call to ``is_true()`` also returns True (and the subsequent
-  operations go this time to the other successor block). 
+  operations go this time to the other successor block).
 
 (This section to be extended...)
 

pypy/interpreter/baseobjspace.py

             _warnings.warn(msg, warningcls, stacklevel=2)
         """)
 
-    def resolve_target(self, w_obj):
-        """ A space method that can be used by special object spaces (like
-        thunk) to replace an object by another. """
-        return w_obj
-
 
 class AppExecCache(SpaceCache):
     def build(cache, source):

pypy/interpreter/interactive.py

             self.space.settrace()
 
     def checktrace(self):
-        from pypy.objspace import trace
-
         s = self.space
 
         # Did we modify __pytrace__
             print "Tracing disabled"
 
         if self.tracelevel == 0 and tracelevel > 0:
-            trace.create_trace_space(s)
             self.space.unsettrace()
             print "Tracing enabled"
 
 
 class IncompleteInput(Exception):
     pass
-

pypy/objspace/descroperation.py

             # sanity reasons, we just compare the two places where the
             # __xxx__ and __rxxx__ methods where found by identity.
             # Note that space.is_w() is potentially not happy if one of them
-            # is None (e.g. with the thunk space)...
+            # is None...
             if w_left_src is not w_right_src:    # XXX
                 # -- cpython bug compatibility: see objspace/std/test/
                 # -- test_unicodeobject.test_str_unicode_concat_overrides.

pypy/objspace/dump.py

-import os
-from pypy.objspace.proxy import patch_space_in_place
-from pypy.objspace.std.objspace import StdObjSpace, W_Object
-from pypy.interpreter.error import OperationError
-from pypy.interpreter import baseobjspace
-
-DUMP_FILE_NAME = 'pypy-space-dump'
-DUMP_FILE_MODE = 0600
-
-class Dumper(object):
-    dump_fd = -1
-
-    def __init__(self, space):
-        self.space = space
-        self.dumpspace_reprs = {}
-
-    def open(self):
-        space = self.space
-        self.dumpspace_reprs.update({
-            space.w_None:  'None',
-            space.w_False: 'False',
-            space.w_True:  'True',
-            })
-        if self.dump_fd < 0:
-            self.dump_fd = os.open(DUMP_FILE_NAME,
-                                   os.O_WRONLY|os.O_CREAT|os.O_TRUNC,
-                                   DUMP_FILE_MODE)
-
-    def close(self):
-        if self.dump_fd >= 0:
-            os.close(self.dump_fd)
-            self.dump_fd = -1
-        self.dumpspace_reprs.clear()
-
-    def dump_get_repr(self, w_obj):
-        try:
-            return self.dumpspace_reprs[w_obj]
-        except KeyError:
-            saved_fd = self.dump_fd
-            try:
-                self.dump_fd = -1
-                space = self.space
-                if isinstance(w_obj, W_Object):
-                    w_type = space.type(w_obj)
-                else:
-                    w_type = None
-                if w_type is space.w_int:
-                    n = space.int_w(w_obj)
-                    s = str(n)
-                elif w_type is space.w_str:
-                    s = space.str_w(w_obj)
-                    digit2hex = '0123456789abcdef'
-                    lst = ["'"]
-                    for c in s:
-                        if c == '\\':
-                            lst.append('\\')
-                        if c >= ' ':
-                            lst.append(c)
-                        else:
-                            lst.append('\\')
-                            if c == '\n':
-                                lst.append('n')
-                            elif c == '\t':
-                                lst.append('t')
-                            else:
-                                lst.append('x')
-                                lst.append(digit2hex[ord(c) >> 4])
-                                lst.append(digit2hex[ord(c) & 0xf])
-                    lst.append("'")
-                    s = ''.join(lst)
-                elif w_type is space.w_float:
-                    n = space.float_w(w_obj)
-                    s = str(n)
-                else:
-                    s = '%s at 0x%x' % (w_obj, id(w_obj))
-                self.dumpspace_reprs[w_obj] = s
-            finally:
-                self.dump_fd = saved_fd
-            return s
-
-    def dump_enter(self, opname, args_w):
-        if self.dump_fd >= 0:
-            text = '\t'.join([self.dump_get_repr(w_arg) for w_arg in args_w])
-            os.write(self.dump_fd, '%s CALL   %s\n' % (opname, text))
-
-    def dump_returned_wrapped(self, opname, w_obj):
-        if self.dump_fd >= 0:
-            s = self.dump_get_repr(w_obj)
-            os.write(self.dump_fd, '%s RETURN %s\n' % (opname, s))
-
-    def dump_returned(self, opname):
-        if self.dump_fd >= 0:
-            os.write(self.dump_fd, '%s RETURN\n' % (opname,))
-
-    def dump_raised(self, opname, e):
-        if self.dump_fd >= 0:
-            if isinstance(e, OperationError):
-                s = e.errorstr(self.space)
-            else:
-                s = '%s' % (e,)
-            os.write(self.dump_fd, '%s RAISE  %s\n' % (opname, s))
-
-
-# for now, always make up a wrapped StdObjSpace
-class DumpSpace(StdObjSpace):
-
-    def __init__(self, *args, **kwds):
-        self.dumper = Dumper(self)
-        StdObjSpace.__init__(self, *args, **kwds)
-        patch_space_in_place(self, 'dump', proxymaker)
-
-    def _freeze_(self):
-        # remove strange things from the caches of self.dumper
-        # before we annotate
-        self.dumper.close()
-        return StdObjSpace._freeze_(self)
-
-    def startup(self):
-        StdObjSpace.startup(self)
-        self.dumper.open()
-
-    def finish(self):
-        self.dumper.close()
-        StdObjSpace.finish(self)
-
-    def wrap(self, x):
-        w_res = StdObjSpace.wrap(self, x)
-        self.dumper.dump_returned_wrapped('           wrap', w_res)
-        return w_res
-    wrap._annspecialcase_ = "specialize:wrap"
-
-
-Space = DumpSpace
-
-# __________________________________________________________________________
-
-nb_args = {}
-op_returning_wrapped = {}
-
-def setup():
-    nb_args.update({
-        # ---- irregular operations ----
-        'wrap': 0,
-        'str_w': 1,
-        'int_w': 1,
-        'float_w': 1,
-        'uint_w': 1,
-        'unicode_w': 1,
-        'bigint_w': 1,
-        'interpclass_w': 1,
-        'unwrap': 1,
-        'is_true': 1,
-        'is_w': 2,
-        'newtuple': 0,
-        'newlist': 0,
-        'newdict': 0,
-        'newslice': 0,
-        'call_args': 1,
-        'marshal_w': 1,
-        'log': 1,
-        })
-    op_returning_wrapped.update({
-        'wrap': True,
-        'newtuple': True,
-        'newlist': True,
-        'newdict': True,
-        'newslice': True,
-        'call_args': True,
-        })
-    for opname, _, arity, _ in baseobjspace.ObjSpace.MethodTable:
-        nb_args.setdefault(opname, arity)
-        op_returning_wrapped[opname] = True
-    for opname in baseobjspace.ObjSpace.IrregularOpTable:
-        assert opname in nb_args, "missing %r" % opname
-
-setup()
-del setup
-
-# __________________________________________________________________________
-
-def proxymaker(space, opname, parentfn):
-    if opname == 'wrap':
-        return None
-    returns_wrapped = opname in op_returning_wrapped
-    aligned_opname = '%15s' % opname
-    n = nb_args[opname]
-    def proxy(*args, **kwds):
-        dumper = space.dumper
-        args_w = list(args[:n])
-        dumper.dump_enter(aligned_opname, args_w)
-        try:
-            res = parentfn(*args, **kwds)
-        except Exception, e:
-            dumper.dump_raised(aligned_opname, e)
-            raise
-        else:
-            if returns_wrapped:
-                dumper.dump_returned_wrapped(aligned_opname, res)
-            else:
-                dumper.dump_returned(aligned_opname)
-            return res
-    proxy.func_name = 'proxy_%s' % (opname,)
-    return proxy

pypy/objspace/std/stdtypedef.py

             dest.append(expr_arg)
     renaming = ', '.join(dest) +" = "+', '.join(src)
 
-    # add a call to resolve_target to give the thunk space a chance to replace
-    # the thing with something else
-    offset = len(multimethod.argnames_before)
-    renaming += "; %s = space.resolve_target(%s)" % (
-            exprargs[selfindex+offset], exprargs[selfindex+offset])
-
     if allow_NotImplemented_results and (len(multimethod.specialnames) > 1 or
                                          multimethod.name.startswith('inplace_')):
         # turn FailedToImplement into NotImplemented

pypy/objspace/test/test_thunkobjspace.py

-from pypy.tool.pytest.objspace import gettestobjspace
-from pypy.interpreter import gateway
-
-class AppTest_Thunk:
-
-    def setup_class(cls):
-        cls.space = gettestobjspace('thunk')
-
-    def test_simple(self):
-        from __pypy__ import thunk, become
-        computed = []
-        def f():
-            computed.append(True)
-            return 6*7
-        x = thunk(f)
-        assert computed == []
-        t = type(x)
-        assert t is int
-        assert computed == [True]
-        t = type(x)
-        assert t is int
-        assert computed == [True]
-
-    def test_setitem(self):
-        from __pypy__ import thunk, become
-        computed = []
-        def f(a):
-            computed.append(True)
-            return a*7
-        x = thunk(f, 6)
-        d = {5: x}
-        d[6] = x
-        d[7] = []
-        d[7].append(x)
-        assert computed == []
-        y = d[5], d[6], d.values(), d.items()
-        assert computed == []
-        d[7][0] += 1
-        assert computed == [True]
-        assert d[7] == [43]
-
-    def test_become(self):
-        from __pypy__ import thunk, become
-        x = []
-        y = []
-        assert x is not y
-        become(x, y)
-        assert x is y
-
-    def test_id(self):
-        from __pypy__ import thunk, become
-        # these are the Smalltalk semantics of become().
-        x = []; idx = id(x)
-        y = []; idy = id(y)
-        assert idx != idy
-        become(x, y)
-        assert id(x) == id(y) == idy
-
-    def test_double_become(self):
-        skip("fix me")
-        from __pypy__ import thunk, become
-        x = [1]
-        y = [2]
-        z = [3]
-        become(x, y)
-        become(y, z)
-        assert x is y is z
-        a = []
-        a.extend(x)
-        a.extend(y)
-        a.extend(z)
-        assert a == [3, 3, 3]
-
-    def test_double_become2(self):
-        from __pypy__ import thunk, become
-        x = []
-        y = []
-        z = []
-        become(x, y)
-        become(x, z)
-        assert x is y is z
-
-    def test_thunk_forcing_while_forcing(self):
-        from __pypy__ import thunk, become
-        def f():
-            return x+1
-        x = thunk(f)
-        raises(RuntimeError, 'x+1')
-
-    def test_thunk_forcing_while_forcing_2(self):
-        from __pypy__ import thunk, become
-        def f():
-            return x
-        x = thunk(f)
-        raises(RuntimeError, 'x+1')
-
-    def test_is_thunk(self):
-        from __pypy__ import thunk, become, is_thunk
-        def f():
-            pass
-        assert is_thunk(thunk(f))
-        assert not is_thunk(42)
-
-    def test_is_thunk2(self):
-        from __pypy__ import thunk, become, is_thunk
-        def f():
-            return 42
-        x = thunk(f)
-        assert is_thunk(x)
-        assert x == 42
-        assert not is_thunk(x)
-
-    def test_is_thunk_become(self):
-        from __pypy__ import thunk, become, is_thunk
-        def f():
-            return 42
-        x = thunk(f)
-        y = []
-        become(y, x)
-        assert is_thunk(y)
-        assert y == 42
-        assert not is_thunk(y)
-
-    def test_lazy(self):
-        from __pypy__ import lazy
-        lst = []
-        def f(x):
-            lst.append(x)
-            return x+5
-        f = lazy(f)
-        y = f(3)
-        assert lst == []
-        assert type(y) is int
-        assert lst == [3]
-        assert type(y) is int
-        assert lst == [3]
-
-    def test_exception_in_thunk(self):
-        from __pypy__ import lazy
-        def f(x):
-            if x:
-                return 42
-            raise ValueError
-        f = lazy(f)
-        y = f(3)
-        assert y == 42
-        y = f(0)
-        raises(ValueError, "str(y)")
-        raises(ValueError, "str(y)")
-
-    def test_become_yourself(self):
-        from __pypy__ import become
-        x = []
-        become(x, x)
-        assert str(x) == "[]"
-
-    def test_thunk_special_method(self):
-        skip("fix me")
-        from __pypy__ import thunk
-        x = thunk(lambda : 42)
-        assert 1 .__add__(x) == 43
-        
-
-class AppTest_ThunkCallMethod(AppTest_Thunk):
-
-    def setup_class(cls):
-        cls.space = gettestobjspace('thunk', CALL_METHOD=True, multimethods='doubledispatch')
-
-    def test_method_call(self):
-        from __pypy__ import thunk
-        d = {}
-        # need the method to use the pypy compiler
-        exec """if 1:
-        def f(x):
-            return [x]
-        def g(l):
-            l.append(1)
-        """ in d
-        l = thunk(d['f'], 10)
-        d['g'](l)
-        assert l == [10, 1] 
-
-
-class AppTest_ThunkCallMethodMRD(AppTest_ThunkCallMethod):
-
-    def setup_class(cls):
-        cls.space = gettestobjspace('thunk', CALL_METHOD=True, multimethods='mrd')

pypy/objspace/test/test_traceobjspace.py

-from pypy.objspace import trace 
-from pypy.tool import pydis
-from pypy.interpreter import gateway 
-    
-class Test_TraceObjSpace:
-
-    def setup_method(self,method):
-        trace.create_trace_space(self.space)
-        
-    def teardown_method(self,method):
-        self.space.reset_trace()
-
-    def perform_trace(self, app_func):
-        tspace = self.space
-        func_gw = gateway.app2interp_temp(app_func)
-        func = func_gw.get_function(tspace)
-        tspace.settrace()
-        tspace.call_function(tspace.wrap(func))
-        res = tspace.getresult()
-        return res 
-
-    def test_traceobjspace_basic(self):
-        tspace = self.space
-        assert tspace.is_true(tspace.builtin)
-        #for name, value in vars(self.space).items():
-        #    if not name.startswith('_'):
-        #        self.assert_(value is getattr(t, name))
-        #self.assert_(t.is_true(t.make_standard_globals()))
-
-    def test_simpletrace(self):
-        def app_f(): 
-            pass
-        res = self.perform_trace(app_f)
-        disresult = pydis.pydis(app_f)
-        assert disresult.bytecodes == list(res.getbytecodes())
-
-    def test_some_builtin1(self):
-        def app_f():
-            len([1,2,3,4,5])
-        res = self.perform_trace(app_f)
-        disresult = pydis.pydis(app_f)
-        assert len(disresult.bytecodes) == len(list(res.getbytecodes()))
-
-    def test_some_builtin2(self):
-        def app_f(): 
-            filter(None, []) # filter implemented in appspace -> has many more bytecodes        
-        res = self.perform_trace(app_f)
-        disresult = pydis.pydis(app_f)
-        assert len(disresult.bytecodes) <= len(list(res.getbytecodes()))
-
-    def get_operation(self, iter, optype, name):
-        for op in iter:
-            if isinstance(op, optype):
-                if op.callinfo.name == name:
-                    return op
-                
-    def test_trace_oneop(self):
-        def app_f(): 
-            x = 1
-            x + 1
-        res = self.perform_trace(app_f)
-        disresult = pydis.pydis(app_f)
-        uw = self.space.unwrap
-        ops = res.getoperations()
-        op_start = self.get_operation(ops, trace.CallBegin, "add")
-        args = [uw(x) for x in op_start.callinfo.args]
-        assert args == [1, 1]
-        op_end = self.get_operation(ops, trace.CallFinished, "add")        
-        assert uw(op_end.res) == 2

pypy/objspace/thunk.py

-"""Example usage:
-
-    $ py.py -o thunk
-    >>> from __pypy__ import thunk, lazy, become
-    >>> def f():
-    ...     print 'computing...'
-    ...     return 6*7
-    ...
-    >>> x = thunk(f)
-    >>> x
-    computing...
-    42
-    >>> x
-    42
-    >>> y = thunk(f)
-    >>> type(y)
-    computing...
-    <pypy type 'int'>
-
-    >>> @lazy
-    ... def g(n):
-    ...     print 'computing...'
-    ...     return n + 5
-    ...
-    >>> y = g(12)
-    >>> y
-    computing...
-    17
-"""
-
-from pypy.objspace.proxy import patch_space_in_place
-from pypy.interpreter import gateway, baseobjspace, argument
-from pypy.interpreter.error import OperationError
-from pypy.interpreter.function import Method
-
-# __________________________________________________________________________
-
-# 'w_obj.w_thunkalias' points to another object that 'w_obj' has turned into
-baseobjspace.W_Root.w_thunkalias = None
-
-# adding a name in __slots__ after class creation doesn't "work" in Python,
-# but in this case it has the effect of telling the annotator that this
-# attribute is allowed to be moved up to this class.
-baseobjspace.W_Root.__slots__ += ('w_thunkalias',)
-
-class W_Thunk(baseobjspace.W_Root, object):
-    def __init__(w_self, w_callable, args):
-        w_self.w_callable = w_callable
-        w_self.args = args
-        w_self.operr = None
-
-# special marker to say that w_self has not been computed yet
-w_NOT_COMPUTED_THUNK = W_Thunk(None, None)
-W_Thunk.w_thunkalias = w_NOT_COMPUTED_THUNK
-
-
-def _force(space, w_self):
-    w_alias = w_self.w_thunkalias
-    while w_alias is not None:
-        if w_alias is w_NOT_COMPUTED_THUNK:
-            assert isinstance(w_self, W_Thunk)
-            if w_self.operr is not None:
-                raise w_self.operr
-            w_callable = w_self.w_callable
-            args       = w_self.args
-            if w_callable is None or args is None:
-                raise OperationError(space.w_RuntimeError,
-                                 space.wrap("thunk is already being computed"))
-            w_self.w_callable = None
-            w_self.args       = None
-            try:
-                w_alias = space.call_args(w_callable, args)
-            except OperationError, operr:
-                w_self.operr = operr
-                raise
-            if _is_circular(w_self, w_alias):
-                operr = OperationError(space.w_RuntimeError,
-                                       space.wrap("circular thunk alias"))
-                w_self.operr = operr
-                raise operr
-            w_self.w_thunkalias = w_alias
-        # XXX do path compression?
-        w_self = w_alias
-        w_alias = w_self.w_thunkalias
-    return w_self
-
-def _is_circular(w_obj, w_alias):
-    assert (w_obj.w_thunkalias is None or
-            w_obj.w_thunkalias is w_NOT_COMPUTED_THUNK)
-    while 1:
-        if w_obj is w_alias:
-            return True
-        w_next = w_alias.w_thunkalias
-        if w_next is None:
-            return False
-        if w_next is w_NOT_COMPUTED_THUNK:
-            return False
-        w_alias = w_next
-
-def force(space, w_self):
-    if w_self.w_thunkalias is not None:
-        w_self = _force(space, w_self)
-    return w_self
-
-def thunk(w_callable, __args__):
-    """thunk(f, *args, **kwds) -> an object that behaves like the
-    result of the call f(*args, **kwds).  The call is performed lazily."""
-    return W_Thunk(w_callable, __args__)
-app_thunk = gateway.interp2app(thunk)
-
-def is_thunk(space, w_obj):
-    """Check if an object is a thunk that has not been computed yet."""
-    while 1:
-        w_alias = w_obj.w_thunkalias
-        if w_alias is None:
-            return space.w_False
-        if w_alias is w_NOT_COMPUTED_THUNK:
-            return space.w_True
-        w_obj = w_alias
-app_is_thunk = gateway.interp2app(is_thunk)
-
-def become(space, w_target, w_source):
-    """Globally replace the target object with the source one."""
-    w_target = force(space, w_target)
-    if not _is_circular(w_target, w_source):
-        w_target.w_thunkalias = w_source
-    return space.w_None
-app_become = gateway.interp2app(become)
-
-def lazy(space, w_callable):
-    """Decorator to make a callable return its results wrapped in a thunk."""
-    meth = Method(space, space.w_fn_thunk,
-                  w_callable, space.type(w_callable))
-    return space.wrap(meth)
-app_lazy = gateway.interp2app(lazy)
-
-# __________________________________________________________________________
-
-nb_forcing_args = {}
-
-def setup():
-    nb_forcing_args.update({
-        'setattr': 2,   # instead of 3
-        'setitem': 2,   # instead of 3
-        'get': 2,       # instead of 3
-        # ---- irregular operations ----
-        'wrap': 0,
-        'str_w': 1,
-        'int_w': 1,
-        'float_w': 1,
-        'uint_w': 1,
-        'unicode_w': 1,
-        'bigint_w': 1,
-        'interpclass_w': 1,
-        'unwrap': 1,
-        'is_true': 1,
-        'is_w': 2,
-        'newtuple': 0,
-        'newlist': 0,
-        'newdict': 0,
-        'newslice': 0,
-        'call_args': 1,
-        'marshal_w': 1,
-        'log': 1,
-        })
-    for opname, _, arity, _ in baseobjspace.ObjSpace.MethodTable:
-        nb_forcing_args.setdefault(opname, arity)
-    for opname in baseobjspace.ObjSpace.IrregularOpTable:
-        assert opname in nb_forcing_args, "missing %r" % opname
-
-setup()
-del setup
-
-# __________________________________________________________________________
-
-def proxymaker(space, opname, parentfn):
-    nb_args = nb_forcing_args[opname]
-    if nb_args == 0:
-        proxy = None
-    elif nb_args == 1:
-        def proxy(w1, *extra):
-            w1 = force(space, w1)
-            return parentfn(w1, *extra)
-    elif nb_args == 2:
-        def proxy(w1, w2, *extra):
-            w1 = force(space, w1)
-            w2 = force(space, w2)
-            return parentfn(w1, w2, *extra)
-    elif nb_args == 3:
-        def proxy(w1, w2, w3, *extra):
-            w1 = force(space, w1)
-            w2 = force(space, w2)
-            w3 = force(space, w3)
-            return parentfn(w1, w2, w3, *extra)
-    elif nb_args == 4:
-        def proxy(w1, w2, w3, w4, *extra):
-            w1 = force(space, w1)
-            w2 = force(space, w2)
-            w3 = force(space, w3)
-            w4 = force(space, w4)
-            return parentfn(w1, w2, w3, w4, *extra)
-    else:
-        raise NotImplementedError("operation %r has arity %d" %
-                                  (opname, nb_args))
-    return proxy
-
-def Space(*args, **kwds):
-    # for now, always make up a wrapped StdObjSpace
-    from pypy.objspace import std
-    space = std.Space(*args, **kwds)
-    patch_space_in_place(space, 'thunk', proxymaker)
-    space.resolve_target = lambda w_arg: _force(space, w_arg)
-    w___pypy__ = space.getbuiltinmodule("__pypy__")
-    space.w_fn_thunk = space.wrap(app_thunk)
-    space.setattr(w___pypy__, space.wrap('thunk'),
-                  space.w_fn_thunk)
-    space.setattr(w___pypy__, space.wrap('is_thunk'),
-                  space.wrap(app_is_thunk))
-    space.setattr(w___pypy__, space.wrap('become'),
-                 space.wrap(app_become))
-    space.setattr(w___pypy__, space.wrap('lazy'),
-                 space.wrap(app_lazy))
-    return space

pypy/objspace/trace.py

-"""
-   Trace object space traces operations and bytecode execution
-   in frames.
-"""
-
-from pypy.tool import pydis
-from pypy.rlib.rarithmetic import intmask
-# __________________________________________________________________________
-#
-# Tracing Events 
-# __________________________________________________________________________
-#
-
-class ExecBytecode(object):
-    """ bytecode trace. """
-    def __init__(self, frame):
-        self.frame = frame
-        self.code = frame.pycode
-        self.index = intmask(frame.last_instr)
-
-class EnterFrame(object):
-    def __init__(self, frame):
-        self.frame = frame
-
-class LeaveFrame(object):
-    def __init__(self, frame):
-        self.frame = frame
-
-class CallInfo(object):
-    """ encapsulates a function call with its arguments. """
-    def __init__(self, name, func, args, kwargs):
-        self.name = name
-        self.func = func
-        self.args = args
-        self.kwargs = kwargs
-
-class CallBegin(object):
-    def __init__(self, callinfo):
-        self.callinfo = callinfo
-
-class CallFinished(object):
-    def __init__(self, callinfo, res):
-        self.callinfo = callinfo
-        self.res = res
-        
-class CallException(object):
-    def __init__(self, callinfo, e):
-        self.callinfo = callinfo
-        self.ex = e
-                
-class TraceResult(object):
-    """ This is the state of tracing-in-progress. """
-    def __init__(self, tracespace, **printer_options):
-        self.events = []
-        self.reentrant = True
-        self.tracespace = tracespace
-        result_printer_clz = printer_options["result_printer_clz"]
-        self.printer = result_printer_clz(**printer_options)
-        self._cache = {}
-        
-    def append(self, event):
-        if self.reentrant:
-            self.reentrant = False
-            self.events.append(event)
-            self.printer.print_event(self.tracespace, self, event)
-            self.reentrant = True
-
-    def getbytecodes(self):
-        for event in self.events:
-            if isinstance(event, ExecBytecode):
-                disres = self.getdisresult(event.frame)
-                yield disres.getbytecode(event.index)
-
-    def getoperations(self):
-        for event in self.events:
-            if isinstance(event, (CallBegin, CallFinished, CallException)):
-                yield event
-                
-    def getevents(self):
-        for event in self.events:
-            yield event
-
-    def getdisresult(self, frame):
-        """ return (possibly cached) pydis result for the given frame. """
-
-        try:
-            return self._cache[id(frame.pycode)]
-        except KeyError:
-            res = self._cache[id(frame.pycode)] = pydis.pydis(frame.pycode)
-            assert res is not None
-            return res
-
-# __________________________________________________________________________
-#
-# Tracer Proxy objects 
-# __________________________________________________________________________
-#
-
-class ExecutionContextTracer(object):
-    def __init__(self, result, ec):
-        self.ec = ec
-        self.result = result
-        
-    def __getattr__(self, name):
-        """ generically pass through everything else ... """
-        return getattr(self.ec, name)
-
-    def enter(self, frame):
-        """ called just before (continuing to) evaluating a frame. """
-        self.result.append(EnterFrame(frame))
-        self.ec.enter(frame)
-
-    def leave(self, frame, w_exitvalue, got_exception):
-        """ called just after evaluating of a frame is suspended/finished. """
-        self.result.append(LeaveFrame(frame))
-        self.ec.leave(frame, w_exitvalue, got_exception)
-
-    def bytecode_trace(self, frame):
-        """ called just before execution of a bytecode. """
-        self.result.append(ExecBytecode(frame))
-        self.ec.bytecode_trace(frame)
-
-class CallableTracer(object):
-    def __init__(self, result, name, func):
-        self.result = result
-        self.name = name
-        self.func = func
-        
-    def __call__(self, *args, **kwargs):
-        callinfo = CallInfo(self.name, self.func, args, kwargs) 
-        self.result.append(CallBegin(callinfo))
-
-        try:
-            res = self.func(*args, **kwargs)
-        except Exception, e:
-            self.result.append(CallException(callinfo, e))
-            raise 
-        else:
-            self.result.append(CallFinished(callinfo, res))
-            return res
-
-    def __getattr__(self, name):
-        """ generically pass through everything we don't intercept. """
-        return getattr(self.func, name)
-
-    def __str__(self):
-        return "%s - CallableTracer(%s)" % (self.name, self.func)
-
-    __repr__ = __str__
-
-# __________________________________________________________________________
-#
-# Tracer factory 
-# __________________________________________________________________________
-#            
-
-def create_trace_space(space):    
-    """ Will turn the supplied into a traceable space by extending its class."""
-
-    # Don't trace an already traceable space
-    if hasattr(space, "__pypytrace__"):
-        return space
-
-    class Trace(space.__class__):
-
-        def __getattribute__(self, name):
-            obj = super(Trace, self).__getattribute__(name)
-            if name in ["_result", "_in_cache", "_ect_cache",
-                        "_tracing", "_config_options"]:
-                return obj
-
-            if not self._tracing or self._in_cache:
-                return obj
-
-            if name in self._config_options["operations"]:
-                assert callable(obj)
-                obj = CallableTracer(self._result, name, obj)
-                            
-            return obj
-
-        def __pypytrace__(self):
-            pass
-
-        def enter_cache_building_mode(self):
-            self._in_cache += 1
-
-        def leave_cache_building_mode(self, val):
-            self._in_cache -= 1
-
-        def settrace(self):
-            self._result = TraceResult(self, **self._config_options)
-            self._ect_cache = {}
-            self._tracing = True
-
-        def unsettrace(self):
-            self._tracing = False
-            
-        def getresult(self):
-            return self._result
-            
-        def getexecutioncontext(self):
-            ec = super(Trace, self).getexecutioncontext()
-            if not self._in_cache:
-                try:
-                    ect = self._ect_cache[ec]
-                except KeyError:
-                    assert not isinstance(ec, ExecutionContextTracer)
-                    ect = ExecutionContextTracer(self._result, ec)
-                    self._ect_cache[ec] = ect
-                return ect
-            return ec
-        
-        # XXX Rename
-        def reset_trace(self):
-            """ Returns the class to its original form. """
-            space.__class__ = space.__oldclass__
-            del space.__oldclass__
-
-            for k in ["_result", "_in_cache", "_ect_cache",
-                      "_config_options", "_operations"]:
-                if hasattr(self, k):
-                    delattr(self, k)
-            
-    trace_clz = type("Trace%s" % repr(space), (Trace,), {})
-    space.__oldclass__, space.__class__ = space.__class__, trace_clz
-
-    # Do config
-    from pypy.tool.traceconfig import config
-    space._tracing = False
-    space._result = None
-    space._ect_cache = {}
-    space._in_cache = 0
-    space._config_options = config
-
-    space.settrace()
-    return space
-
-# ______________________________________________________________________
-# End of trace.py

pypy/tool/option.py

 extra_useage = """For detailed descriptions of all the options see
 http://codespeak.net/pypy/dist/pypy/doc/config/commandline.html"""
 
-def run_tb_server(option, opt, value, parser):
-    from pypy.tool import tb_server
-    tb_server.start()
-
 def get_standard_options():
     config = get_pypy_config()
-    parser = to_optparse(config, useoptions=["objspace.*"],
-                         extra_useage=extra_useage)
-    parser.add_option(
-        '-H', action="callback",
-        callback=run_tb_server,
-        help="use web browser for traceback info")
+    parser = to_optparse(config, extra_useage=extra_useage)
     return config, parser
 
 def process_options(parser, argv=None):
     and kwds """
 
     config = get_pypy_config(translating=False)
-    objspace = kwds.pop("objspace", None)
-    if objspace is not None:
-        config.objspace.name = objspace
     for modname in kwds.pop("usemodules", []):
         setattr(config.objspace.usemodules, modname, True)
     config.set(**kwds)
     return config
 
 def make_objspace(config):
-    mod = __import__('pypy.objspace.%s' % config.objspace.name,
+    mod = __import__('pypy.objspace.std',
                      None, None, ['Space'])
     Space = mod.Space
-    #conf.objspace.logbytecodes = True
-    space = Space(config)
-    return space
-
+    return Space(config)

pypy/tool/pytest/objspace.py

 from pypy.conftest import option
 
 _SPACECACHE={}
-def gettestobjspace(name=None, **kwds):
+def gettestobjspace(**kwds):
     """ helper for instantiating and caching space's for testing.
     """
     try:
-        config = make_config(option, objspace=name, **kwds)
+        config = make_config(option,**kwds)
     except ConflictConfigError, e:
         # this exception is typically only raised if a module is not available.
         # in this case the test should be skipped
         return _SPACECACHE[key]
     except KeyError:
         if getattr(option, 'runappdirect', None):
-            if name not in (None, 'std'):
-                myname = getattr(sys, 'pypy_objspaceclass', '')
-                if not myname.lower().startswith(name):
-                    py.test.skip("cannot runappdirect test: "
-                                 "%s objspace required" % (name,))
             return TinyObjSpace(**kwds)
         space = maketestobjspace(config)
         _SPACECACHE[key] = space

pypy/tool/traceop.py

-#
-# support code for the trace object space
-#
-import autopath
-
-import sys
-
-
-class Stack(list):
-    push = list.append
-
-    def pop(self):
-        return super(Stack, self).pop(-1)
-
-    def top(self):
-        try:
-            return self[-1]
-        except IndexError:
-            return None
-
-class ResultPrinter(object):
-
-    def __init__(self,
-                 indentor = '  ',
-                 repr_type_simple = True,
-                 show_bytecode = True,
-                 output_filename = None,
-                 tree_pos_indicator = "|-",
-                 show_hidden_applevel = False,
-                 recursive_operations = False,
-                 show_wrapped_consts_bytecode = True,
-                 **kwds
-                 ):
-
-        if output_filename is None:
-            self.out = sys.stdout
-        else:
-            self.out = open(output_filename, "w")
-            
-        # Configurable stuff
-        self.indentor = indentor        
-        self.tree_pos_indicator = tree_pos_indicator
-        self.show_bytecode = show_bytecode
-        self.show_hidden_applevel = show_hidden_applevel
-        self.recursive_operations = recursive_operations
-        self.show_wrapped_consts_bytecode = show_wrapped_consts_bytecode
-        if repr_type_simple:
-            self.repr_value = simple_repr
-        else:
-            self.repr_value = repr_value
-        
-        # Keeps a stack of current state to handle
-        # showing of applevel and recursive operations
-        self.indent_state = Stack()
-
-        # Some printing state
-        self.last_line_was_new = True
-
-    def reset(self):
-        self.indent_state = Stack()
-
-    def valid_state(self):
-        state = self.indent_state.top()
-        if state is not None and not state[0]:
-            return False
-        return True
-
-    def print_line(self, line, new_line = True):
-        if self.last_line_was_new:
-            indent_count = len([c for c, t, f in self.indent_state if c])
-            if indent_count:
-                indent = indent_count - 1
-                assert (indent >= 0)
-                line = (self.indentor * indent) + self.tree_pos_indicator + line 
-
-        if new_line:
-            self.last_line_was_new = True
-            print >>self.out, line
-        else:
-            print >>self.out, line,
-            self.last_line_was_new = False
-                
-    def print_frame(self, print_type, frame):
-        if not self.valid_state():
-            return
-        
-        # Force new line if not the case
-        if not self.last_line_was_new:
-            print >>self.out, ""
-            self.last_line_was_new = True
-            
-        code = getattr(frame, 'pycode', None)
-        filename = getattr(code, 'co_filename', "")
-        filename = filename.replace("\n", "\\n")
-        lineno = getattr(code, 'co_firstlineno', "")
-
-        s = " <<<< %s %s @ %s >>>>" % (print_type, filename, lineno)
-        self.print_line(s)        
-
-    def print_bytecode(self, index, bytecode, space):
-        if not self.valid_state():
-            return
-            
-        if self.show_bytecode:
-            if self.show_wrapped_consts_bytecode:
-                bytecode_str = repr(bytecode)
-            else:
-                bytecode_str = bytecode.repr_with_space(space)
-
-            s = "%2d%s%s" % (index, (self.indentor * 2), bytecode_str)
-            self.print_line(s)
-
-    def print_op_enter(self, space, name, args):
-        if not self.valid_state():
-            return
-
-        s = " " * 4
-        s += "%s" % name
-        s += "(" + ", ".join([self.repr_value(space, ii) for ii in args]) + ")"
-        self.print_line(s, new_line=False)
-        
-    def print_op_leave(self, space, name, res):
-        if not self.valid_state():
-            return
-
-        if self.last_line_was_new:
-            s = " " * 4
-        else:
-            s = "  "
-
-        s += "-> %s" % self.repr_value(space, res)
-        self.print_line(s)
-
-    def print_op_exc(self, name, exc, space):
-        if not self.valid_state():
-            return
-
-        if self.last_line_was_new:
-            s = " " * 4
-        else:
-            s = "  "
-        s += "-> <raised> (%s)" % self.repr_value(space, exc)
-
-        self.print_line(s)
-            
-    def print_event(self, space, event_result, event):
-        from pypy.objspace import trace
-        
-        if isinstance(event, trace.EnterFrame):
-            frame = event.frame
-            if self.show_hidden_applevel or not frame.pycode.hidden_applevel:
-                show = True
-            else:
-                show = False
-
-            self.indent_state.push((show, trace.EnterFrame, frame))
-            self.print_frame("enter", frame)
-
-        elif isinstance(event, trace.LeaveFrame):
-
-            lastframe = self.indent_state.top()[2]
-            assert lastframe is not None
-
-            self.print_frame("leave", lastframe)           
-            self.indent_state.pop()
-