[pypy-svn] rev 1276 - in pypy/branch/builtinrefactor/pypy: interpreter module objspace

arigo at codespeak.net arigo at codespeak.net
Mon Sep 8 20:53:16 CEST 2003


Author: arigo
Date: Mon Sep  8 20:53:13 2003
New Revision: 1276

Added:
   pypy/branch/builtinrefactor/pypy/interpreter/extmodule.py
   pypy/branch/builtinrefactor/pypy/interpreter/miscutils.py   (contents, props changed)
      - copied, changed from rev 1267, pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py
Removed:
   pypy/branch/builtinrefactor/pypy/interpreter/appfile.py
   pypy/branch/builtinrefactor/pypy/interpreter/opcode_app.py
   pypy/branch/builtinrefactor/pypy/interpreter/threadlocals.py
Modified:
   pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py
   pypy/branch/builtinrefactor/pypy/interpreter/error.py
   pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py
   pypy/branch/builtinrefactor/pypy/interpreter/function.py
   pypy/branch/builtinrefactor/pypy/interpreter/gateway.py
   pypy/branch/builtinrefactor/pypy/interpreter/interactive.py
   pypy/branch/builtinrefactor/pypy/interpreter/main.py
   pypy/branch/builtinrefactor/pypy/interpreter/nestedscope.py
   pypy/branch/builtinrefactor/pypy/interpreter/pycode.py
   pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py
   pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py
   pypy/branch/builtinrefactor/pypy/interpreter/unittest_w.py
   pypy/branch/builtinrefactor/pypy/module/builtin.py
   pypy/branch/builtinrefactor/pypy/module/sysmodule.py
   pypy/branch/builtinrefactor/pypy/objspace/trivial.py
Log:
getting closer, some tests start passing again

Deleted: /pypy/branch/builtinrefactor/pypy/interpreter/appfile.py
==============================================================================
--- /pypy/branch/builtinrefactor/pypy/interpreter/appfile.py	Mon Sep  8 20:53:13 2003
+++ (empty file)
@@ -1,69 +0,0 @@
-import os
-
-class AppFile:
-    """Dynamic loader of a set of Python functions and objects that
-    should work at the application level (conventionally in .app.py files)"""
-
-    # absolute name of the parent directory
-    ROOTDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-    DEFAULT_PATH_EXT = [('appspace', '.py')]
-    LOCAL_PATH = []
-
-    def __init__(self, modulename, localpath=[]):
-        "Load and compile the helper file."
-        # XXX looking for a pre-compiled file here will be quite essential
-        #     when we want to bootstrap the compiler
-
-        # 'modulename' could be 'package.module' if passed in as __name__
-        # we ignore that package part
-        modulename = modulename.split('.')[-1]
-        path_ext = [(path, '_app.py') for path in localpath + self.LOCAL_PATH]
-        for path, ext in path_ext + self.DEFAULT_PATH_EXT:
-            dirname = os.path.join(self.ROOTDIR, path.replace('.', os.sep))
-            filename = os.path.join(dirname, modulename+ext)
-            if os.path.exists(filename):
-                break
-        else:
-            raise IOError, "cannot locate helper module '%s' in %s" % (
-                modulename, path_ext)
-        f = open(filename, 'r')
-        src = f.read()
-        f.close()
-        #print filename
-        self.bytecode = compile(src, filename, 'exec')
-
-
-class Namespace:
-
-    def __init__(self, space, w_namespace=None):
-        self.space = space
-        ec = space.getexecutioncontext()
-        if w_namespace is None:
-            w_namespace = ec.make_standard_w_globals()
-        self.w_namespace = w_namespace
-
-    def get(self, objname):
-        "Returns a wrapped copy of an object by name."
-        w_name = self.space.wrap(objname)
-        w_obj = self.space.getitem(self.w_namespace, w_name)
-        return w_obj
-
-    def call(self, functionname, args):
-        "Call a module function."
-        w_func = self.get(functionname)
-        w_args = self.space.newtuple(args)
-        w_keywords = self.space.newdict([])
-        return self.space.call(w_func, w_args, w_keywords)
-
-    def runbytecode(self, bytecode):
-        # initialize the module by running the bytecode in a new
-        # dictionary, in a new execution context
-        from pypy.interpreter.gateway import ScopedCode
-        scopedcode = ScopedCode(self.space, bytecode, self.w_namespace)
-        scopedcode.eval_frame()
-
-class AppHelper(Namespace):
-
-    def __init__(self, space, appfile, w_namespace=None):
-        Namespace.__init__(self, space, w_namespace)
-        self.runbytecode(appfile.bytecode)

Modified: pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py	Mon Sep  8 20:53:13 2003
@@ -1,6 +1,6 @@
-from pypy.interpreter.executioncontext import ExecutionContext, Stack
+from pypy.interpreter.executioncontext import ExecutionContext
 from pypy.interpreter.error import OperationError
-from pypy.interpreter import threadlocals
+from pypy.interpreter.miscutils import Stack, getthreadlocals
 
 __all__ = ['ObjSpace', 'OperationError', 'NoValue']
 
@@ -17,7 +17,7 @@
 
 class ObjSpace:
     """Base class for the interpreter-level implementations of object spaces.
-    XXX describe here in more details what the object spaces are."""
+    http://codespeak.net/moin/pypy/moin.cgi/ObjectSpace"""
 
     def __init__(self):
         "Basic initialization of objects."
@@ -31,8 +31,9 @@
         
         from pypy.module import builtin
         self.builtin = builtin.__builtin__(self)
-        self.w_builtin = self.builtin._wrapped
-        self.w_builtins = self.getattr(self.w_builtin, self.wrap("__dict__"))
+        self.w_builtin = self.wrap(self.builtin)
+        #self.w_builtins = self.getattr(self.w_builtin, self.wrap("__dict__"))
+        self.w_builtins = self.builtin.w_dict
 
         for name, value in self.__dict__.items():
             if name.startswith('w_'):
@@ -42,14 +43,14 @@
                 #print "setitem: space instance %-20s into builtins" % name
                 self.setitem(self.w_builtins, self.wrap(name), value)
 
-        self.sys._setmodule(self.builtin)
+        self.sys._setmodule(self.w_builtin)
 
     def make_sys(self):
         assert not hasattr(self, 'sys')
         from pypy.module import sysmodule
-        self.sys = sysmodule.sys(self)
-        self.w_sys = self.sys._wrapped
-        self.sys._setmodule(self.sys)
+        self.sys = sysmodule.Sys(self)
+        self.w_sys = self.wrap(self.sys)
+        self.sys._setmodule(self.w_sys)
 
     # XXX get rid of this. 
     def get_builtin_module(self, w_name):
@@ -66,7 +67,7 @@
 
     def getexecutioncontext(self):
         "Return what we consider to be the active execution context."
-        ec = threadlocals.getlocals().executioncontext
+        ec = getthreadlocals().executioncontext
         if ec is None:
             ec = self.createexecutioncontext()
         return ec

Modified: pypy/branch/builtinrefactor/pypy/interpreter/error.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/error.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/error.py	Mon Sep  8 20:53:13 2003
@@ -69,7 +69,7 @@
             tb.reverse()
             print >> file, "Traceback (application-level):"
             for f, i in tb:
-                co = f.bytecode
+                co = f.code
                 lineno = offset2lineno(co, i)
                 fname = co.co_filename
                 if fname.startswith('<inline>\n'):

Modified: pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py	Mon Sep  8 20:53:13 2003
@@ -1,4 +1,4 @@
-from pypy.interpreter import threadlocals
+from pypy.interpreter.miscutils import getthreadlocals, Stack
 
 class ExecutionContext:
     """An ExecutionContext holds the state of an execution thread
@@ -10,13 +10,14 @@
         self.framestack = Stack()
 
     def enter(self, frame):
-        locals = threadlocals.getlocals()
+        locals = getthreadlocals()
         self.framestack.push(frame)
         previous_ec = locals.executioncontext
         locals.executioncontext = self
         return previous_ec
 
     def leave(self, previous_ec):
+        locals = getthreadlocals()
         locals.executioncontext = previous_ec
         self.framestack.pop()
 
@@ -49,37 +50,3 @@
             if frame.last_exception is not None:
                 return frame.last_exception
         return None
-
-
-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

Added: pypy/branch/builtinrefactor/pypy/interpreter/extmodule.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/extmodule.py	Mon Sep  8 20:53:13 2003
@@ -0,0 +1,35 @@
+"""
+
+Helpers to build extension modules.
+
+"""
+
+from pypy.interpreter.gateway import DictProxy
+from pypy.interpreter.miscutils import InitializedClass
+from pypy.interpreter.baseobjspace import Wrappable
+
+
+class ExtModule(Wrappable):
+    """An empty extension module.
+    Non-empty extension modules are made by subclassing ExtModule."""
+
+    def __init__(self, space):
+        self.space = space
+        self.w_dict = self._appdict.makedict(space, self)
+
+    __metaclass__ = InitializedClass
+    def __initclass__(cls):
+        # make sure that the class has its own appdict
+        if '_appdict' not in cls.__dict__:
+            cls._appdict = DictProxy(implicitspace=True,
+                                     implicitself=True)
+        # automatically publish all functions from this class
+        cls._appdict.exportall(cls.__dict__)
+
+    def __getattr__(self, attr):
+        # XXX temporary, for use by objspace.trivial and
+        # objspace.std.cpythonobject
+        try:
+            return self.__class__._appdict.content[attr]
+        except KeyError:
+            raise AttributeError, attr

Modified: pypy/branch/builtinrefactor/pypy/interpreter/function.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/function.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/function.py	Mon Sep  8 20:53:13 2003
@@ -6,7 +6,9 @@
 attribute.
 """
 
-class Function:
+from error import OperationError
+
+class Function(object):
     """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."""
@@ -53,14 +55,15 @@
         # put as many positional input arguments into place as available
         args_w = space.unpacktuple(w_args)
         scope_w = args_w[:co_argcount]
+        input_argcount = len(scope_w)
 
         # check that no keyword argument conflicts with these
-        for name in argnames[:len(scope_w)]:
+        for name in argnames[:input_argcount]:
             w_name = space.wrap(name)
             if space.is_true(space.contains(w_kwargs, w_name)):
                 self.raise_argerr_multiple_values(name)
 
-        if len(scope_w) < co_argcount:
+        if input_argcount < co_argcount:
             # not enough args, fill in kwargs or defaults if exists
             def_first = co_argcount - len(self.defs_w)
             for i in range(input_argcount, co_argcount):
@@ -112,7 +115,7 @@
             else:
                 msg1 = "at least"
                 n -= defcount
-            if kws:
+            if kwargname is not None:
                 msg2 = "non-keyword "
             else:
                 msg2 = ""
@@ -126,7 +129,7 @@
                 n,
                 msg2,
                 plural,
-                len(args))
+                nargs)
         raise OperationError(self.space.w_TypeError, msg)
 
     def raise_argerr_multiple_values(self, argname):
@@ -148,3 +151,21 @@
                 self.func_code.co_name,
                 nkwds)
         raise OperationError(self.space.w_TypeError, msg)
+
+
+    def __get__(self, inst, cls=None):
+        # for TrivialObjSpace only !!!
+        # use the mecanisms of gateway.py otherwise
+        import sys, new
+        assert 'pypy.objspace.trivial' in sys.modules, (
+            "don't try to __get__() Function instances out of classes")
+        self.__name__ = self.func_code.co_name
+        return new.instancemethod(self, inst, cls)
+
+    def __call__(self, *args, **kwds):
+        # for TrivialObjSpace only !!!
+        # use the mecanisms of gateway.py otherwise
+        import sys, new
+        assert 'pypy.objspace.trivial' in sys.modules, (
+            "don't try to __call__() Function instances directly")
+        return self.call(args, kwds)

Modified: pypy/branch/builtinrefactor/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/gateway.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/gateway.py	Mon Sep  8 20:53:13 2003
@@ -1,14 +1,22 @@
 """
 
 Gateway between app-level and interpreter-level:
-* 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)
+* BuiltinCode (call interp-level code from app-level)
+* app2interp  (embed an app-level function into an interp-level callable)
+* interp2app  (publish an interp-level object to be visible from app-level)
+* publishall  (mass-call interp2app on a whole list of objects)
 
 """
 
+#
+# XXX warning, this module is a bit scary in the number of classes that
+#     all play a similar role but in slightly different contexts
+#
+
+import types
 from pypy.interpreter import eval, pycode
-from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.baseobjspace import Wrappable, ObjSpace
+from pypy.interpreter.function import Function
 
 
 class BuiltinCode(eval.Code):
@@ -17,23 +25,47 @@
     # When a BuiltinCode is stored in a Function object,
     # you get the functionality of CPython's built-in function type.
 
-    def __init__(self, func):
+    def __init__(self, func, **argflags):
         # 'implfunc' is the interpreter-level function.
-        # note that this uses a lot of (construction-time) introspection.
+        # See below for 'argflags'.
+        # Note that this uses a lot of (construction-time) introspection.
         eval.Code.__init__(self, func.__name__)
         self.func = func
+        self.argflags = argflags
         # extract the signature from the (CPython-level) code object
         tmp = pycode.PyCode(None)
         tmp._from_code(func.func_code)
         self.sig = tmp.signature()
+        if isinstance(func, types.MethodType) and func.im_self is not None:
+            argnames, varargname, kwargname = self.sig
+            argnames = argnames[1:]  # implicit hidden self argument
+            self.sig = argnames, varargname, kwargname
         self.nargs = len(self.getvarnames())
 
+    def bind_code(self, instance):
+        """Create another version of this code object that calls 'func'
+        as a method, with implicit first argument 'instance'."""
+        return BuiltinCode(self.func.__get__(instance, instance.__class__),
+                           **self.argflags)
+
     def create_frame(self, space, w_globals, closure=None):
         return BuiltinFrame(space, self, w_globals, numlocals=self.nargs)
 
     def signature(self):
         return self.sig
 
+# An application-level function always implicitely expects wrapped arguments,
+# but not an interpreter-level function not. The extra keywords given to the
+# constructor of BuiltinCode describes what kind of arguments 'func' expects.
+#
+# Default signature:
+#   def func(space, w_arg1, w_arg2...)            <- plain functions
+#   def func(self, space, w_arg1, w_arg2...)      <- methods
+#
+# Flags:  (XXX need more)
+#   implicitspace=True    method with no 'space' arg. We use 'self.space'
+#   implicitself=True     the app-level doesn't see any 'self' argument
+
 
 class BuiltinFrame(eval.Frame):
     "Frame emulation for BuiltinCode."
@@ -42,8 +74,11 @@
     # via the interface defined in eval.Frame.
 
     def run(self):
+        argarray = self.fastlocals_w
+        if not self.code.argflags.get('implicitspace'):
+            argarray = [space] + argarray
         return call_with_prepared_arguments(self.space, self.code.func,
-                                            self.fastlocals_w)
+                                            argarray)
 
 
 def call_with_prepared_arguments(space, function, argarray):
@@ -56,33 +91,47 @@
     # you don't need to look at it :-)
     keywords = {}
     co = function.func_code
-    if co.flags & 8:  # CO_VARKEYWORDS
+    if co.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
+    if co.co_flags & 4:  # CO_VARARGS
         w_varargs = argarray[-1]
         argarray = argarray[:-1] + space.unpacktuple(w_varargs)
     return function(*argarray, **keywords)
 
 
-class code2interp(object):
+class Gateway(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
+    # 'argflags' controls how the Gateway instance should decode its
+    # arguments. It only influences calls made from interpreter-level.
+    # It has the same format as BuiltinCode.argflags.
 
-    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 __init__(self, code, staticglobals, staticdefs=[], **argflags):
+        self.code = code
+        self.staticglobals = staticglobals  # a DictProxy instance
+        self.staticdefs = staticdefs
+        self.argflags = argflags
+
+    def make_function(self, space, bind_instance=None, w_globals=None):
+        if w_globals is None:
+            w_globals = space.wrap(self.staticglobals)
+        defs_w = [space.wrap(def_value) for def_value in self.staticdefs]
+        code = self.code
+        if self.argflags.get('implicitself') and isinstance(code, BuiltinCode):
+            assert bind_instance is not None, ("built-in function can only "
+                                               "be used as a method")
+            code = code.bind_code(bind_instance)
+        return Function(space, code, w_globals, defs_w)
+
+    def __wrap__(self, space):
+        # to wrap a Gateway, we first make a real Function object out of it
+        # and the result is a wrapped version of this Function.
+        return space.wrap(self.make_function(space))
 
     def __call__(self, space, *args, **kwds):
         wrap = space.wrap
@@ -92,325 +141,151 @@
         fn = self.make_function(space)
         return fn.call(w_args, w_kwds)
 
+    def __get__(self, obj, cls=None):
+        if obj is None:
+            return self
+        else:
+            return BoundGateway(self, obj)
+
 
-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()
+class BoundGateway(object):
+
+    def __init__(self, gateway, obj):
+        self.gateway = gateway
+        self.obj = obj
+
+    def __call__(self, *args, **kwds):
+        if self.gateway.argflags.get('implicitspace'):
+            # we read 'self.space' from the object we are bound to
+            space = self.obj.space
         else:
-            mro = list(content.__mro__)
-            mro.reverse()
-            content = {}
-            for c in mro:
-                content.update(c.__dict__)
-        self.content = content
+            space = args[0]  # explicit 'space' as a first argument
+            args = args[1:]
+            if not isinstance(space, ObjSpace):
+                raise TypeError, "'space' expected as first argument"
+        if self.gateway.argflags.get('implicitself'):
+            pass  # app-space gets no 'self' argument
+        else:
+            args = (space.wrap(self.obj),) + args  # insert 'w_self'
+        return self.gateway(space, *args, **kwds)
 
-    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 ()))
+class DictProxy(Wrappable):
+    # This class exposes at app-level a read-only dict-like interface.
+    # The items in the DictProxy are not wrapped (they are independent
+    # of any object space, and are just interpreter-level objects) until
+    # app-level code reads them.
+
+    # Instances of DictProxy play the role of the 'globals' for app-level
+    # helpers. This is why app2interp and interp2app are methods of
+    # DictProxy. Calling them on the same DictProxy for several functions
+    # gives all these functions the same 'globals', allowing them to see
+    # and call each others.
+
+    # XXX a detail has been (temporarily?) changed because too many
+    # places (notably in pyopcode.py) assume that the globals should
+    # satisfy 'instance(globals, dict)'. Now wrapping a DictProxy
+    # gives you a real dict.
+
+    def __init__(self, basedict=None, **defaultargflags):
+        if basedict is None:
+            self.content = {}
+        else:
+            self.content = basedict.content.copy()
+        self.defaultargflags = defaultargflags
 
-    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)
+    #def __getitem__(self, key):
+    #    return self.content[key]
+    #
+    #def __iter__(self):
+    #    return iter(self.content)
+    def __wrap__(self, space):
+        return self.makedict(space)
+
+    def app2interp(self, app, app_name=None, **argflags):
+        """Build a Gateway that calls 'app' at app-level and insert it
+        into the DictProxy."""
+        # app must be a function whose name starts with 'app_'
+        if not isinstance(app, types.FunctionType):
+            raise TypeError, "function expected, got %r instead" % app
+        if app_name is None:
+            if not app.func_name.startswith('app_'):
+                raise ValueError, ("function name must start with 'app_'; "
+                                   "%r does not" % app.func_name)
+            app_name = app.func_name[4:]
+        argflags1 = self.defaultargflags.copy()
+        argflags1.update(argflags)
+        code = pycode.PyCode(None)
+        code._from_code(app.func_code)
+        staticdefs = list(app.func_defaults or ())
+        gateway = Gateway(code, self, staticdefs, **argflags1)
+        self.content[app_name] = gateway
+        return gateway
+
+    def interp2app(self, f, **argflags):
+        """Insert an interp-level function into the DictProxy to make
+        it callable from app-level."""
+        # f must be a function whose name does NOT starts with 'app_'
+        if not isinstance(f, types.FunctionType):
+            raise TypeError, "function expected, got %r instead" % f
+        assert not f.func_name.startswith('app_'), (
+            "function name %r suspiciously starts with 'app_'" % f.func_name)
+        argflags1 = self.defaultargflags.copy()
+        argflags1.update(argflags)
+        builtincode = BuiltinCode(f, **argflags1)
+        staticdefs = list(f.func_defaults or ())
+        gateway = Gateway(builtincode, self, staticdefs, **argflags1)
+        self.content[f.func_name] = gateway
+
+    def exportname(self, name, obj, optional=0):
+        """Publish an object of the given name by inserting it into the
+        DictProxy. See implementation for the known types of 'obj'."""
+        if name.startswith('app_'):
+            publicname = name[4:]
+            optional = 0
+        else:
+            publicname = name
+        if isinstance(obj, types.FunctionType):
+            assert name == obj.func_name
+            if name == publicname:
+                # an interpreter-level function
+                self.interp2app(obj)
+            else:
+                # an app-level function
+                self.app2interp(obj)
+        elif not optional:
+            # assume a simple, easily wrappable object
+            self.content[publicname] = obj
+        # else skip the object if we cannot recognize it
+
+    def exportall(self, d):
+        """Publish every object from a dict."""
+        for name, obj in d.items():
+            # ignore names in '_xyz'
+            if not name.startswith('_') or name.endswith('_'):
+                self.exportname(name, obj, optional=1)
+
+    def importall(self, newd):
+        """Import all app_-level functions as Gateways into a dict.
+        Also import literals whose name starts with 'app_'."""
+        for name, obj in newd.items():
+            if name.startswith('app_') and name[4:] not in newd:
+                if isinstance(obj, types.FunctionType):
+                    # an app-level function
+                    assert name == obj.func_name
+                    newd[name[4:]] = self.app2interp(obj)
+                else:
+                    # assume a simple, easily wrappable object
+                    newd[name[4:]] = obj
+
+    def makedict(self, space, bind_instance=None):
+        """Turn the proxy into a normal dict.
+        Gateways to interpreter-level functions that were defined
+        with 'implicitself' are bound to 'bind_instance', so that
+        calling them from app-space will add this extra hidden argument."""
+        w_dict = space.newdict([])
+        for key, value in self.content.items():
+            if isinstance(value, Gateway):
+                value = value.make_function(space, bind_instance, w_dict)
+            space.setitem(w_dict, space.wrap(key), space.wrap(value))
+        return w_dict

Modified: pypy/branch/builtinrefactor/pypy/interpreter/interactive.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/interactive.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/interactive.py	Mon Sep  8 20:53:13 2003
@@ -34,12 +34,17 @@
                 self.space.__class__.__name__)
         code.InteractiveConsole.interact(self, banner)
 
+    def raw_input(self, prompt=""):
+        # add a character to the PyPy prompt so that you know where you
+        # are when you debug it with "python -i py.py"
+        return code.InteractiveConsole.raw_input(self, prompt[0] + prompt)
+
     def runcode(self, code):
-        from pypy.interpreter.gateway import ScopedCode
-        scopedcode = ScopedCode(self.space, code, self.w_globals)
-        frame = scopedcode.create_frame()
+        # 'code' is a CPython code object
+        from pypy.interpreter.pycode import PyCode
+        pycode = PyCode()._from_code(code)
         try:
-            self.ec.eval_frame(frame)
+            pycode.exec_code(self.space, self.w_globals, self.w_globals)
         except baseobjspace.OperationError, operationerr:
             # XXX insert exception info into the application-level sys.last_xxx
             operationerr.print_detailed_traceback(self.space)

Modified: pypy/branch/builtinrefactor/pypy/interpreter/main.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/main.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/main.py	Mon Sep  8 20:53:13 2003
@@ -1,5 +1,5 @@
 import autopath
-from pypy.tool import test, option
+from pypy.tool import option
 from pypy.interpreter import executioncontext, baseobjspace, gateway
 import sys, os
 
@@ -23,18 +23,17 @@
 
         w_mainmodule = space.newmodule(space.wrap("__main__"))
         w_globals = space.getattr(w_mainmodule, space.wrap("__dict__"))
-        space.setitem(w_globals, space.wrap("__builtins__"), space.w_builtins)
        
     except baseobjspace.OperationError, operationerr:
         operationerr.record_interpreter_traceback()
         raise baseobjspace.PyPyError(space, operationerr)
     else:
-        scopedcode = gateway.ScopedCode(space, space.unwrap(w_code), w_globals)
-        frame = scopedcode.create_frame()
+        pycode = space.unwrap(w_code)
+        retval = pycode.exec_code(space, w_globals, w_globals)
         if eval:
-            return ec.eval_frame(frame)
+            return retval
         else:
-            ec.eval_frame(frame)
+            return
     
 def run_string(source, filename='<string>', space=None):
     _run_eval_string(source, filename, space, False)

Copied: pypy/branch/builtinrefactor/pypy/interpreter/miscutils.py (from rev 1267, pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py)
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/miscutils.py	Mon Sep  8 20:53:13 2003
@@ -1,54 +1,8 @@
-from pypy.interpreter import threadlocals
+"""
+Miscellaneous utilities.
+"""
 
-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 enter(self, frame):
-        locals = threadlocals.getlocals()
-        self.framestack.push(frame)
-        previous_ec = locals.executioncontext
-        locals.executioncontext = self
-        return previous_ec
-
-    def leave(self, previous_ec):
-        locals.executioncontext = previous_ec
-        self.framestack.pop()
-
-    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
+import types
 
 
 class Stack:
@@ -83,3 +37,27 @@
 
     def empty(self):
         return not self.items
+
+
+class InitializedClass(type):
+    """A meta-class that allows a class to initialize itself (or its
+    subclasses) by calling __initclass__() as a class method."""
+    def __init__(self, name, bases, dict):
+        super(InitializedClass, self).__init__(name, bases, dict)
+        if hasattr(self, '__initclass__'):
+            raw = dict.get('__initclass__')
+            if isinstance(raw, types.FunctionType):
+                self.__initclass__ = classmethod(raw)
+            self.__initclass__()
+
+
+class ThreadLocals:
+    """Thread-local storage."""
+
+    def __init__(self):
+        self.executioncontext = None
+
+# XXX no thread support yet, so this is easy :-)
+_locals = ThreadLocals()
+def getthreadlocals():
+    return _locals

Modified: pypy/branch/builtinrefactor/pypy/interpreter/nestedscope.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/nestedscope.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/nestedscope.py	Mon Sep  8 20:53:13 2003
@@ -165,6 +165,3 @@
         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()

Deleted: /pypy/branch/builtinrefactor/pypy/interpreter/opcode_app.py
==============================================================================
--- /pypy/branch/builtinrefactor/pypy/interpreter/opcode_app.py	Mon Sep  8 20:53:13 2003
+++ (empty file)
@@ -1,185 +0,0 @@
-def prepare_raise0():
-    import sys
-    return sys.exc_info()
-    
-def prepare_raise(etype, value, traceback):
-#    import types
-    # XXX we get an infinite loop if this import fails:
-    #    import types -> IMPORT_NAME -> import_name -> raise ImportError
-    #    -> RAISE_VARARGS -> prepare_raise -> import types ...
-#    if not isinstance(traceback, (types.NoneType, types.TracebackType)):
-#        raise TypeError, "raise: arg 3 must be traceback or None"
-    while isinstance(etype, tuple):
-        etype = etype[0]
-    if type(etype) is str:
-        # warn
-        pass
-    elif isinstance(etype, Exception):
-        if value is not None:
-            raise TypeError, "instance exception may not have a separate value"
-        value = etype
-        etype = value.__class__
-    elif isinstance(etype, type) and issubclass(etype, Exception):
-        if value is None:
-            value = ()
-        elif not isinstance(value, tuple):
-            value = (value,)
-        value = etype(*value)
-    else:
-        raise TypeError, ("exceptions must be instances or subclasses of "
-                          "Exception or strings (deprecated), not %s" %
-                          (type(etype).__name__,))
-    return etype, value, traceback
-
-def print_expr(x):
-    import sys
-    try:
-        displayhook = sys.displayhook
-    except AttributeError:
-        raise RuntimeError, "lost sys.displayhook"
-    displayhook(x)
-
-
-def file_softspace(file, newflag):
-    try:
-        softspace = file.softspace
-    except AttributeError:
-        softspace = 0
-    try:
-        file.softspace = newflag
-    except AttributeError:
-        pass
-    return softspace
-
-def print_item_to(x, stream):
-    if file_softspace(stream, False):
-        stream.write(" ")
-    stream.write(str(x))
-    # add a softspace unless we just printed a string which ends in a '\t'
-    # or '\n' -- or more generally any whitespace character but ' '
-#    if isinstance(x, str) and len(x) and x[-1].isspace() and x[-1]!=' ':
-#        return
-    # XXX add unicode handling
-    file_softspace(stream, True)
-
-def print_item(x):
-    import sys
-    try:
-        stream = sys.stdout
-    except AttributeError:
-        raise RuntimeError, "lost sys.stdout"
-    print_item_to(x, stream)
-
-def print_newline_to(stream):
-    stream.write("\n")
-    file_softspace(stream, False)
-
-def print_newline():
-    import sys
-    try:
-        stream = sys.stdout
-    except AttributeError:
-        raise RuntimeError, "lost sys.stdout"
-    print_newline_to(stream)
-
-def import_name(builtins, modulename, globals, locals, fromlist):
-    try:
-        import_ = builtins["__import__"]
-    except KeyError:
-        raise ImportError, "__import__ not found"
-    return import_(modulename, globals, locals, fromlist)
-
-def import_all_from(module, locals):
-    try:
-        all = module.__all__
-    except AttributeError:
-        try:
-            dict = module.__dict__
-        except AttributeError:
-            raise ImportError, ("from-import-* object has no __dict__ "
-                                "and no __all__")
-        all = dict.keys()
-        skip_leading_underscores = True
-    else:
-        skip_leading_underscores = False
-    for name in all:
-        if skip_leading_underscores and name[0]=='_':
-            continue
-        locals[name] = getattr(module, name)
-
-def import_from(module, name):
-    try:
-        return getattr(module, name)
-    except AttributeError:
-        raise ImportError, "cannot import name '%s'" % name
-
-def load_name(name, locals, globals, builtins):
-    try:
-        return locals[name]
-    except KeyError:
-        try:
-            return globals[name]
-        except KeyError:
-            try:
-                return builtins[name]
-            except KeyError:
-                raise NameError, "name '"+name+"' is not defined"
-
-def concatenate_arguments(args, extra_args):
-    return args + tuple(extra_args)
-
-def concatenate_keywords(kw, extra_kw):
-    if not isinstance(extra_kw, dict):
-        raise TypeError, "argument after ** must be a dictionary"
-    result = kw.copy()
-    for key, value in extra_kw.items():
-        if key in result:
-            # XXX fix error message
-            raise TypeError, ("got multiple values "
-                              "for keyword argument '%s'" % key)
-        result[key] = value
-    return result
-
-def exec_statement(prog, globals, locals,
-                   builtins, caller_globals, caller_locals):
-    """Manipulate parameters to exec statement to (codeobject, dict, dict).
-    """
-    import types
-    if (globals is None and locals is None and
-        isinstance(prog, builtins['tuple']) and
-        (len(prog) == 2 or len(prog) == 3)):
-        globals = prog[1]
-        if len(prog) == 3:
-            locals = prog[2]
-        prog = prog[0]
-    if globals is None:
-        globals = caller_globals
-        if locals is None:
-            locals = caller_locals
-    if locals is None:
-        locals = globals
-    if not isinstance(globals, dict):
-        raise TypeError("exec: arg 2 must be a dictionary or None")
-    elif not globals.has_key('__builtins__'):
-        globals['__builtins__'] = builtins
-    if not isinstance(locals, dict):
-        raise TypeError("exec: arg 3 must be a dictionary or None")
-##     # XXX - HACK to check for code object
-##     co = compile('1','<string>','eval')
-##     print prog
-    if isinstance(prog, types.CodeType):
-        return (prog, globals, locals)
-    if not isinstance(prog, types.StringTypes):
-##     if not (isinstance(prog, types.StringTypes) or
-##             isinstance(prog, types.FileType)):
-        raise TypeError("exec: arg 1 must be a string, file, or code object")
-##     if isinstance(prog, types.FileType):
-##         flags = 0
-##         ## XXX add in parent flag merging
-##         co = compile(prog.read(),prog.name,'exec',flags,1)
-##         return (co,globals,locals)
-    else: # prog is a string
-        flags = 0
-        ## XXX add in parent flag merging
-        co = compile(prog,'<string>','exec',flags,1)
-        return (co,globals,locals)

Modified: pypy/branch/builtinrefactor/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/pycode.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pycode.py	Mon Sep  8 20:53:13 2003
@@ -19,7 +19,7 @@
 class PyCode(eval.Code):
     "CPython-style code objects."
     
-    def __init__(self, co_name):
+    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
@@ -52,12 +52,10 @@
         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,)
+                const = PyCode()._from_code(const)
+            newconsts = newconsts + (const,)
         self.co_consts = newconsts
+        return self
 
     def create_frame(self, space, w_globals, closure=None):
         "Create an empty PyFrame suitable for this code object."
@@ -89,3 +87,8 @@
 
     def is_generator(self):
         return self.co_flags & CO_GENERATOR
+
+    def dictscope_needed(self):
+        # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
+        # class bodies only have CO_NEWLOCALS.
+        return not (self.co_flags & CO_OPTIMIZED)

Modified: pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py	Mon Sep  8 20:53:13 2003
@@ -1,10 +1,10 @@
 """ PyFrame class implementation with the interpreter main loop.
 """
 
-from pypy.interpreter.executioncontext import Stack
-from pypy.interpreter.error import OperationError
 from pypy.interpreter import eval, baseobjspace
-from pypy.interpreter.gateway import noglobals
+from pypy.interpreter.miscutils import Stack
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import DictProxy
 
 
 class PyFrame(eval.Frame):
@@ -23,12 +23,17 @@
     """
 
     def __init__(self, space, code, w_globals, closure):
-        eval.Frame.__init__(self, space, code, w_globals)
+        eval.Frame.__init__(self, space, code, w_globals, code.co_nlocals)
         self.valuestack = Stack()
         self.blockstack = Stack()
         self.last_exception = None
         self.next_instr = 0
         self.w_builtins = self.space.w_builtins
+        # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
+        # class bodies only have CO_NEWLOCALS.
+        if code.dictscope_needed():
+            self.w_locals = space.newdict([])  # set to None by Frame.__init__
+
 
 ##    def XXXclone(self):
 ##        f = self.__class__()
@@ -145,13 +150,16 @@
             # 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)
+            w_normalized = normalize_exception(frame.space,
+                                               operationerr.w_type,
+                                               operationerr.w_value)
+            w_type, w_value = frame.space.unpacktuple(w_normalized, 2)
             # 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))
-            frame.valuestack.push(operationerr.w_value)
-            frame.valuestack.push(operationerr.w_type)
+            frame.valuestack.push(w_value)
+            frame.valuestack.push(w_type)
             frame.next_instr = self.handlerposition   # jump to the handler
             raise StopUnrolling
 
@@ -174,7 +182,7 @@
     else:
         raise Exception, "?!"   # XXX
     return etype, evalue
-normalize_exception = noglobals.app2interp(app_normalize_exception)
+normalize_exception = DictProxy().app2interp(app_normalize_exception)
 
 
 class FinallyBlock(FrameBlock):

Modified: pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py	(original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py	Mon Sep  8 20:53:13 2003
@@ -5,9 +5,10 @@
 """
 
 from pypy.interpreter.baseobjspace import OperationError, NoValue
-import dis
-from pypy.interpreter import baseobjspace
-from pypy.interpreter.pyframe import PyFrame
+from pypy.interpreter.eval import UNDEFINED
+from pypy.interpreter import baseobjspace, pyframe
+from pypy.interpreter.miscutils import InitializedClass
+from pypy.interpreter.gateway import DictProxy
 
 
 class unaryoperation:
@@ -30,14 +31,11 @@
         f.valuestack.push(w_result)
 
 
-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
-
+class PyInterpFrame(pyframe.PyFrame):
+    """A PyFrame that knows about interpretation of standard Python opcodes
+    minus the ones related to nested scopes."""
+    appdict = DictProxy(implicitspace=True)
+    
     ### opcode dispatch ###
 
     # 'dispatch_table' is a class attribute: a list of functions.
@@ -270,24 +268,23 @@
 
     def PRINT_EXPR(f):
         w_expr = f.valuestack.pop()
-        #print f.space.unwrap(w_expr)
-        f.space.gethelper(appfile).call("print_expr", [w_expr])
+        print_expr(f.space, 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])
+        print_item_to(f.space, w_item, w_stream)
 
     def PRINT_ITEM(f):
         w_item = f.valuestack.pop()
-        f.space.gethelper(appfile).call("print_item", [w_item])
+        print_item_to(f.space, w_item, sys_stdout(f.space))
 
     def PRINT_NEWLINE_TO(f):
         w_stream = f.valuestack.pop()
-        f.space.gethelper(appfile).call("print_newline_to", [w_stream])
+        print_newline_to(f.space, w_stream)
 
     def PRINT_NEWLINE(f):
-        f.space.gethelper(appfile).call("print_newline", [])
+        print_newline_to(f.space, sys_stdout(f.space))
 
     def BREAK_LOOP(f):
         raise pyframe.SBreakLoop
@@ -299,26 +296,12 @@
         # 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)
+        w_type = w_value = w_traceback = f.space.w_None
+        if nbargs >= 3: w_traceback = f.valuestack.pop()
+        if nbargs >= 2: w_value     = f.valuestack.pop()
+        if nbargs >= 1: w_type      = f.valuestack.pop()
+        w_resulttuple = prepare_raise(f.space, w_type, w_value, w_traceback)
+        w_type, w_value, w_traceback = f.space.unpacktuple(w_resulttuple, 3)
         # XXX the three-arguments 'raise' is not supported yet
         raise OperationError(w_type, w_value)
 
@@ -338,20 +321,58 @@
         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)
+        w_resulttuple = f.prepare_exec(w_prog, w_globals, w_locals)
+        w_prog, w_globals, w_locals = f.space.unpacktuple(w_resulttuple)
+
+        plain = f.space.is_true(f.space.is_(w_locals, f.w_locals))
+        if plain:
+            w_locals = f.getdictscope()
+        pycode = f.space.unwrap(w_prog)
+        pycode.exec_code(f.space, w_globals, w_locals)
         if plain:
-            f.setlocaldict(w_locals)
+            f.setdictscope(w_locals)
+
+    def app_prepare_exec(f, prog, globals, locals):
+        """Manipulate parameters to exec statement to (codeobject, dict, dict).
+        """
+        # XXX INCOMPLETE
+        if (globals is None and locals is None and
+            isinstance(prog, tuple) and
+            (len(prog) == 2 or len(prog) == 3)):
+            globals = prog[1]
+            if len(prog) == 3:
+                locals = prog[2]
+            prog = prog[0]
+        if globals is None:
+            globals = f.w_globals    # XXX should be f.f_globals
+            if locals is None:
+                locals = f.w_locals  # XXX should be f.f_locals
+        if locals is None:
+            locals = globals
+        if not isinstance(globals, dict):
+            raise TypeError("exec: arg 2 must be a dictionary or None")
+        elif not globals.has_key('__builtins__'):
+            globals['__builtins__'] = f.w_builtins # XXX should be f.f_builtins
+        if not isinstance(locals, dict):
+            raise TypeError("exec: arg 3 must be a dictionary or None")
+        # XXX - HACK to check for code object
+        co = compile('1','<string>','eval')
+        if isinstance(prog, type(co)):
+            return (prog, globals, locals)
+        if not isinstance(prog, str):
+    ##     if not (isinstance(prog, types.StringTypes) or
+    ##             isinstance(prog, types.FileType)):
+            raise TypeError("exec: arg 1 must be a string, file, or code object")
+    ##     if isinstance(prog, types.FileType):
+    ##         flags = 0
+    ##         ## XXX add in parent flag merging
+    ##         co = compile(prog.read(),prog.name,'exec',flags,1)
+    ##         return (co,globals,locals)
+        else: # prog is a string
+            flags = 0
+            ## XXX add in parent flag merging
+            co = compile(prog,'<string>','exec',flags,1)
+            return (co, globals, locals)
 
     def POP_BLOCK(f):
         block = f.blockstack.pop()
@@ -373,27 +394,12 @@
         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)
+        w_metaclass = find_metaclass(f.space, w_bases,
+                                     w_methodsdict, f.w_globals)
+        w_newclass = f.space.call_function(w_metaclass, w_name,
+                                           w_bases, w_methodsdict)
         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)
@@ -474,9 +480,8 @@
         # 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)
+        #    w_value = f.load_name(w_varname)
+        #    f.valuestack.push(w_value)
 
     def LOAD_GLOBAL(f, nameindex):
         assert f.w_globals is not None
@@ -576,23 +581,31 @@
         f.valuestack.push(w_result)
 
     def IMPORT_NAME(f, nameindex):
+        space = f.space
         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])
+        try:
+            w_import = space.getitem(f.w_builtins, space.wrap("__import__"))
+        except OperationError, e:
+            if not e.match(space, space.w_KeyError):
+                raise
+            raise OperationError(space.w_ImportError,
+                                 space.wrap("__import__ not found"))
+        w_obj = space.call_function(w_import, space.wrap(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])
+        w_locals = f.getfastscope()
+        import_all_from(f.space, w_module, w_locals)
+        f.setfastscope(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])
+        w_obj = import_from(f.space, w_module, w_name)
         f.valuestack.push(w_obj)
 
     def JUMP_FORWARD(f, stepby):
@@ -660,14 +673,27 @@
         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])
+            w_arguments = f.update_star_args(w_arguments, w_varargs)
         if with_varkw:
-            w_keywords  = f.space.gethelper(appfile).call("concatenate_keywords",
-                                                          [w_keywords,  w_varkw])
+            w_keywords  = f.update_keyword_args(w_keywords, w_varkw)
         w_result = f.space.call(w_function, w_arguments, w_keywords)
         f.valuestack.push(w_result)
 
+    def app_update_star_args(f, args, extra_args):
+        return args + tuple(extra_args)
+
+    def app_update_keyword_args(f, kw, extra_kw):
+        if not isinstance(extra_kw, dict):
+            raise TypeError, "argument after ** must be a dictionary"
+        result = kw.copy()
+        for key, value in extra_kw.items():
+            if key in result:
+                # XXX should mention the function name in error message
+                raise TypeError, ("got multiple values "
+                                  "for keyword argument '%s'" % key)
+            result[key] = value
+        return result
+
     def CALL_FUNCTION(f, oparg):
         f.call_function_extra(oparg, False, False)
 
@@ -715,24 +741,154 @@
     def MISSING_OPCODE(f, oparg=None):
         raise pyframe.BytecodeCorruption, "unknown opcode"
 
-    ################################################################
+    ### dispatch_table ###
 
     # 'dispatch_table' is a class attribute: a list of functions
     # it is created by 'cls.setup_dispatch_table()'.
 
-    def setup_dispatch_table(cls):
+    __metaclass__ = InitializedClass
+    def __initclass__(cls):
         # create the 'cls.dispatch_table' attribute
+        import dis
         dispatch_table = []
         missing_opcode = cls.MISSING_OPCODE
         for i in range(256):
             opname = dis.opname[i].replace('+', '_')
             fn = getattr(cls, opname, missing_opcode)
+            fn = getattr(fn, 'im_func',fn)
+            fn.has_arg = i >= dis.HAVE_ARGUMENT
             #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)
 
 
-PyInterpFrame.setup_dispatch_table()
+    appdict.importall(locals())
+
+
+### helpers written at the application-level ###
+# Some of these functions are expected to be generally useful if other
+# parts of the code needs to do the same thing as a non-trivial opcode,
+# like finding out which metaclass a new class should have.
+# This is why they are not methods of PyInterpFrame.
+# There are also a couple of helpers that are methods, defined in the
+# class above.
+
+def app_print_expr(x):
+    import sys
+    try:
+        displayhook = sys.displayhook
+    except AttributeError:
+        raise RuntimeError("lost sys.displayhook")
+    displayhook(x)
+
+def app_file_softspace(file, newflag):
+    try:
+        softspace = file.softspace
+    except AttributeError:
+        softspace = 0
+    try:
+        file.softspace = newflag
+    except AttributeError:
+        pass
+    return softspace
+
+def app_sys_stdout():
+    import sys
+    try:
+        return sys.stdout
+    except AttributeError:
+        raise RuntimeError("lost sys.stdout")
+
+def app_print_item_to(x, stream):
+    if file_softspace(stream, False):
+        stream.write(" ")
+    stream.write(str(x))
+    # add a softspace unless we just printed a string which ends in a '\t'
+    # or '\n' -- or more generally any whitespace character but ' '
+    #    if isinstance(x, str) and len(x) and x[-1].isspace() and x[-1]!=' ':
+    #        return
+    # XXX add unicode handling
+    file_softspace(stream, True)
+
+def app_print_newline_to(stream):
+    stream.write("\n")
+    file_softspace(stream, False)
+
+def app_prepare_raise(etype, value, traceback):
+    # careful if 'import types' is added here!
+    # we get an infinite loop if this import fails:
+    #    import types -> IMPORT_NAME -> import_name -> raise ImportError
+    #    -> RAISE_VARARGS -> prepare_raise -> import types ...
+    if etype is None:
+        # reraise
+        # XXX this means that "raise" is equivalent to "raise None"
+        #     which is not the case in CPython, but well
+        import sys
+        etype, value, traceback = sys.exc_info()
+    #if not isinstance(traceback, (types.NoneType, types.TracebackType)):
+    #    raise TypeError, "raise: arg 3 must be traceback or None"
+    while isinstance(etype, tuple):
+        etype = etype[0]
+    if type(etype) is str:
+        # XXX warn
+        pass
+    elif isinstance(etype, Exception):
+        if value is not None:
+            raise TypeError("instance exception may not have a separate value")
+        value = etype
+        etype = value.__class__
+    elif isinstance(etype, type) and issubclass(etype, Exception):
+        if value is None:
+            value = ()
+        elif not isinstance(value, tuple):
+            value = (value,)
+        value = etype(*value)
+    else:
+        raise TypeError("exceptions must be instances or subclasses of "
+                        "Exception or strings (deprecated), not %s" %
+                        (type(etype).__name__,))
+    return etype, value, traceback
+
+def app_find_metaclass(bases, namespace, globals):
+    if '__metaclass__' in namespace:
+        return namespace['__metaclass__']
+    elif len(bases) > 0:
+        base = bases[0]
+        if hasattr(base, '__class__'):
+            return base.__class__
+        else:
+            return type(base)
+    elif '__metaclass__' in globals:
+        return globals['__metaclass__']
+    else:
+        return type
+
+def app_import_all_from(module, into_locals):
+    try:
+        all = module.__all__
+    except AttributeError:
+        try:
+            dict = module.__dict__
+        except AttributeError:
+            raise ImportError("from-import-* object has no __dict__ "
+                              "and no __all__")
+        all = dict.keys()
+        skip_leading_underscores = True
+    else:
+        skip_leading_underscores = False
+    for name in all:
+        if skip_leading_underscores and name[0]=='_':
+            continue
+        into_locals[name] = getattr(module, name)
+
+def app_import_from(module, name):
+    try:
+        return getattr(module, name)
+    except AttributeError:
+        raise ImportError("cannot import name '%s'" % name)
+
+
+appdict = DictProxy()
+appdict.importall(globals())   # app_xxx() -> xxx()

Deleted: /pypy/branch/builtinrefactor/pypy/interpreter/threadlocals.py
==============================================================================
--- /pypy/branch/builtinrefactor/pypy/interpreter/threadlocals.py	Mon Sep  8 20:53:13 2003
+++ (empty file)
@@ -1,13 +0,0 @@
-# Thread-local storage.
-
-# XXX no thread support yet, so this is easy :-)
-
-class ThreadLocals:
-    pass
-
-locals = ThreadLocals()
-locals.executioncontext = None
-
-
-def getlocals():
-    return locals

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	Mon Sep  8 20:53:13 2003
@@ -2,28 +2,28 @@
 
 import sys, os
 import unittest
-#from pypy.interpreter.gateway import InterpretedMethod, InterpretedFunction
-#   FIX ME FIX ME FIX ME
+from pypy.interpreter.gateway import DictProxy
 
 def make_testcase_class(space, tc_w):
     # XXX this is all a bit insane (but it works)
-    
-    #from pypy.interpreter.extmodule import make_builtin_func
-    w = space.wrap
-    d = space.newdict([])
-    space.setitem(d, w('failureException'), space.w_AssertionError)
 
+    # space-independent part: collect the test methods into
+    # a DictProxy.
+    d = DictProxy(implicitspace=True)
     for name in dir(AppTestCase):
         if ( name.startswith('assert') or name.startswith('fail')
              and name != 'failureException'):
-            func = InterpretedMethod(space, getattr(tc_w, name).im_func)
-            w_func = space.wrap(func)
-            #w_func = wrap_func(space, getattr(tc_w, name).im_func)
-            space.setitem(d, w(name), w_func)
+            d.app2interp(getattr(tc_w, name).im_func, name)
+
+    # space-dependent part: make an object-space-level dictionary
+    # and use it to build the class.
+    w = space.wrap
+    w_dict = d.makedict(space)
+    space.setitem(w_dict, w('failureException'), space.w_AssertionError)
     w_tc = space.call_function(space.w_type,
                                w('TestCase'),
                                space.newtuple([]),
-                               d)
+                               w_dict)
     return space.call_function(w_tc)
 
 
@@ -34,9 +34,7 @@
         self.testMethod = testMethod
 
     def __call__(self):
-        from pypy.interpreter import executioncontext
         space = self.testCase.space
-        w = space.wrap
 
         w_tc_attr = 'tc-attr-hacky-thing'
         if hasattr(space, w_tc_attr):
@@ -45,7 +43,9 @@
             w_tc = make_testcase_class(space, self.testCase)
             setattr(space, w_tc_attr, w_tc)
 
-        w_f = space.wrap(InterpretedFunction(space, self.testMethod.im_func))
+        f = self.testMethod.im_func
+        gateway = DictProxy(implicitspace=True).app2interp(f, f.func_name)
+        w_f = space.wrap(gateway)
         # w_f = wrap_func(space, self.testMethod.im_func)
         space.call_function(w_f, w_tc)
 

Modified: pypy/branch/builtinrefactor/pypy/module/builtin.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/module/builtin.py	(original)
+++ pypy/branch/builtinrefactor/pypy/module/builtin.py	Mon Sep  8 20:53:13 2003
@@ -1,5 +1,6 @@
 from pypy.interpreter import executioncontext
-from pypy.interpreter.gateway import AppVisibleModule, ScopedCode
+from pypy.interpreter.extmodule import ExtModule
+from pypy.interpreter.error import OperationError
 
 #######################
 ####  __builtin__  ####
@@ -7,7 +8,11 @@
 
 import __builtin__ as cpy_builtin
 
-class __builtin__(AppVisibleModule):
+class __builtin__(ExtModule):
+    """ Template for PyPy's '__builtin__' module.
+    """
+    
+    app___name__ = '__builtin__'
 
     def _actframe(self, index=-1):
         return self.space.getexecutioncontext().framestack.items[index]
@@ -24,7 +29,7 @@
         try:
             w_mod = space.getitem(space.sys.w_modules, w_modulename)
             return w_mod
-        except executioncontext.OperationError,e:
+        except OperationError,e:
             if not e.match(space, space.w_KeyError):
                 raise
             w_mod = space.get_builtin_module(w_modulename)
@@ -53,7 +58,7 @@
                     return w_mod
             
             w_exc = space.call_function(space.w_ImportError, w_modulename)
-            raise executioncontext.OperationError(
+            raise OperationError(
                       space.w_ImportError, w_exc)
 
     def compile(self, w_str, w_filename, w_startstr,
@@ -77,7 +82,8 @@
 
         #print (str, filename, startstr, supplied_flags, dont_inherit)
         c = cpy_builtin.compile(str, filename, startstr, supplied_flags, dont_inherit)
-        return space.wrap(c)
+        from pypy.interpreter.pycode import PyCode
+        return space.wrap(PyCode()._from_code(c))
 
     def execfile(self, w_filename, w_globals=None, w_locals=None):
         space = self.space
@@ -361,7 +367,7 @@
         else:
             return 1
 
-    def app__vars(*obj):
+    def app_vars(*obj):
         """return a dictionary of all the attributes currently bound in obj.  If
         called with no argument, return the variables bound in local scope."""
 

Modified: pypy/branch/builtinrefactor/pypy/module/sysmodule.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/module/sysmodule.py	(original)
+++ pypy/branch/builtinrefactor/pypy/module/sysmodule.py	Mon Sep  8 20:53:13 2003
@@ -1,28 +1,32 @@
-from pypy.interpreter.baseobjspace import OperationError
-from pypy.interpreter.gateway import AppVisibleModule
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.extmodule import ExtModule
 import os, pypy
 
 import sys as cpy_sys
 
-class sys(AppVisibleModule):
-    """ PyPy's 'sys' module.
+class Sys(ExtModule):
+    """ Template for PyPy's 'sys' module.
 
     Currently we only provide 'path', 'modules', 'stdout' and 'displayhook'
     """
 
+    app___name__ = 'sys'
+
     def __init__(self, space):
         opd = os.path.dirname
         pypydir = opd(opd(os.path.abspath(pypy.__file__)))
         appdir = os.path.join(pypydir, 'pypy', 'appspace')
         self.path = [appdir] + [p for p in cpy_sys.path if p!= pypydir]
         self.w_modules = space.newdict([])
-        AppVisibleModule.__init__(self, space)
-   
-    stdout = cpy_sys.stdout 
+        ExtModule.__init__(self, space)
+
+    stdout = cpy_sys.stdout
+    stderr = cpy_sys.stderr
 
-    def _setmodule(self, module):
+    def _setmodule(self, w_module):
         """ put a module into the modules list """
-        self.space.setitem(self.w_modules, module.w___name__, module._wrapped)
+        w_name = self.space.getattr(w_module, self.space.wrap('__name__'))
+        self.space.setitem(self.w_modules, w_name, w_module)
 
     def displayhook(self, w_x):
         space = self.space

Modified: pypy/branch/builtinrefactor/pypy/objspace/trivial.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/objspace/trivial.py	(original)
+++ pypy/branch/builtinrefactor/pypy/objspace/trivial.py	Mon Sep  8 20:53:13 2003
@@ -4,62 +4,62 @@
 # correctly wrap the exceptions.
 #
 
-from pypy.interpreter import pyframe
+from pypy.interpreter import pyframe, gateway
 from pypy.interpreter.baseobjspace import *
-import operator, types, new, sys
+import operator, types, new, sys, __builtin__
 
-class nugen(object):
-    def __init__(self, frame):
-        self.space = frame.space
-        self.frame = frame
-        self.running = 0
-
-    def next(self):
-        if self.running:
-            raise OperationError(self.space.w_ValueError,
-                                 "generator already executing")
-        ec = self.space.getexecutioncontext()
+##class nugen(object):
+##    def __init__(self, frame):
+##        self.space = frame.space
+##        self.frame = frame
+##        self.running = 0
+
+##    def next(self):
+##        if self.running:
+##            raise OperationError(self.space.w_ValueError,
+##                                 "generator already executing")
+##        ec = self.space.getexecutioncontext()
+
+##        self.running = 1
+##        try:
+##            try:
+##                ret = ec.eval_frame(self.frame)
+##            except NoValue:
+##                raise StopIteration
+##        finally:
+##            self.running = 0
+
+##        return ret
+
+##    def __iter__(self):
+##        return self
+
+##from pypy.interpreter.gateway import InterpretedFunction, InterpretedFunctionFromCode
+
+##class numeth(InterpretedFunction):
+##    def __init__(self, ifunc, instance, cls):
+##        self.ifunc = ifunc
+##        self.instance = instance
+##        self.cls = cls
+
+##    def __call__(self, *args, **kws):
+##        if self.instance is None and self.cls is not type(None):
+##            pass
+##        else:
+##            args = (self.instance,) + args
+##        return self.ifunc(*args, **kws)
+
+##class nufun(InterpretedFunctionFromCode):
+
+##    def __call__(self, *args, **kwargs):
+##        if self.cpycode.co_flags & 0x0020:
+##            frame = self.create_frame(args, kwargs)
+##            return nugen(frame)
+##        else:
+##            return self.eval_frame(args, kwargs)
 
-        self.running = 1
-        try:
-            try:
-                ret = ec.eval_frame(self.frame)
-            except NoValue:
-                raise StopIteration
-        finally:
-            self.running = 0
-
-        return ret
-
-    def __iter__(self):
-        return self
-
-from pypy.interpreter.gateway import InterpretedFunction, InterpretedFunctionFromCode
-
-class numeth(InterpretedFunction):
-    def __init__(self, ifunc, instance, cls):
-        self.ifunc = ifunc
-        self.instance = instance
-        self.cls = cls
-
-    def __call__(self, *args, **kws):
-        if self.instance is None and self.cls is not type(None):
-            pass
-        else:
-            args = (self.instance,) + args
-        return self.ifunc(*args, **kws)
-
-class nufun(InterpretedFunctionFromCode):
-
-    def __call__(self, *args, **kwargs):
-        if self.cpycode.co_flags & 0x0020:
-            frame = self.create_frame(args, kwargs)
-            return nugen(frame)
-        else:
-            return self.eval_frame(args, kwargs)
-
-    def __get__(self, ob, cls=None):
-        return numeth(self, ob, cls)
+##    def __get__(self, ob, cls=None):
+##        return numeth(self, ob, cls)
 
 
 class TrivialObjSpace(ObjSpace):
@@ -120,7 +120,6 @@
         self.w_False = False
         self.w_NotImplemented = NotImplemented
         self.w_Ellipsis = Ellipsis
-        import __builtin__, types
         newstuff = {"False": self.w_False,
                     "True" : self.w_True,
                     "NotImplemented" : self.w_NotImplemented,
@@ -144,7 +143,10 @@
 
     # general stuff
     def wrap(self, x):
-        return x
+        if hasattr(x, '__wrap__'):
+            return x.__wrap__(self)
+        else:
+            return x
 
     def unwrap(self, w):
         return w
@@ -171,88 +173,79 @@
             nv = evalue
         raise OperationError(nt, nv)
 
+    def _auto(name, sourcefn, classlocals):
+        s = """
+def %(name)s(self, *args):
+    try:
+        value = %(sourcefn)s(*args)
+    except:
+        self.reraise()
+    return self.wrap(value)
+""" % locals()
+        exec s in globals(), classlocals
+
     # from the built-ins
-    id        = id
-    type      = type
-    issubtype = issubclass
-    newtuple  = tuple
-    newlist   = list
-    newdict   = dict
-    newslice  = slice  # maybe moved away to application-space at some time
-    newmodule = new.module
-    iter      = iter
-    repr      = repr
-    str       = str
-    len       = len
-    pow       = pow
-    divmod    = divmod
-    hash      = hash
-    setattr   = setattr
-    delattr   = delattr
+    _auto('issubtype', 'issubclass', locals())
+    _auto('newmodule', 'new.module', locals())
+    _auto('newtuple',  'tuple',      locals())
+    _auto('newlist',   'list',       locals())
+    _auto('newdict',   'dict',       locals())
+    _auto('newslice',  'slice',      locals())
     is_true   = operator.truth
     # 'is_true' is not called 'truth' because it returns a *non-wrapped* boolean
 
-    def getattr(self, w_obj, w_name):
-        obj = self.unwrap(w_obj)
-        name = self.unwrap(w_name)
-        try:
-            return getattr(obj, name)
-        except:
-            self.reraise()
+    for _name in ('id', 'type', 'iter', 'repr', 'str', 'len',
+                  'pow', 'divmod', 'hash', 'setattr', 'delattr', 'hex',
+                  'oct', 'ord', 'getattr'):
+        _auto(_name, _name, locals())
 
     for _name in ('pos', 'neg', 'not_', 'abs', 'invert',
                   'mul', 'truediv', 'floordiv', 'div', 'mod',
                   'add', 'sub', 'lshift', 'rshift', 'and_', 'xor', 'or_',
                   'lt', 'le', 'eq', 'ne', 'gt', 'ge', 'contains'):
-        exec """
-def %(_name)s(self, *args):
-    try:
-        return operator.%(_name)s(*args)
-    except:
-        self.reraise()
-""" % locals()
+        _auto(_name, 'operator.' + _name, locals())
 
     # in-place operators
     def inplace_pow(self, w1, w2):
         w1 **= w2
-        return w1
+        return self.wrap(w1)
     def inplace_mul(self, w1, w2):
         w1 *= w2
-        return w1
+        return self.wrap(w1)
     def inplace_truediv(self, w1, w2):
         w1 /= w2  # XXX depends on compiler flags
-        return w1
+        return self.wrap(w1)
     def inplace_floordiv(self, w1, w2):
         w1 //= w2
-        return w1
+        return self.wrap(w1)
     def inplace_div(self, w1, w2):
         w1 /= w2  # XXX depends on compiler flags
-        return w1
+        return self.wrap(w1)
     def inplace_mod(self, w1, w2):
         w1 %= w2
-        return w1
+        return self.wrap(w1)
 
     def inplace_add(self, w1, w2):
         w1 += w2
-        return w1
+        return self.wrap(w1)
     def inplace_sub(self, w1, w2):
         w1 -= w2
-        return w1
+        return self.wrap(w1)
     def inplace_lshift(self, w1, w2):
         w1 <<= w2
-        return w1
+        return self.wrap(w1)
     def inplace_rshift(self, w1, w2):
         w1 >>= w2
-        return w1
+        return self.wrap(w1)
     def inplace_and(self, w1, w2):
         w1 &= w2
-        return w1
+        return self.wrap(w1)
     def inplace_or(self, w1, w2):
         w1 |= w2
-        return w1
+        return self.wrap(w1)
     def inplace_xor(self, w1, w2):
         w1 ^= w2
-        return w1
+        return self.wrap(w1)
 
 
     # slicing
@@ -274,9 +267,9 @@
         sindex = self.old_slice(index)
         try:
             if sindex is None:
-                return obj[index]
+                return self.wrap(obj[index])
             else:
-                return operator.getslice(obj, sindex[0], sindex[1])
+                return self.wrap(operator.getslice(obj, sindex[0], sindex[1]))
         except:
             self.reraise()
 
@@ -289,7 +282,7 @@
             if sindex is None:
                 obj[index] = value
             else:
-                return operator.setslice(obj, sindex[0], sindex[1], value)
+                operator.setslice(obj, sindex[0], sindex[1], value)
         except:
             self.reraise()
 
@@ -308,7 +301,7 @@
     # misc
     def next(self, w):
         try:
-            return w.next()
+            return self.wrap(w.next())
         except StopIteration:
             raise NoValue
 
@@ -319,7 +312,12 @@
         #assert hasattr(code, 'co_name')
         #assert hasattr(code, 'build_arguments')
         #assert hasattr(code, 'eval_code')
-        return nufun(self, code, defs, globals, closure)
+
+        # XXX the newxxx() interface should disappear at some point
+        # XXX because the interpreter can perfectly do the following
+        # XXX itself without bothering the object space
+        from pypy.interpreter.function import Function
+        return self.wrap(Function(self, code, globals, defs, closure))
 
     def newstring(self, asciilist):
         try:
@@ -336,13 +334,16 @@
                 self.reraise()
             if hasattr(r, '__init__'):
                 self.call(r.__init__, args, kwds)
-            return r
-        if (isinstance(callable, types.MethodType)
-            and callable.im_self is not None):
-            args = (callable.im_self,) + args
-            callable = callable.im_func
+            return self.wrap(r)
+        #if (isinstance(callable, types.MethodType)
+        #    and callable.im_self is not None):
+        #    args = (callable.im_self,) + args
+        #    callable = callable.im_func
+        assert not isinstance(callable, gateway.Gateway), (
+            "trivial object space is detecting an object that has not "
+            "been wrapped")
         try:
-            return callable(*args, **(kwds or {}))
+            return self.wrap(callable(*args, **(kwds or {})))
         except OperationError:
             raise
         except:
@@ -351,32 +352,14 @@
             #print "kwds", kwds
             self.reraise()
                 
-    def hex(self, ob):
-        try:
-            return hex(ob)
-        except:
-            self.reraise()
-
-    def oct(self, ob):
-        try:
-            return oct(ob)
-        except:
-            self.reraise()
-
-    def ord(self, ob):
-        try:
-            return ord(ob)
-        except:
-            self.reraise()
-
     def get(self, descr, ob, cls):
         try:
-            return descr.__get__(ob, cls)
+            return self.wrap(descr.__get__(ob, cls))
         except:
             self.reraise()
 
     def new(self, type, args, kw):
-        return type(args, kw)
+        return self.wrap(type(args, kw))
 
     def init(self, type, args, kw):
         pass


More information about the Pypy-commit mailing list