[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