[pypy-svn] r35256 - in pypy/dist/pypy: bin objspace/fake objspace/fake/test translator
antocuni at codespeak.net
antocuni at codespeak.net
Mon Dec 4 16:06:13 CET 2006
Author: antocuni
Date: Mon Dec 4 16:06:12 2006
New Revision: 35256
Added:
pypy/dist/pypy/bin/checkmodule.py (contents, props changed)
pypy/dist/pypy/objspace/fake/
pypy/dist/pypy/objspace/fake/__init__.py (contents, props changed)
pypy/dist/pypy/objspace/fake/checkmodule.py (contents, props changed)
pypy/dist/pypy/objspace/fake/objspace.py (contents, props changed)
pypy/dist/pypy/objspace/fake/test/
pypy/dist/pypy/objspace/fake/test/__init__.py (contents, props changed)
pypy/dist/pypy/objspace/fake/test/test_checkmodule.py (contents, props changed)
Modified:
pypy/dist/pypy/translator/driver.py
Log:
First version of the Fake object space and the checkmodule.py tool,
which is useful for checking whether a module compiles without the
need of a full translation.
checkmodule is far from being complete: so far the only module known
to pass is _dotnet.
Added: pypy/dist/pypy/bin/checkmodule.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/bin/checkmodule.py Mon Dec 4 16:06:12 2006
@@ -0,0 +1,38 @@
+#! /usr/bin/env python
+"""
+Usage: checkmodule.py [-b backend] <module-name>
+
+Compiles the PyPy extension module from pypy/module/<module-name>/
+into a fake program which does nothing. Useful for testing whether a
+modules compiles without doing a full translation, especially the ones
+that cannot be compiled with compilemodule.py because rely on
+ootypesystem features (such as _dotnet). Default backend is cli.
+
+WARNING: this is still incomplete: there are chances that the
+compilation fails with strange errors not due to the module. If a
+module is known to compile during a translation but don't pass
+checkmodule.py, please report the bug (or, better, correct it :-).
+"""
+import autopath
+import sys
+
+from pypy.objspace.fake.checkmodule import checkmodule
+
+def main(argv):
+ try:
+ assert len(argv) in (2, 4)
+ if len(argv) == 2:
+ backend = 'cli'
+ modname = argv[1]
+ else:
+ _, b, backend, modname = argv
+ assert b == '-b'
+ except AssertionError:
+ print >> sys.stderr, __doc__
+ sys.exit(2)
+ else:
+ checkmodule(modname, backend, interactive=True)
+ print 'Module compiled succesfully'
+
+if __name__ == '__main__':
+ main(sys.argv)
Added: pypy/dist/pypy/objspace/fake/__init__.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/fake/__init__.py Mon Dec 4 16:06:12 2006
@@ -0,0 +1,2 @@
+from objspace import FakeObjSpace
+Space = FakeObjSpace
Added: pypy/dist/pypy/objspace/fake/checkmodule.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/fake/checkmodule.py Mon Dec 4 16:06:12 2006
@@ -0,0 +1,102 @@
+from copy import copy
+from pypy.tool.error import debug
+from pypy.interpreter.argument import AbstractArguments
+from pypy.interpreter.gateway import interp2app
+from pypy.rlib.nonconst import NonConstant
+
+def my_import(name):
+ mod = __import__(name)
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
+
+def find_gateways(modname, basepath, module):
+ res = []
+ for name in module.interpleveldefs.values():
+ submod_name, obj_name = name.split('.')
+ submod_name = '%s.%s.%s' % (basepath, modname, submod_name)
+ submod = my_import(submod_name)
+ obj = getattr(submod, obj_name)
+ res += find_gw_in_obj(obj)
+ return res
+
+def find_gw_in_obj(obj):
+ if hasattr(obj, 'typedef'):
+ typedef = obj.typedef
+ return typedef.rawdict.values() # XXX: check they are interp2app
+ elif hasattr(obj, 'func_code'):
+ return [interp2app(obj)]
+ else:
+ assert False
+
+## Since the fake objspace is more a hack than a real object space, it
+## happens that the annotator complains about operations that cannot
+## succeed because it knows too much about the objects involved. For
+## example, if it knows that a list is always empty, it will block
+## each operations that tries to access that list. This is not what we
+## want, because we know that with real objectspaces that operations
+## will succeed.
+
+## As a workaround, we insert dummy rpython code (the function
+## dummy_rpython) that manipulates the variables in order to give
+## them a more sensible annotation. This is the preferred way to solve
+## the problems so far.
+
+## If the solution above doesn't work, the alternative is to
+## substitute the interpreter code with something that doesn't hurt
+## the annotator. It's a very ugly hack, better solutions are welcome
+## :-)
+
+
+# dummy rpython code to give some variables more sensible annotations
+def dummy_rpython(dummy_function):
+ # to make the annotator flow-in without executing the code
+ if NonConstant(False):
+ dummy_function.defs_w = [None] # else the annotator would see an always empty list
+
+def patch_pypy():
+ from pypy.interpreter.baseobjspace import W_Root
+
+ def descr_call_mismatch(self, space, opname, RequiredClass, args):
+ from pypy.interpreter.error import OperationError
+ msg = 'This message will never be displayed :-)'
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ W_Root.descr_call_mismatch = descr_call_mismatch
+
+
+def checkmodule(modname, backend, interactive=False, basepath='pypy.module'):
+ "Compile a fake PyPy module."
+ from pypy.objspace.fake.objspace import FakeObjSpace, W_Object
+ from pypy.translator.driver import TranslationDriver
+
+ space = FakeObjSpace()
+ space.config.translating = True
+ ModuleClass = __import__(basepath + '.%s' % modname,
+ None, None, ['Module']).Module
+ module = ModuleClass(space, space.wrap(modname))
+ w_moduledict = module.getdict()
+
+ gateways = find_gateways(modname, basepath, module)
+ functions = [gw.__spacebind__(space) for gw in gateways]
+ arguments = AbstractArguments.frompacked(space, W_Object(None), W_Object(None))
+ dummy_function = copy(functions[0])
+
+ def main(argv): # use the standalone mode not to allow SomeObject
+ dummy_rpython(dummy_function)
+ for func in functions:
+ func.call_args(arguments)
+ return 0
+
+ patch_pypy()
+ driver = TranslationDriver()
+ driver.setup(main, None)
+ try:
+ driver.proceed(['compile_' + backend])
+ except SystemExit:
+ raise
+ except:
+ if not interactive:
+ raise
+ debug(driver)
+ raise SystemExit(1)
Added: pypy/dist/pypy/objspace/fake/objspace.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/fake/objspace.py Mon Dec 4 16:06:12 2006
@@ -0,0 +1,144 @@
+from pypy.interpreter.baseobjspace import ObjSpace, Wrappable, W_Root
+from pypy.rlib.nonconst import NonConstant
+from pypy.rlib.rarithmetic import r_uint
+
+class W_Type(W_Root):
+ pass
+
+class W_Object(W_Root):
+ def __init__(self, value):
+ self.value = value
+W_Object.typedef = W_Type()
+
+def make_dummy(a=W_Object(None), b=W_Object(None)):
+ def fn(*args):
+ if NonConstant(True):
+ return a
+ else:
+ return b
+ return fn
+
+int_dummy = make_dummy(42, 43)
+float_dummy = make_dummy(42.0, 42.1)
+uint_dummy = make_dummy(r_uint(42), r_uint(43))
+str_dummy = make_dummy('foo', 'bar')
+bool_dummy = make_dummy(True, False)
+
+class FakeObjSpace(ObjSpace):
+ w_None = W_Object(None)
+ w_False = W_Object(None)
+ w_True = W_Object(None)
+ w_Ellipsis = W_Object(None)
+ w_NotImplemented = W_Object(None)
+ w_int = W_Object(None)
+ w_dict = W_Object(None)
+ w_float = W_Object(None)
+ w_long = W_Object(None)
+ w_tuple = W_Object(None)
+ w_str = W_Object(None)
+ w_unicode = W_Object(None)
+ w_type = W_Object(None)
+ w_instance = W_Object(None)
+ w_slice = W_Object(None)
+ w_hex = W_Object(None)
+ w_oct = W_Object(None)
+
+ def initialize(self):
+ self.config.objspace.geninterp = False
+ self.wrap_cache = {}
+ self.make_builtins()
+
+ def _freeze_(self):
+ return True
+
+ def wrap(self, x):
+ if isinstance(x, Wrappable):
+ w_result = x.__spacebind__(self)
+ return w_result
+ return W_Object(x)
+ wrap._annspecialcase_ = "specialize:argtype(1)"
+
+ def unwrap(self, w_obj):
+ assert isinstance(w_obj, W_Object)
+ return w_obj.value
+
+ lookup = make_dummy()
+ allocate_instance = make_dummy()
+ getattr = make_dummy()
+ setattr = make_dummy()
+ getitem = make_dummy()
+ setitem = make_dummy()
+ delitem = make_dummy()
+ int_w = int_dummy
+ uint_w = uint_dummy
+ float_w = float_dummy
+ iter = make_dummy()
+ type = make_dummy()
+ str = make_dummy()
+ repr = make_dummy()
+ id = make_dummy()
+ len = make_dummy()
+ str_w = str_dummy
+ call_args = make_dummy()
+ new_interned_str = make_dummy()
+ newstring = make_dummy()
+ newunicode = make_dummy()
+ newint = make_dummy()
+ newlong = make_dummy()
+ newfloat = make_dummy()
+ newdict = make_dummy()
+ newlist = make_dummy()
+ emptylist = make_dummy()
+ newtuple = make_dummy()
+ newslice = make_dummy()
+ lt = make_dummy()
+ le = make_dummy()
+ eq = make_dummy()
+ ne = make_dummy()
+ gt = make_dummy()
+ ge = make_dummy()
+ lt_w = bool_dummy
+ le_w = bool_dummy
+ eq_w = bool_dummy
+ ne_w = bool_dummy
+ gt_w = bool_dummy
+ ge_w = bool_dummy
+ is_w = bool_dummy
+ is_ = make_dummy()
+ next = make_dummy()
+ is_true = bool_dummy
+ nonzero = make_dummy()
+ issubtype = make_dummy()
+ ord = make_dummy()
+ hash = make_dummy()
+ delattr = make_dummy() # should return None?
+ contains = make_dummy()
+ hex = make_dummy()
+ oct = make_dummy()
+ pow = make_dummy()
+ inplace_pow = make_dummy()
+ cmp = make_dummy()
+
+ # XXsX missing operations
+ def coerce(self, *args): raise NotImplementedError("space.coerce()")
+ def get(self, *args): raise NotImplementedError("space.get()")
+ def set(self, *args): raise NotImplementedError("space.set()")
+ def delete(self, *args): raise NotImplementedError("space.delete()")
+ def userdel(self, *args): raise NotImplementedError("space.userdel()")
+ def marshal_w(self, *args):raise NotImplementedError("space.marshal_w()")
+ def log(self, *args): raise NotImplementedError("space.log()")
+
+ def exec_(self, statement, w_globals, w_locals, hidden_applevel=False):
+ "NOT_RPYTHON"
+ raise NotImplementedError("space.exec_")
+
+ gettypefor = make_dummy()
+ gettypeobject = make_dummy()
+ unpackiterable = make_dummy([W_Object(None)], [W_Object(None)])
+
+
+## Register all exceptions
+import exceptions
+for name in ObjSpace.ExceptionTable:
+ exc = getattr(exceptions, name)
+ setattr(FakeObjSpace, 'w_' + name, W_Object(None))
Added: pypy/dist/pypy/objspace/fake/test/__init__.py
==============================================================================
Added: pypy/dist/pypy/objspace/fake/test/test_checkmodule.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/fake/test/test_checkmodule.py Mon Dec 4 16:06:12 2006
@@ -0,0 +1,6 @@
+import py
+from pypy.objspace.fake.checkmodule import checkmodule
+
+def test_dotnet():
+ # the only module known to pass checkmodule is _dotnet so far
+ checkmodule('_dotnet', 'cli')
Modified: pypy/dist/pypy/translator/driver.py
==============================================================================
--- pypy/dist/pypy/translator/driver.py (original)
+++ pypy/dist/pypy/translator/driver.py Mon Dec 4 16:06:12 2006
@@ -7,6 +7,7 @@
from pypy.annotation.listdef import s_list_of_strings
from pypy.annotation import policy as annpolicy
from py.compat import optparse
+from pypy.tool.udir import udir
import py
from pypy.tool.ansi_print import ansi_log
@@ -563,7 +564,6 @@
def task_source_cli(self):
from pypy.translator.cli.gencli import GenCli
from pypy.translator.cli.entrypoint import get_entrypoint
- from pypy.tool.udir import udir
entry_point_graph = self.translator.graphs[0]
self.gen = GenCli(udir, self.translator, get_entrypoint(entry_point_graph),
@@ -579,7 +579,8 @@
filename = self.gen.build_exe()
self.c_entryp = CliFunctionWrapper(filename)
# restore original os values
- unpatch(*self.old_cli_defs)
+ if hasattr(self, 'old_cli_defs'):
+ unpatch(*self.old_cli_defs)
self.log.info("Compiled %s" % filename)
task_compile_cli = taskdef(task_compile_cli, ['source_cli'],
More information about the Pypy-commit
mailing list