[pypy-svn] r46018 - in pypy/branch/pypy-more-rtti-inprogress: rpython/module rpython/ootypesystem/module translator/cli/test
arigo at codespeak.net
arigo at codespeak.net
Mon Aug 27 13:46:53 CEST 2007
Author: arigo
Date: Mon Aug 27 13:46:51 2007
New Revision: 46018
Added:
pypy/branch/pypy-more-rtti-inprogress/rpython/module/r_os_stat.py (contents, props changed)
Modified:
pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py
pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py
pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py
Log:
Custom annotation and rtyping support for os.stat_result objects.
They are rtyped just like a tuple of the correct length supporting
only indexing and the st_xxx attributes. We need a custom StatResultRepr
because when rtyping for LL backends we have extra platform-dependent
items at the end of the tuple, but for OO backends we only want the
portable items. This allows the OO backends to assume a fixed shape for
the tuples returned by os.stat().
The gencli os.stat() tests pass.
Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_stat.py Mon Aug 27 13:46:51 2007
@@ -4,36 +4,27 @@
"""
import os, sys
from pypy.annotation import model as annmodel
+from pypy.annotation.pairtype import pairtype
from pypy.tool.sourcetools import func_with_new_name
-from pypy.rpython.controllerentry import Controller, SomeControlledInstance
+from pypy.rpython import extregistry
from pypy.rpython.extfunc import register_external
from pypy.rpython.lltypesystem import rffi, lltype
-if sys.platform.startswith('win'):
- # XXX on Windows, stat() is flawed; see CPython's posixmodule.c for
- # an implementation based on the Win32 API
- LongLongIfNotWindows = lltype.Signed
-else:
- LongLongIfNotWindows = lltype.SignedLongLong
+# XXX on Windows, stat() is flawed; see CPython's posixmodule.c for
+# an implementation based on the Win32 API
-# NOTE: float times are disabled for now, for compatibility with CPython
-if 0: #sys.platform.startswith('linux2'):
- # XXX assume the tv_nsec way of accessing the sub-second timestamps
- # XXX also assume, as in Linux, that it's in a 'struct timespec'
- TIMESPEC = rffi.CStructPtr('timespec',
- ('tv_sec', lltype.Signed),
- ('tv_nsec', lltype.Signed))
- ModTime = rffi.DOUBLE
-else:
- # XXX add support for more platforms
- TIMESPEC = None
- ModTime = lltype.Signed
+# NOTE: float times are disabled for now, for simplicity. They make the life
+# of OO backends more complicated because for them we try to not depend on
+# the details of the platform on which we do the translation. Also, they
+# seem not essential because they are disabled by default in CPython.
+TIMESPEC = None
+ModTime = lltype.Signed
# all possible fields - some of them are not available on all platforms
ALL_STAT_FIELDS = [
("st_mode", lltype.Signed),
("st_ino", lltype.SignedLongLong),
- ("st_dev", LongLongIfNotWindows),
+ ("st_dev", lltype.SignedLongLong),
("st_nlink", lltype.Signed),
("st_uid", lltype.Signed),
("st_gid", lltype.Signed),
@@ -61,6 +52,7 @@
def _expand(lst, originalname, timespecname):
if TIMESPEC is not None:
+ XXX # code not used right now
for i, (_name, _TYPE) in enumerate(lst):
if _name == originalname:
# replace the 'st_atime' field of type rffi.DOUBLE
@@ -75,40 +67,56 @@
del _expand, _name, _TYPE
+# For OO backends, expose only the portable fields (the first 10).
+PORTABLE_STAT_FIELDS = STAT_FIELDS[:N_INDEXABLE_FIELDS]
+
# ____________________________________________________________
#
# Annotation support
-class StatResultController(Controller):
- """Controls a stat_result object in RPython: internally it is just a
- tuple, but the Controller adds the support for the st_xxx attributes.
- """
+class SomeStatResult(annmodel.SomeObject):
knowntype = os.stat_result
- def getitem(self, obj, index):
- if 0 <= index < N_INDEXABLE_FIELDS:
- return obj[index]
- else:
- raise IndexError
- getitem._annspecialcase_ = 'specialize:arg(2)' # 'index' must be constant
-
- def install_getter(cls, name):
- # def get_st_mode(), def get_st_ino(), etc...
- index = STAT_FIELD_NAMES.index(name)
- def get_st_xxx(self, obj):
- return obj[index]
- method_name = 'get_%s' % (name,)
- setattr(cls, method_name, func_with_new_name(get_st_xxx, method_name))
- install_getter = classmethod(install_getter)
-
-for _name in STAT_FIELD_NAMES:
- StatResultController.install_getter(_name)
-
-stat_controller = StatResultController()
-s_tuple_StatResult = annmodel.SomeTuple([annmodel.lltype_to_annotation(_TYPE)
- for _name, _TYPE in STAT_FIELDS])
-s_StatResult = SomeControlledInstance(s_tuple_StatResult,
- controller = stat_controller)
+ def rtyper_makerepr(self, rtyper):
+ from pypy.rpython.module import r_os_stat
+ return r_os_stat.StatResultRepr(rtyper)
+
+ def rtyper_makekey_ex(self, rtyper):
+ return self.__class__,
+
+ def getattr(self, s_attr):
+ assert s_attr.is_constant(), "non-constant attr name in getattr()"
+ attrname = s_attr.const
+ TYPE = STAT_FIELD_TYPES[attrname]
+ return annmodel.lltype_to_annotation(TYPE)
+
+class __extend__(pairtype(SomeStatResult, annmodel.SomeInteger)):
+ def getitem((s_sta, s_int)):
+ assert s_int.is_constant(), "os.stat()[index]: index must be constant"
+ index = s_int.const
+ assert 0 <= index < N_INDEXABLE_FIELDS, "os.stat()[index] out of range"
+ name, TYPE = STAT_FIELDS[index]
+ return annmodel.lltype_to_annotation(TYPE)
+
+s_StatResult = SomeStatResult()
+
+def make_stat_result(tup):
+ """Turn a tuple into an os.stat_result object."""
+ positional = tup[:N_INDEXABLE_FIELDS]
+ kwds = {}
+ for i, name in enumerate(STAT_FIELD_NAMES[N_INDEXABLE_FIELDS:]):
+ kwds[name] = tup[N_INDEXABLE_FIELDS + i]
+ return os.stat_result(positional, kwds)
+
+class MakeStatResultEntry(extregistry.ExtRegistryEntry):
+ _about_ = make_stat_result
+
+ def compute_result_annotation(self, s_tup):
+ return s_StatResult
+
+ def specialize_call(self, hop):
+ from pypy.rpython.module import r_os_stat
+ return r_os_stat.specialize_make_stat_result(hop)
# ____________________________________________________________
#
@@ -124,6 +132,7 @@
def build_stat_result(st):
+ # only for LL backends
if TIMESPEC is not None:
atim = st.c_st_atim; atime = atim.c_tv_sec + 1E-9 * atim.c_tv_nsec
mtim = st.c_st_mtim; mtime = mtim.c_tv_sec + 1E-9 * mtim.c_tv_nsec
@@ -149,7 +158,7 @@
if "st_rdev" in STAT_FIELD_TYPES: result += (st.c_st_rdev,)
if "st_flags" in STAT_FIELD_TYPES: result += (st.c_st_flags,)
- return stat_controller.box(result)
+ return make_stat_result(result)
def register_stat_variant(name):
Added: pypy/branch/pypy-more-rtti-inprogress/rpython/module/r_os_stat.py
==============================================================================
--- (empty file)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/r_os_stat.py Mon Aug 27 13:46:51 2007
@@ -0,0 +1,68 @@
+"""
+RTyping support for os.stat_result objects.
+They are rtyped just like a tuple of the correct length supporting
+only indexing and the st_xxx attributes. We need a custom StatResultRepr
+because when rtyping for LL backends we have extra platform-dependent
+items at the end of the tuple, but for OO backends we only want the
+portable items. This allows the OO backends to assume a fixed shape for
+the tuples returned by os.stat().
+"""
+from pypy.annotation import model as annmodel
+from pypy.objspace.flow.model import Constant
+from pypy.tool.pairtype import pairtype
+from pypy.rpython.rmodel import Repr, IntegerRepr
+from pypy.rpython.error import TyperError
+from pypy.rpython.module import ll_os_stat
+
+
+class StatResultRepr(Repr):
+
+ def __init__(self, rtyper):
+ self.rtyper = rtyper
+ if rtyper.type_system.name == "lltypesystem":
+ self.stat_fields = ll_os_stat.STAT_FIELDS
+ else:
+ self.stat_fields = ll_os_stat.PORTABLE_STAT_FIELDS
+
+ self.stat_field_indexes = {}
+ for i, (name, TYPE) in enumerate(self.stat_fields):
+ self.stat_field_indexes[name] = i
+
+ self.s_tuple = annmodel.SomeTuple([annmodel.lltype_to_annotation(TYPE)
+ for name, TYPE in self.stat_fields])
+ self.r_tuple = rtyper.getrepr(self.s_tuple)
+ self.lowleveltype = self.r_tuple.lowleveltype
+
+ def redispatch_getfield(self, hop, index):
+ rtyper = self.rtyper
+ s_index = rtyper.annotator.bookkeeper.immutablevalue(index)
+ hop2 = hop.copy()
+ hop2.forced_opname = 'getitem'
+ hop2.args_v = [hop2.args_v[0], Constant(index)]
+ hop2.args_s = [self.s_tuple, s_index]
+ hop2.args_r = [self.r_tuple, rtyper.getrepr(s_index)]
+ return hop2.dispatch()
+
+ def rtype_getattr(self, hop):
+ s_attr = hop.args_s[1]
+ attr = s_attr.const
+ try:
+ index = self.stat_field_indexes[attr]
+ except KeyError:
+ raise TyperError("os.stat().%s: field not available" % (attr,))
+ return self.redispatch_getfield(hop, index)
+
+
+class __extend__(pairtype(StatResultRepr, IntegerRepr)):
+
+ def rtype_getitem((r_sta, r_int), hop):
+ s_int = hop.args_s[1]
+ index = s_int.const
+ return r_sta.redispatch_getfield(hop, index)
+
+
+def specialize_make_stat_result(hop):
+ r_StatResult = hop.rtyper.getrepr(ll_os_stat.s_StatResult)
+ [v_result] = hop.inputargs(r_StatResult.r_tuple)
+ # no-op conversion from r_StatResult.r_tuple to r_StatResult
+ return v_result
Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py Mon Aug 27 13:46:51 2007
@@ -8,4 +8,6 @@
fields = dict(zip(fieldnames, FIELDS))
return ootype.Record(fields)
-STAT_RESULT = _make_tuple([ootype.Signed]*10)
+from pypy.rpython.module.ll_os_stat import PORTABLE_STAT_FIELDS
+
+STAT_RESULT = _make_tuple([_TYPE for _name, _TYPE in PORTABLE_STAT_FIELDS])
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_builtin.py Mon Aug 27 13:46:51 2007
@@ -91,9 +91,14 @@
assert contents == long2str(MAGIC)
def test_os_stat(self):
- def fn():
- return os.stat('.')[0]
- mode = self.interpret(fn, [])
+ def fn(flag):
+ if flag:
+ return os.stat('.')[0]
+ else:
+ return os.stat('.').st_mode
+ mode = self.interpret(fn, [0])
+ assert stat.S_ISDIR(mode)
+ mode = self.interpret(fn, [1])
assert stat.S_ISDIR(mode)
def test_os_stat_oserror(self):
More information about the Pypy-commit
mailing list