[pypy-svn] rev 1278 - in pypy/branch/builtinrefactor/pypy: interpreterinterpreter/test objspace

arigo at codespeak.net arigo at codespeak.net
Tue Sep 9 21:38:31 CEST 2003


Author: arigo
Date: Tue Sep  9 21:38:29 2003
New Revision: 1278

Added:
   pypy/branch/builtinrefactor/pypy/interpreter/generator.py
Modified:
   pypy/branch/builtinrefactor/pypy/interpreter/function.py
   pypy/branch/builtinrefactor/pypy/interpreter/nestedscope.py
   pypy/branch/builtinrefactor/pypy/interpreter/pycode.py
   pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py
   pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py
   pypy/branch/builtinrefactor/pypy/interpreter/test/test_interpreter.py
   pypy/branch/builtinrefactor/pypy/interpreter/test/test_objspace.py
   pypy/branch/builtinrefactor/pypy/objspace/trivial.py
Log:
interpreter tests working again

Modified: pypy/branch/builtinrefactor/pypy/interpreter/function.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/function.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/function.py	Tue Sep  9 21:38:29 2003
@@ -25,7 +25,8 @@
 
     def call(self, w_args, w_kwds=None):
         scope_w = self.parse_args(w_args, w_kwds)
-        frame = self.func_code.create_frame(self.space, self.w_globals)
+        frame = self.func_code.create_frame(self.space, self.w_globals,
+                                            self.closure)
         frame.setfastscope(scope_w)
         return frame.run()
 

Added: pypy/branch/builtinrefactor/pypy/interpreter/generator.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/generator.py	Tue Sep  9 21:38:29 2003
@@ -0,0 +1,88 @@
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.baseobjspace import NoValue
+from pypy.interpreter.eval import Frame
+from pypy.interpreter.pyframe import ControlFlowException, ExitFrame
+
+#
+# Generator support. Note that GeneratorFrame is not a subclass of PyFrame.
+# PyCode objects use a custom subclass of both PyFrame and GeneratorFrame
+# when they need to interpret Python bytecode that is a generator.
+# Otherwise, GeneratorFrame could also be used to define, say,
+# built-in generators (which are usually done in CPython as functions
+# that return iterators).
+#
+
+class GeneratorFrame(Frame):
+    "A frame attached to a generator."
+
+    def run(self):
+        "Build a generator-iterator."
+        self.exhausted = False
+        return GeneratorIterator(self)
+
+    ### extra opcodes ###
+
+    # XXX mmmh, GeneratorFrame is supposed to be independent from
+    # Python bytecode... Well, it is. These are not used when
+    # GeneratorFrame is used with other kinds of Code subclasses.
+
+    def RETURN_VALUE(f):  # overridden
+        raise SGeneratorReturn()
+
+    def YIELD_VALUE(f):
+        w_yieldedvalue = f.valuestack.pop()
+        raise SYieldValue(w_yieldedvalue)
+    YIELD_STMT = YIELD_VALUE  # misnamed in old versions of dis.opname
+
+
+class GeneratorIterator(object):
+    "An iterator created by a generator."
+    
+    def __init__(self, frame):
+        self.frame = frame
+        self.running = False
+
+    def nextvalue(self):
+        # raise NoValue when exhausted
+        if self.running:
+            space = self.frame.space
+            raise OperationError(space.w_ValueError,
+                                 space.wrap('generator already executing'))
+        if self.frame.exhausted:
+            raise NoValue
+        self.running = True
+        try:
+            return Frame.run(self.frame)
+        finally:
+            self.running = False
+
+
+    # XXX trick for trivialobjspace
+    # XXX make these __iter__() and next() app-visible
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        # XXX trivialobjspace only !!
+        try:
+            return self.nextvalue()
+        except NoValue:
+            raise StopIteration
+
+#
+# the specific ControlFlowExceptions used by generators
+#
+
+class SYieldValue(ControlFlowException):
+    """Signals a 'yield' statement.
+    Argument is the wrapped object to return."""
+    def action(self, frame, last_instr, executioncontext):
+        w_yieldvalue = self.args[0]
+        raise ExitFrame(w_yieldvalue)
+
+class SGeneratorReturn(ControlFlowException):
+    """Signals a 'return' statement inside a generator."""
+    def emptystack(self, frame):
+        frame.exhausted = True
+        raise NoValue

Modified: pypy/branch/builtinrefactor/pypy/interpreter/nestedscope.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/nestedscope.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/nestedscope.py	Tue Sep  9 21:38:29 2003
@@ -1,3 +1,4 @@
+from pypy.interpreter.error import OperationError
 from pypy.interpreter.eval import UNDEFINED
 from pypy.interpreter.pyopcode import PyInterpFrame
 
@@ -56,6 +57,7 @@
                 raise OperationError(space.w_TypeError,
                                      "directly executed code object "
                                      "may not contain free variables")
+            closure = []
         else:
             if len(closure) != nfreevars:
                 raise ValueError("code object received a closure with "
@@ -88,7 +90,7 @@
                 cell.set(w_value)
 
     def setfastscope(self, scope_w):
-        PyInterpFrame.setfastscope(scope_w)
+        PyInterpFrame.setfastscope(self, scope_w)
         if self.code.co_cellvars:
             # the first few cell vars could shadow already-set arguments,
             # in the same order as they appear in co_varnames
@@ -158,10 +160,9 @@
         nfreevars = len(codeobj.co_freevars)
         freevars = [f.valuestack.pop() for i in range(nfreevars)]
         freevars.reverse()
-        w_freevars = f.space.newtuple(freevars)
         defaultarguments = [f.valuestack.pop() for i in range(numdefaults)]
         defaultarguments.reverse()
         w_defaultarguments = f.space.newtuple(defaultarguments)
         w_func = f.space.newfunction(f.space.unwrap(w_codeobj),
-                                     f.w_globals, w_defaultarguments, w_freevars)
+                                     f.w_globals, w_defaultarguments, freevars)
         f.valuestack.push(w_func)

Modified: pypy/branch/builtinrefactor/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/pycode.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pycode.py	Tue Sep  9 21:38:29 2003
@@ -60,11 +60,14 @@
     def create_frame(self, space, w_globals, closure=None):
         "Create an empty PyFrame suitable for this code object."
         # select the appropriate kind of frame
+        from pypy.interpreter.pyopcode import PyInterpFrame as Frame
         if self.co_cellvars or self.co_freevars:
             from pypy.interpreter.nestedscope import PyNestedScopeFrame as F
-        else:
-            from pypy.interpreter.pyopcode import PyInterpFrame as F
-        return F(space, self, w_globals, closure)
+            Frame = enhanceclass(Frame, F)
+        if self.co_flags & CO_GENERATOR:
+            from pypy.interpreter.generator import GeneratorFrame as F
+            Frame = enhanceclass(Frame, F)
+        return Frame(space, self, w_globals, closure)
 
     def signature(self):
         "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
@@ -85,10 +88,23 @@
     def getvarnames(self):
         return self.co_varnames
 
-    def is_generator(self):
-        return self.co_flags & CO_GENERATOR
-
     def dictscope_needed(self):
         # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
         # class bodies only have CO_NEWLOCALS.
         return not (self.co_flags & CO_OPTIMIZED)
+
+
+def enhanceclass(baseclass, newclass, cache={}):
+    # this is a bit too dynamic for RPython, but it looks nice
+    # and I assume that we can easily change it into a static
+    # pre-computed table
+    if issubclass(newclass, baseclass):
+        return newclass
+    else:
+        try:
+            return cache[baseclass, newclass]
+        except KeyError:
+            class Mixed(newclass, baseclass):
+                pass
+            cache[baseclass, newclass] = Mixed
+            return Mixed

Modified: pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py	Tue Sep  9 21:38:29 2003
@@ -265,15 +265,6 @@
     """Signals a 'return' statement.
     Argument is the wrapped object to return."""
     def emptystack(self, frame):
-        if frame.code.is_generator():
-            raise baseobjspace.NoValue
-        w_returnvalue = self.args[0]
-        raise ExitFrame(w_returnvalue)
-
-class SYieldValue(ControlFlowException):
-    """Signals a 'yield' statement.
-    Argument is the wrapped object to return."""
-    def action(self, frame, last_instr, executioncontext):
         w_returnvalue = self.args[0]
         raise ExitFrame(w_returnvalue)
 

Modified: pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py	Tue Sep  9 21:38:29 2003
@@ -312,11 +312,6 @@
         w_returnvalue = f.valuestack.pop()
         raise pyframe.SReturnValue(w_returnvalue)
 
-    def YIELD_VALUE(f):
-        w_yieldedvalue = f.valuestack.pop()
-        raise pyframe.SYieldValue(w_yieldedvalue)
-    YIELD_STMT = YIELD_VALUE  # misnamed in dis.opname
-
     def EXEC_STMT(f):
         w_locals  = f.valuestack.pop()
         w_globals = f.valuestack.pop()

Modified: pypy/branch/builtinrefactor/pypy/interpreter/test/test_interpreter.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/test/test_interpreter.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/test/test_interpreter.py	Tue Sep  9 21:38:29 2003
@@ -19,9 +19,9 @@
         w_tempmodule = space.newmodule(w("__temp__"))
         w_glob = space.getattr(w_tempmodule, w("__dict__"))
         space.setitem(w_glob, w("__builtins__"), space.w_builtins)
-       
-        scopedcode = gateway.ScopedCode(space, space.unwrap(w_code), w_glob)
-        scopedcode.eval_frame()
+
+        code = space.unwrap(w_code)
+        code.exec_code(space, w_glob, w_glob)
 
         wrappedargs = w(args)
         wrappedfunc = space.getitem(w_glob, w(functionname))

Modified: pypy/branch/builtinrefactor/pypy/interpreter/test/test_objspace.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/test/test_objspace.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/test/test_objspace.py	Tue Sep  9 21:38:29 2003
@@ -68,7 +68,8 @@
         def f(x):
             return x
 
-        cpycode = f.func_code
+        from pypy.interpreter.pycode import PyCode
+        cpycode = PyCode()._from_code(f.func_code)
         w_globals = self.space.newdict([])
         w_defs = self.space.newtuple([])
         w_f = self.space.newfunction(cpycode, w_globals, w_defs)

Modified: pypy/branch/builtinrefactor/pypy/objspace/trivial.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/objspace/trivial.py	(original)
+++ pypy/branch/builtinrefactor/pypy/objspace/trivial.py	Tue Sep  9 21:38:29 2003
@@ -157,7 +157,9 @@
         #ec = self.getexecutioncontext() # .framestack.items[-1]
         #ec.print_detailed_traceback(self)
 
-        etype, evalue = sys.exc_info()[:2]
+        etype, evalue, etb = sys.exc_info()
+        if etype is OperationError:
+            raise etype, evalue, etb   # just re-raise it
         name = etype.__name__
         if hasattr(self, 'w_' + name):
             nt = getattr(self, 'w_' + name)
@@ -171,7 +173,7 @@
         else:
             nt = etype
             nv = evalue
-        raise OperationError(nt, nv)
+        raise OperationError, OperationError(nt, nv), etb
 
     def _auto(name, sourcefn, classlocals):
         s = """


More information about the Pypy-commit mailing list