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

arigo at codespeak.net arigo at codespeak.net
Sun Aug 10 21:34:27 CEST 2003


Author: arigo
Date: Sun Aug 10 21:34:26 2003
New Revision: 1265

Added:
   pypy/branch/builtinrefactor/pypy/interpreter/nestedscope.py
      - copied, changed from rev 1264, pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py
Removed:
   pypy/branch/builtinrefactor/pypy/interpreter/pyfastscope.py
   pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py
Modified:
   pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py
   pypy/branch/builtinrefactor/pypy/interpreter/eval.py
   pypy/branch/builtinrefactor/pypy/interpreter/gateway.py
   pypy/branch/builtinrefactor/pypy/interpreter/pycode.py
   pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py
   pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py
   pypy/branch/builtinrefactor/pypy/interpreter/unittest_w.py
Log:
Still nothing that works, far from it, but progress nevertheless
(I think).


Modified: pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py	Sun Aug 10 21:34:26 2003
@@ -5,6 +5,11 @@
 __all__ = ['ObjSpace', 'OperationError', 'NoValue']
 
 
+class Wrappable(object):
+    """A subclass of Wrappable is an internal, interpreter-level class
+    that can nevertheless be exposed at application-level by space.wrap()."""
+
+
 class NoValue(Exception):
     """Raised to signal absence of value, e.g. in the iterator accessing
     method 'op.next()' of object spaces."""

Modified: pypy/branch/builtinrefactor/pypy/interpreter/eval.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/eval.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/eval.py	Sun Aug 10 21:34:26 2003
@@ -25,43 +25,31 @@
         "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
         return [], None, None
 
-    def getargcount(self):
-        "Number of arguments including * and **."
+    def getvarnames(self):
+        """List of names including the arguments, vararg and kwarg,
+        and possibly more locals."""
         argnames, varargname, kwargname = self.signature()
-        count = len(argnames)
         if varargname is not None:
-            count += 1
+            argnames.append(argname)
         if kwargname is not None:
-            count += 1
-        return count
+            argnames.append(kwargname)
+        return argnames
 
-    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"
+
+UNDEFINED = object()  # marker for undefined local variables
 
 
 class Frame(object):
     """A frame is an environment supporting the execution of a code object.
     Abstract base class."""
 
-    def __init__(self, space, code, w_globals):
+    def __init__(self, space, code, w_globals, numlocals=0):
         self.space      = space
         self.code       = code       # Code instance
         self.w_globals  = w_globals  # wrapped dict of globals
         self.w_locals   = None       # wrapped dict of locals
+        # flat list of wrapped locals
+        self.fastlocals_w = [UNDEFINED]*numlocals
 
     def run(self):
         "Run the frame."
@@ -78,21 +66,45 @@
         raise TypeError, "abstract"
 
     def getdictscope(self):
-        "Overriden by subclasses with another representation for locals."
+        "Get the locals as a dictionary."
+        self.fast2locals()
         return self.w_locals
 
     def setdictscope(self, w_locals):
-        """Initialize the locals from a dictionary.
-        Overriden by subclasses with another representation for locals."""
+        "Initialize the locals from a dictionary."
         self.w_locals = w_locals
+        self.locals2fast()
+
+    def getfastscope(self):
+        "Get the fast locals as a list."
+        return self.fastlocals_w
 
     def setfastscope(self, scope_w):
-        """Initialize the locals from a list of values,
-        where the order is according to self.code.signature().
-        Default implementation, to be overridden."""
-        space = self.space
+        """Initialize the fast locals from a list of values,
+        where the order is according to self.code.signature()."""
+        if len(scope_w) > len(self.fastlocals_w):
+            raise ValueError, "too many fastlocals"
+        self.fastlocals_w[:len(scope_w)] = scope_w
+
+    def fast2locals(self):
+        # Copy values from self.fastlocals_w to self.w_locals
         if self.w_locals is None:
-            self.w_locals = space.newdict([])
-        for i in range(len(scope_w)):
-            varname = self.code.getlocalvarname(i)
-            space.setitem(self.w_locals, space.wrap(varname), scope_w[i])
+            self.w_locals = self.space.newdict([])
+        varnames = self.code.getvarnames()
+        for name, w_value in zip(varnames, self.fastlocals_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.fastlocals_w
+        varnames = self.code.getvarnames()
+        for name, i in zip(varnames, range(len(self.fastlocals_w))):
+            w_name = self.space.wrap(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.fastlocals_w[i] = w_value

Modified: pypy/branch/builtinrefactor/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/gateway.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/gateway.py	Sun Aug 10 21:34:26 2003
@@ -1,331 +1,416 @@
 """
 
 Gateway between app-level and interpreter-level:
-the Wrappable base class.
+* BuiltinCode (calling interp-level code from app-level)
+* code2interp (embedding a code object into an interpreter-level callable)
+* app2interp  (embedding an app-level function's code object in the same way)
 
 """
 
-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.
-    (the local scope is given when you call 'eval_frame')
-    """
-    def __init__(self, space, cpycode, w_globals=None, closure_w=()):
-        self.space = space
-        self.cpycode = cpycode
-        self.w_code = space.wrap(cpycode)
-        self.closure_w = closure_w
-        if w_globals is None:
-            w_globals = space.newdict([])
-        self.w_globals = w_globals
-
-    def create_frame(self, w_locals=None):
-        """ return result of executing code object within a frame"""
-        from pyframe import PyFrame
-        frame = PyFrame()
-        frame.initialize(self)
-        if w_locals is None:
-            w_locals = self.w_globals
-        frame.setdictscope(w_locals)
-        return frame
-
-    def eval_frame(self, *args, **kwargs):
-        frame = self.create_frame(*args, **kwargs)
-        return self.space.getexecutioncontext().eval_frame(frame)
-
-class app2interp(object):
-    """ this class exposes an app-level method at interpreter-level.
-
-    Note that the wrapped method must *NOT* use a 'self' argument. 
-    Assumption: the instance on which this method is bound to has a
-                'space' attribute. 
-    """
-    def __init__(self, appfunc):
-        self.appfunc = appfunc
-
-    def __get__(self, instance, cls=None):
-        return InterpretedFunction(instance.space, self.appfunc)
-
-class InterpretedFunctionFromCode(ScopedCode):
-    def __init__(self, space, cpycode, w_defs, w_globals=None, closure_w=()):
-        ScopedCode.__init__(self, space, cpycode, w_globals, closure_w)
-        self.w_defs = w_defs
-        self.simple = cpycode.co_flags & (CO_VARARGS|CO_VARKEYWORDS)==0
-        self.func_code = cpycode
-
-    def parse_args(self, frame, w_args, w_kwargs):
-        """ parse args and kwargs and set fast scope of frame.
-        """
-        space = self.space
-        loc_w = None
-        if self.simple and (w_kwargs is None or not space.is_true(w_kwargs)):
-            try:
-                loc_w = space.unpacktuple(w_args, self.cpycode.co_argcount)
-            except ValueError:
-                pass
-        if loc_w is None:
-            #print "complicated case of arguments for", self.cpycode.co_name, "simple=", self.simple
-            w_loc = self.parse_args_complex(self.w_code, w_args, w_kwargs, self.w_defs)
-            loc_w = space.unpacktuple(w_loc)
-        loc_w.extend([_NULL] * (self.cpycode.co_nlocals - len(loc_w)))
-
-        # make nested cells
-        if self.cpycode.co_cellvars:
-            varnames = list(self.cpycode.co_varnames)
-            for name in self.cpycode.co_cellvars:
-                i = varnames.index(name)
-                w_value = loc_w[i] 
-                loc_w[i] = _NULL
-                frame.closure_w += (Cell(w_value),)
-
-        assert len(loc_w) == self.cpycode.co_nlocals, "local arguments not prepared correctly"
-        frame.setfastscope(loc_w)
-
-    def create_frame(self, w_args, w_kwargs):
-        """ parse arguments and execute frame """
-        from pyframe import PyFrame
-        frame = PyFrame()
-        frame.initialize(self)
-        self.parse_args(frame, w_args, w_kwargs)
-        return frame
-
-    def app_parse_args_complex(cpycode, args, kwargs, defs):
-        """ return list of initial local values parsed from 
-        'args', 'kwargs' and defaults.
-        """
-        #if cpycode.co_name == 'failUnlessRaises':
-        #    print "co_name", cpycode.co_name
-        #    print "co_argcount", cpycode.co_argcount
-        #    print "co_nlocals", cpycode.co_nlocals
-        #    print "co_varnames", cpycode.co_varnames
-        #    print "args", args
-        #    print "kwargs", kwargs
-        #    print "defs", defs
-
-        CO_VARARGS, CO_VARKEYWORDS = 0x4, 0x8
-
-        #   co_argcount number of expected positional arguments 
-        #   (elipsis args like *args and **kwargs do not count) 
-        co_argcount = cpycode.co_argcount
-
-        # construct list of positional args 
-        positional_args = list(args[:co_argcount])
-
-        len_args = len(args)
-        len_defs = len(defs)
-
-        if len_args < co_argcount:
-            # not enough args, fill in kwargs or defaults if exists
-            i = len_args
-            while i < co_argcount:
-                name = cpycode.co_varnames[i]
-                if name in kwargs:
-                    positional_args.append(kwargs[name])
-                    del kwargs[name]
-                else:
-                    if i + len_defs < co_argcount:
-                        raise TypeError, "Not enough arguments"
-                    positional_args.append(defs[i-co_argcount])
-                i+=1
-        if cpycode.co_flags & CO_VARARGS:
-            positional_args.append(tuple(args[co_argcount:]))
-        elif len_args > co_argcount:
-            raise TypeError, "Too many arguments"
-
-        # we only do the next loop for determining multiple kw-values
-        i = 0
-        while i < len_args and i < co_argcount:
-            name = cpycode.co_varnames[i]
-            if name in kwargs:
-                raise TypeError, "got multiple values for argument %r" % name
-            i+=1
-
-        if cpycode.co_flags & CO_VARKEYWORDS:
-            positional_args.append(kwargs)
-        elif kwargs:
-            raise TypeError, "got unexpected keyword argument(s) %s" % repr(kwargs.keys()[0])
-
-        return positional_args
-    parse_args_complex = app2interp(app_parse_args_complex)
-
-    def __call__(self, *args_w, **kwargs_w):
-        """ execute function and take arguments with
-        native interp-level parameter passing convention """
-        w_args = self.space.newtuple(args_w)
-        w = self.space.wrap
-        w_kwargs = self.space.newdict([])
-        for name, w_value in kwargs_w.items():
-            self.space.setitem(w_kwargs, w(name), w_value)
-        return self.eval_frame(w_args, w_kwargs)
-
-class InterpretedFunction(InterpretedFunctionFromCode):
-    """ a function which executes at app-level (by interpreting bytecode
-    and dispatching operations on an objectspace). 
-    """
-
-    def __init__(self, space, cpyfunc, w_globals=None, closure_w=()): 
-        """ initialization similar to base class but it also wraps 
-        some function-specific stuff (like defaults). 
-        """
-        assert not hasattr(cpyfunc, 'im_self')
-        InterpretedFunctionFromCode.__init__(self, space, 
-                                             cpyfunc.func_code,
-                                             space.wrap(cpyfunc.func_defaults or ()),
-                                             w_globals, closure_w)
-
-class InterpretedMethod(InterpretedFunction):
-    """ an InterpretedFunction with 'self' spice.
-
-    XXX hpk: i think we want to eliminate all uses for this class
-             as bound/unbound methods should be done in objspace?!
-
-    """
-
-    def __init__(self, *args):
-        InterpretedFunction.__init__(self, *args)
-
-    def parse_args(self, frame, w_args, w_kwargs):
-        """ fills in "self" arg and dispatch to InterpreterFunction.
-        """
-        space = self.space
-        args_w = space.unpacktuple(w_args)
-        args_w = [space.wrap(self)] + args_w
-        w_args = space.newtuple(args_w)
-        return InterpretedFunction.parse_args(self, frame, w_args, w_kwargs)
-
-class AppVisibleModule:
-    """ app-level visible Module defined at interpreter-level.
-
-    Inherit from this class if you want to have a module that accesses
-    the PyPy interpreter (e.g. builtins like 'locals()' require accessing the
-    frame). You can mix in application-level code by prefixing your method
-    with 'app_'. Both non-underscore methods and app-level methods will
-    be available on app-level with their respective name. 
-
-    Note that app-level functions don't get a 'self' argument because it doesn't
-    make sense and we really only need the function (there is no notion of beeing 
-    'bound' or 'unbound' for them).
-    
-    """
-    def __init__(self, space):
-        self.space = space
-
-        space = self.space
-        modname = self.__class__.__name__
-        self.w___name__ = space.wrap(modname)
-        self._wrapped = _wrapped = space.newmodule(self.w___name__)
-
-        # go through all items in the module class instance
-        for name in dir(self):
-            # skip spurious info and internal methods
-            if name == '__module__' or name.startswith('_') and not name.endswith('_'):
-                #print modname, "skipping", name
-                continue
-            obj = getattr(self, name)
-            # see if we just need to expose an already wrapped value
-            if name.startswith('w_'):
-                space.setattr(_wrapped, space.wrap(name[2:]), obj)
-
-            # see if have something defined at app-level
-            elif name.startswith('app_'):
-                obj = self.__class__.__dict__.get(name)
-                name = name[4:]
-                w_res = wrap_applevel(space, name, obj)
-            # nope then we must expose interpreter-level to app-level
-            else:
-                w_res = wrap_interplevel(space, name, obj)
-                setattr(self, 'w_'+name, w_res)
-            w_name = space.wrap(name)
-            space.setattr(_wrapped, w_name, w_res)
-
-def wrap_applevel(space, name, obj):
-    """ wrap an app-level style object which was compiled at interp-level. """
-    if hasattr(obj, 'func_code'):
-        return space.wrap(InterpretedFunction(space, obj))
-    elif inspect.isclass(obj):
-        # XXX currently (rev 1020) unused, but it may be useful
-        #     to define builtin app-level classes at interp-level. 
-        return wrap_applevel_class(space, name, obj)
-    else:
-        raise ValueError, "cannot wrap %s, %s" % (name, obj)
-
-def wrap_applevel_class(space, name, obj):
-    """ construct an app-level class by reproducing the
-    source definition and running it through the interpreter.
-    It's a bit ugly but i don't know a better way (holger).
-    """
-    assert 1!=1, "Oh you want to use this function?"
-    l = ['class %s:' % name]
-    indent = '    '
-    for key, value in vars(obj).items():
-        if hasattr(value, 'func_code'):
-            s = inspect.getsource(value)
-            l.append(s)
-            indent = " " * (len(s) - len(s.lstrip()))
-
-    if getattr(obj, '__doc__', None):
-        l.insert(1, indent + obj.__doc__)
-
-    for key, value in vars(obj).items():
-        if not key in ('__module__', '__doc__'):
-            if isinstance(value, (str, int, float, tuple, list)):
-                l.append('%s%s = %r' % (indent, key, value))
-
-    s = "\n".join(l)
-    code = compile(s, s, 'exec')
-    scopedcode = ScopedCode(space, code, None)
-    scopedcode.eval_frame()
-    w_name = space.wrap(name)
-    w_res = space.getitem(scopedcode.w_globals, w_name)
-    return w_res
-
-
-def wrap_interplevel(space, name, obj):
-    """ make an interp-level object accessible on app-level. """
-    return space.wrap(obj)
-
-## Cells (used for nested scopes only) ##
-
-_NULL = object() # Marker object
-
-class Cell:
-    def __init__(self, w_value=_NULL):
-        self.w_value = w_value
-
-    def clone(self):
-        return self.__class__(self.w_value)
-
-    def get(self):
-        if self.w_value is _NULL:
-            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 _NULL:
-            raise ValueError, "make_empty() on an empty cell"
-        self.w_value = _NULL
-
-    def __repr__(self):
-        """ representation for debugging purposes """
-        if self.w_value is _NULL:
-            return "%s()" % self.__class__.__name__
-        else:
-            return "%s(%s)" % (self.__class__.__name__, self.w_value)
+from pypy.interpreter import eval, pycode
+from pypy.interpreter.baseobjspace import Wrappable
+
 
+class BuiltinCode(eval.Code):
+    "The code object implementing a built-in (interpreter-level) hook."
 
+    # When a BuiltinCode is stored in a Function object,
+    # you get the functionality of CPython's built-in function type.
+
+    def __init__(self, func):
+        # 'implfunc' is the interpreter-level function.
+        # note that this uses a lot of (construction-time) introspection.
+        eval.Code.__init__(self, func.__name__)
+        self.func = func
+        # extract the signature from the (CPython-level) code object
+        tmp = pycode.PyCode(None)
+        tmp._from_code(func.func_code)
+        self.sig = tmp.signature()
+        self.nargs = len(self.getvarnames())
+
+    def create_frame(self, space, w_globals, closure=None):
+        return BuiltinFrame(space, self, w_globals, numlocals=self.nargs)
+
+    def signature(self):
+        return self.sig
+
+
+class BuiltinFrame(eval.Frame):
+    "Frame emulation for BuiltinCode."
+    # This is essentially just a delegation to the 'func' of the BuiltinCode.
+    # Initialization of locals is already done by the time run() is called,
+    # via the interface defined in eval.Frame.
+
+    def run(self):
+        return call_with_prepared_arguments(self.space, self.code.func,
+                                            self.fastlocals_w)
+
+
+def call_with_prepared_arguments(space, function, argarray):
+    """Call the given function. 'argarray' is a correctly pre-formatted
+    list of values for the formal parameters, including one for * and one
+    for **."""
+    # XXX there is no clean way to do this in Python,
+    # we have to hack back an arguments tuple and keywords dict.
+    # This algorithm is put in its own well-isolated function so that
+    # you don't need to look at it :-)
+    keywords = {}
+    co = function.func_code
+    if co.flags & 8:  # CO_VARKEYWORDS
+        w_kwds = argarray[-1]
+        for w_key in space.unpackiterable(w_kwds):
+            keywords[space.unwrap(w_key)] = space.getitem(w_kwds, w_key)
+        argarray = argarray[:-1]
+    if co.flags & 4:  # CO_VARARGS
+        w_varargs = argarray[-1]
+        argarray = argarray[:-1] + space.unpacktuple(w_varargs)
+    return function(*argarray, **keywords)
+
+
+class code2interp(object):
+    # General-purpose utility for the interpreter-level to create callables
+    # that transparently invoke code objects (and thus possibly interpreted
+    # app-level code).
+
+    def __init__(self, code, staticglobals, staticdefaults=[]):
+        self.code = code
+        self.staticglobals = staticglobals  # a StaticGlobals instance
+        self.staticdefaults = staticdefaults
+
+    def make_function(self, space):
+        assert self.staticglobals.is_frozen(), (
+            "gateway not callable before the StaticGlobals is frozen")
+        w_globals = space.wrap(self.staticglobals)
+        defs_w = [space.wrap(def_value) for def_value in self.staticdefaults]
+        return Function(space, self.code, w_globals, defs_w)
+
+    def __call__(self, space, *args, **kwds):
+        wrap = space.wrap
+        w_args = [wrap(arg) for arg in args]
+        w_kwds = space.newdict([(wrap(key), wrap(value))
+                                for key, value in kwds.items()])
+        fn = self.make_function(space)
+        return fn.call(w_args, w_kwds)
+
+
+class StaticGlobals(Wrappable):
+    # This class captures a part of the content of an interpreter module
+    # or of a class definition, to be exposed at app-level with a read-only
+    # dict-like interface.
+
+    def __init__(self, content=None):
+        self.content = None
+        if content is not None:
+            self.freeze(content)
+
+    def freeze(self, content):
+        # Freeze the object to the value given by 'content':
+        # either a dictionary or a (new-style) class
+        assert self.content is None, "%r already frozen" % self
+        if isinstance(content, dict):
+            content = content.copy()
+        else:
+            mro = list(content.__mro__)
+            mro.reverse()
+            content = {}
+            for c in mro:
+                content.update(c.__dict__)
+        self.content = content
+
+    def is_frozen(self):
+        return self.content is not None
+
+    def app2interp(self, app_f):
+        "Build a code2interp gateway that calls 'app_f' at app-level."
+        code = pycode.PyCode(None)
+        code._from_code(app_f.func_code)
+        return code2interp(code, self, list(app_f.func_defaults or ()))
+
+    def __getitem__(self, key):
+        # XXX is only present for today's stdobjspace.cpythonobject wrapper
+        return self.content[key]
+
+noglobals = StaticGlobals({})
+
+
+##class app2interp(object):
+##    """ this class exposes an app-level method at interpreter-level.
+
+##    Note that the wrapped method must *NOT* use a 'self' argument. 
+##    Assumption: the instance on which this method is bound to has a
+##                'space' attribute. 
+##    """
+##    def __init__(self, appfunc):
+##        self.appfunc = appfunc
+
+##    def __get__(self, instance, cls=None):
+##        return InterpretedFunction(instance.space, self.appfunc)
+
+##class InterpretedFunctionFromCode(ScopedCode):
+##    def __init__(self, space, cpycode, w_defs, w_globals=None, closure_w=()):
+##        ScopedCode.__init__(self, space, cpycode, w_globals, closure_w)
+##        self.w_defs = w_defs
+##        self.simple = cpycode.co_flags & (CO_VARARGS|CO_VARKEYWORDS)==0
+##        self.func_code = cpycode
+
+##    def parse_args(self, frame, w_args, w_kwargs):
+##        """ parse args and kwargs and set fast scope of frame.
+##        """
+##        space = self.space
+##        loc_w = None
+##        if self.simple and (w_kwargs is None or not space.is_true(w_kwargs)):
+##            try:
+##                loc_w = space.unpacktuple(w_args, self.cpycode.co_argcount)
+##            except ValueError:
+##                pass
+##        if loc_w is None:
+##            #print "complicated case of arguments for", self.cpycode.co_name, "simple=", self.simple
+##            w_loc = self.parse_args_complex(self.w_code, w_args, w_kwargs, self.w_defs)
+##            loc_w = space.unpacktuple(w_loc)
+##        loc_w.extend([_NULL] * (self.cpycode.co_nlocals - len(loc_w)))
+
+##        # make nested cells
+##        if self.cpycode.co_cellvars:
+##            varnames = list(self.cpycode.co_varnames)
+##            for name in self.cpycode.co_cellvars:
+##                i = varnames.index(name)
+##                w_value = loc_w[i] 
+##                loc_w[i] = _NULL
+##                frame.closure_w += (Cell(w_value),)
+
+##        assert len(loc_w) == self.cpycode.co_nlocals, "local arguments not prepared correctly"
+##        frame.setfastscope(loc_w)
+
+##    def create_frame(self, w_args, w_kwargs):
+##        """ parse arguments and execute frame """
+##        from pyframe import PyFrame
+##        frame = PyFrame()
+##        frame.initialize(self)
+##        self.parse_args(frame, w_args, w_kwargs)
+##        return frame
+
+##    def app_parse_args_complex(cpycode, args, kwargs, defs):
+##        """ return list of initial local values parsed from 
+##        'args', 'kwargs' and defaults.
+##        """
+##        #if cpycode.co_name == 'failUnlessRaises':
+##        #    print "co_name", cpycode.co_name
+##        #    print "co_argcount", cpycode.co_argcount
+##        #    print "co_nlocals", cpycode.co_nlocals
+##        #    print "co_varnames", cpycode.co_varnames
+##        #    print "args", args
+##        #    print "kwargs", kwargs
+##        #    print "defs", defs
+
+##        CO_VARARGS, CO_VARKEYWORDS = 0x4, 0x8
+
+##        #   co_argcount number of expected positional arguments 
+##        #   (elipsis args like *args and **kwargs do not count) 
+##        co_argcount = cpycode.co_argcount
+
+##        # construct list of positional args 
+##        positional_args = list(args[:co_argcount])
+
+##        len_args = len(args)
+##        len_defs = len(defs)
+
+##        if len_args < co_argcount:
+##            # not enough args, fill in kwargs or defaults if exists
+##            i = len_args
+##            while i < co_argcount:
+##                name = cpycode.co_varnames[i]
+##                if name in kwargs:
+##                    positional_args.append(kwargs[name])
+##                    del kwargs[name]
+##                else:
+##                    if i + len_defs < co_argcount:
+##                        raise TypeError, "Not enough arguments"
+##                    positional_args.append(defs[i-co_argcount])
+##                i+=1
+##        if cpycode.co_flags & CO_VARARGS:
+##            positional_args.append(tuple(args[co_argcount:]))
+##        elif len_args > co_argcount:
+##            raise TypeError, "Too many arguments"
+
+##        # we only do the next loop for determining multiple kw-values
+##        i = 0
+##        while i < len_args and i < co_argcount:
+##            name = cpycode.co_varnames[i]
+##            if name in kwargs:
+##                raise TypeError, "got multiple values for argument %r" % name
+##            i+=1
+
+##        if cpycode.co_flags & CO_VARKEYWORDS:
+##            positional_args.append(kwargs)
+##        elif kwargs:
+##            raise TypeError, "got unexpected keyword argument(s) %s" % repr(kwargs.keys()[0])
+
+##        return positional_args
+##    parse_args_complex = app2interp(app_parse_args_complex)
+
+##    def __call__(self, *args_w, **kwargs_w):
+##        """ execute function and take arguments with
+##        native interp-level parameter passing convention """
+##        w_args = self.space.newtuple(args_w)
+##        w = self.space.wrap
+##        w_kwargs = self.space.newdict([])
+##        for name, w_value in kwargs_w.items():
+##            self.space.setitem(w_kwargs, w(name), w_value)
+##        return self.eval_frame(w_args, w_kwargs)
+
+##class InterpretedFunction(InterpretedFunctionFromCode):
+##    """ a function which executes at app-level (by interpreting bytecode
+##    and dispatching operations on an objectspace). 
+##    """
+
+##    def __init__(self, space, cpyfunc, w_globals=None, closure_w=()): 
+##        """ initialization similar to base class but it also wraps 
+##        some function-specific stuff (like defaults). 
+##        """
+##        assert not hasattr(cpyfunc, 'im_self')
+##        InterpretedFunctionFromCode.__init__(self, space, 
+##                                             cpyfunc.func_code,
+##                                             space.wrap(cpyfunc.func_defaults or ()),
+##                                             w_globals, closure_w)
+
+##class InterpretedMethod(InterpretedFunction):
+##    """ an InterpretedFunction with 'self' spice.
+
+##    XXX hpk: i think we want to eliminate all uses for this class
+##             as bound/unbound methods should be done in objspace?!
+
+##    """
+
+##    def __init__(self, *args):
+##        InterpretedFunction.__init__(self, *args)
+
+##    def parse_args(self, frame, w_args, w_kwargs):
+##        """ fills in "self" arg and dispatch to InterpreterFunction.
+##        """
+##        space = self.space
+##        args_w = space.unpacktuple(w_args)
+##        args_w = [space.wrap(self)] + args_w
+##        w_args = space.newtuple(args_w)
+##        return InterpretedFunction.parse_args(self, frame, w_args, w_kwargs)
+
+##class AppVisibleModule:
+##    """ app-level visible Module defined at interpreter-level.
+
+##    Inherit from this class if you want to have a module that accesses
+##    the PyPy interpreter (e.g. builtins like 'locals()' require accessing the
+##    frame). You can mix in application-level code by prefixing your method
+##    with 'app_'. Both non-underscore methods and app-level methods will
+##    be available on app-level with their respective name. 
+
+##    Note that app-level functions don't get a 'self' argument because it doesn't
+##    make sense and we really only need the function (there is no notion of beeing 
+##    'bound' or 'unbound' for them).
+    
+##    """
+##    def __init__(self, space):
+##        self.space = space
+
+##        space = self.space
+##        modname = self.__class__.__name__
+##        self.w___name__ = space.wrap(modname)
+##        self._wrapped = _wrapped = space.newmodule(self.w___name__)
+
+##        # go through all items in the module class instance
+##        for name in dir(self):
+##            # skip spurious info and internal methods
+##            if name == '__module__' or name.startswith('_') and not name.endswith('_'):
+##                #print modname, "skipping", name
+##                continue
+##            obj = getattr(self, name)
+##            # see if we just need to expose an already wrapped value
+##            if name.startswith('w_'):
+##                space.setattr(_wrapped, space.wrap(name[2:]), obj)
+
+##            # see if have something defined at app-level
+##            elif name.startswith('app_'):
+##                obj = self.__class__.__dict__.get(name)
+##                name = name[4:]
+##                w_res = wrap_applevel(space, name, obj)
+##            # nope then we must expose interpreter-level to app-level
+##            else:
+##                w_res = wrap_interplevel(space, name, obj)
+##                setattr(self, 'w_'+name, w_res)
+##            w_name = space.wrap(name)
+##            space.setattr(_wrapped, w_name, w_res)
+
+##def wrap_applevel(space, name, obj):
+##    """ wrap an app-level style object which was compiled at interp-level. """
+##    if hasattr(obj, 'func_code'):
+##        return space.wrap(InterpretedFunction(space, obj))
+##    elif inspect.isclass(obj):
+##        # XXX currently (rev 1020) unused, but it may be useful
+##        #     to define builtin app-level classes at interp-level. 
+##        return wrap_applevel_class(space, name, obj)
+##    else:
+##        raise ValueError, "cannot wrap %s, %s" % (name, obj)
+
+##def wrap_applevel_class(space, name, obj):
+##    """ construct an app-level class by reproducing the
+##    source definition and running it through the interpreter.
+##    It's a bit ugly but i don't know a better way (holger).
+##    """
+##    assert 1!=1, "Oh you want to use this function?"
+##    l = ['class %s:' % name]
+##    indent = '    '
+##    for key, value in vars(obj).items():
+##        if hasattr(value, 'func_code'):
+##            s = inspect.getsource(value)
+##            l.append(s)
+##            indent = " " * (len(s) - len(s.lstrip()))
+
+##    if getattr(obj, '__doc__', None):
+##        l.insert(1, indent + obj.__doc__)
+
+##    for key, value in vars(obj).items():
+##        if not key in ('__module__', '__doc__'):
+##            if isinstance(value, (str, int, float, tuple, list)):
+##                l.append('%s%s = %r' % (indent, key, value))
+
+##    s = "\n".join(l)
+##    code = compile(s, s, 'exec')
+##    scopedcode = ScopedCode(space, code, None)
+##    scopedcode.eval_frame()
+##    w_name = space.wrap(name)
+##    w_res = space.getitem(scopedcode.w_globals, w_name)
+##    return w_res
+
+
+##def wrap_interplevel(space, name, obj):
+##    """ make an interp-level object accessible on app-level. """
+##    return space.wrap(obj)
+
+#### Cells (used for nested scopes only) ##
+
+##_NULL = object() # Marker object
+
+##class Cell:
+##    def __init__(self, w_value=_NULL):
+##        self.w_value = w_value
+
+##    def clone(self):
+##        return self.__class__(self.w_value)
+
+##    def get(self):
+##        if self.w_value is _NULL:
+##            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 _NULL:
+##            raise ValueError, "make_empty() on an empty cell"
+##        self.w_value = _NULL
+
+##    def __repr__(self):
+##        """ representation for debugging purposes """
+##        if self.w_value is _NULL:
+##            return "%s()" % self.__class__.__name__
+##        else:
+##            return "%s(%s)" % (self.__class__.__name__, self.w_value)

Copied: pypy/branch/builtinrefactor/pypy/interpreter/nestedscope.py (from rev 1264, pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py)
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/nestedscope.py	Sun Aug 10 21:34:26 2003
@@ -1,4 +1,5 @@
-from pypy.interpreter.pyfastscope import PyFastScopeFrame, UNDEFINED
+from pypy.interpreter.eval import UNDEFINED
+from pypy.interpreter.pyopcode import PyInterpFrame
 
 
 class Cell(object):
@@ -36,7 +37,7 @@
                                      content, id(self))
 
 
-class PyNestedScopeFrame(PyFastScopeFrame):
+class PyNestedScopeFrame(PyInterpFrame):
     """This class enhances a standard frame with nested scope abilities,
     i.e. handling of cell/free variables."""
 
@@ -47,14 +48,23 @@
     # 'closure' is a list of Cell instances: the received free vars.
 
     def __init__(self, space, code, w_globals, closure):
-        PyFastScopeFrame.__init__(self, space, code, w_globals, closure)
+        PyInterpFrame.__init__(self, space, code, w_globals, closure)
         ncellvars = len(code.co_cellvars)
         nfreevars = len(code.co_freevars)
+        if closure is None:
+            if nfreevars:
+                raise OperationError(space.w_TypeError,
+                                     "directly executed code object "
+                                     "may not contain free variables")
+        else:
+            if len(closure) != nfreevars:
+                raise ValueError("code object received a closure with "
+                                 "an unexpected number of free variables")
         self.cells = [Cell() for i in range(ncellvars)] + closure
 
     def fast2locals(self):
-        PyFastScopeFrame.fast2locals(self)
-        freevarnames = self.bytecode.co_cellvars + self.bytecode.co_freevars
+        PyInterpFrame.fast2locals(self)
+        freevarnames = self.code.co_cellvars + self.code.co_freevars
         for name, cell in zip(freevarnames, self.cells):
             try:
                 w_value = cell.get()
@@ -65,8 +75,8 @@
                 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
+        PyInterpFrame.locals2fast(self)
+        freevarnames = self.code.co_cellvars + self.code.co_freevars
         for name, cell in zip(freevarnames, self.cells):
             w_name = self.space.wrap(name)
             try:
@@ -78,11 +88,11 @@
                 cell.set(w_value)
 
     def setfastscope(self, scope_w):
-        PyFastScopeFrame.setfastscope(scope_w)
-        if self.bytecode.co_cellvars:
+        PyInterpFrame.setfastscope(scope_w)
+        if self.code.co_cellvars:
             # the first few cell vars could shadow already-set arguments,
             # in the same order as they appear in co_varnames
-            code     = self.bytecode
+            code     = self.code
             argvars  = code.co_varnames
             cellvars = code.co_cellvars
             next     = 0
@@ -99,12 +109,12 @@
                         break   # all cell vars initialized this way
 
     def getfreevarname(self, index):
-        freevarnames = self.bytecode.co_cellvars + self.bytecode.co_freevars
+        freevarnames = self.code.co_cellvars + self.code.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)
+        return index < len(self.code.co_cellvars)
 
     ### extra opcodes ###
 

Modified: pypy/branch/builtinrefactor/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/pycode.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pycode.py	Sun Aug 10 21:34:26 2003
@@ -5,9 +5,6 @@
 """
 
 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
@@ -64,14 +61,12 @@
 
     def create_frame(self, space, w_globals, closure=None):
         "Create an empty PyFrame suitable for this code object."
-        # select the appropriate kind of frame; see below
+        # select the appropriate kind of frame
         if self.co_cellvars or self.co_freevars:
-            frameclass = PyNestedScopeFrame
-        elif self.co_nlocals:
-            frameclass = PyFastScopeFrame
+            from pypy.interpreter.nestedscope import PyNestedScopeFrame as F
         else:
-            frameclass = PyOperationalFrame
-        return frameclass(space, self, w_globals, closure)
+            from pypy.interpreter.pyopcode import PyInterpFrame as F
+        return F(space, self, w_globals, closure)
 
     def signature(self):
         "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
@@ -89,17 +84,8 @@
             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 getvarnames(self):
+        return self.co_varnames
 
     def is_generator(self):
         return self.co_flags & CO_GENERATOR

Deleted: /pypy/branch/builtinrefactor/pypy/interpreter/pyfastscope.py
==============================================================================
--- /pypy/branch/builtinrefactor/pypy/interpreter/pyfastscope.py	Sun Aug 10 21:34:26 2003
+++ (empty file)
@@ -1,88 +0,0 @@
-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, w_globals, closure):
-        PyOperationalFrame.__init__(self, space, code, w_globals, closure)
-        self.locals_w = [UNDEFINED] * code.co_nlocals
-
-    def getlocalvarname(self, index):
-        return self.bytecode.co_varnames[index]
-
-    def getdictlocals(self):
-        self.fast2locals()
-        return self.w_locals
-
-    def setdictlocals(self, w_locals):
-        self.w_locals = w_locals
-        self.locals2fast()
-
-    def setfastlocals(self, scope_w):
-        self.locals_w[:len(scope_w)] = scope_w
-
-    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	Sun Aug 10 21:34:26 2003
@@ -3,8 +3,8 @@
 
 from pypy.interpreter.executioncontext import Stack
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.gateway import app2interp
 from pypy.interpreter import eval, baseobjspace
+from pypy.interpreter.gateway import noglobals
 
 
 class PyFrame(eval.Frame):
@@ -15,7 +15,7 @@
 
     Public fields:
      * 'space' is the object space this frame is running in
-     * 'bytecode' is the PyCode object this frame runs
+     * 'code' 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
@@ -24,7 +24,6 @@
 
     def __init__(self, space, code, w_globals, closure):
         eval.Frame.__init__(self, space, code, w_globals)
-        self.bytecode = code   # Misnomer; this is really like a code object
         self.valuestack = Stack()
         self.blockstack = Stack()
         self.last_exception = None
@@ -81,31 +80,6 @@
             w_exitvalue = e.args[0]
             return w_exitvalue
 
-    ### 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]
-        self.next_instr += 1
-        return ord(c)
-
-    def nextarg(self):
-        lo = self.nextop()
-        hi = self.nextop()
-        return (hi<<8) + lo
-
     ### exception stack ###
 
     def clean_exceptionstack(self):
@@ -171,40 +145,37 @@
             # push the exception to the value stack for inspection by the
             # exception handler (the code after the except:)
             operationerr = unroller.args[0]
+            operationerr.normalize(frame.space)
             # the stack setup is slightly different than in CPython:
             # instead of the traceback, we store the unroller object,
             # wrapped.
             frame.valuestack.push(frame.space.wrap(unroller))
-
-            s = frame.space
-            w_value = operationerr.w_value
-            w_type = operationerr.w_type
-##             import pdb
-##             pdb.set_trace()
-##             print w_type, `w_value`, frame.bytecode.co_name
-            self.space = s # needed for the following call
-            w_res = self.normalize_exception(w_type, w_value)
-            w_value = s.getitem(w_res, s.wrap(1))
-            
-            frame.valuestack.push(w_value)
-            frame.valuestack.push(w_type)
+            frame.valuestack.push(operationerr.w_value)
+            frame.valuestack.push(operationerr.w_type)
             frame.next_instr = self.handlerposition   # jump to the handler
             raise StopUnrolling
 
-    def app_normalize_exception(etype, evalue):
-        # mistakes here usually show up as infinite recursion, which is fun.
-        if isinstance(evalue, etype):
-            return etype, evalue
-        if isinstance(etype, type) and issubclass(etype, Exception):
-            if evalue is None:
-                evalue = ()
-            elif not isinstance(evalue, tuple):
-                evalue = (evalue,)
-            evalue = etype(*evalue)
-        else:
-            raise Exception, "?!"   # XXX
+def app_normalize_exception(etype, evalue):
+    # XXX should really be defined as a method on OperationError,
+    # but this is not so easy because OperationError cannot be
+    # at the same time an old-style subclass of Exception and a
+    # new-style subclass of Wrappable :-(
+    # moreover, try importing gateway from errors.py and you'll see :-(
+    
+    # mistakes here usually show up as infinite recursion, which is fun.
+    if isinstance(evalue, etype):
         return etype, evalue
-    normalize_exception = app2interp(app_normalize_exception)
+    if isinstance(etype, type) and issubclass(etype, Exception):
+        if evalue is None:
+            evalue = ()
+        elif not isinstance(evalue, tuple):
+            evalue = (evalue,)
+        evalue = etype(*evalue)
+    else:
+        raise Exception, "?!"   # XXX
+    return etype, evalue
+normalize_exception = noglobals.app2interp(app_normalize_exception)
+
 
 class FinallyBlock(FrameBlock):
     """A try:finally: block.  Stores the position of the exception handler."""
@@ -286,7 +257,7 @@
     """Signals a 'return' statement.
     Argument is the wrapped object to return."""
     def emptystack(self, frame):
-        if frame.bytecode.is_generator():
+        if frame.code.is_generator():
             raise baseobjspace.NoValue
         w_returnvalue = self.args[0]
         raise ExitFrame(w_returnvalue)

Deleted: /pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py
==============================================================================
--- /pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py	Sun Aug 10 21:34:26 2003
+++ (empty file)
@@ -1,160 +0,0 @@
-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."""
-
-    # 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.
-
-    def __init__(self, space, code, w_globals, closure):
-        PyFastScopeFrame.__init__(self, space, code, w_globals, closure)
-        ncellvars = len(code.co_cellvars)
-        nfreevars = len(code.co_freevars)
-        self.cells = [Cell() for i in range(ncellvars)] + closure
-
-    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 setfastscope(self, scope_w):
-        PyFastScopeFrame.setfastscope(scope_w)
-        if self.bytecode.co_cellvars:
-            # the first few cell vars could shadow already-set arguments,
-            # in the same order as they appear in co_varnames
-            code     = self.bytecode
-            argvars  = code.co_varnames
-            cellvars = code.co_cellvars
-            next     = 0
-            nextname = cellvars[0]
-            for i in range(len(scope_w)):
-                if argvars[i] == nextname:
-                    # argument i has the same name as the next cell var
-                    w_value = scope_w[i]
-                    self.cells[next] = Cell(w_value)
-                    next += 1
-                    try:
-                        nextname = cellvars[next]
-                    except IndexError:
-                        break   # all cell vars initialized this way
-
-    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]
-        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()

Modified: pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py	Sun Aug 10 21:34:26 2003
@@ -30,17 +30,49 @@
         f.valuestack.push(w_result)
 
 
-class PyOperationalFrame(PyFrame):
-    """A PyFrame that knows about all operational Python opcodes.
-    It does not know about 'fast variables' nor 'nested scopes'."""
+class PyInterpFrame(PyFrame):
+    """A PyFrame that knows about interpretation of standard Python opcodes,
+    with the exception of nested scopes."""
+
+    def __init__(self, space, code, w_globals, closure):
+        PyFrame.__init__(self, space, code, w_globals, closure,
+                         code.co_nlocals)   # size of fastlocals_w array
+
+    ### 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.code.co_code[self.next_instr]
+        self.next_instr += 1
+        return ord(c)
+
+    def nextarg(self):
+        lo = self.nextop()
+        hi = self.nextop()
+        return (hi<<8) + lo
 
     ### accessor functions ###
 
+    def getlocalvarname(self, index):
+        return self.code.co_varnames[index]
+
     def getconstant(self, index):
-        return self.bytecode.co_consts[index]
+        return self.code.co_consts[index]
 
     def getname(self, index):
-        return self.bytecode.co_names[index]
+        return self.code.co_names[index]
 
     ################################################################
     ##  Implementation of the "operational" opcodes
@@ -50,10 +82,32 @@
     #  the 'self' argument of opcode implementations is called 'f'
     #  for historical reasons
 
+    def LOAD_FAST(f, varindex):
+        # access a local variable directly
+        w_value = f.fastlocals_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 LOAD_CONST(f, constindex):
         w_const = f.space.wrap(f.getconstant(constindex))
         f.valuestack.push(w_const)
 
+    def STORE_FAST(f, varindex):
+        w_newvalue = f.valuestack.pop()
+        f.fastlocals_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.code)
+        #    print "co_varnames", f.code.co_varnames
+        #    print "co_nlocals", f.code.co_nlocals
+        #    raise
+
     def POP_TOP(f):
         f.valuestack.pop()
 
@@ -447,6 +501,13 @@
                 raise OperationError(w_exc_type, w_exc_value)
         f.valuestack.push(w_value)
 
+    def DELETE_FAST(f, varindex):
+        if f.fastlocals_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.fastlocals_w[varindex] = UNDEFINED
+
     def BUILD_TUPLE(f, itemcount):
         items = [f.valuestack.pop() for i in range(itemcount)]
         items.reverse()
@@ -674,4 +735,4 @@
     setup_dispatch_table = classmethod(setup_dispatch_table)
 
 
-PyOperationalFrame.setup_dispatch_table()
+PyInterpFrame.setup_dispatch_table()

Modified: pypy/branch/builtinrefactor/pypy/interpreter/unittest_w.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/unittest_w.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/unittest_w.py	Sun Aug 10 21:34:26 2003
@@ -2,7 +2,8 @@
 
 import sys, os
 import unittest
-from pypy.interpreter.gateway import InterpretedMethod, InterpretedFunction
+#from pypy.interpreter.gateway import InterpretedMethod, InterpretedFunction
+#   FIX ME FIX ME FIX ME
 
 def make_testcase_class(space, tc_w):
     # XXX this is all a bit insane (but it works)


More information about the Pypy-commit mailing list