[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