[pypy-svn] r10004 - in pypy/dist/pypy: interpreter objspace tool

arigo at codespeak.net arigo at codespeak.net
Mon Mar 21 18:29:44 CET 2005


Author: arigo
Date: Mon Mar 21 18:29:44 2005
New Revision: 10004

Added:
   pypy/dist/pypy/objspace/proxy.py
      - copied, changed from r9991, pypy/dist/pypy/objspace/trace.py
   pypy/dist/pypy/objspace/thunk.py
Modified:
   pypy/dist/pypy/interpreter/interactive.py
   pypy/dist/pypy/tool/option.py
Log:
Replaced py.py  -T  and  -S  options with  -o <name>.

Implemented a simple "thunk object space".  See example usage in the
docstring.



Modified: pypy/dist/pypy/interpreter/interactive.py
==============================================================================
--- pypy/dist/pypy/interpreter/interactive.py	(original)
+++ pypy/dist/pypy/interpreter/interactive.py	Mon Mar 21 18:29:44 2005
@@ -31,7 +31,7 @@
             #    self.space.__class__.__name__)
             elapsed = time.time() - self.space._starttime
             banner = "PyPy in %s on top of Python %s (startupttime: %.2f secs)" % (
-                self.space.__class__.__name__, sys.version.split()[0], elapsed)
+                self.space.__repr__(), sys.version.split()[0], elapsed)
         code.InteractiveConsole.interact(self, banner)
 
     def raw_input(self, prompt=""):

Copied: pypy/dist/pypy/objspace/proxy.py (from r9991, pypy/dist/pypy/objspace/trace.py)
==============================================================================
--- pypy/dist/pypy/objspace/trace.py	(original)
+++ pypy/dist/pypy/objspace/proxy.py	Mon Mar 21 18:29:44 2005
@@ -1,216 +1,32 @@
-"""
-   Trace object space traces operations and bytecode execution
-   in frames.
-"""
-
-from __future__ import generators
-from pypy.tool import pydis 
+import py
 from pypy.interpreter.baseobjspace import ObjSpace
 
 # __________________________________________________________________________
-#
-# Tracing Events 
-# __________________________________________________________________________
-#
-
-class ExecBytecode(object):
-    """ bytecode trace. """
-    def __init__(self, frame):
-        self.frame = frame
-        self.code = frame.code
-        self.index = frame.next_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):
-        self.events = []
-        self.tracespace = tracespace
-
-    def append(self, arg):
-        self.events.append(arg)
-
-    def getdisresult(self, frame, _cache = {}):
-        """ return (possibly cached) pydis result for the given frame. """
-        try:
-            return _cache[id(frame.code)]
-        except KeyError:
-            res = _cache[id(frame.code)] = pydis.pydis(frame.code)
-            assert res is not None
-            return res
-
-    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
-
-# __________________________________________________________________________
-#
-# 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))
-        return self.ec.enter(frame)
-
-    def leave(self, previous_ec):
-        """ called just after evaluating of a frame is suspended/finished. """
-        frame = self.ec.framestack.top()
-        self.result.append(LeaveFrame(frame))
-        return self.ec.leave(previous_ec)
-
-    def bytecode_trace(self, frame):
-        """ called just before execution of a bytecode. """
-        self.result.append(ExecBytecode(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__
+def get_operations():
+    return [r[0] for r in ObjSpace.MethodTable] + ObjSpace.IrregularOpTable
 
-# __________________________________________________________________________
-#
-# Tracer factory 
-# __________________________________________________________________________
-#            
+def create_proxy_space(proxyname, proxymaker, operations=None, space=None):
+    """ Will create a proxy object space if no space supplied.  Otherwise
+    will patch the supplied space."""
 
-operations = None
-def get_operations():
-    global operations
-    if operations is None:
-        operations = dict([(r[0], r[0]) for r in ObjSpace.MethodTable])
-        for name in ObjSpace.IrregularOpTable+ ["get_and_call_function"]:
-            operations[name] = name
-
-    return operations
-
-def create_trace_space(space = None, operations = None):    
-    """ Will create a trace object space if no space supplied.  Otherwise
-    will turn the supplied into a tracable space by extending its class."""
-
-    # Don't trace an already tracable space
-    if hasattr(space, "__pypytrace__"):
-        return space
-    
     if space is None:
-        # make up a TrivialObjSpace by default
-        # ultimately, remove this hack and fix the -P option of tests
-        from pypy.objspace import trivial
-        space = trivial.TrivialObjSpace()
+        # make up a StdObjSpace by default
+        from pypy.objspace import std
+        space = std.Space()
 
     if operations is None:
         operations = get_operations()
 
-    class Trace(space.__class__):
-
-        def __getattribute__(self, name):
-            obj = super(Trace, self).__getattribute__(name)
-            if name in operations:
-                assert callable(obj)
-                obj = CallableTracer(self._result, name, obj)
-            return obj
-
-        def __pypytrace__(self):
-            pass
-
-        def settrace(self):
-            self._result = TraceResult(self)
-
-        def getresult(self):
-            return self._result
-            
-        def getexecutioncontext(self):
-            ec = super(Trace, self).getexecutioncontext()
-            assert not isinstance(ec, ExecutionContextTracer)
-            return ExecutionContextTracer(self._result, ec)
-        
-        def reset_trace(self):
-            """ Returns the class to it's original form. """
-            space.__class__ = space.__oldclass__
-            del space.__oldclass__
+    for name in operations:
+        parentfn = getattr(space, name)
+        proxy = proxymaker(space, name, parentfn)
+        if proxy:
+            setattr(space, name, proxy)
 
-            if hasattr(self, "_result"):
-                del self._result            
+    prevrepr = space.__repr__()
+    space.__repr__ = lambda: '%s(%s)' % (proxyname, prevrepr)
 
-    trace_clz = type("Trace" + space.__class__.__name__, (Trace,), {})
-    space.__oldclass__, space.__class__ = space.__class__, trace_clz
-
-    # XXX Ensure space's sys & builtin are fully loaded?
-    space.settrace()
     return space
 
-# ______________________________________________________________________
-# End of trace.py
+# __________________________________________________________________________

Added: pypy/dist/pypy/objspace/thunk.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/thunk.py	Mon Mar 21 18:29:44 2005
@@ -0,0 +1,66 @@
+"""Example usage:
+
+    $ python interpreter/py.py -o thunk
+    >>> def f():
+    ...     print 'computing...'
+    ...     return 6*7
+    ...
+    >>> x = thunk(f)
+    >>> x
+    computing...
+    42
+    >>> x
+    42
+    >>> y = thunk(f)
+    >>> type(y)
+    computing...
+    <pypy type 'int'>
+"""
+
+from proxy import create_proxy_space
+from pypy.interpreter import gateway
+from pypy.interpreter.baseobjspace import W_Root
+
+# __________________________________________________________________________
+
+class Thunk(W_Root, object):
+    def __init__(w_self, space, w_callable):
+        w_self.space = space
+        w_self.w_callable = w_callable
+        w_self.w_value = None
+
+def force(w_self):
+    while isinstance(w_self, Thunk):
+        if w_self.w_value is None:
+            w_self.w_value = w_self.space.call_function(w_self.w_callable)
+            w_self.w_callable = None
+        w_self = w_self.w_value
+    return w_self
+
+def thunk(space, w_callable):
+    return Thunk(space, w_callable)
+app_thunk = gateway.interp2app(thunk)
+
+# __________________________________________________________________________
+
+operation_args_that_dont_force = {
+    ('setattr', 2): True,
+    ('setitem', 2): True,
+    }
+
+def proxymaker(space, opname, parentfn):
+    def proxy(*args):
+        newargs = []
+        for i in range(len(args)):
+            a = args[i]
+            if (opname, i) not in operation_args_that_dont_force:
+                a = force(a)
+            newargs.append(a)
+        return parentfn(*newargs)
+    return proxy
+
+def Space():
+    space = create_proxy_space('thunk', proxymaker)
+    space.setitem(space.builtin.w_dict, space.wrap('thunk'),
+                  space.wrap(app_thunk))
+    return space

Modified: pypy/dist/pypy/tool/option.py
==============================================================================
--- pypy/dist/pypy/tool/option.py	(original)
+++ pypy/dist/pypy/tool/option.py	Mon Mar 21 18:29:44 2005
@@ -14,21 +14,17 @@
 def get_standard_options():
     options = []
 
-    def objspace_callback(option, opt, value, parser, space):
-        parser.values.spaces.append(space)
+    def objspace_callback(option, opt, value, parser):
+        parser.values.spaces.append(value)
 
     options.append(make_option(
-        '-S', action="callback",
-        callback=objspace_callback, callback_args=("std",),
-        help="run in std object space"))
+        '-o', '--objspace', action="callback",
+        callback=objspace_callback, type="string",
+        help="object space to run PyPy on."))
     options.append(make_option(
         '--oldstyle', action="store_true",dest="oldstyle",
         help="enable oldstyle classes as default metaclass (std objspace only)"))    
     options.append(make_option(
-        '-T', action="callback",
-        callback=objspace_callback, callback_args=("trivial",),
-        help="run in trivial object space"))
-    options.append(make_option(
         '-w', action="store_true", dest="showwarning",
         help="enable warnings (disabled by default)"))
     options.append(make_option(



More information about the Pypy-commit mailing list