[pypy-svn] r9937 - in pypy/dist: lib-python-2.3.4/test pypy/interpreter pypy/module/sys2 pypy/objspace

ac at codespeak.net ac at codespeak.net
Sun Mar 20 18:13:18 CET 2005


Author: ac
Date: Sun Mar 20 18:13:18 2005
New Revision: 9937

Modified:
   pypy/dist/lib-python-2.3.4/test/test_scope.py
   pypy/dist/pypy/interpreter/eval.py
   pypy/dist/pypy/interpreter/executioncontext.py
   pypy/dist/pypy/interpreter/pyframe.py
   pypy/dist/pypy/interpreter/typedef.py
   pypy/dist/pypy/module/sys2/__init__.py
   pypy/dist/pypy/module/sys2/vm.py
   pypy/dist/pypy/objspace/trace.py
Log:
Preliminary work on sys.settrace() functionality. Stay tuned for more checkins.

Modified: pypy/dist/lib-python-2.3.4/test/test_scope.py
==============================================================================
--- pypy/dist/lib-python-2.3.4/test/test_scope.py	(original)
+++ pypy/dist/lib-python-2.3.4/test/test_scope.py	Sun Mar 20 18:13:18 2005
@@ -437,6 +437,7 @@
 d = f(2)(4)
 verify(d.has_key('h'))
 del d['h']
+print d
 verify(d == {'x': 2, 'y': 7, 'w': 6})
 
 print "19. var is bound and free in class"

Modified: pypy/dist/pypy/interpreter/eval.py
==============================================================================
--- pypy/dist/pypy/interpreter/eval.py	(original)
+++ pypy/dist/pypy/interpreter/eval.py	Sun Mar 20 18:13:18 2005
@@ -65,12 +65,7 @@
     def resume(self):
         "Resume the execution of the frame from its current state."
         executioncontext = self.space.getexecutioncontext()
-        previous = executioncontext.enter(self)
-        try:
-            result = self.eval(executioncontext)
-        finally:
-            executioncontext.leave(previous)
-        return result
+        return self.eval(executioncontext)
 
     # running a frame is usually the same as resuming it from its
     # initial state, but not for generator frames

Modified: pypy/dist/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/dist/pypy/interpreter/executioncontext.py	(original)
+++ pypy/dist/pypy/interpreter/executioncontext.py	Sun Mar 20 18:13:18 2005
@@ -10,7 +10,9 @@
         self.space = space
         self.framestack = Stack()
         self.stateDict = {}
-        
+        self.w_tracefunc = None
+        self.is_tracing = 0
+
     def enter(self, frame):
         if self.framestack.depth() > self.space.sys.recursionlimit:
             raise OperationError(self.space.w_RuntimeError,
@@ -18,10 +20,17 @@
         locals = getthreadlocals()
         previous_ec = locals.executioncontext
         locals.executioncontext = self
+        if self.framestack.empty():
+            frame.f_back = None
+        else:
+            frame.f_back = self.framestack.top()
         self.framestack.push(frame)
+        self.call_trace(frame, 'call', self.space.w_None)
         return previous_ec
 
-    def leave(self, previous_ec):
+    def leave(self, previous_ec, w_retval=None):
+        if w_retval is not None:
+            self.call_trace(self.framestack.top(), 'return', w_retval)
         self.framestack.pop()
         locals = getthreadlocals()
         locals.executioncontext = previous_ec
@@ -46,6 +55,8 @@
     def exception_trace(self, operationerr):
         "Trace function called upon OperationError."
         operationerr.record_interpreter_traceback()
+        self.call_trace(self.framestack.top(), 'exception',
+                        self.sys_exc_info())
         #operationerr.print_detailed_traceback(self.space)
 
     def sys_exc_info(self):
@@ -62,3 +73,32 @@
         Similar to cpython's PyThreadState_GetDict.
         """
         return self.stateDict
+
+    def settrace(self, w_func):
+        """Set the global trace function."""
+        if self.space.is_(w_func, self.space.w_None):
+            self.w_tracefunc = None
+        else:
+            self.w_tracefunc = w_func
+
+    def call_trace(self, frame, event, w_arg):
+        if event == 'call':
+            w_callback = self.w_tracefunc
+        else:
+            w_callback = frame.w_f_trace
+        if self.is_tracing or w_callback is None:
+            return
+        self.is_tracing += 1
+        try:
+            try:
+                w_result = self.space.call(w_callback, self.space.wrap(frame), self.space.wrap(event), w_arg)
+                if self.space.is_(w_result, self.space.w_None):
+                    frame.w_f_trace = None
+                else:
+                    frame.w_f_trace = w_result
+            except:
+                self.settrace(self.space.w_None)
+                frame.w_f_trace = None
+        finally:
+            self.is_traceing -= 1
+            

Modified: pypy/dist/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyframe.py	(original)
+++ pypy/dist/pypy/interpreter/pyframe.py	Sun Mar 20 18:13:18 2005
@@ -40,7 +40,10 @@
             self.w_locals = space.newdict([])  # set to None by Frame.__init__
 
         self.fastlocals_w = [None]*self.numlocals
-
+        self.w_f_trace = None
+        self.last_instr = -1
+        self.f_back = None
+        
     def getfastscope(self):
         "Get the fast locals as a list."
         return self.fastlocals_w
@@ -60,8 +63,9 @@
 
     def eval(self, executioncontext):
         "Interpreter main loop!"
+        previous = executioncontext.enter(self)
         try:
-            last_instr = -1
+            self.last_instr = -1
             while True:
                 try:
                     try:
@@ -70,7 +74,7 @@
                                 # fetch and dispatch the next opcode
                                 # dispatch() is abstract, see pyopcode.
                                 executioncontext.bytecode_trace(self)
-                                last_instr = self.next_instr
+                                self.last_instr = self.next_instr
                                 self.dispatch()
                         # catch asynchronous exceptions and turn them
                         # into OperationErrors
@@ -89,7 +93,7 @@
 
                     except OperationError, e:
                         pytraceback.record_application_traceback(
-                            self.space, e, self, last_instr)
+                            self.space, e, self, self.last_instr)
                         executioncontext.exception_trace(e)
                         # convert an OperationError into a control flow
                         # exception
@@ -100,13 +104,17 @@
                 except ControlFlowException, ctlflowexc:
                     # we have a reason to change the control flow
                     # (typically unroll the stack)
-                    ctlflowexc.action(self, last_instr, executioncontext)
+                    ctlflowexc.action(self, self.last_instr, executioncontext)
             
         except ExitFrame, e:
             # leave that frame
             w_exitvalue = e.args[0]
+            executioncontext.leave(previous, w_exitvalue)
             return w_exitvalue
-
+        except:
+            executioncontext.leave(previous)
+            raise
+        
     ### exception stack ###
 
     def clean_exceptionstack(self):
@@ -138,7 +146,22 @@
         self = space.interpclass_w(w_self)
         return self.builtin.getdict()
 
+    def fget_f_back(space, w_self):
+        self = space.interpclass_w(w_self)
+        return self.space.wrap(self.f_back)
 
+    def fget_f_lasti(space, w_self):
+        self = space.interpclass_w(w_self)
+        return self.space.wrap(self.last_instr)
+
+    def fget_f_trace(space, w_self):
+        self = space.interpclass_w(w_self)
+        return self.w_f_trace
+
+    def fset_f_trace(space, w_self, w_trace):
+        self = space.interpclass_w(w_self)
+        self.w_f_trace = w_trace
+        
 ### Frame Blocks ###
 
 class FrameBlock:

Modified: pypy/dist/pypy/interpreter/typedef.py
==============================================================================
--- pypy/dist/pypy/interpreter/typedef.py	(original)
+++ pypy/dist/pypy/interpreter/typedef.py	Sun Mar 20 18:13:18 2005
@@ -325,6 +325,9 @@
 PyFrame.typedef = TypeDef('frame',
     f_builtins = GetSetProperty(PyFrame.fget_f_builtins),
     f_lineno = GetSetProperty(PyFrame.fget_f_lineno),
+    f_back = GetSetProperty(PyFrame.fget_f_back),
+    f_lasti = GetSetProperty(PyFrame.fget_f_lasti),
+    f_trace = GetSetProperty(PyFrame.fget_f_trace, PyFrame.fset_f_trace),
     **Frame.typedef.rawdict)
 
 Module.typedef = TypeDef("module",

Modified: pypy/dist/pypy/module/sys2/__init__.py
==============================================================================
--- pypy/dist/pypy/module/sys2/__init__.py	(original)
+++ pypy/dist/pypy/module/sys2/__init__.py	Sun Mar 20 18:13:18 2005
@@ -42,7 +42,9 @@
         'getcheckinterval'      : 'vm.getcheckinterval', 
         'exc_info'              : 'vm.exc_info', 
         'exc_clear'             : 'vm.exc_clear', 
-
+        'settrace'              : 'vm.settrace',
+        'setprofile'            : 'vm.setprofile',
+        
         'executable'            : 'space.wrap("py.py")', 
         'copyright'             : 'space.wrap("MIT-License")', 
         'api_version'           : 'space.wrap(1012)', 

Modified: pypy/dist/pypy/module/sys2/vm.py
==============================================================================
--- pypy/dist/pypy/module/sys2/vm.py	(original)
+++ pypy/dist/pypy/module/sys2/vm.py	Sun Mar 20 18:13:18 2005
@@ -93,3 +93,17 @@
     # value of 6 to get results comparable to cpythons. /Arre
     return space.wrap(sys.getrefcount(w_obj) - 6)
 
+def settrace(space, w_func):
+    """settrace(function)
+
+Set the global debug tracing function.  It will be called on each
+function call.  See the debugger chapter in the library manual.
+"""
+
+def setprofile(space, w_func):
+    """setprofile(function)
+
+Set the profiling function.  It will be called on each function call
+and return.  See the profiler chapter in the library manual.
+"""
+

Modified: pypy/dist/pypy/objspace/trace.py
==============================================================================
--- pypy/dist/pypy/objspace/trace.py	(original)
+++ pypy/dist/pypy/objspace/trace.py	Sun Mar 20 18:13:18 2005
@@ -103,11 +103,11 @@
         self.result.append(EnterFrame(frame))
         return self.ec.enter(frame)
 
-    def leave(self, previous_ec):
+    def leave(self, previous_ec, w_exitval=None):
         """ 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)
+        return self.ec.leave(previous_ec, w_exitval)
 
     def bytecode_trace(self, frame):
         """ called just before execution of a bytecode. """



More information about the Pypy-commit mailing list