[pypy-svn] rev 1263 - pypy/branch/builtinrefactor/pypy/interpreter

arigo at codespeak.net arigo at codespeak.net
Sat Aug 9 15:48:31 CEST 2003


Author: arigo
Date: Sat Aug  9 15:48:30 2003
New Revision: 1263

Added:
   pypy/branch/builtinrefactor/pypy/interpreter/error.py   (contents, props changed)
      - copied, changed from rev 1262, pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py
   pypy/branch/builtinrefactor/pypy/interpreter/eval.py
   pypy/branch/builtinrefactor/pypy/interpreter/function.py
   pypy/branch/builtinrefactor/pypy/interpreter/pycode.py
   pypy/branch/builtinrefactor/pypy/interpreter/pyfastscope.py
   pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py
   pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py   (contents, props changed)
      - copied, changed from rev 1262, pypy/branch/builtinrefactor/pypy/interpreter/opcode.py
Removed:
   pypy/branch/builtinrefactor/pypy/interpreter/opcode.py
Modified:
   pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py
   pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py
   pypy/branch/builtinrefactor/pypy/interpreter/gateway.py
   pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py
Log:
This is a middle-work check-in. Nothing works.

A    interpreter/eval.py
  New abstract base classes Code and Frame

A    interpreter/pycode.py
M    interpreter/pyframe.py
  Concrete subclasses of Code and Frame

D    interpreter/opcode.py
AM   interpreter/pyopcode.py
A    interpreter/pyfastscope.py
A    interpreter/pynestedscope.py
  Opcodes moved into three seperate files
  defining a subclass of PyFrame each

M    interpreter/gateway.py
M    interpreter/baseobjspace.py
  Various changes here, work in progress

A    interpreter/function.py
  The one and unique Function class, with argument parsing

M    interpreter/executioncontext.py
AM   interpreter/error.py
  OperationError moved to its own module


Modified: pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py	Sat Aug  9 15:48:30 2003
@@ -1,18 +1,14 @@
-from executioncontext import ExecutionContext, OperationError, NoValue
-import threadlocals
+from pypy.interpreter.executioncontext import ExecutionContext, Stack
+from pypy.interpreter.error import OperationError
+from pypy.interpreter import threadlocals
 
-__all__ = ['ObjSpace', 'OperationError', 'NoValue', 'PyPyError']
+__all__ = ['ObjSpace', 'OperationError', 'NoValue']
+
+
+class NoValue(Exception):
+    """Raised to signal absence of value, e.g. in the iterator accessing
+    method 'op.next()' of object spaces."""
 
-class PyPyError(Exception):
-    "Raise this when you encounter an exceptional situation in PyPy itself."
-    def __init__(self, space, operationerr):
-        self.space = space
-        self.operationerr = operationerr
-
-class Null:
-    """ marker object for Null values within the interpreter
-        (not visible at app-level)
-    """
 
 class ObjSpace:
     """Base class for the interpreter-level implementations of object spaces.
@@ -146,31 +142,19 @@
         check_list = [w_check_class]
         while check_list:
             w_item = check_list.pop()
-            #Test within iterables (i.e. tuples)
+            # Match identical items.
+            if self.is_true(self.is_(w_exc_type, w_item)):
+                return True
+            # Test within iterables (i.e. tuples)
             try:
                 exclst = self.unpackiterable(w_item)
                 check_list.extend(exclst)
-            except KeyboardInterrupt:
-                raise
-            except:
-                #w_check_class is not iterable
-                pass
-            #w_item should now be an Exception (or string?)
-            #Match identical items.
-            w_rv = self.is_(w_exc_type, w_item)
-            if self.is_true(w_rv):
-                return w_rv
-            #Match subclasses.
-            try:
-                w_rv = self.issubtype(w_exc_type, w_item)
-            except KeyboardInterrupt:
-                raise
-            except:
-                pass
-            else:
-                if self.is_true(w_rv):
-                    return w_rv
-        return self.w_False
+            except OperationError:
+                # w_item is not iterable; it should then be an Exception.
+                # Match subclasses.
+                if self.is_true(self.issubtype(w_exc_type, w_item)):
+                    return True
+        return False
 
     def call_function(self, w_func, *args_w, **kw_w):
         w_kw = self.newdict([(self.wrap(k), w_v) for k, w_v in kw_w.iteritems()])

Copied: pypy/branch/builtinrefactor/pypy/interpreter/error.py (from rev 1262, pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py)
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/error.py	Sat Aug  9 15:48:30 2003
@@ -1,53 +1,11 @@
 import sys
-import threadlocals
 
-class ExecutionContext:
 
-    def __init__(self, space):
+class PyPyError(Exception):
+    "Raise this when you encounter an exceptional situation in PyPy itself."
+    def __init__(self, space, operationerr):
         self.space = space
-        self.framestack = Stack()
-
-    def eval_frame(self, frame):
-        locals = threadlocals.getlocals()
-        self.framestack.push(frame)
-        previous_ec = locals.executioncontext
-        locals.executioncontext = self
-        try:
-            result = frame.eval(self)
-        finally:
-            locals.executioncontext = previous_ec
-            self.framestack.pop()
-        return result
-
-    def get_w_builtins(self):
-        if self.framestack.empty():
-            return self.space.w_builtins
-        else:
-            return self.framestack.top().w_builtins
-
-    def make_standard_w_globals(self):
-        "Create a new empty 'globals' dictionary."
-        w_key = self.space.wrap("__builtins__")
-        w_value = self.get_w_builtins()
-        w_globals = self.space.newdict([(w_key, w_value)])
-        return w_globals
-
-    def bytecode_trace(self, frame):
-        "Trace function called before each bytecode."
-
-    def exception_trace(self, operationerr):
-        "Trace function called upon OperationError."
-        operationerr.record_interpreter_traceback()
-        #operationerr.print_detailed_traceback(self.space)
-
-    def sys_exc_info(self):
-        """Implements sys.exc_info().
-        Return an OperationError instance or None."""
-        for i in range(self.framestack.depth()):
-            frame = self.framestack.top(i)
-            if frame.last_exception is not None:
-                return frame.last_exception
-        return None
+        self.operationerr = operationerr
 
 
 class OperationError(Exception):
@@ -71,7 +29,7 @@
 
     def match(self, space, w_check_class):
         "Check if this application-level exception matches 'w_check_class'."
-        return space.is_true(space.exception_match(self.w_type, w_check_class))
+        return space.exception_match(self.w_type, w_check_class)
 
     def __str__(self):
         "Convenience for tracebacks."
@@ -155,11 +113,6 @@
             print >> file, exc_typename+':', exc_value
 
 
-class NoValue(Exception):
-    """Raised to signal absence of value, e.g. in the iterator accessing
-    method 'op.next()' of object spaces."""
-
-
 # Utilities
 
 def inlinecompile(source, space, symbol='exec'):
@@ -203,40 +156,6 @@
         if self.linestart:
             self.file.write('\n')
 
-class Stack:
-    """Utility class implementing a stack."""
-
-    def __init__(self):
-        self.items = []
-
-    def clone(self):
-        s = self.__class__()
-        for item in self.items:
-            try:
-                item = item.clone()
-            except AttributeError:
-                pass
-            s.push(item)
-        return s
-
-
-    def push(self, item):
-        self.items.append(item)
-
-    def pop(self):
-        return self.items.pop()
-
-    def top(self, position=0):
-        """'position' is 0 for the top of the stack, 1 for the item below,
-        and so on.  It must not be negative."""
-        return self.items[~position]
-
-    def depth(self):
-        return len(self.items)
-
-    def empty(self):
-        return not self.items
-
 # installing the excepthook for OperationErrors
 def operr_excepthook(exctype, value, traceback):
     if issubclass(exctype, OperationError):

Added: pypy/branch/builtinrefactor/pypy/interpreter/eval.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/eval.py	Sat Aug  9 15:48:30 2003
@@ -0,0 +1,118 @@
+"""
+This module defines the abstract base classes that support execution:
+Code and Frame.
+"""
+
+
+class Code(object):
+    """A code is a compiled version of some source code.
+    Abstract base class."""
+
+    def __init__(self, co_name):
+        self.co_name = co_name
+
+    def create_frame(self, space):
+        "Create an empty frame object suitable for evaluation of this code."
+        raise TypeError, "abstract"
+
+    def exec_code(self, space, w_globals, w_locals):
+        "Implements the 'exec' statement."
+        frame = self.create_frame(space)
+        frame.setglobaldict(w_globals)
+        frame.setlocaldict(w_locals)
+        frame.setclosure(None)
+        return frame.run()
+
+    def signature(self):
+        "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
+        return [], None, None
+
+    def getargcount(self):
+        "Number of arguments including * and **."
+        argnames, varargname, kwargname = self.signature()
+        count = len(argnames)
+        if varargname is not None:
+            count += 1
+        if kwargname is not None:
+            count += 1
+        return count
+
+    def getlocalvarname(self, index):
+        "Default implementation, can be overridden."
+        argnames, varargname, kwargname = self.signature()
+        try:
+            return argnames[index]
+        except IndexError:
+            index -= len(argnames)
+            if varargname is not None:
+                if index == 0:
+                    return varargname
+                index -= 1
+            if kwargname is not None:
+                if index == 0:
+                    return kwargname
+                index -= 1
+            raise IndexError, "local variable index out of bounds"
+
+
+class Frame(object):
+    """A frame is an environment supporting the execution of a code object.
+    Abstract base class."""
+
+    def __init__(self, space, code):
+        self.space      = space
+        self.code       = code       # Code instance
+        self.w_globals  = None       # wrapped dict of globals
+        self.w_locals   = None       # wrapped dict of locals
+
+    def run(self):
+        "Run the frame."
+        executioncontext = self.space.getexecutioncontext()
+        previous = executioncontext.enter(self)
+        try:
+            result = self.eval(executioncontext)
+        finally:
+            executioncontext.leave(previous)
+        return result
+
+    def eval(self, executioncontext):
+        "Abstract method to override."
+        raise TypeError, "abstract"
+
+    def getglobaldict(self):
+        return self.w_globals
+
+    def setglobaldict(self):
+        self.w_globals = w_globals
+
+    def getlocaldict(self):
+        "Overriden by subclasses with another representation for locals."
+        return self.w_locals
+
+    def setlocaldict(self, w_locals):
+        """Initialize the locals from a dictionary.
+        Overriden by subclasses with another representation for locals."""
+        self.w_locals = w_locals
+
+    def getlocalvar(self, index):
+        """Get the value of the indexth local variable
+        where numbering is according to self.code.signature().
+        Default implementation, to be overridden."""
+        varname = self.code.getlocalvarname(index)
+        return self.space.getitem(w_locals, self.space.wrap(varname))
+
+    def setlocalvar(self, index, w_value):
+        """Set the value of the indexth local variable,
+        where numbering is according to self.code.signature().
+        Default implementation, to be overridden."""
+        if self.w_locals is None:
+            self.w_locals = self.space.newdict([])
+        varname = self.code.getlocalvarname(index)
+        self.space.setitem(self.w_locals, self.space.wrap(varname), w_value)
+
+    def setclosure(self, closure):
+        """Initialize the closure from the given data, which should be None or
+        a list of Cells for PyFrame.  This should be called after setlocalvar()
+        or setlocaldict() is used to initialize the frame."""
+        if closure:
+            raise TypeError, "%s instance expects no closure" % self.__class__

Modified: pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py	Sat Aug  9 15:48:30 2003
@@ -1,23 +1,24 @@
-import sys
-import threadlocals
+from pypy.interpreter import threadlocals
 
 class ExecutionContext:
-
+    """An ExecutionContext holds the state of an execution thread
+    in the Python interpreter."""
+    
     def __init__(self, space):
+        # Note that self.framestack only contains PyFrames
         self.space = space
         self.framestack = Stack()
 
-    def eval_frame(self, frame):
+    def enter(self, frame):
         locals = threadlocals.getlocals()
         self.framestack.push(frame)
         previous_ec = locals.executioncontext
         locals.executioncontext = self
-        try:
-            result = frame.eval(self)
-        finally:
-            locals.executioncontext = previous_ec
-            self.framestack.pop()
-        return result
+        return previous_ec
+
+    def leave(self, previous_ec):
+        locals.executioncontext = previous_ec
+        self.framestack.pop()
 
     def get_w_builtins(self):
         if self.framestack.empty():
@@ -50,159 +51,6 @@
         return None
 
 
-class OperationError(Exception):
-    """Interpreter-level exception that signals an exception that should be
-    sent to the application level.
-
-    OperationError instances have three public attributes (and no .args),
-    w_type, w_value and application_traceback, which contain the wrapped
-    type and value describing the exception, and the unwrapped list of
-    (frame, instruction_position) making the application-level traceback.
-    """
-
-    def __init__(self, w_type, w_value):
-        self.w_type = w_type
-        self.w_value = w_value
-        self.application_traceback = []
-        self.debug_tbs = []
-
-    def record_application_traceback(self, frame, last_instruction):
-        self.application_traceback.append((frame, last_instruction))
-
-    def match(self, space, w_check_class):
-        "Check if this application-level exception matches 'w_check_class'."
-        return space.is_true(space.exception_match(self.w_type, w_check_class))
-
-    def __str__(self):
-        "Convenience for tracebacks."
-        return '[%s: %s]' % (self.w_type, self.w_value)
-
-    def errorstr(self, space):
-        "The exception class and value, as a string."
-        exc_type  = space.unwrap(
-            space.getattr(self.w_type, space.wrap('__name__')))
-        exc_value = space.unwrap(space.str(self.w_value))
-        return '%s: %s' % (exc_type, exc_value)
-
-    def getframe(self):
-        "The frame this exception was raised in, or None."
-        if self.application_traceback:
-            frame, last_instruction = self.application_traceback[0]
-            return frame
-        else:
-            return None
-
-    def record_interpreter_traceback(self):
-        """Records the current traceback inside the interpreter.
-        This traceback is only useful to debug the interpreter, not the
-        application."""
-        self.debug_tbs.append(sys.exc_info()[2])
-
-    def print_application_traceback(self, space, file=None):
-        "Dump a standard application-level traceback."
-        if file is None: file = sys.stderr
-        self.print_app_tb_only(file)
-        print >> file, self.errorstr(space)
-
-    def print_app_tb_only(self, file):
-        tb = self.application_traceback[:]
-        if tb:
-            import linecache
-            tb.reverse()
-            print >> file, "Traceback (application-level):"
-            for f, i in tb:
-                co = f.bytecode
-                lineno = offset2lineno(co, i)
-                fname = co.co_filename
-                if fname.startswith('<inline>\n'):
-                    lines = fname.split('\n')
-                    fname = lines[0].strip()
-                    try:
-                        l = lines[lineno]
-                    except IndexError:
-                        l = ''
-                else:
-                    l = linecache.getline(fname, lineno)
-                print >> file, "  File \"%s\"," % fname,
-                print >> file, "line", lineno, "in", co.co_name
-                if l:
-                    if l.endswith('\n'):
-                        l = l[:-1]
-                    print >> file, l
-
-    def print_detailed_traceback(self, space=None, file=None):
-        """Dump a nice detailed interpreter- and application-level traceback,
-        useful to debug the interpreter."""
-        if file is None: file = sys.stderr
-        for i in range(len(self.debug_tbs)-1, -1, -1):
-            import traceback
-            interpr_file = LinePrefixer(file, '||')
-            print >> interpr_file, "Traceback (interpreter-level):"
-            traceback.print_tb(self.debug_tbs[i], file=interpr_file)
-        self.print_app_tb_only(file)
-        if space is None:
-            exc_typename = str(self.w_type)
-            exc_value    = self.w_value
-        else:
-            w = space.wrap
-            exc_typename  = space.unwrap(
-                space.getattr(self.w_type, w('__name__')))
-            exc_value = space.unwrap(space.str(self.w_value))
-            print >> file, '(application-level)',
-        if exc_value is None:
-            print >> file, exc_typename
-        else:
-            print >> file, exc_typename+':', exc_value
-
-
-class NoValue(Exception):
-    """Raised to signal absence of value, e.g. in the iterator accessing
-    method 'op.next()' of object spaces."""
-
-
-# Utilities
-
-def inlinecompile(source, space, symbol='exec'):
-    """Compile the given 'source' string.
-    This function differs from the built-in compile() because it abuses
-    co_filename to store a copy of the complete source code.
-    This lets OperationError.print_application_traceback() print the
-    actual source line in the traceback."""
-    compile = space.builtin.compile
-    w = space.wrap
-    return compile(w(source), w('<inline>\n%s'%source), w(symbol), w(0), w(0))
-
-
-def offset2lineno(c, stopat):
-    tab = c.co_lnotab
-    line = c.co_firstlineno
-    addr = 0
-    for i in range(0, len(tab), 2):
-        addr = addr + ord(tab[i])
-        if addr > stopat:
-            break
-        line = line + ord(tab[i+1])
-    return line
-
-class LinePrefixer:
-    """File-like class that inserts a prefix string
-    at the beginning of each line it prints."""
-    def __init__(self, file, prefix):
-        self.file = file
-        self.prefix = prefix
-        self.linestart = True
-    def write(self, data):
-        if self.linestart:
-            self.file.write(self.prefix)
-        if data.endswith('\n'):
-            data = data[:-1]
-            self.linestart = True
-        else:
-            self.linestart = False
-        self.file.write(data.replace('\n', '\n'+self.prefix))
-        if self.linestart:
-            self.file.write('\n')
-
 class Stack:
     """Utility class implementing a stack."""
 
@@ -219,7 +67,6 @@
             s.push(item)
         return s
 
-
     def push(self, item):
         self.items.append(item)
 
@@ -236,13 +83,3 @@
 
     def empty(self):
         return not self.items
-
-# installing the excepthook for OperationErrors
-def operr_excepthook(exctype, value, traceback):
-    if issubclass(exctype, OperationError):
-        value.debug_tbs.append(traceback)
-        value.print_detailed_traceback()
-    else:
-        old_excepthook(exctype, value, traceback)
-old_excepthook = sys.excepthook
-sys.excepthook = operr_excepthook

Added: pypy/branch/builtinrefactor/pypy/interpreter/function.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/function.py	Sat Aug  9 15:48:30 2003
@@ -0,0 +1,168 @@
+"""
+Function objects.
+
+In PyPy there is no difference between built-in and user-defined function
+objects; the difference lies in the code object found in their func_code
+attribute.
+"""
+
+class Function:
+    """A function is a code object captured with some environment:
+    an object space, a dictionary of globals, default arguments,
+    and an arbitrary 'closure' passed to the code object."""
+    
+    def __init__(self, space, code, w_globals, w_defs=None, closure=None):
+        self.space     = space
+        self.func_code = code       # Code instance
+        self.w_globals = w_globals  # the globals dictionary
+        self.w_defs    = w_defs     # wrapped sequence of default args or None
+        self.closure   = closure    # normally, list of Cell instances or None
+
+    def parse_args(self, frame, w_args, w_kwargs=None):
+        """ parse args and kwargs to initialize the frame.
+        """
+        space = self.space
+        signature = self.func_code.signature()
+        argnames, varargname, kwargname = signature
+        # test for 'simple case':
+        if (varargname is None and kwargname is None and          # no */**
+            (w_kwargs is None or not space.is_true(w_kwargs)) and # no kwargs
+            self.unwrap(self.len(w_args)) == len(argnames)):  # correct #args
+            for index in range(len(argnames)):
+                w_index = self.wrap(index)
+                w_argument = self.getitem(w_args, w_index)
+                frame.setlocalvar(index, w_argument)
+        else:
+            #print "complicated case of arguments for", self.func_code.co_name
+            if w_kwargs is None:
+                w_kwargs = space.w_None
+            self.parse_args_complex(frame, w_args, w_kwargs,
+                                    space.wrap(signature))
+        frame.setclosure(self.closure)
+
+    def app_parse_args_complex(self, frame, args, kws, signature):
+        """ app-level helper for the complex case of parse_args().
+        """
+        # ===== ATTENTION =====
+        #
+        # This code is pretty fundamental to pypy and great care must be taken
+        # to avoid infinite recursion.  In particular:
+        #
+        # - All calls here must be "easy", i.e. not involve default or keyword
+        #   arguments.  For example, all range() calls need three arguments.
+        #
+        # - You cannot *catch* any exceptions (raising is fine).
+        #
+        # Assumptions:
+        #   frame = empty frame to be initialized
+        #   args = sequence of the normal actual parameters
+        #   kws = dictionary of keyword parameters or None
+        #   self.defs = sequence of defaults
+        #
+        # We try to give error messages following CPython's, which are
+        # very informative.
+
+        argnames, varargname, kwargname = signature
+        input_argcount = len(args)
+        co_argcount = len(argnames)
+        deffirst = co_argcount - len(self.defs)
+        if kws:
+            kwargs = kws.copy()
+        else:
+            kwargs = {}
+
+        # fetch all arguments left-to-right
+        for i in range(0, co_argcount, 1):
+            argname = argnames[i]
+            if i < input_argcount:
+                value = args[i]
+                # check that no keyword argument also gives a value here
+                if argname in kwargs:
+                    raise TypeError, self.argerr_multiple_values(argname)
+            elif argname in kwargs:
+                # positional arguments exhausted,
+                # complete with keyword arguments
+                value = kwargs[argname]
+                del kwargs[argname]
+            elif i >= deffirst:
+                # no matching keyword argument, but there is a default value
+                value = self.defs[i - deffirst]
+            else:
+                raise TypeError, self.argerr(signature, args, kws, False)
+            frame.setlocalvar(i, value)
+
+        # collect extra positional arguments into the *vararg
+        specialarg = co_argcount
+        if varargname is not None:
+            var_tuple = args[co_argcount:]
+            frame.setlocalvar(specialarg, var_tuple)
+            specialarg += 1
+        elif input_argcount > co_argcount:
+            # cannot do anything with these extra positional arguments
+            raise TypeError, self.argerr(signature, args, kws, True)
+
+        # collect extra keyword arguments into the **kwarg
+        if kwargname is not None:
+            # XXX this doesn't check that the keys of kwargs are strings
+            frame.setlocalvar(specialarg, kwargs)
+            specialarg += 1
+        elif kwargs:
+            # cannot do anything with these extra keyword arguments
+            raise TypeError, self.argerr_unknown_kwds(kwargs)
+    parse_args_complex = app2interp(app_parse_args_complex)
+
+    # helper functions to build error message for the above
+
+    def app_argerr(self, signature, args, kws, too_many):
+        argnames, varargname, kwargname = signature
+        n = len(argnames)
+        if n == 0:
+            n = len(args)
+            if kwargname is not None:
+                msg2 = "non-keyword "
+            else:
+                msg2 = ""
+                n += len(kws)
+            return "%s() takes no %sargument (%d given)" % (
+                self.func_code.co_name,
+                msg2,
+                n)
+        else:
+            defcount = len(self.defs)
+            if defcount == 0:
+                msg1 = "exactly"
+            elif too_many:
+                msg1 = "at most"
+            else:
+                msg1 = "at least"
+                n -= defcount
+            if kws:
+                msg2 = "non-keyword "
+            else:
+                msg2 = ""
+            if n == 1:
+                plural = ""
+            else:
+                plural = "s"
+            return "%s() takes %s %d %sargument%s (%d given)" % (
+                self.func_code.co_name,
+                msg1,
+                n,
+                msg2,
+                plural,
+                len(args))
+
+    def app_argerr_multiple_values(self, argname):
+        return "%s() got multiple values for keyword argument %s" % (
+            self.func_code.co_name,
+            argname)
+
+    def app_argerr_unknown_kwds(self, kws):
+        if len(kws) == 1:
+            return "%s() got an unexpected keyword argument '%s'" % (
+                self.func_code.co_name,
+                kws.keys()[0])
+        else:
+            return "%s() got %d unexpected keyword arguments" % (
+                self.func_code.co_name,
+                len(kws))

Modified: pypy/branch/builtinrefactor/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/gateway.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/gateway.py	Sat Aug  9 15:48:30 2003
@@ -1,10 +1,23 @@
 """
 
-gateway between app-level and interpreter-level 
+Gateway between app-level and interpreter-level:
+the Wrappable base class.
 
 """
-import inspect
-CO_VARARGS, CO_VARKEYWORDS = 0x4, 0x8
+
+class Wrappable(object):
+    """A subclass of Wrappable is an internal, interpreter-level class
+    that can nevertheless be exposed at application-level,
+    via space.wrap().
+
+    The methods and attributes that a class wants to expose are defined
+    with a naming convension: 'app_xxx' is exposed as 'xxx'.
+    In general, 'app_xxx' should be a gateway (see below)."""
+
+# XXX most code from some classes below have been "stolen" in
+# XXX new classes in other modules. Will be removed.
+
+
 
 class ScopedCode(object):
     """ a code object within a certain global and closure scope.

Deleted: /pypy/branch/builtinrefactor/pypy/interpreter/opcode.py
==============================================================================
--- /pypy/branch/builtinrefactor/pypy/interpreter/opcode.py	Sat Aug  9 15:48:30 2003
+++ (empty file)
@@ -1,758 +0,0 @@
-from appfile import AppFile
-from pypy.interpreter.baseobjspace import OperationError, NoValue
-from pypy.interpreter.pyframe import _NULL
-import dis
-from pypy.interpreter import pyframe, baseobjspace
-from pypy.interpreter.gateway import InterpretedFunction, ScopedCode
-
-
-# dynamically loaded application-space utilities
-appfile = AppFile(__name__, ["interpreter"])
-
-
-class unaryoperation:
-    def __init__(self, operationname):
-        self.operationname = operationname
-    def __call__(self, f):
-        operation = getattr(f.space, self.operationname)
-        w_1 = f.valuestack.pop()
-        w_result = operation(w_1)
-        f.valuestack.push(w_result)
-
-class binaryoperation:
-    def __init__(self, operationname):
-        self.operationname = operationname
-    def __call__(self, f):
-        operation = getattr(f.space, self.operationname)
-        w_2 = f.valuestack.pop()
-        w_1 = f.valuestack.pop()
-        w_result = operation(w_1, w_2)
-        f.valuestack.push(w_result)
-
-
-################################################################
-##  Implementation of the opcodes
-##
-
-def LOAD_FAST(f, varindex):
-    # access a local variable through its cell object
-    w_value = f.locals_w[varindex]
-    if w_value is _NULL:
-        varname = f.getlocalvarname(varindex)
-        message = "local variable '%s' referenced before assignment" % varname
-        raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
-    f.valuestack.push(w_value)
-
-def LOAD_CONST(f, constindex):
-    w_const = f.space.wrap(f.getconstant(constindex))
-    f.valuestack.push(w_const)
-
-def STORE_FAST(f, varindex):
-    try:
-        w_newvalue = f.valuestack.pop()
-        f.locals_w[varindex] = w_newvalue
-    except:
-        print "exception: got index error"
-        print " varindex:", varindex
-        print " len(locals_w)", len(f.locals_w)
-        import dis
-        print dis.dis(f.bytecode)
-        print "co_varnames", f.bytecode.co_varnames
-        print "co_nlocals", f.bytecode.co_nlocals
-        raise
-
-
-def POP_TOP(f):
-    f.valuestack.pop()
-
-def ROT_TWO(f):
-    w_1 = f.valuestack.pop()
-    w_2 = f.valuestack.pop()
-    f.valuestack.push(w_1)
-    f.valuestack.push(w_2)
-
-def ROT_THREE(f):
-    w_1 = f.valuestack.pop()
-    w_2 = f.valuestack.pop()
-    w_3 = f.valuestack.pop()
-    f.valuestack.push(w_1)
-    f.valuestack.push(w_3)
-    f.valuestack.push(w_2)
-
-def ROT_FOUR(f):
-    w_1 = f.valuestack.pop()
-    w_2 = f.valuestack.pop()
-    w_3 = f.valuestack.pop()
-    w_4 = f.valuestack.pop()
-    f.valuestack.push(w_1)
-    f.valuestack.push(w_4)
-    f.valuestack.push(w_3)
-    f.valuestack.push(w_2)
-
-def DUP_TOP(f):
-    w_1 = f.valuestack.top()
-    f.valuestack.push(w_1)
-
-def DUP_TOPX(f, itemcount):
-    assert 1 <= itemcount <= 5, "limitation of the current interpreter"
-    for i in range(itemcount):
-        w_1 = f.valuestack.top(itemcount-1)
-        f.valuestack.push(w_1)
-
-UNARY_POSITIVE = unaryoperation("pos")
-UNARY_NEGATIVE = unaryoperation("neg")
-UNARY_NOT      = unaryoperation("not_")
-UNARY_CONVERT  = unaryoperation("repr")
-UNARY_INVERT   = unaryoperation("invert")
-
-def BINARY_POWER(f):
-    w_2 = f.valuestack.pop()
-    w_1 = f.valuestack.pop()
-    w_result = f.space.pow(w_1, w_2, f.space.w_None)
-    f.valuestack.push(w_result)
-
-BINARY_MULTIPLY = binaryoperation("mul")
-BINARY_TRUE_DIVIDE  = binaryoperation("truediv")
-BINARY_FLOOR_DIVIDE = binaryoperation("floordiv")
-BINARY_DIVIDE       = binaryoperation("div")
-BINARY_MODULO       = binaryoperation("mod")
-BINARY_ADD      = binaryoperation("add")
-BINARY_SUBTRACT = binaryoperation("sub")
-BINARY_SUBSCR   = binaryoperation("getitem")
-BINARY_LSHIFT   = binaryoperation("lshift")
-BINARY_RSHIFT   = binaryoperation("rshift")
-BINARY_AND = binaryoperation("and_")
-BINARY_XOR = binaryoperation("xor")
-BINARY_OR  = binaryoperation("or_")
-
-def INPLACE_POWER(f):
-    w_2 = f.valuestack.pop()
-    w_1 = f.valuestack.pop()
-    w_result = f.space.inplace_pow(w_1, w_2, f.space.w_None)
-    f.valuestack.push(w_result)
-
-INPLACE_MULTIPLY = binaryoperation("inplace_mul")
-INPLACE_TRUE_DIVIDE  = binaryoperation("inplace_truediv")
-INPLACE_FLOOR_DIVIDE = binaryoperation("inplace_floordiv")
-INPLACE_DIVIDE       = binaryoperation("inplace_div")
-INPLACE_MODULO       = binaryoperation("inplace_mod")
-INPLACE_ADD      = binaryoperation("inplace_add")
-INPLACE_SUBTRACT = binaryoperation("inplace_sub")
-INPLACE_LSHIFT   = binaryoperation("inplace_lshift")
-INPLACE_RSHIFT   = binaryoperation("inplace_rshift")
-INPLACE_AND = binaryoperation("inplace_and")
-INPLACE_XOR = binaryoperation("inplace_xor")
-INPLACE_OR  = binaryoperation("inplace_or")
-
-def slice(f, w_start, w_end):
-    w_slice = f.space.newslice(w_start, w_end, None)
-    w_obj = f.valuestack.pop()
-    w_result = f.space.getitem(w_obj, w_slice)
-    f.valuestack.push(w_result)
-
-def SLICE_0(f):
-    slice(f, None, None)
-
-def SLICE_1(f):
-    w_start = f.valuestack.pop()
-    slice(f, w_start, None)
-
-def SLICE_2(f):
-    w_end = f.valuestack.pop()
-    slice(f, None, w_end)
-
-def SLICE_3(f):
-    w_end = f.valuestack.pop()
-    w_start = f.valuestack.pop()
-    slice(f, w_start, w_end)
-
-def storeslice(f, w_start, w_end):
-    w_slice = f.space.newslice(w_start, w_end, None)
-    w_obj = f.valuestack.pop()
-    w_newvalue = f.valuestack.pop()
-    f.space.setitem(w_obj, w_slice, w_newvalue)
-
-def STORE_SLICE_0(f):
-    storeslice(f, None, None)
-
-def STORE_SLICE_1(f):
-    w_start = f.valuestack.pop()
-    storeslice(f, w_start, None)
-
-def STORE_SLICE_2(f):
-    w_end = f.valuestack.pop()
-    storeslice(f, None, w_end)
-
-def STORE_SLICE_3(f):
-    w_end = f.valuestack.pop()
-    w_start = f.valuestack.pop()
-    storeslice(f, w_start, w_end)
-
-def deleteslice(f, w_start, w_end):
-    w_slice = f.space.newslice(w_start, w_end, None)
-    w_obj = f.valuestack.pop()
-    f.space.delitem(w_obj, w_slice)
-
-def DELETE_SLICE_0(f):
-    deleteslice(f, None, None)
-
-def DELETE_SLICE_1(f):
-    w_start = f.valuestack.pop()
-    deleteslice(f, w_start, None)
-
-def DELETE_SLICE_2(f):
-    w_end = f.valuestack.pop()
-    deleteslice(f, None, w_end)
-
-def DELETE_SLICE_3(f):
-    w_end = f.valuestack.pop()
-    w_start = f.valuestack.pop()
-    deleteslice(f, w_start, w_end)
-
-def STORE_SUBSCR(f):
-    "obj[subscr] = newvalue"
-    w_subscr = f.valuestack.pop()
-    w_obj = f.valuestack.pop()
-    w_newvalue = f.valuestack.pop()
-    f.space.setitem(w_obj, w_subscr, w_newvalue)
-
-def DELETE_SUBSCR(f):
-    "del obj[subscr]"
-    w_subscr = f.valuestack.pop()
-    w_obj = f.valuestack.pop()
-    f.space.delitem(w_obj, w_subscr)
-
-def PRINT_EXPR(f):
-    w_expr = f.valuestack.pop()
-    #print f.space.unwrap(w_expr)
-    f.space.gethelper(appfile).call("print_expr", [w_expr])
-
-def PRINT_ITEM_TO(f):
-    w_stream = f.valuestack.pop()
-    w_item = f.valuestack.pop()
-    f.space.gethelper(appfile).call("print_item_to", [w_item, w_stream])
-
-def PRINT_ITEM(f):
-    w_item = f.valuestack.pop()
-    f.space.gethelper(appfile).call("print_item", [w_item])
-
-def PRINT_NEWLINE_TO(f):
-    w_stream = f.valuestack.pop()
-    f.space.gethelper(appfile).call("print_newline_to", [w_stream])
-
-def PRINT_NEWLINE(f):
-    f.space.gethelper(appfile).call("print_newline", [])
-
-def BREAK_LOOP(f):
-    raise pyframe.SBreakLoop
-
-def CONTINUE_LOOP(f, startofloop):
-    raise pyframe.SContinueLoop(startofloop)
-
-def RAISE_VARARGS(f, nbargs):
-    # we use the .app.py file to prepare the exception/value/traceback
-    # but not to actually raise it, because we cannot use the 'raise'
-    # statement to implement RAISE_VARARGS
-    if nbargs == 0:
-        w_resulttuple = f.space.gethelper(appfile).call("prepare_raise0", [])
-    elif nbargs == 1:
-        w_type = f.valuestack.pop()
-        w_resulttuple = f.space.gethelper(appfile).call(
-            "prepare_raise", [w_type, f.space.w_None, f.space.w_None])
-    elif nbargs == 2:
-        w_value = f.valuestack.pop()
-        w_type  = f.valuestack.pop()
-        w_resulttuple = f.space.gethelper(appfile).call(
-            "prepare_raise", [w_type, w_value, f.space.w_None])
-    elif nbargs == 3:
-        w_traceback = f.valuestack.pop()
-        w_value     = f.valuestack.pop()
-        w_type      = f.valuestack.pop()
-        w_resulttuple = f.space.gethelper(appfile).call(
-            "prepare_raise", [w_type, w_value, w_traceback])
-    else:
-        raise pyframe.BytecodeCorruption, "bad RAISE_VARARGS oparg"
-    w_type, w_value, w_traceback = f.space.unpacktuple(w_resulttuple)
-    # XXX the three-arguments 'raise' is not supported yet
-    raise OperationError(w_type, w_value)
-
-def LOAD_LOCALS(f):
-    f.valuestack.push(f.w_locals)
-
-def RETURN_VALUE(f):
-    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()
-    w_prog    = f.valuestack.pop()
-    w_tuple = f.space.gethelper(appfile).call("exec_statement",
-                                    [w_prog, w_globals, w_locals,
-                                     f.w_builtins, f.w_globals, f.w_locals])
-    w_prog = f.space.getitem(w_tuple,f.space.wrap(0))
-    w_globals = f.space.getitem(w_tuple,f.space.wrap(1))
-    w_locals = f.space.getitem(w_tuple,f.space.wrap(2))
-
-    plain = (w_locals is f.w_locals)
-    if plain:
-        f.fast2locals()
-    scopedcode = ScopedCode(f.space, f.space.unwrap(w_prog), w_globals)
-    scopedcode.eval_frame(w_locals)
-    #f.space.unwrap(w_prog).eval_code(f.space, w_globals, w_locals)
-    if plain:
-        f.locals2fast()
-    
-def POP_BLOCK(f):
-    block = f.blockstack.pop()
-    block.cleanup(f)  # the block knows how to clean up the value stack
-
-def END_FINALLY(f):
-    # unlike CPython, when we reach this opcode the value stack has
-    # always been set up as follows (topmost first):
-    #   [exception type  or None]
-    #   [exception value or None]
-    #   [wrapped stack unroller ]
-    f.valuestack.pop()   # ignore the exception type
-    f.valuestack.pop()   # ignore the exception value
-    unroller = f.space.unwrap(f.valuestack.pop())
-    if unroller is not None:
-        raise unroller   # re-raise the unroller, if any
-    
-def BUILD_CLASS(f):
-    w_methodsdict = f.valuestack.pop()
-    w_bases       = f.valuestack.pop()
-    w_name        = f.valuestack.pop()
-    # XXX it would be best to have all opcodes on a class that has a 'space' attribute
-    #     then the following initialization could be done at init-time. 
-    build_class = InterpretedFunction(f.space.gethelperspace(), app_build_class)
-    w_newclass = build_class(w_name, w_bases, w_methodsdict, f.w_globals)
-    f.valuestack.push(w_newclass)
-
-def app_build_class(name, bases, namespace, globals):
-    if '__metaclass__' in namespace:
-        metaclass = namespace['__metaclass__']
-    elif len(bases) > 0:
-        base = bases[0]
-        if hasattr(base, '__class__'):
-            metaclass = base.__class__
-        else:
-            metaclass = type(base)
-    elif '__metaclass__' in globals:
-        metaclass = globals['__metaclass__']
-    else:
-        metaclass = type
-    return metaclass(name, bases, namespace)
-
-def STORE_NAME(f, varindex):
-    varname = f.getname(varindex)
-    w_varname = f.space.wrap(varname)
-    w_newvalue = f.valuestack.pop()
-    f.space.setitem(f.w_locals, w_varname, w_newvalue)
-
-def DELETE_NAME(f, varindex):
-    varname = f.getname(varindex)
-    w_varname = f.space.wrap(varname)
-    try:
-        f.space.delitem(f.w_locals, w_varname)
-    except OperationError, e:
-        # catch KeyErrors and turn them into NameErrors
-        if not e.match(f.space, f.space.w_KeyError):
-            raise
-        message = "name '%s' is not defined" % varname
-        raise OperationError(f.space.w_NameError, f.space.wrap(message))
-
-def UNPACK_SEQUENCE(f, itemcount):
-    w_iterable = f.valuestack.pop()
-    try:
-        items = f.space.unpackiterable(w_iterable, itemcount)
-    except ValueError, e:
-        raise OperationError(f.space.w_ValueError, f.space.wrap(str(e)))
-    items.reverse()
-    for item in items:
-        f.valuestack.push(item)
-
-def STORE_ATTR(f, nameindex):
-    "obj.attributename = newvalue"
-    attributename = f.getname(nameindex)
-    w_attributename = f.space.wrap(attributename)
-    w_obj = f.valuestack.pop()
-    w_newvalue = f.valuestack.pop()
-    f.space.setattr(w_obj, w_attributename, w_newvalue)
-
-def DELETE_ATTR(f, nameindex):
-    "del obj.attributename"
-    attributename = f.getname(nameindex)
-    w_attributename = f.space.wrap(attributename)
-    w_obj = f.valuestack.pop()
-    f.space.delattr(w_obj, w_attributename)
-
-def STORE_GLOBAL(f, nameindex):
-    varname = f.getname(nameindex)
-    w_varname = f.space.wrap(varname)
-    w_newvalue = f.valuestack.pop()
-    f.space.setitem(f.w_globals, w_varname, w_newvalue)
-
-def DELETE_GLOBAL(f, nameindex):
-    varname = f.getname(nameindex)
-    w_varname = f.space.wrap(varname)
-    f.space.delitem(f.w_globals, w_varname)
-
-def LOAD_NAME(f, nameindex):
-    varname = f.getname(nameindex)
-    w_varname = f.space.wrap(varname)
-    try:
-        w_value = f.space.getitem(f.w_locals, w_varname)
-    except OperationError, e:
-        if not e.match(f.space, f.space.w_KeyError):
-            raise
-        try:
-            w_value = f.space.getitem(f.w_globals, w_varname)
-        except OperationError, e:
-            if not e.match(f.space, f.space.w_KeyError):
-                raise
-            try:
-                w_value = f.space.getitem(f.w_builtins, w_varname)
-            except OperationError, e:
-                if not e.match(f.space, f.space.w_KeyError):
-                    raise
-                message = "global name '%s' is not defined" % varname
-                w_exc_type = f.space.w_NameError
-                w_exc_value = f.space.wrap(message)
-                raise OperationError(w_exc_type, w_exc_value)
-    f.valuestack.push(w_value)
-    # XXX the implementation can be pushed back into app-space as an
-    # when exception handling begins to behave itself.  For now, it
-    # was getting on my nerves -- mwh
-#    w_value = f.space.gethelper(appfile).call(
-#        "load_name", [w_varname, f.w_locals, f.w_globals, f.w_builtins])
-#    f.valuestack.push(w_value)
-
-def LOAD_GLOBAL(f, nameindex):
-    assert f.w_globals is not None
-    varname = f.getname(nameindex)
-    w_varname = f.space.wrap(varname)
-    try:
-        w_value = f.space.getitem(f.w_globals, w_varname)
-    except OperationError, e:
-        # catch KeyErrors
-        if not e.match(f.space, f.space.w_KeyError):
-            raise
-        # we got a KeyError, now look in the built-ins
-        try:
-            w_value = f.space.getitem(f.w_builtins, w_varname)
-        except OperationError, e:
-            # catch KeyErrors again
-            if not e.match(f.space, f.space.w_KeyError):
-                raise
-            message = "global name '%s' is not defined" % varname
-            w_exc_type = f.space.w_NameError
-            w_exc_value = f.space.wrap(message)
-            raise OperationError(w_exc_type, w_exc_value)
-    f.valuestack.push(w_value)
-
-def DELETE_FAST(f, varindex):
-    w_value = f.locals_w[varindex]
-    if f.locals_w[varindex] is _NULL:
-        varname = f.getlocalvarname(varindex)
-        message = "local variable '%s' referenced before assignment" % varname
-        raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
-    f.locals_w[varindex] = _NULL
-
-def LOAD_CLOSURE(f, varindex):
-    # nested scopes: access the cell object
-    cell = f.closure_w[varindex]
-    w_value = f.space.wrap(cell)
-    f.valuestack.push(w_value)
-
-def LOAD_DEREF(f, varindex):
-    # nested scopes: access a variable through its cell object
-    cell = f.closure_w[varindex]
-    try:
-        w_value = cell.get()
-    except ValueError:
-        varname = f.getfreevarname(varindex)
-        if f.iscellvar(varindex):
-            message = "local variable '%s' referenced before assignment"
-            w_exc_type = f.space.w_UnboundLocalError
-        else:
-            message = ("free variable '%s' referenced before assignment"
-                       " in enclosing scope")
-            w_exc_type = f.space.w_NameError
-        raise OperationError(w_exc_type, f.space.wrap(message % varname))
-    f.valuestack.push(w_value)
-
-def STORE_DEREF(f, varindex):
-    # nested scopes: access a variable through its cell object
-    w_newvalue = f.valuestack.pop()
-    try:
-        cell = f.closure_w[varindex]
-    except IndexError:
-        #import pdb; pdb.set_trace()
-        raise
-    cell.set(w_newvalue)
-
-def BUILD_TUPLE(f, itemcount):
-    items = [f.valuestack.pop() for i in range(itemcount)]
-    items.reverse()
-    w_tuple = f.space.newtuple(items)
-    f.valuestack.push(w_tuple)
-
-def BUILD_LIST(f, itemcount):
-    items = [f.valuestack.pop() for i in range(itemcount)]
-    items.reverse()
-    w_list = f.space.newlist(items)
-    f.valuestack.push(w_list)
-
-def BUILD_MAP(f, zero):
-    if zero != 0:
-        raise pyframe.BytecodeCorruption
-    w_dict = f.space.newdict([])
-    f.valuestack.push(w_dict)
-
-def LOAD_ATTR(f, nameindex):
-    "obj.attributename"
-    attributename = f.getname(nameindex)
-    w_attributename = f.space.wrap(attributename)
-    w_obj = f.valuestack.pop()
-    w_value = f.space.getattr(w_obj, w_attributename)
-    f.valuestack.push(w_value)
-
-def cmp_lt(f, w_1, w_2):  return f.space.lt(w_1, w_2)
-def cmp_le(f, w_1, w_2):  return f.space.le(w_1, w_2)
-def cmp_eq(f, w_1, w_2):  return f.space.eq(w_1, w_2)
-def cmp_ne(f, w_1, w_2):  return f.space.ne(w_1, w_2)
-def cmp_gt(f, w_1, w_2):  return f.space.gt(w_1, w_2)
-def cmp_ge(f, w_1, w_2):  return f.space.ge(w_1, w_2)
-
-def cmp_in(f, w_1, w_2):
-    return f.space.contains(w_2, w_1)
-def cmp_not_in(f, w_1, w_2):
-    return f.space.not_(f.space.contains(w_2, w_1))
-def cmp_is(f, w_1, w_2):
-    return f.space.is_(w_1, w_2)
-def cmp_is_not(f, w_1, w_2):
-    return f.space.not_(f.space.is_(w_1, w_2))
-def cmp_exc_match(f, w_1, w_2):
-    return f.space.exception_match(w_1, w_2)
-
-compare_dispatch_table = {
-    0: cmp_lt,   # "<"
-    1: cmp_le,   # "<="
-    2: cmp_eq,   # "=="
-    3: cmp_ne,   # "!="
-    4: cmp_gt,   # ">"
-    5: cmp_ge,   # ">="
-    6: cmp_in,
-    7: cmp_not_in,
-    8: cmp_is,
-    9: cmp_is_not,
-    10: cmp_exc_match,
-    }
-def COMPARE_OP(f, testnum):
-    w_2 = f.valuestack.pop()
-    w_1 = f.valuestack.pop()
-    try:
-        testfn = compare_dispatch_table[testnum]
-    except KeyError:
-        raise pyframe.BytecodeCorruption, "bad COMPARE_OP oparg"
-    w_result = testfn(f, w_1, w_2)
-    f.valuestack.push(w_result)
-
-def IMPORT_NAME(f, nameindex):
-    modulename = f.getname(nameindex)
-    w_modulename = f.space.wrap(modulename)
-    w_fromlist = f.valuestack.pop()
-    w_obj = f.space.gethelper(appfile).call(
-        "import_name", [f.w_builtins,
-                        w_modulename, f.w_globals, f.w_locals, w_fromlist])
-    f.valuestack.push(w_obj)
-
-def IMPORT_STAR(f):
-    w_module = f.valuestack.pop()
-    f.space.gethelper(appfile).call("import_all_from", [w_module, f.w_locals])
-
-def IMPORT_FROM(f, nameindex):
-    name = f.getname(nameindex)
-    w_name = f.space.wrap(name)
-    w_module = f.valuestack.top()
-    w_obj = f.space.gethelper(appfile).call("import_from", [w_module, w_name])
-    f.valuestack.push(w_obj)
-
-def JUMP_FORWARD(f, stepby):
-    f.next_instr += stepby
-
-def JUMP_IF_FALSE(f, stepby):
-    w_cond = f.valuestack.top()
-    if not f.space.is_true(w_cond):
-        f.next_instr += stepby
-
-def JUMP_IF_TRUE(f, stepby):
-    w_cond = f.valuestack.top()
-    if f.space.is_true(w_cond):
-        f.next_instr += stepby
-
-def JUMP_ABSOLUTE(f, jumpto):
-    f.next_instr = jumpto
-
-def GET_ITER(f):
-    w_iterable = f.valuestack.pop()
-    w_iterator = f.space.iter(w_iterable)
-    f.valuestack.push(w_iterator)
-
-def FOR_ITER(f, jumpby):
-    w_iterator = f.valuestack.top()
-    try:
-        w_nextitem = f.space.next(w_iterator)
-    except NoValue:
-        # iterator exhausted
-        f.valuestack.pop()
-        f.next_instr += jumpby
-    else:
-        f.valuestack.push(w_nextitem)
-
-def FOR_LOOP(f, oparg):
-    raise pyframe.BytecodeCorruption, "old opcode, no longer in use"
-
-def SETUP_LOOP(f, offsettoend):
-    block = pyframe.LoopBlock(f, f.next_instr + offsettoend)
-    f.blockstack.push(block)
-
-def SETUP_EXCEPT(f, offsettoend):
-    block = pyframe.ExceptBlock(f, f.next_instr + offsettoend)
-    f.blockstack.push(block)
-
-def SETUP_FINALLY(f, offsettoend):
-    block = pyframe.FinallyBlock(f, f.next_instr + offsettoend)
-    f.blockstack.push(block)
-
-def call_function_extra(f, oparg, with_varargs, with_varkw):
-    n_arguments = oparg & 0xff
-    n_keywords = (oparg>>8) & 0xff
-    if with_varkw:
-        w_varkw = f.valuestack.pop()
-    if with_varargs:
-        w_varargs = f.valuestack.pop()
-    keywords = []
-    for i in range(n_keywords):
-        w_value = f.valuestack.pop()
-        w_key   = f.valuestack.pop()
-        keywords.append((w_key, w_value))
-    arguments = [f.valuestack.pop() for i in range(n_arguments)]
-    arguments.reverse()
-    w_function  = f.valuestack.pop()
-    w_arguments = f.space.newtuple(arguments)
-    w_keywords  = f.space.newdict(keywords)
-    if with_varargs:
-        w_arguments = f.space.gethelper(appfile).call("concatenate_arguments",
-                                                      [w_arguments, w_varargs])
-    if with_varkw:
-        w_keywords  = f.space.gethelper(appfile).call("concatenate_keywords",
-                                                      [w_keywords,  w_varkw])
-    w_result = f.space.call(w_function, w_arguments, w_keywords)
-    f.valuestack.push(w_result)
-
-def CALL_FUNCTION(f, oparg):
-    call_function_extra(f, oparg, False, False)
-
-def CALL_FUNCTION_VAR(f, oparg):
-    call_function_extra(f, oparg, True,  False)
-
-def CALL_FUNCTION_KW(f, oparg):
-    call_function_extra(f, oparg, False, True)
-
-def CALL_FUNCTION_VAR_KW(f, oparg):
-    call_function_extra(f, oparg, True,  True)
-
-def MAKE_FUNCTION(f, numdefaults):
-    w_codeobj = f.valuestack.pop()
-    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)
-    f.valuestack.push(w_func)
-
-def MAKE_CLOSURE(f, numdefaults):
-    w_codeobj = f.valuestack.pop()
-    codeobj = f.space.unwrap(w_codeobj)
-    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.valuestack.push(w_func)
-
-def BUILD_SLICE(f, numargs):
-    if numargs == 3:
-        w_step = f.valuestack.pop()
-    elif numargs == 2:
-        w_step = None
-    else:
-        raise pyframe.BytecodeCorruption
-    w_end   = f.valuestack.pop()
-    w_start = f.valuestack.pop()
-    w_slice = f.space.newslice(w_start, w_end, w_step)
-    f.valuestack.push(w_slice)
-
-def SET_LINENO(f, lineno):
-    pass
-
-def EXTENDED_ARG(f, oparg):
-    opcode = f.nextop()
-    oparg = oparg<<16 | f.nextarg()
-    dispatch_arg(f, oparg)
-
-def MISSING_OPCODE(f, oparg=None):
-    raise pyframe.BytecodeCorruption, "unknown opcode"
-
-
-################################################################
-
-dispatch_table = []
-for i in range(256):
-    opname = dis.opname[i].replace('+', '_')
-    fn = MISSING_OPCODE
-    if opname in globals():
-        fn = globals()[opname]
-    elif not opname.startswith('<') and i>0:
-        #import warnings
-        #warnings.warn("* Warning, missing opcode %s" % opname)
-        pass
-    dispatch_table.append(fn)
-
-
-def name(thing):
-    try:
-        return thing.operationname
-    except AttributeError:
-        return thing.__name__
-
-def has_arg(opcode):
-    return opcode >= dis.HAVE_ARGUMENT
-
-def dispatch_noarg(f, opcode):
-    try:
-        fn = dispatch_table[opcode]
-#        print name(fn)
-    except KeyError:
-        raise KeyError, "missing opcode %s" % dis.opname[opcode]
-    fn(f)
-
-def dispatch_arg(f, opcode, oparg):
-    assert oparg >= 0
-    try:
-        fn = dispatch_table[opcode]
-#        print name(fn)
-    except KeyError:
-        raise KeyError, "missing opcode %s" % dis.opname[opcode]
-    fn(f, oparg)

Added: pypy/branch/builtinrefactor/pypy/interpreter/pycode.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pycode.py	Sat Aug  9 15:48:30 2003
@@ -0,0 +1,105 @@
+"""
+Python-style code objects.
+PyCode instances have the same co_xxx arguments as CPython code objects.
+The bytecode interpreter itself is implemented by the PyFrame class.
+"""
+
+from pypy.interpreter import eval
+from pypy.interpreter.pyopcode      import PyOperationalFrame
+from pypy.interpreter.pyfastscope   import PyFastScopeFrame
+from pypy.interpreter.pynestedscope import PyNestedScopeFrame
+
+
+# code object contants, for co_flags below
+CO_OPTIMIZED    = 0x0001
+CO_NEWLOCALS    = 0x0002
+CO_VARARGS      = 0x0004
+CO_VARKEYWORDS  = 0x0008
+CO_NESTED       = 0x0010
+CO_GENERATOR    = 0x0020
+
+
+class PyCode(eval.Code):
+    "CPython-style code objects."
+    
+    def __init__(self, co_name):
+        eval.Code.__init__(self, co_name)
+        self.co_argcount = 0         # #arguments, except *vararg and **kwarg
+        self.co_nlocals = 0          # #local variables
+        self.co_stacksize = 0        # #entries needed for evaluation stack
+        self.co_flags = 0            # CO_..., see above
+        self.co_code = None          # string: instruction opcodes
+        self.co_consts = ()          # tuple: constants used
+        self.co_names = ()           # tuple of strings: names (for attrs,...)
+        self.co_varnames = ()        # tuple of strings: local variable names
+        self.co_freevars = ()        # tuple of strings: free variable names
+        self.co_cellvars = ()        # tuple of strings: cell variable names
+        # The rest doesn't count for hash/cmp
+        self.co_filename = ""        # string: where it was loaded from
+        #self.co_name (in base class)# string: name, for reference
+        self.co_firstlineno = 0      # first source line number
+        self.co_lnotab = ""          # string: encoding addr<->lineno mapping
+
+    def _from_code(self, code):
+        """ Initialize the code object from a real (CPython) one.
+            This is just a hack, until we have our own compile.
+            At the moment, we just fake this.
+            This method is called by our compile builtin function.
+        """
+        import types
+        assert isinstance(code, types.CodeType)
+        # simply try to suck in all attributes we know of
+        for name in self.__dict__.keys():
+            value = getattr(code, name)
+            setattr(self, name, value)
+        newconsts = ()
+        for const in code.co_consts:
+            if isinstance(const, types.CodeType):
+                newc = PyCode(const.co_name)
+                newc._from_code(const)
+                newconsts = newconsts + (newc,)
+            else:
+                newconsts = newconsts + (const,)
+        self.co_consts = newconsts
+
+    def create_frame(self, space):
+        "Create an empty PyFrame suitable for this code object."
+        # select the appropriate kind of frame; see below
+        if self.co_cellvars or self.co_freevars:
+            frameclass = PyNestedScopeFrame
+        elif self.co_nlocals:
+            frameclass = PyFastScopeFrame
+        else:
+            frameclass = PyOperationalFrame
+        return frameclass(space, self)
+
+    def signature(self):
+        "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
+        argcount = self.co_argcount
+        argnames = self.co_varnames[:argcount]
+        if self.co_flags & CO_VARARGS:
+            varargname = self.co_varnames[argcount]
+            argcount += 1
+        else:
+            varargname = None
+        if self.co_flags & CO_VARKEYWORDS:
+            kwargname = self.co_varnames[argcount]
+            argcount += 1
+        else:
+            kwargname = None
+        return argnames, varargname, kwargname
+
+    def getargcount(self):
+        count = self.co_argcount
+        if self.co_flags & CO_VARARGS:
+            count += 1
+        if self.co_flags & CO_VARKEYWORDS:
+            count += 1
+        return count
+
+    def getlocalvarname(self, index):
+        # nb. this is duplicated in PyFastScopeFrame.getlocalvarname()
+        return self.co_varnames[index]
+
+    def is_generator(self):
+        return self.co_flags & CO_GENERATOR

Added: pypy/branch/builtinrefactor/pypy/interpreter/pyfastscope.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pyfastscope.py	Sat Aug  9 15:48:30 2003
@@ -0,0 +1,91 @@
+from pypy.interpreter.pyopcode import PyOperationalFrame
+
+
+UNDEFINED = object()  # marker for undefined local variables
+
+
+class PyFastScopeFrame(PyOperationalFrame):
+    "A PyFrame that knows about fast scopes."
+
+    # this is the class that knows about "fast locals", i.e.
+    # the fact that local variables are better represented as an array
+    # of values accessed by index (by the LOAD_FAST, STORE_FAST and
+    # DELETE_FAST opcodes).
+
+    def __init__(self, space, code):
+        PyOperationalFrame.__init__(self, space, code)
+        self.locals_w = [UNDEFINED] * code.co_nlocals
+
+    def getlocalvarname(self, index):
+        return self.bytecode.co_varnames[index]
+
+    def getlocaldict(self):
+        self.fast2locals()
+        return self.w_locals
+
+    def setlocaldict(self, w_locals):
+        self.w_locals = w_locals
+        self.locals2fast()
+
+    def getlocalvar(self, index):
+        return self.locals_w[index]
+
+    def setlocalvar(self, index, w_value):
+        self.locals_w[index] = w_value
+
+    def fast2locals(self):
+        # Copy values from self.locals_w to self.w_locals
+        if self.w_locals is None:
+            self.w_locals = self.space.newdict([])
+        for name, w_value in zip(self.bytecode.co_varnames, self.locals_w):
+            if w_value is not UNDEFINED:
+                w_name = self.space.wrap(name)
+                self.space.setitem(self.w_locals, w_name, w_value)
+
+    def locals2fast(self):
+        # Copy values from self.w_locals to self.locals_w
+        for i in range(self.bytecode.co_nlocals):
+            w_name = self.space.wrap(self.bytecode.co_varnames[i])
+            try:
+                w_value = self.space.getitem(self.w_locals, w_name)
+            except OperationError, e:
+                if not e.match(self.space, self.space.w_KeyError):
+                    raise
+            else:
+                self.locals_w[i] = w_value
+
+    ### extra opcodes ###
+
+    def LOAD_FAST(f, varindex):
+        # access a local variable directly
+        w_value = f.locals_w[varindex]
+        if w_value is UNDEFINED:
+            varname = f.getlocalvarname(varindex)
+            message = "local variable '%s' referenced before assignment" % varname
+            raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
+        f.valuestack.push(w_value)
+
+    def STORE_FAST(f, varindex):
+        try:
+            w_newvalue = f.valuestack.pop()
+            f.locals_w[varindex] = w_newvalue
+        except:
+            print "exception: got index error"
+            print " varindex:", varindex
+            print " len(locals_w)", len(f.locals_w)
+            import dis
+            print dis.dis(f.bytecode)
+            print "co_varnames", f.bytecode.co_varnames
+            print "co_nlocals", f.bytecode.co_nlocals
+            raise
+
+    def DELETE_FAST(f, varindex):
+        w_value = f.locals_w[varindex]
+        if f.locals_w[varindex] is UNDEFINED:
+            varname = f.getlocalvarname(varindex)
+            message = "local variable '%s' referenced before assignment" % varname
+            raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
+        f.locals_w[varindex] = UNDEFINED
+
+
+PyFastScopeFrame.setup_dispatch_table()

Modified: pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py	Sat Aug  9 15:48:30 2003
@@ -1,61 +1,53 @@
 """ PyFrame class implementation with the interpreter main loop.
 """
 
-from pypy.interpreter.executioncontext import OperationError, Stack, NoValue
-from pypy.interpreter.gateway import app2interp, Cell, _NULL
+from pypy.interpreter.executioncontext import Stack
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import app2interp
+from pypy.interpreter import eval, baseobjspace
 
 
-class PyFrame:
+class PyFrame(eval.Frame):
     """Represents a frame for a regular Python function
     that needs to be interpreted.
 
+    See also pyopcode.PyStandardFrame and pynestedscope.PyNestedScopeFrame.
+
     Public fields:
      * 'space' is the object space this frame is running in
+     * 'bytecode' is the PyCode object this frame runs
      * 'w_locals' is the locals dictionary to use
      * 'w_globals' is the attached globals dictionary
      * 'w_builtins' is the attached built-ins dictionary
      * 'valuestack', 'blockstack', 'next_instr' control the interpretation
     """
 
-    def initialize(self, scopedcode):
-        self.space = scopedcode.space
-        self.bytecode = scopedcode.cpycode
-        self.w_globals = scopedcode.w_globals
-        self.closure_w = scopedcode.closure_w or ()
+    def __init__(self, space, code):
+        eval.Frame.__init__(self, space, code)
+        self.bytecode = code   # Misnomer; this is really like a code object
         self.valuestack = Stack()
         self.blockstack = Stack()
         self.last_exception = None
         self.next_instr = 0
         self.w_builtins = self.space.w_builtins
 
-    def setdictscope(self, w_locals):
-        self.w_locals = w_locals
-        self.locals_w = [_NULL] * self.bytecode.co_nlocals
-        self.locals2fast()
-
-    def setfastscope(self, locals_w):
-        self.locals_w = locals_w
-        self.w_locals = self.space.newdict([])
-        self.fast2locals()
-
-    def XXXclone(self):
-        f = self.__class__()
-        f.space = self.space
-        f.bytecode = self.bytecode
-        f.w_globals = self.w_globals
-        f.w_locals = self.w_locals
-        f.w_builtins = self.w_builtins
-        f.valuestack = self.valuestack.clone()
-        f.blockstack = self.blockstack.clone()
-        f.localcells = [x.clone() for x in self.localcells]
-        f.nestedcells = [x.clone() for x in self.nestedcells]
-        f.last_exception = self.last_exception
-        f.next_instr = self.next_instr
-        return f
+##    def XXXclone(self):
+##        f = self.__class__()
+##        f.space = self.space
+##        f.bytecode = self.bytecode
+##        f.w_globals = self.w_globals
+##        f.w_locals = self.w_locals
+##        f.w_builtins = self.w_builtins
+##        f.valuestack = self.valuestack.clone()
+##        f.blockstack = self.blockstack.clone()
+##        f.localcells = [x.clone() for x in self.localcells]
+##        f.nestedcells = [x.clone() for x in self.nestedcells]
+##        f.last_exception = self.last_exception
+##        f.next_instr = self.next_instr
+##        return f
 
     def eval(self, executioncontext):
         "Interpreter main loop!"
-        from pypy.interpreter import opcode
         try:
             while True:
                 try:
@@ -63,12 +55,8 @@
                     last_instr = self.next_instr
                     try:
                         # fetch and dispatch the next opcode
-                        op = self.nextop()
-                        if opcode.has_arg(op):
-                            oparg = self.nextarg()
-                            opcode.dispatch_arg(self, op, oparg)
-                        else:
-                            opcode.dispatch_noarg(self, op)
+                        # dispatch() is abstract, see pyopcode.
+                        self.dispatch()
                     except OperationError, e:
                         #import traceback
                         #traceback.print_exc()
@@ -93,7 +81,20 @@
             w_exitvalue = e.args[0]
             return w_exitvalue
 
-    ### accessor functions ###
+    ### opcode dispatch ###
+
+    # 'dispatch_table' is a class attribute: a list of functions.
+    # Currently, it is always created by setup_dispatch_table in pyopcode.py
+    # but it could be a custom table.
+
+    def dispatch(self):
+        opcode = self.nextop()
+        fn = self.dispatch_table[opcode]
+        if fn.has_arg:
+            oparg = self.nextarg()
+            fn(self, oparg)
+        else:
+            fn(self)
 
     def nextop(self):
         c = self.bytecode.co_code[self.next_instr]
@@ -105,45 +106,6 @@
         hi = self.nextop()
         return (hi<<8) + lo
 
-    def getconstant(self, index):
-        return self.bytecode.co_consts[index]
-
-    def getlocalvarname(self, index):
-        return self.bytecode.co_varnames[index]
-
-    def getname(self, index):
-        return self.bytecode.co_names[index]
-
-    def getfreevarname(self, index):
-        freevarnames = self.bytecode.co_cellvars + self.bytecode.co_freevars
-        return freevarnames[index]
-
-    def iscellvar(self, index):
-        # is the variable given by index a cell or a free var?
-        return index < len(self.bytecode.co_cellvars)
-
-    def fast2locals(self):
-        # Copy values from self.localcells to self.w_locals
-        for name, w_value in zip(self.bytecode.co_varnames, self.locals_w):
-            w_name = self.space.wrap(name)
-            if w_value is not _NULL:
-                self.space.setitem(self.w_locals, w_name, w_value)
-
-    def locals2fast(self):
-        # Copy values from self.w_locals to self.localcells
-        for i in range(self.bytecode.co_nlocals):
-            w_name = self.space.wrap(self.bytecode.co_varnames[i])
-            try:
-                w_value = self.space.getitem(self.w_locals, w_name)
-            except OperationError, e:
-                if not e.match(self.space, self.space.w_KeyError):
-                    raise
-            else:
-                self.locals_w[i] = w_value
-
-    ### frame initialization ###
-
-
     ### exception stack ###
 
     def clean_exceptionstack(self):
@@ -240,7 +202,7 @@
                 evalue = (evalue,)
             evalue = etype(*evalue)
         else:
-            raise Exception, "?!"
+            raise Exception, "?!"   # XXX
         return etype, evalue
     normalize_exception = app2interp(app_normalize_exception)
 
@@ -324,8 +286,8 @@
     """Signals a 'return' statement.
     Argument is the wrapped object to return."""
     def emptystack(self, frame):
-        if frame.bytecode.co_flags & 0x0020:#CO_GENERATOR:
-            raise NoValue
+        if frame.bytecode.is_generator():
+            raise baseobjspace.NoValue
         w_returnvalue = self.args[0]
         raise ExitFrame(w_returnvalue)
 

Added: pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py	Sat Aug  9 15:48:30 2003
@@ -0,0 +1,173 @@
+from pypy.interpreter.pyfastscope import PyFastScopeFrame, UNDEFINED
+
+
+class Cell(object):
+    "A simple container for a wrapped value."
+    
+    def __init__(self, w_value=UNDEFINED):
+        self.w_value = w_value
+
+    def clone(self):
+        return self.__class__(self.w_value)
+
+    def empty(self):
+        return self.w_value is UNDEFINED
+
+    def get(self):
+        if self.w_value is UNDEFINED:
+            raise ValueError, "get() from an empty cell"
+        return self.w_value
+
+    def set(self, w_value):
+        self.w_value = w_value
+
+    def delete(self):
+        if self.w_value is UNDEFINED:
+            raise ValueError, "delete() on an empty cell"
+        self.w_value = UNDEFINED
+
+    def __repr__(self):
+        """ representation for debugging purposes """
+        if self.w_value is UNDEFINED:
+            content = ""
+        else:
+            content = repr(self.w_value)
+        return "<%s(%s) at 0x%x>" % (self.__class__.__name__,
+                                     content, id(self))
+
+
+class PyNestedScopeFrame(PyFastScopeFrame):
+    """This class enhances a standard frame with nested scope abilities,
+    i.e. handling of cell/free variables."""
+
+    def __init__(self, space, code):
+        PyFastScopeFrame.__init__(self, space, code)
+        ncellvars = len(code.co_cellvars)
+        nfreevars = len(code.co_freevars)
+        self.cells = [None] * (ncellvars + nfreevars)
+
+    def fast2locals(self):
+        PyFastScopeFrame.fast2locals(self)
+        freevarnames = self.bytecode.co_cellvars + self.bytecode.co_freevars
+        for name, cell in zip(freevarnames, self.cells):
+            try:
+                w_value = cell.get()
+            except ValueError:
+                pass
+            else:
+                w_name = self.space.wrap(name)
+                self.space.setitem(self.w_locals, w_name, w_value)
+
+    def locals2fast(self):
+        PyFastScopeFrame.locals2fast(self)
+        freevarnames = self.bytecode.co_cellvars + self.bytecode.co_freevars
+        for name, cell in zip(freevarnames, self.cells):
+            w_name = self.space.wrap(name)
+            try:
+                w_value = self.space.getitem(self.w_locals, w_name)
+            except OperationError, e:
+                if not e.match(self.space, self.space.w_KeyError):
+                    raise
+            else:
+                cell.set(w_value)
+
+    def setclosure(self, closure):
+        # Cell Vars:
+        #     my local variables that are exposed to my inner functions
+        # Free Vars:
+        #     variables coming from a parent function in which i'm nested
+        # 'closure' is a list of Cell instances: the received free vars.
+        code = self.bytecode
+        ncellvars = len(code.co_cellvars)
+        nfreevars = len(code.co_freevars)
+        if ncellvars:
+            # the first few cell vars could shadow already-set arguments,
+            # in the same order as they appear in co_varnames
+            nargvars = code.getargcount()
+            argvars  = code.co_varnames
+            cellvars = code.co_cellvars
+            next     = 0
+            nextname = cellvars[0]
+            for i in range(nargvars):
+                if argvars[i] == nextname:
+                    # argument i has the same name as the next cell var
+                    w_value = self.locals_w[i]
+                    self.cells[next] = Cell(w_value)
+                    next += 1
+                    try:
+                        nextname = cellvars[next]
+                    except IndexError:
+                        break   # all cell vars initialized this way
+            else:
+                # the remaining cell vars are empty
+                for i in range(next, ncellvars):
+                    self.cells[i] = Cell()
+        # following the cell vars are the free vars, copied from 'closure'
+        if closure is None:
+            closure = []
+        if len(closure) != nfreevars:
+            raise TypeError, ("%d free variables expected, got %d" %
+                              (nfreevars, len(closure)))   # internal error
+        self.cells[ncellvars:] = closure
+
+    def getfreevarname(self, index):
+        freevarnames = self.bytecode.co_cellvars + self.bytecode.co_freevars
+        return freevarnames[index]
+
+    def iscellvar(self, index):
+        # is the variable given by index a cell or a free var?
+        return index < len(self.bytecode.co_cellvars)
+
+    ### extra opcodes ###
+
+    def LOAD_CLOSURE(f, varindex):
+        # nested scopes: access the cell object
+        cell = f.cells[varindex]
+        assert cell is not None, "setclosure() was not called"
+        w_value = f.space.wrap(cell)
+        f.valuestack.push(w_value)
+
+    def LOAD_DEREF(f, varindex):
+        # nested scopes: access a variable through its cell object
+        cell = f.cells[varindex]
+        try:
+            w_value = cell.get()
+        except ValueError:
+            varname = f.getfreevarname(varindex)
+            if f.iscellvar(varindex):
+                message = "local variable '%s' referenced before assignment"
+                w_exc_type = f.space.w_UnboundLocalError
+            else:
+                message = ("free variable '%s' referenced before assignment"
+                           " in enclosing scope")
+                w_exc_type = f.space.w_NameError
+            raise OperationError(w_exc_type, f.space.wrap(message % varname))
+        else:
+            f.valuestack.push(w_value)
+
+    def STORE_DEREF(f, varindex):
+        # nested scopes: access a variable through its cell object
+        w_newvalue = f.valuestack.pop()
+        #try:
+        cell = f.cells[varindex]
+        #except IndexError:
+        #    import pdb; pdb.set_trace()
+        #    raise
+        cell.set(w_newvalue)
+
+    def MAKE_CLOSURE(f, numdefaults):
+        w_codeobj = f.valuestack.pop()
+        codeobj = f.space.unwrap(w_codeobj)
+        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.valuestack.push(w_func)
+
+
+PyNestedScopeFrame.setup_dispatch_table()

Copied: pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py (from rev 1262, pypy/branch/builtinrefactor/pypy/interpreter/opcode.py)
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/opcode.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py	Sat Aug  9 15:48:30 2003
@@ -1,13 +1,13 @@
-from appfile import AppFile
+"""
+Implementation of a part of the standard Python opcodes.
+The rest, dealing with variables in optimized ways, is in
+pyfastscope.py and pynestedscope.py.
+"""
+
 from pypy.interpreter.baseobjspace import OperationError, NoValue
-from pypy.interpreter.pyframe import _NULL
 import dis
-from pypy.interpreter import pyframe, baseobjspace
-from pypy.interpreter.gateway import InterpretedFunction, ScopedCode
-
-
-# dynamically loaded application-space utilities
-appfile = AppFile(__name__, ["interpreter"])
+from pypy.interpreter import baseobjspace
+from pypy.interpreter.pyframe import PyFrame
 
 
 class unaryoperation:
@@ -30,729 +30,648 @@
         f.valuestack.push(w_result)
 
 
-################################################################
-##  Implementation of the opcodes
-##
-
-def LOAD_FAST(f, varindex):
-    # access a local variable through its cell object
-    w_value = f.locals_w[varindex]
-    if w_value is _NULL:
-        varname = f.getlocalvarname(varindex)
-        message = "local variable '%s' referenced before assignment" % varname
-        raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
-    f.valuestack.push(w_value)
-
-def LOAD_CONST(f, constindex):
-    w_const = f.space.wrap(f.getconstant(constindex))
-    f.valuestack.push(w_const)
+class PyOperationalFrame(PyFrame):
+    """A PyFrame that knows about all operational Python opcodes.
+    It does not know about 'fast variables' nor 'nested scopes'."""
+
+    ### accessor functions ###
+
+    def getconstant(self, index):
+        return self.bytecode.co_consts[index]
+
+    def getname(self, index):
+        return self.bytecode.co_names[index]
+
+    ################################################################
+    ##  Implementation of the "operational" opcodes
+    ##  See also pyfastscope.py and pynestedscope.py for the rest.
+    ##
+    
+    #  the 'self' argument of opcode implementations is called 'f'
+    #  for historical reasons
 
-def STORE_FAST(f, varindex):
-    try:
-        w_newvalue = f.valuestack.pop()
-        f.locals_w[varindex] = w_newvalue
-    except:
-        print "exception: got index error"
-        print " varindex:", varindex
-        print " len(locals_w)", len(f.locals_w)
-        import dis
-        print dis.dis(f.bytecode)
-        print "co_varnames", f.bytecode.co_varnames
-        print "co_nlocals", f.bytecode.co_nlocals
-        raise
-
-
-def POP_TOP(f):
-    f.valuestack.pop()
-
-def ROT_TWO(f):
-    w_1 = f.valuestack.pop()
-    w_2 = f.valuestack.pop()
-    f.valuestack.push(w_1)
-    f.valuestack.push(w_2)
-
-def ROT_THREE(f):
-    w_1 = f.valuestack.pop()
-    w_2 = f.valuestack.pop()
-    w_3 = f.valuestack.pop()
-    f.valuestack.push(w_1)
-    f.valuestack.push(w_3)
-    f.valuestack.push(w_2)
-
-def ROT_FOUR(f):
-    w_1 = f.valuestack.pop()
-    w_2 = f.valuestack.pop()
-    w_3 = f.valuestack.pop()
-    w_4 = f.valuestack.pop()
-    f.valuestack.push(w_1)
-    f.valuestack.push(w_4)
-    f.valuestack.push(w_3)
-    f.valuestack.push(w_2)
-
-def DUP_TOP(f):
-    w_1 = f.valuestack.top()
-    f.valuestack.push(w_1)
-
-def DUP_TOPX(f, itemcount):
-    assert 1 <= itemcount <= 5, "limitation of the current interpreter"
-    for i in range(itemcount):
-        w_1 = f.valuestack.top(itemcount-1)
+    def LOAD_CONST(f, constindex):
+        w_const = f.space.wrap(f.getconstant(constindex))
+        f.valuestack.push(w_const)
+
+    def POP_TOP(f):
+        f.valuestack.pop()
+
+    def ROT_TWO(f):
+        w_1 = f.valuestack.pop()
+        w_2 = f.valuestack.pop()
         f.valuestack.push(w_1)
+        f.valuestack.push(w_2)
 
-UNARY_POSITIVE = unaryoperation("pos")
-UNARY_NEGATIVE = unaryoperation("neg")
-UNARY_NOT      = unaryoperation("not_")
-UNARY_CONVERT  = unaryoperation("repr")
-UNARY_INVERT   = unaryoperation("invert")
-
-def BINARY_POWER(f):
-    w_2 = f.valuestack.pop()
-    w_1 = f.valuestack.pop()
-    w_result = f.space.pow(w_1, w_2, f.space.w_None)
-    f.valuestack.push(w_result)
-
-BINARY_MULTIPLY = binaryoperation("mul")
-BINARY_TRUE_DIVIDE  = binaryoperation("truediv")
-BINARY_FLOOR_DIVIDE = binaryoperation("floordiv")
-BINARY_DIVIDE       = binaryoperation("div")
-BINARY_MODULO       = binaryoperation("mod")
-BINARY_ADD      = binaryoperation("add")
-BINARY_SUBTRACT = binaryoperation("sub")
-BINARY_SUBSCR   = binaryoperation("getitem")
-BINARY_LSHIFT   = binaryoperation("lshift")
-BINARY_RSHIFT   = binaryoperation("rshift")
-BINARY_AND = binaryoperation("and_")
-BINARY_XOR = binaryoperation("xor")
-BINARY_OR  = binaryoperation("or_")
-
-def INPLACE_POWER(f):
-    w_2 = f.valuestack.pop()
-    w_1 = f.valuestack.pop()
-    w_result = f.space.inplace_pow(w_1, w_2, f.space.w_None)
-    f.valuestack.push(w_result)
-
-INPLACE_MULTIPLY = binaryoperation("inplace_mul")
-INPLACE_TRUE_DIVIDE  = binaryoperation("inplace_truediv")
-INPLACE_FLOOR_DIVIDE = binaryoperation("inplace_floordiv")
-INPLACE_DIVIDE       = binaryoperation("inplace_div")
-INPLACE_MODULO       = binaryoperation("inplace_mod")
-INPLACE_ADD      = binaryoperation("inplace_add")
-INPLACE_SUBTRACT = binaryoperation("inplace_sub")
-INPLACE_LSHIFT   = binaryoperation("inplace_lshift")
-INPLACE_RSHIFT   = binaryoperation("inplace_rshift")
-INPLACE_AND = binaryoperation("inplace_and")
-INPLACE_XOR = binaryoperation("inplace_xor")
-INPLACE_OR  = binaryoperation("inplace_or")
-
-def slice(f, w_start, w_end):
-    w_slice = f.space.newslice(w_start, w_end, None)
-    w_obj = f.valuestack.pop()
-    w_result = f.space.getitem(w_obj, w_slice)
-    f.valuestack.push(w_result)
-
-def SLICE_0(f):
-    slice(f, None, None)
-
-def SLICE_1(f):
-    w_start = f.valuestack.pop()
-    slice(f, w_start, None)
-
-def SLICE_2(f):
-    w_end = f.valuestack.pop()
-    slice(f, None, w_end)
-
-def SLICE_3(f):
-    w_end = f.valuestack.pop()
-    w_start = f.valuestack.pop()
-    slice(f, w_start, w_end)
-
-def storeslice(f, w_start, w_end):
-    w_slice = f.space.newslice(w_start, w_end, None)
-    w_obj = f.valuestack.pop()
-    w_newvalue = f.valuestack.pop()
-    f.space.setitem(w_obj, w_slice, w_newvalue)
-
-def STORE_SLICE_0(f):
-    storeslice(f, None, None)
-
-def STORE_SLICE_1(f):
-    w_start = f.valuestack.pop()
-    storeslice(f, w_start, None)
-
-def STORE_SLICE_2(f):
-    w_end = f.valuestack.pop()
-    storeslice(f, None, w_end)
-
-def STORE_SLICE_3(f):
-    w_end = f.valuestack.pop()
-    w_start = f.valuestack.pop()
-    storeslice(f, w_start, w_end)
-
-def deleteslice(f, w_start, w_end):
-    w_slice = f.space.newslice(w_start, w_end, None)
-    w_obj = f.valuestack.pop()
-    f.space.delitem(w_obj, w_slice)
-
-def DELETE_SLICE_0(f):
-    deleteslice(f, None, None)
-
-def DELETE_SLICE_1(f):
-    w_start = f.valuestack.pop()
-    deleteslice(f, w_start, None)
-
-def DELETE_SLICE_2(f):
-    w_end = f.valuestack.pop()
-    deleteslice(f, None, w_end)
-
-def DELETE_SLICE_3(f):
-    w_end = f.valuestack.pop()
-    w_start = f.valuestack.pop()
-    deleteslice(f, w_start, w_end)
-
-def STORE_SUBSCR(f):
-    "obj[subscr] = newvalue"
-    w_subscr = f.valuestack.pop()
-    w_obj = f.valuestack.pop()
-    w_newvalue = f.valuestack.pop()
-    f.space.setitem(w_obj, w_subscr, w_newvalue)
-
-def DELETE_SUBSCR(f):
-    "del obj[subscr]"
-    w_subscr = f.valuestack.pop()
-    w_obj = f.valuestack.pop()
-    f.space.delitem(w_obj, w_subscr)
-
-def PRINT_EXPR(f):
-    w_expr = f.valuestack.pop()
-    #print f.space.unwrap(w_expr)
-    f.space.gethelper(appfile).call("print_expr", [w_expr])
-
-def PRINT_ITEM_TO(f):
-    w_stream = f.valuestack.pop()
-    w_item = f.valuestack.pop()
-    f.space.gethelper(appfile).call("print_item_to", [w_item, w_stream])
-
-def PRINT_ITEM(f):
-    w_item = f.valuestack.pop()
-    f.space.gethelper(appfile).call("print_item", [w_item])
-
-def PRINT_NEWLINE_TO(f):
-    w_stream = f.valuestack.pop()
-    f.space.gethelper(appfile).call("print_newline_to", [w_stream])
-
-def PRINT_NEWLINE(f):
-    f.space.gethelper(appfile).call("print_newline", [])
-
-def BREAK_LOOP(f):
-    raise pyframe.SBreakLoop
-
-def CONTINUE_LOOP(f, startofloop):
-    raise pyframe.SContinueLoop(startofloop)
-
-def RAISE_VARARGS(f, nbargs):
-    # we use the .app.py file to prepare the exception/value/traceback
-    # but not to actually raise it, because we cannot use the 'raise'
-    # statement to implement RAISE_VARARGS
-    if nbargs == 0:
-        w_resulttuple = f.space.gethelper(appfile).call("prepare_raise0", [])
-    elif nbargs == 1:
-        w_type = f.valuestack.pop()
-        w_resulttuple = f.space.gethelper(appfile).call(
-            "prepare_raise", [w_type, f.space.w_None, f.space.w_None])
-    elif nbargs == 2:
-        w_value = f.valuestack.pop()
-        w_type  = f.valuestack.pop()
-        w_resulttuple = f.space.gethelper(appfile).call(
-            "prepare_raise", [w_type, w_value, f.space.w_None])
-    elif nbargs == 3:
-        w_traceback = f.valuestack.pop()
-        w_value     = f.valuestack.pop()
-        w_type      = f.valuestack.pop()
-        w_resulttuple = f.space.gethelper(appfile).call(
-            "prepare_raise", [w_type, w_value, w_traceback])
-    else:
-        raise pyframe.BytecodeCorruption, "bad RAISE_VARARGS oparg"
-    w_type, w_value, w_traceback = f.space.unpacktuple(w_resulttuple)
-    # XXX the three-arguments 'raise' is not supported yet
-    raise OperationError(w_type, w_value)
-
-def LOAD_LOCALS(f):
-    f.valuestack.push(f.w_locals)
-
-def RETURN_VALUE(f):
-    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()
-    w_prog    = f.valuestack.pop()
-    w_tuple = f.space.gethelper(appfile).call("exec_statement",
-                                    [w_prog, w_globals, w_locals,
-                                     f.w_builtins, f.w_globals, f.w_locals])
-    w_prog = f.space.getitem(w_tuple,f.space.wrap(0))
-    w_globals = f.space.getitem(w_tuple,f.space.wrap(1))
-    w_locals = f.space.getitem(w_tuple,f.space.wrap(2))
-
-    plain = (w_locals is f.w_locals)
-    if plain:
-        f.fast2locals()
-    scopedcode = ScopedCode(f.space, f.space.unwrap(w_prog), w_globals)
-    scopedcode.eval_frame(w_locals)
-    #f.space.unwrap(w_prog).eval_code(f.space, w_globals, w_locals)
-    if plain:
-        f.locals2fast()
-    
-def POP_BLOCK(f):
-    block = f.blockstack.pop()
-    block.cleanup(f)  # the block knows how to clean up the value stack
-
-def END_FINALLY(f):
-    # unlike CPython, when we reach this opcode the value stack has
-    # always been set up as follows (topmost first):
-    #   [exception type  or None]
-    #   [exception value or None]
-    #   [wrapped stack unroller ]
-    f.valuestack.pop()   # ignore the exception type
-    f.valuestack.pop()   # ignore the exception value
-    unroller = f.space.unwrap(f.valuestack.pop())
-    if unroller is not None:
-        raise unroller   # re-raise the unroller, if any
-    
-def BUILD_CLASS(f):
-    w_methodsdict = f.valuestack.pop()
-    w_bases       = f.valuestack.pop()
-    w_name        = f.valuestack.pop()
-    # XXX it would be best to have all opcodes on a class that has a 'space' attribute
-    #     then the following initialization could be done at init-time. 
-    build_class = InterpretedFunction(f.space.gethelperspace(), app_build_class)
-    w_newclass = build_class(w_name, w_bases, w_methodsdict, f.w_globals)
-    f.valuestack.push(w_newclass)
-
-def app_build_class(name, bases, namespace, globals):
-    if '__metaclass__' in namespace:
-        metaclass = namespace['__metaclass__']
-    elif len(bases) > 0:
-        base = bases[0]
-        if hasattr(base, '__class__'):
-            metaclass = base.__class__
+    def ROT_THREE(f):
+        w_1 = f.valuestack.pop()
+        w_2 = f.valuestack.pop()
+        w_3 = f.valuestack.pop()
+        f.valuestack.push(w_1)
+        f.valuestack.push(w_3)
+        f.valuestack.push(w_2)
+
+    def ROT_FOUR(f):
+        w_1 = f.valuestack.pop()
+        w_2 = f.valuestack.pop()
+        w_3 = f.valuestack.pop()
+        w_4 = f.valuestack.pop()
+        f.valuestack.push(w_1)
+        f.valuestack.push(w_4)
+        f.valuestack.push(w_3)
+        f.valuestack.push(w_2)
+
+    def DUP_TOP(f):
+        w_1 = f.valuestack.top()
+        f.valuestack.push(w_1)
+
+    def DUP_TOPX(f, itemcount):
+        assert 1 <= itemcount <= 5, "limitation of the current interpreter"
+        for i in range(itemcount):
+            w_1 = f.valuestack.top(itemcount-1)
+            f.valuestack.push(w_1)
+
+    UNARY_POSITIVE = unaryoperation("pos")
+    UNARY_NEGATIVE = unaryoperation("neg")
+    UNARY_NOT      = unaryoperation("not_")
+    UNARY_CONVERT  = unaryoperation("repr")
+    UNARY_INVERT   = unaryoperation("invert")
+
+    def BINARY_POWER(f):
+        w_2 = f.valuestack.pop()
+        w_1 = f.valuestack.pop()
+        w_result = f.space.pow(w_1, w_2, f.space.w_None)
+        f.valuestack.push(w_result)
+
+    BINARY_MULTIPLY = binaryoperation("mul")
+    BINARY_TRUE_DIVIDE  = binaryoperation("truediv")
+    BINARY_FLOOR_DIVIDE = binaryoperation("floordiv")
+    BINARY_DIVIDE       = binaryoperation("div")
+    BINARY_MODULO       = binaryoperation("mod")
+    BINARY_ADD      = binaryoperation("add")
+    BINARY_SUBTRACT = binaryoperation("sub")
+    BINARY_SUBSCR   = binaryoperation("getitem")
+    BINARY_LSHIFT   = binaryoperation("lshift")
+    BINARY_RSHIFT   = binaryoperation("rshift")
+    BINARY_AND = binaryoperation("and_")
+    BINARY_XOR = binaryoperation("xor")
+    BINARY_OR  = binaryoperation("or_")
+
+    def INPLACE_POWER(f):
+        w_2 = f.valuestack.pop()
+        w_1 = f.valuestack.pop()
+        w_result = f.space.inplace_pow(w_1, w_2, f.space.w_None)
+        f.valuestack.push(w_result)
+
+    INPLACE_MULTIPLY = binaryoperation("inplace_mul")
+    INPLACE_TRUE_DIVIDE  = binaryoperation("inplace_truediv")
+    INPLACE_FLOOR_DIVIDE = binaryoperation("inplace_floordiv")
+    INPLACE_DIVIDE       = binaryoperation("inplace_div")
+    INPLACE_MODULO       = binaryoperation("inplace_mod")
+    INPLACE_ADD      = binaryoperation("inplace_add")
+    INPLACE_SUBTRACT = binaryoperation("inplace_sub")
+    INPLACE_LSHIFT   = binaryoperation("inplace_lshift")
+    INPLACE_RSHIFT   = binaryoperation("inplace_rshift")
+    INPLACE_AND = binaryoperation("inplace_and")
+    INPLACE_XOR = binaryoperation("inplace_xor")
+    INPLACE_OR  = binaryoperation("inplace_or")
+
+    def slice(f, w_start, w_end):
+        w_slice = f.space.newslice(w_start, w_end, None)
+        w_obj = f.valuestack.pop()
+        w_result = f.space.getitem(w_obj, w_slice)
+        f.valuestack.push(w_result)
+
+    def SLICE_0(f):
+        slice(f, None, None)
+
+    def SLICE_1(f):
+        w_start = f.valuestack.pop()
+        slice(f, w_start, None)
+
+    def SLICE_2(f):
+        w_end = f.valuestack.pop()
+        slice(f, None, w_end)
+
+    def SLICE_3(f):
+        w_end = f.valuestack.pop()
+        w_start = f.valuestack.pop()
+        slice(f, w_start, w_end)
+
+    def storeslice(f, w_start, w_end):
+        w_slice = f.space.newslice(w_start, w_end, None)
+        w_obj = f.valuestack.pop()
+        w_newvalue = f.valuestack.pop()
+        f.space.setitem(w_obj, w_slice, w_newvalue)
+
+    def STORE_SLICE_0(f):
+        storeslice(f, None, None)
+
+    def STORE_SLICE_1(f):
+        w_start = f.valuestack.pop()
+        storeslice(f, w_start, None)
+
+    def STORE_SLICE_2(f):
+        w_end = f.valuestack.pop()
+        storeslice(f, None, w_end)
+
+    def STORE_SLICE_3(f):
+        w_end = f.valuestack.pop()
+        w_start = f.valuestack.pop()
+        storeslice(f, w_start, w_end)
+
+    def deleteslice(f, w_start, w_end):
+        w_slice = f.space.newslice(w_start, w_end, None)
+        w_obj = f.valuestack.pop()
+        f.space.delitem(w_obj, w_slice)
+
+    def DELETE_SLICE_0(f):
+        deleteslice(f, None, None)
+
+    def DELETE_SLICE_1(f):
+        w_start = f.valuestack.pop()
+        deleteslice(f, w_start, None)
+
+    def DELETE_SLICE_2(f):
+        w_end = f.valuestack.pop()
+        deleteslice(f, None, w_end)
+
+    def DELETE_SLICE_3(f):
+        w_end = f.valuestack.pop()
+        w_start = f.valuestack.pop()
+        deleteslice(f, w_start, w_end)
+
+    def STORE_SUBSCR(f):
+        "obj[subscr] = newvalue"
+        w_subscr = f.valuestack.pop()
+        w_obj = f.valuestack.pop()
+        w_newvalue = f.valuestack.pop()
+        f.space.setitem(w_obj, w_subscr, w_newvalue)
+
+    def DELETE_SUBSCR(f):
+        "del obj[subscr]"
+        w_subscr = f.valuestack.pop()
+        w_obj = f.valuestack.pop()
+        f.space.delitem(w_obj, w_subscr)
+
+    def PRINT_EXPR(f):
+        w_expr = f.valuestack.pop()
+        #print f.space.unwrap(w_expr)
+        f.space.gethelper(appfile).call("print_expr", [w_expr])
+
+    def PRINT_ITEM_TO(f):
+        w_stream = f.valuestack.pop()
+        w_item = f.valuestack.pop()
+        f.space.gethelper(appfile).call("print_item_to", [w_item, w_stream])
+
+    def PRINT_ITEM(f):
+        w_item = f.valuestack.pop()
+        f.space.gethelper(appfile).call("print_item", [w_item])
+
+    def PRINT_NEWLINE_TO(f):
+        w_stream = f.valuestack.pop()
+        f.space.gethelper(appfile).call("print_newline_to", [w_stream])
+
+    def PRINT_NEWLINE(f):
+        f.space.gethelper(appfile).call("print_newline", [])
+
+    def BREAK_LOOP(f):
+        raise pyframe.SBreakLoop
+
+    def CONTINUE_LOOP(f, startofloop):
+        raise pyframe.SContinueLoop(startofloop)
+
+    def RAISE_VARARGS(f, nbargs):
+        # we use the .app.py file to prepare the exception/value/traceback
+        # but not to actually raise it, because we cannot use the 'raise'
+        # statement to implement RAISE_VARARGS
+        if nbargs == 0:
+            w_resulttuple = f.space.gethelper(appfile).call("prepare_raise0", [])
+        elif nbargs == 1:
+            w_type = f.valuestack.pop()
+            w_resulttuple = f.space.gethelper(appfile).call(
+                "prepare_raise", [w_type, f.space.w_None, f.space.w_None])
+        elif nbargs == 2:
+            w_value = f.valuestack.pop()
+            w_type  = f.valuestack.pop()
+            w_resulttuple = f.space.gethelper(appfile).call(
+                "prepare_raise", [w_type, w_value, f.space.w_None])
+        elif nbargs == 3:
+            w_traceback = f.valuestack.pop()
+            w_value     = f.valuestack.pop()
+            w_type      = f.valuestack.pop()
+            w_resulttuple = f.space.gethelper(appfile).call(
+                "prepare_raise", [w_type, w_value, w_traceback])
+        else:
+            raise pyframe.BytecodeCorruption, "bad RAISE_VARARGS oparg"
+        w_type, w_value, w_traceback = f.space.unpacktuple(w_resulttuple)
+        # XXX the three-arguments 'raise' is not supported yet
+        raise OperationError(w_type, w_value)
+
+    def LOAD_LOCALS(f):
+        f.valuestack.push(f.w_locals)
+
+    def RETURN_VALUE(f):
+        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()
+        w_prog    = f.valuestack.pop()
+        w_tuple = f.space.gethelper(appfile).call("exec_statement",
+                                        [w_prog, w_globals, w_locals,
+                                         f.w_builtins, f.w_globals, f.w_locals])
+        w_prog = f.space.getitem(w_tuple,f.space.wrap(0))
+        w_globals = f.space.getitem(w_tuple,f.space.wrap(1))
+        w_locals = f.space.getitem(w_tuple,f.space.wrap(2))
+
+        #plain = ... ...   w_locals = f.getlocaldict()   XXX XXX
+        
+        scopedcode = ScopedCode(f.space, f.space.unwrap(w_prog), w_globals)
+        scopedcode.eval_frame(w_locals)
+        #f.space.unwrap(w_prog).eval_code(f.space, w_globals, w_locals)
+        if plain:
+            f.setlocaldict(w_locals)
+
+    def POP_BLOCK(f):
+        block = f.blockstack.pop()
+        block.cleanup(f)  # the block knows how to clean up the value stack
+
+    def END_FINALLY(f):
+        # unlike CPython, when we reach this opcode the value stack has
+        # always been set up as follows (topmost first):
+        #   [exception type  or None]
+        #   [exception value or None]
+        #   [wrapped stack unroller ]
+        f.valuestack.pop()   # ignore the exception type
+        f.valuestack.pop()   # ignore the exception value
+        unroller = f.space.unwrap(f.valuestack.pop())
+        if unroller is not None:
+            raise unroller   # re-raise the unroller, if any
+
+    def BUILD_CLASS(f):
+        w_methodsdict = f.valuestack.pop()
+        w_bases       = f.valuestack.pop()
+        w_name        = f.valuestack.pop()
+        # XXX it would be best to have all opcodes on a class that has a 'space' attribute
+        #     then the following initialization could be done at init-time. 
+        build_class = InterpretedFunction(f.space.gethelperspace(), app_build_class)
+        w_newclass = build_class(w_name, w_bases, w_methodsdict, f.w_globals)
+        f.valuestack.push(w_newclass)
+
+    def app_build_class(name, bases, namespace, globals):
+        if '__metaclass__' in namespace:
+            metaclass = namespace['__metaclass__']
+        elif len(bases) > 0:
+            base = bases[0]
+            if hasattr(base, '__class__'):
+                metaclass = base.__class__
+            else:
+                metaclass = type(base)
+        elif '__metaclass__' in globals:
+            metaclass = globals['__metaclass__']
         else:
-            metaclass = type(base)
-    elif '__metaclass__' in globals:
-        metaclass = globals['__metaclass__']
-    else:
-        metaclass = type
-    return metaclass(name, bases, namespace)
-
-def STORE_NAME(f, varindex):
-    varname = f.getname(varindex)
-    w_varname = f.space.wrap(varname)
-    w_newvalue = f.valuestack.pop()
-    f.space.setitem(f.w_locals, w_varname, w_newvalue)
-
-def DELETE_NAME(f, varindex):
-    varname = f.getname(varindex)
-    w_varname = f.space.wrap(varname)
-    try:
-        f.space.delitem(f.w_locals, w_varname)
-    except OperationError, e:
-        # catch KeyErrors and turn them into NameErrors
-        if not e.match(f.space, f.space.w_KeyError):
-            raise
-        message = "name '%s' is not defined" % varname
-        raise OperationError(f.space.w_NameError, f.space.wrap(message))
-
-def UNPACK_SEQUENCE(f, itemcount):
-    w_iterable = f.valuestack.pop()
-    try:
-        items = f.space.unpackiterable(w_iterable, itemcount)
-    except ValueError, e:
-        raise OperationError(f.space.w_ValueError, f.space.wrap(str(e)))
-    items.reverse()
-    for item in items:
-        f.valuestack.push(item)
-
-def STORE_ATTR(f, nameindex):
-    "obj.attributename = newvalue"
-    attributename = f.getname(nameindex)
-    w_attributename = f.space.wrap(attributename)
-    w_obj = f.valuestack.pop()
-    w_newvalue = f.valuestack.pop()
-    f.space.setattr(w_obj, w_attributename, w_newvalue)
-
-def DELETE_ATTR(f, nameindex):
-    "del obj.attributename"
-    attributename = f.getname(nameindex)
-    w_attributename = f.space.wrap(attributename)
-    w_obj = f.valuestack.pop()
-    f.space.delattr(w_obj, w_attributename)
-
-def STORE_GLOBAL(f, nameindex):
-    varname = f.getname(nameindex)
-    w_varname = f.space.wrap(varname)
-    w_newvalue = f.valuestack.pop()
-    f.space.setitem(f.w_globals, w_varname, w_newvalue)
-
-def DELETE_GLOBAL(f, nameindex):
-    varname = f.getname(nameindex)
-    w_varname = f.space.wrap(varname)
-    f.space.delitem(f.w_globals, w_varname)
-
-def LOAD_NAME(f, nameindex):
-    varname = f.getname(nameindex)
-    w_varname = f.space.wrap(varname)
-    try:
-        w_value = f.space.getitem(f.w_locals, w_varname)
-    except OperationError, e:
-        if not e.match(f.space, f.space.w_KeyError):
-            raise
+            metaclass = type
+        return metaclass(name, bases, namespace)
+
+    def STORE_NAME(f, varindex):
+        varname = f.getname(varindex)
+        w_varname = f.space.wrap(varname)
+        w_newvalue = f.valuestack.pop()
+        f.space.setitem(f.w_locals, w_varname, w_newvalue)
+
+    def DELETE_NAME(f, varindex):
+        varname = f.getname(varindex)
+        w_varname = f.space.wrap(varname)
+        try:
+            f.space.delitem(f.w_locals, w_varname)
+        except OperationError, e:
+            # catch KeyErrors and turn them into NameErrors
+            if not e.match(f.space, f.space.w_KeyError):
+                raise
+            message = "name '%s' is not defined" % varname
+            raise OperationError(f.space.w_NameError, f.space.wrap(message))
+
+    def UNPACK_SEQUENCE(f, itemcount):
+        w_iterable = f.valuestack.pop()
+        try:
+            items = f.space.unpackiterable(w_iterable, itemcount)
+        except ValueError, e:
+            raise OperationError(f.space.w_ValueError, f.space.wrap(str(e)))
+        items.reverse()
+        for item in items:
+            f.valuestack.push(item)
+
+    def STORE_ATTR(f, nameindex):
+        "obj.attributename = newvalue"
+        attributename = f.getname(nameindex)
+        w_attributename = f.space.wrap(attributename)
+        w_obj = f.valuestack.pop()
+        w_newvalue = f.valuestack.pop()
+        f.space.setattr(w_obj, w_attributename, w_newvalue)
+
+    def DELETE_ATTR(f, nameindex):
+        "del obj.attributename"
+        attributename = f.getname(nameindex)
+        w_attributename = f.space.wrap(attributename)
+        w_obj = f.valuestack.pop()
+        f.space.delattr(w_obj, w_attributename)
+
+    def STORE_GLOBAL(f, nameindex):
+        varname = f.getname(nameindex)
+        w_varname = f.space.wrap(varname)
+        w_newvalue = f.valuestack.pop()
+        f.space.setitem(f.w_globals, w_varname, w_newvalue)
+
+    def DELETE_GLOBAL(f, nameindex):
+        varname = f.getname(nameindex)
+        w_varname = f.space.wrap(varname)
+        f.space.delitem(f.w_globals, w_varname)
+
+    def LOAD_NAME(f, nameindex):
+        varname = f.getname(nameindex)
+        w_varname = f.space.wrap(varname)
+        try:
+            w_value = f.space.getitem(f.w_locals, w_varname)
+        except OperationError, e:
+            if not e.match(f.space, f.space.w_KeyError):
+                raise
+            try:
+                w_value = f.space.getitem(f.w_globals, w_varname)
+            except OperationError, e:
+                if not e.match(f.space, f.space.w_KeyError):
+                    raise
+                try:
+                    w_value = f.space.getitem(f.w_builtins, w_varname)
+                except OperationError, e:
+                    if not e.match(f.space, f.space.w_KeyError):
+                        raise
+                    message = "global name '%s' is not defined" % varname
+                    w_exc_type = f.space.w_NameError
+                    w_exc_value = f.space.wrap(message)
+                    raise OperationError(w_exc_type, w_exc_value)
+        f.valuestack.push(w_value)
+        # XXX the implementation can be pushed back into app-space as an
+        # when exception handling begins to behave itself.  For now, it
+        # was getting on my nerves -- mwh
+    #    w_value = f.space.gethelper(appfile).call(
+    #        "load_name", [w_varname, f.w_locals, f.w_globals, f.w_builtins])
+    #    f.valuestack.push(w_value)
+
+    def LOAD_GLOBAL(f, nameindex):
+        assert f.w_globals is not None
+        varname = f.getname(nameindex)
+        w_varname = f.space.wrap(varname)
         try:
             w_value = f.space.getitem(f.w_globals, w_varname)
         except OperationError, e:
+            # catch KeyErrors
             if not e.match(f.space, f.space.w_KeyError):
                 raise
+            # we got a KeyError, now look in the built-ins
             try:
                 w_value = f.space.getitem(f.w_builtins, w_varname)
             except OperationError, e:
+                # catch KeyErrors again
                 if not e.match(f.space, f.space.w_KeyError):
                     raise
                 message = "global name '%s' is not defined" % varname
                 w_exc_type = f.space.w_NameError
                 w_exc_value = f.space.wrap(message)
                 raise OperationError(w_exc_type, w_exc_value)
-    f.valuestack.push(w_value)
-    # XXX the implementation can be pushed back into app-space as an
-    # when exception handling begins to behave itself.  For now, it
-    # was getting on my nerves -- mwh
-#    w_value = f.space.gethelper(appfile).call(
-#        "load_name", [w_varname, f.w_locals, f.w_globals, f.w_builtins])
-#    f.valuestack.push(w_value)
-
-def LOAD_GLOBAL(f, nameindex):
-    assert f.w_globals is not None
-    varname = f.getname(nameindex)
-    w_varname = f.space.wrap(varname)
-    try:
-        w_value = f.space.getitem(f.w_globals, w_varname)
-    except OperationError, e:
-        # catch KeyErrors
-        if not e.match(f.space, f.space.w_KeyError):
-            raise
-        # we got a KeyError, now look in the built-ins
+        f.valuestack.push(w_value)
+
+    def BUILD_TUPLE(f, itemcount):
+        items = [f.valuestack.pop() for i in range(itemcount)]
+        items.reverse()
+        w_tuple = f.space.newtuple(items)
+        f.valuestack.push(w_tuple)
+
+    def BUILD_LIST(f, itemcount):
+        items = [f.valuestack.pop() for i in range(itemcount)]
+        items.reverse()
+        w_list = f.space.newlist(items)
+        f.valuestack.push(w_list)
+
+    def BUILD_MAP(f, zero):
+        if zero != 0:
+            raise pyframe.BytecodeCorruption
+        w_dict = f.space.newdict([])
+        f.valuestack.push(w_dict)
+
+    def LOAD_ATTR(f, nameindex):
+        "obj.attributename"
+        attributename = f.getname(nameindex)
+        w_attributename = f.space.wrap(attributename)
+        w_obj = f.valuestack.pop()
+        w_value = f.space.getattr(w_obj, w_attributename)
+        f.valuestack.push(w_value)
+
+    def cmp_lt(f, w_1, w_2):  return f.space.lt(w_1, w_2)
+    def cmp_le(f, w_1, w_2):  return f.space.le(w_1, w_2)
+    def cmp_eq(f, w_1, w_2):  return f.space.eq(w_1, w_2)
+    def cmp_ne(f, w_1, w_2):  return f.space.ne(w_1, w_2)
+    def cmp_gt(f, w_1, w_2):  return f.space.gt(w_1, w_2)
+    def cmp_ge(f, w_1, w_2):  return f.space.ge(w_1, w_2)
+
+    def cmp_in(f, w_1, w_2):
+        return f.space.contains(w_2, w_1)
+    def cmp_not_in(f, w_1, w_2):
+        return f.space.not_(f.space.contains(w_2, w_1))
+    def cmp_is(f, w_1, w_2):
+        return f.space.is_(w_1, w_2)
+    def cmp_is_not(f, w_1, w_2):
+        return f.space.not_(f.space.is_(w_1, w_2))
+    def cmp_exc_match(f, w_1, w_2):
+        return f.space.newbool(f.space.exception_match(w_1, w_2))
+
+    compare_dispatch_table = {
+        0: cmp_lt,   # "<"
+        1: cmp_le,   # "<="
+        2: cmp_eq,   # "=="
+        3: cmp_ne,   # "!="
+        4: cmp_gt,   # ">"
+        5: cmp_ge,   # ">="
+        6: cmp_in,
+        7: cmp_not_in,
+        8: cmp_is,
+        9: cmp_is_not,
+        10: cmp_exc_match,
+        }
+    def COMPARE_OP(f, testnum):
+        w_2 = f.valuestack.pop()
+        w_1 = f.valuestack.pop()
         try:
-            w_value = f.space.getitem(f.w_builtins, w_varname)
-        except OperationError, e:
-            # catch KeyErrors again
-            if not e.match(f.space, f.space.w_KeyError):
-                raise
-            message = "global name '%s' is not defined" % varname
-            w_exc_type = f.space.w_NameError
-            w_exc_value = f.space.wrap(message)
-            raise OperationError(w_exc_type, w_exc_value)
-    f.valuestack.push(w_value)
-
-def DELETE_FAST(f, varindex):
-    w_value = f.locals_w[varindex]
-    if f.locals_w[varindex] is _NULL:
-        varname = f.getlocalvarname(varindex)
-        message = "local variable '%s' referenced before assignment" % varname
-        raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
-    f.locals_w[varindex] = _NULL
-
-def LOAD_CLOSURE(f, varindex):
-    # nested scopes: access the cell object
-    cell = f.closure_w[varindex]
-    w_value = f.space.wrap(cell)
-    f.valuestack.push(w_value)
-
-def LOAD_DEREF(f, varindex):
-    # nested scopes: access a variable through its cell object
-    cell = f.closure_w[varindex]
-    try:
-        w_value = cell.get()
-    except ValueError:
-        varname = f.getfreevarname(varindex)
-        if f.iscellvar(varindex):
-            message = "local variable '%s' referenced before assignment"
-            w_exc_type = f.space.w_UnboundLocalError
-        else:
-            message = ("free variable '%s' referenced before assignment"
-                       " in enclosing scope")
-            w_exc_type = f.space.w_NameError
-        raise OperationError(w_exc_type, f.space.wrap(message % varname))
-    f.valuestack.push(w_value)
-
-def STORE_DEREF(f, varindex):
-    # nested scopes: access a variable through its cell object
-    w_newvalue = f.valuestack.pop()
-    try:
-        cell = f.closure_w[varindex]
-    except IndexError:
-        #import pdb; pdb.set_trace()
-        raise
-    cell.set(w_newvalue)
-
-def BUILD_TUPLE(f, itemcount):
-    items = [f.valuestack.pop() for i in range(itemcount)]
-    items.reverse()
-    w_tuple = f.space.newtuple(items)
-    f.valuestack.push(w_tuple)
-
-def BUILD_LIST(f, itemcount):
-    items = [f.valuestack.pop() for i in range(itemcount)]
-    items.reverse()
-    w_list = f.space.newlist(items)
-    f.valuestack.push(w_list)
-
-def BUILD_MAP(f, zero):
-    if zero != 0:
-        raise pyframe.BytecodeCorruption
-    w_dict = f.space.newdict([])
-    f.valuestack.push(w_dict)
-
-def LOAD_ATTR(f, nameindex):
-    "obj.attributename"
-    attributename = f.getname(nameindex)
-    w_attributename = f.space.wrap(attributename)
-    w_obj = f.valuestack.pop()
-    w_value = f.space.getattr(w_obj, w_attributename)
-    f.valuestack.push(w_value)
-
-def cmp_lt(f, w_1, w_2):  return f.space.lt(w_1, w_2)
-def cmp_le(f, w_1, w_2):  return f.space.le(w_1, w_2)
-def cmp_eq(f, w_1, w_2):  return f.space.eq(w_1, w_2)
-def cmp_ne(f, w_1, w_2):  return f.space.ne(w_1, w_2)
-def cmp_gt(f, w_1, w_2):  return f.space.gt(w_1, w_2)
-def cmp_ge(f, w_1, w_2):  return f.space.ge(w_1, w_2)
-
-def cmp_in(f, w_1, w_2):
-    return f.space.contains(w_2, w_1)
-def cmp_not_in(f, w_1, w_2):
-    return f.space.not_(f.space.contains(w_2, w_1))
-def cmp_is(f, w_1, w_2):
-    return f.space.is_(w_1, w_2)
-def cmp_is_not(f, w_1, w_2):
-    return f.space.not_(f.space.is_(w_1, w_2))
-def cmp_exc_match(f, w_1, w_2):
-    return f.space.exception_match(w_1, w_2)
-
-compare_dispatch_table = {
-    0: cmp_lt,   # "<"
-    1: cmp_le,   # "<="
-    2: cmp_eq,   # "=="
-    3: cmp_ne,   # "!="
-    4: cmp_gt,   # ">"
-    5: cmp_ge,   # ">="
-    6: cmp_in,
-    7: cmp_not_in,
-    8: cmp_is,
-    9: cmp_is_not,
-    10: cmp_exc_match,
-    }
-def COMPARE_OP(f, testnum):
-    w_2 = f.valuestack.pop()
-    w_1 = f.valuestack.pop()
-    try:
-        testfn = compare_dispatch_table[testnum]
-    except KeyError:
-        raise pyframe.BytecodeCorruption, "bad COMPARE_OP oparg"
-    w_result = testfn(f, w_1, w_2)
-    f.valuestack.push(w_result)
-
-def IMPORT_NAME(f, nameindex):
-    modulename = f.getname(nameindex)
-    w_modulename = f.space.wrap(modulename)
-    w_fromlist = f.valuestack.pop()
-    w_obj = f.space.gethelper(appfile).call(
-        "import_name", [f.w_builtins,
-                        w_modulename, f.w_globals, f.w_locals, w_fromlist])
-    f.valuestack.push(w_obj)
-
-def IMPORT_STAR(f):
-    w_module = f.valuestack.pop()
-    f.space.gethelper(appfile).call("import_all_from", [w_module, f.w_locals])
-
-def IMPORT_FROM(f, nameindex):
-    name = f.getname(nameindex)
-    w_name = f.space.wrap(name)
-    w_module = f.valuestack.top()
-    w_obj = f.space.gethelper(appfile).call("import_from", [w_module, w_name])
-    f.valuestack.push(w_obj)
-
-def JUMP_FORWARD(f, stepby):
-    f.next_instr += stepby
-
-def JUMP_IF_FALSE(f, stepby):
-    w_cond = f.valuestack.top()
-    if not f.space.is_true(w_cond):
-        f.next_instr += stepby
+            testfn = f.compare_dispatch_table[testnum]
+        except KeyError:
+            raise pyframe.BytecodeCorruption, "bad COMPARE_OP oparg"
+        w_result = testfn(f, w_1, w_2)
+        f.valuestack.push(w_result)
+
+    def IMPORT_NAME(f, nameindex):
+        modulename = f.getname(nameindex)
+        w_modulename = f.space.wrap(modulename)
+        w_fromlist = f.valuestack.pop()
+        w_obj = f.space.gethelper(appfile).call(
+            "import_name", [f.w_builtins,
+                            w_modulename, f.w_globals, f.w_locals, w_fromlist])
+        f.valuestack.push(w_obj)
+
+    def IMPORT_STAR(f):
+        w_module = f.valuestack.pop()
+        f.space.gethelper(appfile).call("import_all_from", [w_module, f.w_locals])
+
+    def IMPORT_FROM(f, nameindex):
+        name = f.getname(nameindex)
+        w_name = f.space.wrap(name)
+        w_module = f.valuestack.top()
+        w_obj = f.space.gethelper(appfile).call("import_from", [w_module, w_name])
+        f.valuestack.push(w_obj)
 
-def JUMP_IF_TRUE(f, stepby):
-    w_cond = f.valuestack.top()
-    if f.space.is_true(w_cond):
+    def JUMP_FORWARD(f, stepby):
         f.next_instr += stepby
 
-def JUMP_ABSOLUTE(f, jumpto):
-    f.next_instr = jumpto
+    def JUMP_IF_FALSE(f, stepby):
+        w_cond = f.valuestack.top()
+        if not f.space.is_true(w_cond):
+            f.next_instr += stepby
+
+    def JUMP_IF_TRUE(f, stepby):
+        w_cond = f.valuestack.top()
+        if f.space.is_true(w_cond):
+            f.next_instr += stepby
+
+    def JUMP_ABSOLUTE(f, jumpto):
+        f.next_instr = jumpto
+
+    def GET_ITER(f):
+        w_iterable = f.valuestack.pop()
+        w_iterator = f.space.iter(w_iterable)
+        f.valuestack.push(w_iterator)
 
-def GET_ITER(f):
-    w_iterable = f.valuestack.pop()
-    w_iterator = f.space.iter(w_iterable)
-    f.valuestack.push(w_iterator)
-
-def FOR_ITER(f, jumpby):
-    w_iterator = f.valuestack.top()
-    try:
-        w_nextitem = f.space.next(w_iterator)
-    except NoValue:
-        # iterator exhausted
-        f.valuestack.pop()
-        f.next_instr += jumpby
-    else:
-        f.valuestack.push(w_nextitem)
-
-def FOR_LOOP(f, oparg):
-    raise pyframe.BytecodeCorruption, "old opcode, no longer in use"
-
-def SETUP_LOOP(f, offsettoend):
-    block = pyframe.LoopBlock(f, f.next_instr + offsettoend)
-    f.blockstack.push(block)
-
-def SETUP_EXCEPT(f, offsettoend):
-    block = pyframe.ExceptBlock(f, f.next_instr + offsettoend)
-    f.blockstack.push(block)
-
-def SETUP_FINALLY(f, offsettoend):
-    block = pyframe.FinallyBlock(f, f.next_instr + offsettoend)
-    f.blockstack.push(block)
-
-def call_function_extra(f, oparg, with_varargs, with_varkw):
-    n_arguments = oparg & 0xff
-    n_keywords = (oparg>>8) & 0xff
-    if with_varkw:
-        w_varkw = f.valuestack.pop()
-    if with_varargs:
-        w_varargs = f.valuestack.pop()
-    keywords = []
-    for i in range(n_keywords):
-        w_value = f.valuestack.pop()
-        w_key   = f.valuestack.pop()
-        keywords.append((w_key, w_value))
-    arguments = [f.valuestack.pop() for i in range(n_arguments)]
-    arguments.reverse()
-    w_function  = f.valuestack.pop()
-    w_arguments = f.space.newtuple(arguments)
-    w_keywords  = f.space.newdict(keywords)
-    if with_varargs:
-        w_arguments = f.space.gethelper(appfile).call("concatenate_arguments",
-                                                      [w_arguments, w_varargs])
-    if with_varkw:
-        w_keywords  = f.space.gethelper(appfile).call("concatenate_keywords",
-                                                      [w_keywords,  w_varkw])
-    w_result = f.space.call(w_function, w_arguments, w_keywords)
-    f.valuestack.push(w_result)
-
-def CALL_FUNCTION(f, oparg):
-    call_function_extra(f, oparg, False, False)
-
-def CALL_FUNCTION_VAR(f, oparg):
-    call_function_extra(f, oparg, True,  False)
-
-def CALL_FUNCTION_KW(f, oparg):
-    call_function_extra(f, oparg, False, True)
-
-def CALL_FUNCTION_VAR_KW(f, oparg):
-    call_function_extra(f, oparg, True,  True)
-
-def MAKE_FUNCTION(f, numdefaults):
-    w_codeobj = f.valuestack.pop()
-    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)
-    f.valuestack.push(w_func)
-
-def MAKE_CLOSURE(f, numdefaults):
-    w_codeobj = f.valuestack.pop()
-    codeobj = f.space.unwrap(w_codeobj)
-    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.valuestack.push(w_func)
-
-def BUILD_SLICE(f, numargs):
-    if numargs == 3:
-        w_step = f.valuestack.pop()
-    elif numargs == 2:
-        w_step = None
-    else:
-        raise pyframe.BytecodeCorruption
-    w_end   = f.valuestack.pop()
-    w_start = f.valuestack.pop()
-    w_slice = f.space.newslice(w_start, w_end, w_step)
-    f.valuestack.push(w_slice)
-
-def SET_LINENO(f, lineno):
-    pass
-
-def EXTENDED_ARG(f, oparg):
-    opcode = f.nextop()
-    oparg = oparg<<16 | f.nextarg()
-    dispatch_arg(f, oparg)
-
-def MISSING_OPCODE(f, oparg=None):
-    raise pyframe.BytecodeCorruption, "unknown opcode"
-
-
-################################################################
-
-dispatch_table = []
-for i in range(256):
-    opname = dis.opname[i].replace('+', '_')
-    fn = MISSING_OPCODE
-    if opname in globals():
-        fn = globals()[opname]
-    elif not opname.startswith('<') and i>0:
-        #import warnings
-        #warnings.warn("* Warning, missing opcode %s" % opname)
+    def FOR_ITER(f, jumpby):
+        w_iterator = f.valuestack.top()
+        try:
+            w_nextitem = f.space.next(w_iterator)
+        except NoValue:
+            # iterator exhausted
+            f.valuestack.pop()
+            f.next_instr += jumpby
+        else:
+            f.valuestack.push(w_nextitem)
+
+    def FOR_LOOP(f, oparg):
+        raise pyframe.BytecodeCorruption, "old opcode, no longer in use"
+
+    def SETUP_LOOP(f, offsettoend):
+        block = pyframe.LoopBlock(f, f.next_instr + offsettoend)
+        f.blockstack.push(block)
+
+    def SETUP_EXCEPT(f, offsettoend):
+        block = pyframe.ExceptBlock(f, f.next_instr + offsettoend)
+        f.blockstack.push(block)
+
+    def SETUP_FINALLY(f, offsettoend):
+        block = pyframe.FinallyBlock(f, f.next_instr + offsettoend)
+        f.blockstack.push(block)
+
+    def call_function_extra(f, oparg, with_varargs, with_varkw):
+        n_arguments = oparg & 0xff
+        n_keywords = (oparg>>8) & 0xff
+        if with_varkw:
+            w_varkw = f.valuestack.pop()
+        if with_varargs:
+            w_varargs = f.valuestack.pop()
+        keywords = []
+        for i in range(n_keywords):
+            w_value = f.valuestack.pop()
+            w_key   = f.valuestack.pop()
+            keywords.append((w_key, w_value))
+        arguments = [f.valuestack.pop() for i in range(n_arguments)]
+        arguments.reverse()
+        w_function  = f.valuestack.pop()
+        w_arguments = f.space.newtuple(arguments)
+        w_keywords  = f.space.newdict(keywords)
+        if with_varargs:
+            w_arguments = f.space.gethelper(appfile).call("concatenate_arguments",
+                                                          [w_arguments, w_varargs])
+        if with_varkw:
+            w_keywords  = f.space.gethelper(appfile).call("concatenate_keywords",
+                                                          [w_keywords,  w_varkw])
+        w_result = f.space.call(w_function, w_arguments, w_keywords)
+        f.valuestack.push(w_result)
+
+    def CALL_FUNCTION(f, oparg):
+        f.call_function_extra(oparg, False, False)
+
+    def CALL_FUNCTION_VAR(f, oparg):
+        f.call_function_extra(oparg, True,  False)
+
+    def CALL_FUNCTION_KW(f, oparg):
+        f.call_function_extra(oparg, False, True)
+
+    def CALL_FUNCTION_VAR_KW(f, oparg):
+        f.call_function_extra(oparg, True,  True)
+
+    def MAKE_FUNCTION(f, numdefaults):
+        w_codeobj = f.valuestack.pop()
+        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)
+        f.valuestack.push(w_func)
+
+    def BUILD_SLICE(f, numargs):
+        if numargs == 3:
+            w_step = f.valuestack.pop()
+        elif numargs == 2:
+            w_step = None
+        else:
+            raise pyframe.BytecodeCorruption
+        w_end   = f.valuestack.pop()
+        w_start = f.valuestack.pop()
+        w_slice = f.space.newslice(w_start, w_end, w_step)
+        f.valuestack.push(w_slice)
+
+    def SET_LINENO(f, lineno):
         pass
-    dispatch_table.append(fn)
+
+    def EXTENDED_ARG(f, oparg):
+        opcode = f.nextop()
+        oparg = oparg<<16 | f.nextarg()
+        fn = self.dispatch_table[opcode]
+        if not fn.has_arg:
+            raise pyframe.BytecodeCorruption
+        fn(f, oparg)
+
+    def MISSING_OPCODE(f, oparg=None):
+        raise pyframe.BytecodeCorruption, "unknown opcode"
+
+    ################################################################
+
+    # 'dispatch_table' is a class attribute: a list of functions
+    # it is created by 'cls.setup_dispatch_table()'.
+
+    def setup_dispatch_table(cls):
+        # create the 'cls.dispatch_table' attribute
+        dispatch_table = []
+        missing_opcode = cls.MISSING_OPCODE
+        for i in range(256):
+            opname = dis.opname[i].replace('+', '_')
+            fn = getattr(cls, opname, missing_opcode)
+            #if fn is missing_opcode and not opname.startswith('<') and i>0:
+            #    import warnings
+            #    warnings.warn("* Warning, missing opcode %s" % opname)
+            dispatch_table.append(fn)
+        cls.dispatch_table = dispatch_table
+    setup_dispatch_table = classmethod(setup_dispatch_table)
 
 
-def name(thing):
-    try:
-        return thing.operationname
-    except AttributeError:
-        return thing.__name__
-
-def has_arg(opcode):
-    return opcode >= dis.HAVE_ARGUMENT
-
-def dispatch_noarg(f, opcode):
-    try:
-        fn = dispatch_table[opcode]
-#        print name(fn)
-    except KeyError:
-        raise KeyError, "missing opcode %s" % dis.opname[opcode]
-    fn(f)
-
-def dispatch_arg(f, opcode, oparg):
-    assert oparg >= 0
-    try:
-        fn = dispatch_table[opcode]
-#        print name(fn)
-    except KeyError:
-        raise KeyError, "missing opcode %s" % dis.opname[opcode]
-    fn(f, oparg)
+PyOperationalFrame.setup_dispatch_table()


More information about the Pypy-commit mailing list