[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