[pypy-commit] pypy online-transforms: hg merge default
rlamy
noreply at buildbot.pypy.org
Sun Nov 2 23:41:06 CET 2014
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: online-transforms
Changeset: r74327:d935b9812077
Date: 2014-11-01 05:16 +0000
http://bitbucket.org/pypy/pypy/changeset/d935b9812077/
Log: hg merge default
diff too long, truncating to 2000 out of 4803 lines
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -255,10 +255,6 @@
BoolOption("optimized_list_getitem",
"special case the 'list[integer]' expressions",
default=False),
- BoolOption("builtinshortcut",
- "a shortcut for operations between built-in types. XXX: "
- "deprecated, not really a shortcut any more.",
- default=False),
BoolOption("getattributeshortcut",
"track types that override __getattribute__",
default=False,
@@ -270,9 +266,6 @@
# weakrefs needed, because of get_subclasses()
requires=[("translation.rweakref", True)]),
- ChoiceOption("multimethods", "the multimethod implementation to use",
- ["doubledispatch", "mrd"],
- default="mrd"),
BoolOption("withidentitydict",
"track types that override __hash__, __eq__ or __cmp__ and use a special dict strategy for those which do not",
default=False,
diff --git a/pypy/doc/config/objspace.std.builtinshortcut.txt b/pypy/doc/config/objspace.std.builtinshortcut.txt
deleted file mode 100644
--- a/pypy/doc/config/objspace.std.builtinshortcut.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-A shortcut speeding up primitive operations between built-in types.
-
-This is a space-time trade-off: at the moment, this option makes a
-translated pypy-c executable bigger by about 1.7 MB. (This can probably
-be improved with careful analysis.)
diff --git a/pypy/doc/config/objspace.std.multimethods.txt b/pypy/doc/config/objspace.std.multimethods.txt
deleted file mode 100644
--- a/pypy/doc/config/objspace.std.multimethods.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Choose the multimethod implementation.
-
-* ``doubledispatch`` turns
- a multimethod call into a sequence of normal method calls.
-
-* ``mrd`` uses a technique known as Multiple Row Displacement
- which precomputes a few compact tables of numbers and
- function pointers.
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -35,3 +35,7 @@
Split RPython documentation from PyPy documentation and clean up. There now is
a clearer separation between documentation for users, developers and people
interested in background information.
+
+.. branch: kill-multimethod
+
+Kill multimethod machinery, all multimethods were removed earlier.
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -208,23 +208,6 @@
from pypy.config.pypyoption import set_pypy_opt_level
set_pypy_opt_level(config, translateconfig.opt)
- # as of revision 27081, multimethod.py uses the InstallerVersion1 by default
- # because it is much faster both to initialize and run on top of CPython.
- # The InstallerVersion2 is optimized for making a translator-friendly
- # structure for low level backends. However, InstallerVersion1 is still
- # preferable for high level backends, so we patch here.
-
- from pypy.objspace.std import multimethod
- if config.objspace.std.multimethods == 'mrd':
- assert multimethod.InstallerVersion1.instance_counter == 0,\
- 'The wrong Installer version has already been instatiated'
- multimethod.Installer = multimethod.InstallerVersion2
- elif config.objspace.std.multimethods == 'doubledispatch':
- # don't rely on the default, set again here
- assert multimethod.InstallerVersion2.instance_counter == 0,\
- 'The wrong Installer version has already been instatiated'
- multimethod.Installer = multimethod.InstallerVersion1
-
def print_help(self, config):
self.opt_parser(config).print_help()
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -618,6 +618,7 @@
from pypy.interpreter.nestedscope import Cell
from pypy.interpreter.special import NotImplemented, Ellipsis
+
def descr_get_dict(space, w_obj):
w_dict = w_obj.getdict(space)
if w_dict is None:
@@ -638,6 +639,11 @@
return space.w_None
return lifeline.get_any_weakref(space)
+dict_descr = GetSetProperty(descr_get_dict, descr_set_dict, descr_del_dict,
+ doc="dictionary for instance variables (if defined)")
+dict_descr.name = '__dict__'
+
+
def generic_ne(space, w_obj1, w_obj2):
if space.eq_w(w_obj1, w_obj2):
return space.w_False
diff --git a/pypy/module/_file/test/test_file.py b/pypy/module/_file/test/test_file.py
--- a/pypy/module/_file/test/test_file.py
+++ b/pypy/module/_file/test/test_file.py
@@ -275,6 +275,24 @@
finally:
f.close()
+ def test_ignore_ioerror_in_readall_if_nonempty_result(self):
+ # this is the behavior of regular files in CPython 2.7, as
+ # well as of _io.FileIO at least in CPython 3.3. This is
+ # *not* the behavior of _io.FileIO in CPython 3.4 or 3.5;
+ # see CPython's issue #21090.
+ try:
+ from posix import openpty, fdopen, write, close
+ except ImportError:
+ skip('no openpty on this platform')
+ read_fd, write_fd = openpty()
+ write(write_fd, 'Abc\n')
+ close(write_fd)
+ f = fdopen(read_fd)
+ s = f.read()
+ assert s == 'Abc\r\n'
+ raises(IOError, f.read)
+ f.close()
+
class AppTestNonblocking(object):
def setup_class(cls):
diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -812,11 +812,6 @@
self._check_closed(space, "flush of closed file")
with self.lock:
self._flush_and_rewind_unlocked(space)
- if self.readable:
- # Rewind the raw stream so that its position corresponds to
- # the current logical position.
- self._raw_seek(space, -self._raw_offset(), 1)
- self._reader_reset_buf()
def _flush_and_rewind_unlocked(self, space):
self._writer_flush_unlocked(space)
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -24,8 +24,7 @@
try:
w_value = error.get_w_value(space)
w_errno = space.getattr(w_value, space.wrap("errno"))
- return space.is_true(
- space.eq(w_errno, space.wrap(EINTR)))
+ return space.eq_w(w_errno, space.wrap(EINTR))
except OperationError:
return False
diff --git a/pypy/module/_io/test/test_io.py b/pypy/module/_io/test/test_io.py
--- a/pypy/module/_io/test/test_io.py
+++ b/pypy/module/_io/test/test_io.py
@@ -352,3 +352,13 @@
assert mod == 'io'
else:
assert mod == '_io'
+
+ def test_issue1902(self):
+ import _io
+ with _io.open(self.tmpfile, 'w+b', 4096) as f:
+ f.write(b'\xff' * 13569)
+ f.flush()
+ f.seek(0, 0)
+ f.read(1)
+ f.seek(-1, 1)
+ f.write(b'')
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -1,5 +1,3 @@
-from __future__ import with_statement
-
from rpython.rlib import jit
from rpython.rlib.buffer import Buffer
from rpython.rlib.objectmodel import keepalive_until_here
@@ -15,9 +13,7 @@
interp2app, interpindirect2app, unwrap_spec)
from pypy.interpreter.typedef import (
GetSetProperty, TypeDef, make_weakref_descr)
-from pypy.interpreter.generator import GeneratorIterator
from pypy.module._file.interp_file import W_File
-from pypy.objspace.std.floatobject import W_FloatObject
@unwrap_spec(typecode=str)
@@ -654,7 +650,7 @@
try:
item = unwrap(w_item)
except OperationError, e:
- if isinstance(w_item, W_FloatObject):
+ if space.isinstance_w(w_item, space.w_float):
# Odd special case from cpython
raise
if mytype.method != '' and e.match(space, space.w_TypeError):
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -1035,8 +1035,3 @@
def test_fresh_array_buffer_str(self):
assert str(buffer(self.array('i'))) == ''
-
-
-class AppTestArrayBuiltinShortcut(AppTestArray):
- spaceconfig = AppTestArray.spaceconfig.copy()
- spaceconfig['objspace.std.builtinshortcut'] = True
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -303,11 +303,6 @@
@bootstrap_function
def init_typeobject(space):
- # Probably a hack
- space.model.typeorder[W_PyCTypeObject] = [(W_PyCTypeObject, None),
- (W_TypeObject, None),
- (W_Root, None)]
-
make_typedescr(space.w_type.instancetypedef,
basestruct=PyTypeObject,
alloc=type_alloc,
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -2,7 +2,6 @@
from pypy.interpreter import argument, gateway
from pypy.interpreter.baseobjspace import W_Root, ObjSpace, SpaceCache
from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.objspace.std.stdtypedef import StdTypeDef
from pypy.objspace.std.sliceobject import W_SliceObject
from rpython.rlib.buffer import StringBuffer
from rpython.rlib.objectmodel import instantiate, we_are_translated, specialize
@@ -112,6 +111,10 @@
# ____________________________________________________________
+BUILTIN_TYPES = ['int', 'str', 'float', 'long', 'tuple', 'list', 'dict',
+ 'unicode', 'complex', 'slice', 'bool', 'basestring', 'object',
+ 'bytearray', 'buffer']
+
class FakeObjSpace(ObjSpace):
def __init__(self, config=None):
self._seen_extras = []
@@ -342,9 +345,7 @@
def setup(space):
for name in (ObjSpace.ConstantTable +
ObjSpace.ExceptionTable +
- ['int', 'str', 'float', 'long', 'tuple', 'list',
- 'dict', 'unicode', 'complex', 'slice', 'bool',
- 'basestring', 'object', 'bytearray', 'buffer']):
+ BUILTIN_TYPES):
setattr(space, 'w_' + name, w_some_obj())
space.w_type = w_some_type()
#
@@ -375,7 +376,7 @@
@specialize.memo()
def see_typedef(space, typedef):
assert isinstance(typedef, TypeDef)
- if not isinstance(typedef, StdTypeDef):
+ if typedef.name not in BUILTIN_TYPES:
for name, value in typedef.rawdict.items():
space.wrap(value)
diff --git a/pypy/objspace/std/basestringtype.py b/pypy/objspace/std/basestringtype.py
--- a/pypy/objspace/std/basestringtype.py
+++ b/pypy/objspace/std/basestringtype.py
@@ -1,7 +1,7 @@
-from pypy.objspace.std.stdtypedef import StdTypeDef
+from pypy.interpreter.typedef import TypeDef
-basestring_typedef = StdTypeDef("basestring",
+basestring_typedef = TypeDef("basestring",
__doc__ = ("basestring cannot be instantiated; "
"it is the base for str and unicode.")
)
diff --git a/pypy/objspace/std/boolobject.py b/pypy/objspace/std/boolobject.py
--- a/pypy/objspace/std/boolobject.py
+++ b/pypy/objspace/std/boolobject.py
@@ -6,8 +6,8 @@
from rpython.tool.sourcetools import func_renamer, func_with_new_name
from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef
from pypy.objspace.std.intobject import W_AbstractIntObject, W_IntObject
-from pypy.objspace.std.stdtypedef import StdTypeDef
class W_BoolObject(W_IntObject):
@@ -80,7 +80,7 @@
W_BoolObject.w_True = W_BoolObject(True)
-W_BoolObject.typedef = StdTypeDef("bool", W_IntObject.typedef,
+W_BoolObject.typedef = TypeDef("bool", W_IntObject.typedef,
__doc__ = """bool(x) -> bool
Returns True when the argument x is true, False otherwise.
diff --git a/pypy/objspace/std/builtinshortcut.py b/pypy/objspace/std/builtinshortcut.py
deleted file mode 100644
--- a/pypy/objspace/std/builtinshortcut.py
+++ /dev/null
@@ -1,137 +0,0 @@
-from pypy.interpreter.baseobjspace import ObjSpace
-from pypy.interpreter.error import OperationError
-from pypy.objspace.descroperation import DescrOperation
-from pypy.objspace.std.multimethod import FailedToImplement
-from pypy.objspace.std.boolobject import W_BoolObject
-from rpython.tool.sourcetools import func_with_new_name
-
-# ____________________________________________________________
-#
-# The sole purpose of this file is performance.
-# It speeds up the dispatch of operations between
-# built-in objects.
-#
-
-# this is a selection... a few operations are missing because they are
-# thought to be very rare or most commonly used with non-builtin types
-METHODS_WITH_SHORTCUT = dict.fromkeys(
- ['add', 'sub', 'mul', 'truediv', 'floordiv', 'div',
- 'mod', 'lshift', 'rshift', 'and_', 'or_', 'xor', 'pow',
- 'lt', 'le', 'eq', 'ne', 'gt', 'ge', 'contains',
- # unary
- 'len', 'nonzero', 'repr', 'str', 'hash',
- 'neg', 'invert', 'index', 'iter', 'next', 'buffer',
- 'getitem', 'setitem', 'int',
- # in-place
- 'inplace_add', 'inplace_sub', 'inplace_mul', 'inplace_truediv',
- 'inplace_floordiv', 'inplace_div', 'inplace_mod', 'inplace_pow',
- 'inplace_lshift', 'inplace_rshift', 'inplace_and', 'inplace_or',
- 'inplace_xor',
- # other
- 'format',
- ])
-
-KNOWN_MISSING = ['getattr', # mostly non-builtins or optimized by CALL_METHOD
- 'setattr', 'delattr', 'userdel', # mostly for non-builtins
- 'get', 'set', 'delete', # uncommon (except on functions)
- 'getslice', 'setslice', 'delslice', # see below
- 'delitem', 'trunc', # rare stuff?
- 'abs', 'hex', 'oct', # rare stuff?
- 'pos', 'divmod', 'cmp', # rare stuff?
- 'float', 'long', 'coerce', # rare stuff?
- 'isinstance', 'issubtype',
- ]
-# We cannot support {get,set,del}slice right now because
-# DescrOperation.{get,set,del}slice do a bit more work than just call
-# the special methods: they call old_slice_range(). See e.g.
-# test_builtinshortcut.AppTestString.
-
-for _name, _, _, _specialmethods in ObjSpace.MethodTable:
- if _specialmethods:
- assert _name in METHODS_WITH_SHORTCUT or _name in KNOWN_MISSING, (
- "operation %r should be in METHODS_WITH_SHORTCUT or KNOWN_MISSING"
- % (_name,))
-
-
-def filter_out_conversions(typeorder):
- res = {}
- for cls, order in typeorder.iteritems():
- res[cls] = [(target_type, converter) for (target_type, converter) in
- order if converter is None]
- return res
-
-
-def install(space, mm, fallback_mm=None):
- """Install a function <name>() on the space instance which invokes
- a shortcut for built-in types. Returns the shortcutting multimethod
- object or None.
- """
- name = mm.name
- if name not in METHODS_WITH_SHORTCUT:
- return None
-
- # can be called multiple times without re-installing
- if name in space.__dict__:
- mm1, shortcut_method = space.__dict__[name].builtinshortcut
- assert mm1 is mm
- return shortcut_method
-
- #print 'installing shortcut for:', name
- assert hasattr(DescrOperation, name)
-
- base_method = getattr(space.__class__, name)
-
- # Basic idea: we first try to dispatch the operation using purely
- # the multimethod. If this is done naively, subclassing a built-in
- # type like 'int' and overriding a special method like '__add__'
- # doesn't work any more, because the multimethod will accept the int
- # subclass and compute the result in the built-in way. To avoid
- # this issue, we tweak the shortcut multimethods so that these ones
- # (and only these ones) never match the interp-level subclasses
- # built in pypy.interpreter.typedef.get_unique_interplevel_subclass.
- expanded_order = space.model.get_typeorder_with_empty_usersubcls()
- if fallback_mm:
- mm = mm.merge_with(fallback_mm)
- shortcut_method = mm.install_not_sliced(filter_out_conversions(expanded_order))
-
- def operate(*args_w):
- try:
- return shortcut_method(space, *args_w)
- except FailedToImplement:
- pass
- return base_method(space, *args_w)
-
- operate = func_with_new_name(operate, name)
- operate.builtinshortcut = (mm, shortcut_method)
- setattr(space, name, operate)
- return shortcut_method
-
-
-def install_is_true(space, mm_nonzero, mm_len):
- shortcut = install(space, mm_nonzero, fallback_mm = mm_len)
- assert 'is_true' not in space.__dict__
-
- def is_true(w_obj):
- # a bit of duplication of the logic from DescrOperation.is_true...
- try:
- w_res = shortcut(space, w_obj)
- except FailedToImplement:
- pass
- else:
- # the __nonzero__ method of built-in objects should
- # always directly return a Bool; however, the __len__ method
- # of built-in objects typically returns an unwrappable integer
- if isinstance(w_res, W_BoolObject):
- return bool(w_res.intval)
- try:
- return space.int_w(w_res) != 0
- except OperationError:
- # I think no OperationError other than w_OverflowError
- # could occur here
- w_obj = w_res
-
- # general case fallback
- return _DescrOperation_is_true(space, w_obj)
-
- _DescrOperation_is_true = DescrOperation.is_true.im_func
- space.is_true = is_true
diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -10,8 +10,8 @@
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
from pypy.interpreter.signature import Signature
+from pypy.interpreter.typedef import TypeDef
from pypy.objspace.std.sliceobject import W_SliceObject
-from pypy.objspace.std.stdtypedef import StdTypeDef
from pypy.objspace.std.stringmethods import StringMethods, _get_buffer
from pypy.objspace.std.bytesobject import W_BytesObject
from pypy.objspace.std.util import get_positive_index
@@ -990,7 +990,7 @@
"""
-W_BytearrayObject.typedef = StdTypeDef(
+W_BytearrayObject.typedef = TypeDef(
"bytearray",
__doc__ = BytearrayDocstrings.__doc__,
__new__ = interp2app(W_BytearrayObject.descr_new),
diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -10,10 +10,10 @@
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import (
WrappedDefault, interp2app, interpindirect2app, unwrap_spec)
+from pypy.interpreter.typedef import TypeDef
from pypy.objspace.std import newformat
from pypy.objspace.std.basestringtype import basestring_typedef
from pypy.objspace.std.formatting import mod_format
-from pypy.objspace.std.stdtypedef import StdTypeDef
from pypy.objspace.std.stringmethods import StringMethods
from pypy.objspace.std.unicodeobject import (
_get_encoding_and_errors, decode_object, unicode_from_encoded_object,
@@ -874,7 +874,7 @@
return W_BytesObject(c)
-W_BytesObject.typedef = StdTypeDef(
+W_BytesObject.typedef = TypeDef(
"str", basestring_typedef,
__new__ = interp2app(W_BytesObject.descr_new),
__doc__ = """str(object='') -> string
diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py
--- a/pypy/objspace/std/complexobject.py
+++ b/pypy/objspace/std/complexobject.py
@@ -1,18 +1,19 @@
import math
-from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.error import OperationError, oefmt
-from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
-from pypy.objspace.std import newformat
-from pypy.objspace.std.floatobject import _hash_float
-from pypy.objspace.std.stdtypedef import GetSetProperty, StdTypeDef
from rpython.rlib import jit, rcomplex
from rpython.rlib.rarithmetic import intmask, r_ulonglong
from rpython.rlib.rbigint import rbigint
from rpython.rlib.rfloat import (
- formatd, DTSF_STR_PRECISION, isinf, isnan, copysign, string_to_float)
+ DTSF_STR_PRECISION, copysign, formatd, isinf, isnan, string_to_float)
from rpython.rlib.rstring import ParseStringError
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
+from pypy.interpreter.typedef import GetSetProperty, TypeDef
+from pypy.objspace.std import newformat
+from pypy.objspace.std.floatobject import _hash_float
+
def _split_complex(s):
slen = len(s)
@@ -264,7 +265,7 @@
if self.user_overridden_class:
return None
from rpython.rlib.longlong2float import float2longlong
- from pypy.objspace.std.model import IDTAG_COMPLEX as tag
+ from pypy.objspace.std.util import IDTAG_COMPLEX as tag
real = space.float_w(space.getattr(self, space.wrap("real")))
imag = space.float_w(space.getattr(self, space.wrap("imag")))
real_b = rbigint.fromrarith_int(float2longlong(real))
@@ -587,7 +588,7 @@
return space.newfloat(getattr(w_obj, name))
return GetSetProperty(fget)
-W_ComplexObject.typedef = StdTypeDef("complex",
+W_ComplexObject.typedef = TypeDef("complex",
__doc__ = """complex(real[, imag]) -> complex number
Create a complex number from a real part and an optional imaginary part.
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -11,7 +11,7 @@
WrappedDefault, applevel, interp2app, unwrap_spec)
from pypy.interpreter.mixedmodule import MixedModule
from pypy.interpreter.signature import Signature
-from pypy.objspace.std.stdtypedef import StdTypeDef
+from pypy.interpreter.typedef import TypeDef
from pypy.objspace.std.util import negate
@@ -372,7 +372,7 @@
dictrepr = app.interphook("dictrepr")
-W_DictMultiObject.typedef = StdTypeDef("dict",
+W_DictMultiObject.typedef = TypeDef("dict",
__doc__ = '''dict() -> new empty dictionary.
dict(mapping) -> new dictionary initialized from a mapping object\'s
(key, value) pairs.
@@ -1217,8 +1217,6 @@
class W_BaseDictMultiIterObject(W_Root):
_immutable_fields_ = ["iteratorimplementation"]
- ignore_for_isinstance_cache = True
-
def __init__(self, space, iteratorimplementation):
self.space = space
self.iteratorimplementation = iteratorimplementation
@@ -1309,7 +1307,7 @@
return space.newtuple([w_key, w_value])
raise OperationError(space.w_StopIteration, space.w_None)
-W_DictMultiIterItemsObject.typedef = StdTypeDef(
+W_DictMultiIterItemsObject.typedef = TypeDef(
"dict_iteritems",
__iter__ = interp2app(W_DictMultiIterItemsObject.descr_iter),
next = interp2app(W_DictMultiIterItemsObject.descr_next),
@@ -1317,7 +1315,7 @@
__reduce__ = interp2app(W_BaseDictMultiIterObject.descr_reduce),
)
-W_DictMultiIterKeysObject.typedef = StdTypeDef(
+W_DictMultiIterKeysObject.typedef = TypeDef(
"dict_iterkeys",
__iter__ = interp2app(W_DictMultiIterKeysObject.descr_iter),
next = interp2app(W_DictMultiIterKeysObject.descr_next),
@@ -1325,7 +1323,7 @@
__reduce__ = interp2app(W_BaseDictMultiIterObject.descr_reduce),
)
-W_DictMultiIterValuesObject.typedef = StdTypeDef(
+W_DictMultiIterValuesObject.typedef = TypeDef(
"dict_itervalues",
__iter__ = interp2app(W_DictMultiIterValuesObject.descr_iter),
next = interp2app(W_DictMultiIterValuesObject.descr_next),
@@ -1433,7 +1431,7 @@
def descr_iter(self, space):
return W_DictMultiIterValuesObject(space, self.w_dict.itervalues())
-W_DictViewItemsObject.typedef = StdTypeDef(
+W_DictViewItemsObject.typedef = TypeDef(
"dict_items",
__repr__ = interp2app(W_DictViewItemsObject.descr_repr),
__len__ = interp2app(W_DictViewItemsObject.descr_len),
@@ -1456,7 +1454,7 @@
__rxor__ = interp2app(W_DictViewItemsObject.descr_rxor),
)
-W_DictViewKeysObject.typedef = StdTypeDef(
+W_DictViewKeysObject.typedef = TypeDef(
"dict_keys",
__repr__ = interp2app(W_DictViewKeysObject.descr_repr),
__len__ = interp2app(W_DictViewKeysObject.descr_len),
@@ -1479,7 +1477,7 @@
__rxor__ = interp2app(W_DictViewKeysObject.descr_rxor),
)
-W_DictViewValuesObject.typedef = StdTypeDef(
+W_DictViewValuesObject.typedef = TypeDef(
"dict_values",
__repr__ = interp2app(W_DictViewValuesObject.descr_repr),
__len__ = interp2app(W_DictViewValuesObject.descr_len),
diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py
--- a/pypy/objspace/std/dictproxyobject.py
+++ b/pypy/objspace/std/dictproxyobject.py
@@ -1,8 +1,9 @@
-from pypy.objspace.std.dictmultiobject import DictStrategy, create_iterator_classes
+from rpython.rlib import rerased
+
+from pypy.interpreter.error import OperationError, oefmt
+from pypy.objspace.std.dictmultiobject import (
+ DictStrategy, create_iterator_classes)
from pypy.objspace.std.typeobject import unwrap_cell
-from pypy.interpreter.error import OperationError, oefmt
-
-from rpython.rlib import rerased
class DictProxyStrategy(DictStrategy):
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -2,24 +2,24 @@
import operator
import sys
+from rpython.rlib import rarithmetic, rfloat
+from rpython.rlib.rarithmetic import LONG_BIT, intmask, ovfcheck_float_to_int
+from rpython.rlib.rbigint import rbigint
+from rpython.rlib.rfloat import (
+ DTSF_ADD_DOT_0, DTSF_STR_PRECISION, INFINITY, NAN, copysign,
+ float_as_rbigint_ratio, formatd, isfinite, isinf, isnan)
+from rpython.rlib.rstring import ParseStringError
+from rpython.rlib.unroll import unrolling_iterable
+from rpython.rtyper.lltypesystem.module.ll_math import math_fmod
+from rpython.tool.sourcetools import func_with_new_name
+
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.error import OperationError, oefmt
-from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
-from pypy.interpreter.typedef import GetSetProperty
+from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
+from pypy.interpreter.typedef import GetSetProperty, TypeDef
from pypy.objspace.std import newformat
from pypy.objspace.std.longobject import W_LongObject
-from pypy.objspace.std.stdtypedef import StdTypeDef
from pypy.objspace.std.util import wrap_parsestringerror
-from rpython.rlib import rarithmetic, rfloat
-from rpython.rlib.rarithmetic import ovfcheck_float_to_int, intmask, LONG_BIT
-from rpython.rlib.rbigint import rbigint
-from rpython.rlib.rfloat import (
- isinf, isnan, isfinite, INFINITY, NAN, copysign, formatd,
- DTSF_ADD_DOT_0, DTSF_STR_PRECISION, float_as_rbigint_ratio)
-from rpython.rlib.rstring import ParseStringError
-from rpython.tool.sourcetools import func_with_new_name
-from rpython.rlib.unroll import unrolling_iterable
-from rpython.rtyper.lltypesystem.module.ll_math import math_fmod
def float2string(x, code, precision):
@@ -182,7 +182,7 @@
if self.user_overridden_class:
return None
from rpython.rlib.longlong2float import float2longlong
- from pypy.objspace.std.model import IDTAG_FLOAT as tag
+ from pypy.objspace.std.util import IDTAG_FLOAT as tag
val = float2longlong(space.float_w(self))
b = rbigint.fromrarith_int(val)
b = b.lshift(3).or_(rbigint.fromint(tag))
@@ -646,7 +646,7 @@
return space.wrap("0x%sp%s%d" % (s, sign, exp))
-W_FloatObject.typedef = StdTypeDef("float",
+W_FloatObject.typedef = TypeDef("float",
__doc__ = '''float(x) -> floating point number
Convert a string or number to a floating point number, if possible.''',
diff --git a/pypy/objspace/std/formatting.py b/pypy/objspace/std/formatting.py
--- a/pypy/objspace/std/formatting.py
+++ b/pypy/objspace/std/formatting.py
@@ -1,15 +1,15 @@
-"""
-String formatting routines.
-"""
+"""String formatting routines"""
import sys
-from pypy.interpreter.error import OperationError, oefmt
+
from rpython.rlib import jit
-from rpython.rlib.rfloat import formatd, DTSF_ALT, isnan, isinf
+from rpython.rlib.rarithmetic import INT_MAX
+from rpython.rlib.rfloat import DTSF_ALT, formatd, isnan, isinf
from rpython.rlib.rstring import StringBuilder, UnicodeBuilder
from rpython.rlib.unroll import unrolling_iterable
-from rpython.rlib.rarithmetic import INT_MAX
from rpython.tool.sourcetools import func_with_new_name
+from pypy.interpreter.error import OperationError, oefmt
+
class BaseStringFormatter(object):
def __init__(self, space, values_w, w_valuedict):
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -21,11 +21,10 @@
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef
from pypy.objspace.std import newformat
-from pypy.objspace.std.model import (
- BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_INT)
-from pypy.objspace.std.stdtypedef import StdTypeDef
-from pypy.objspace.std.util import wrap_parsestringerror
+from pypy.objspace.std.util import (
+ BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_INT, wrap_parsestringerror)
SENTINEL = object()
@@ -601,6 +600,16 @@
_divmod, ovf2small=_divmod_ovf2small)
+def setup_prebuilt(space):
+ if space.config.objspace.std.withprebuiltint:
+ W_IntObject.PREBUILT = []
+ for i in range(space.config.objspace.std.prebuiltintfrom,
+ space.config.objspace.std.prebuiltintto):
+ W_IntObject.PREBUILT.append(W_IntObject(i))
+ else:
+ W_IntObject.PREBUILT = None
+
+
def wrapint(space, x):
if not space.config.objspace.std.withprebuiltint:
return W_IntObject(x)
@@ -723,7 +732,7 @@
return w_obj
-W_IntObject.typedef = StdTypeDef("int",
+W_IntObject.typedef = TypeDef("int",
__doc__ = """int(x=0) -> int or long
int(x, base=10) -> int or long
diff --git a/pypy/objspace/std/iterobject.py b/pypy/objspace/std/iterobject.py
--- a/pypy/objspace/std/iterobject.py
+++ b/pypy/objspace/std/iterobject.py
@@ -3,7 +3,7 @@
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.gateway import interp2app, interpindirect2app
from pypy.interpreter.error import OperationError
-from pypy.objspace.std.stdtypedef import StdTypeDef
+from pypy.interpreter.typedef import TypeDef
class W_AbstractSeqIterObject(W_Root):
@@ -40,7 +40,7 @@
def descr_length_hint(self, space):
return self.getlength(space)
-W_AbstractSeqIterObject.typedef = StdTypeDef(
+W_AbstractSeqIterObject.typedef = TypeDef(
"sequenceiterator",
__doc__ = '''iter(collection) -> iterator
iter(callable, sentinel) -> iterator
@@ -159,7 +159,7 @@
raise OperationError(space.w_StopIteration, space.w_None)
return w_item
-W_ReverseSeqIterObject.typedef = StdTypeDef(
+W_ReverseSeqIterObject.typedef = TypeDef(
"reversesequenceiterator",
__iter__ = interp2app(W_ReverseSeqIterObject.descr_iter),
next = interp2app(W_ReverseSeqIterObject.descr_next),
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -10,28 +10,29 @@
import operator
import sys
+from rpython.rlib import debug, jit, rerased
+from rpython.rlib.listsort import make_timsort_class
+from rpython.rlib.objectmodel import (
+ import_from_mixin, instantiate, newlist_hint, resizelist_hint, specialize)
+from rpython.tool.sourcetools import func_with_new_name
+
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.error import OperationError, oefmt
-from pypy.interpreter.gateway import (WrappedDefault, unwrap_spec, applevel,
- interp2app)
+from pypy.interpreter.gateway import (
+ WrappedDefault, applevel, interp2app, unwrap_spec)
from pypy.interpreter.generator import GeneratorIterator
from pypy.interpreter.signature import Signature
+from pypy.interpreter.typedef import TypeDef
from pypy.objspace.std.bytesobject import W_BytesObject
from pypy.objspace.std.floatobject import W_FloatObject
from pypy.objspace.std.intobject import W_IntObject
-from pypy.objspace.std.iterobject import (W_FastListIterObject,
- W_ReverseSeqIterObject)
-from pypy.objspace.std.sliceobject import (W_SliceObject, unwrap_start_stop,
- normalize_simple_slice)
-from pypy.objspace.std.stdtypedef import StdTypeDef
+from pypy.objspace.std.iterobject import (
+ W_FastListIterObject, W_ReverseSeqIterObject)
+from pypy.objspace.std.sliceobject import (
+ W_SliceObject, normalize_simple_slice, unwrap_start_stop)
from pypy.objspace.std.tupleobject import W_AbstractTupleObject
from pypy.objspace.std.unicodeobject import W_UnicodeObject
from pypy.objspace.std.util import get_positive_index, negate
-from rpython.rlib import debug, jit, rerased
-from rpython.rlib.listsort import make_timsort_class
-from rpython.rlib.objectmodel import (
- instantiate, newlist_hint, resizelist_hint, specialize, import_from_mixin)
-from rpython.tool.sourcetools import func_with_new_name
__all__ = ['W_ListObject', 'make_range_list', 'make_empty_list_with_size']
@@ -1830,7 +1831,7 @@
return CustomCompareSort.lt(self, a.w_key, b.w_key)
-W_ListObject.typedef = StdTypeDef("list",
+W_ListObject.typedef = TypeDef("list",
__doc__ = """list() -> new empty list
list(iterable) -> new list initialized from iterable's items""",
__new__ = interp2app(W_ListObject.descr_new),
diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py
--- a/pypy/objspace/std/longobject.py
+++ b/pypy/objspace/std/longobject.py
@@ -12,12 +12,11 @@
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import (
WrappedDefault, interp2app, interpindirect2app, unwrap_spec)
+from pypy.interpreter.typedef import TypeDef
from pypy.objspace.std import newformat
from pypy.objspace.std.intobject import W_AbstractIntObject
-from pypy.objspace.std.model import (
- BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_LONG)
-from pypy.objspace.std.stdtypedef import StdTypeDef
-from pypy.objspace.std.util import wrap_parsestringerror
+from pypy.objspace.std.util import (
+ BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_LONG, wrap_parsestringerror)
def delegate_other(func):
@@ -567,7 +566,7 @@
return w_obj
-W_AbstractLongObject.typedef = StdTypeDef("long",
+W_AbstractLongObject.typedef = TypeDef("long",
__doc__ = """long(x=0) -> long
long(x, base=10) -> long
diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py
deleted file mode 100644
--- a/pypy/objspace/std/model.py
+++ /dev/null
@@ -1,357 +0,0 @@
-"""
-The full list of which Python types and which implementation we want
-to provide in this version of PyPy, along with conversion rules.
-"""
-
-from pypy.objspace.std.multimethod import MultiMethodTable, FailedToImplement
-from pypy.interpreter.baseobjspace import W_Root, ObjSpace
-import pypy.interpreter.pycode
-import pypy.interpreter.special
-
-_registered_implementations = set()
-def registerimplementation(implcls):
- """Hint to objspace.std.model to register the implementation class."""
- assert issubclass(implcls, W_Object)
- _registered_implementations.add(implcls)
-
-option_to_typename = {
- "withsmalllong" : ["smalllongobject.W_SmallLongObject"],
- "withstrbuf" : ["strbufobject.W_StringBufferObject"],
-}
-
-IDTAG_INT = 1
-IDTAG_LONG = 3
-IDTAG_FLOAT = 5
-IDTAG_COMPLEX = 7
-
-class StdTypeModel:
-
- def __init__(self, config):
- """NOT_RPYTHON: inititialization only"""
- self.config = config
- # All the Python types that we want to provide in this StdObjSpace
-
- # The object implementations that we want to 'link' into PyPy must be
- # imported here. This registers them into the multimethod tables,
- # *before* the type objects are built from these multimethod tables.
- from pypy.objspace.std import objectobject
- from pypy.objspace.std import boolobject
- from pypy.objspace.std import intobject
- from pypy.objspace.std import floatobject
- from pypy.objspace.std import complexobject
- from pypy.objspace.std import tupleobject
- from pypy.objspace.std import listobject
- from pypy.objspace.std import dictmultiobject
- from pypy.objspace.std import setobject
- from pypy.objspace.std import basestringtype
- from pypy.objspace.std import bytesobject
- from pypy.objspace.std import bytearrayobject
- from pypy.objspace.std import typeobject
- from pypy.objspace.std import sliceobject
- from pypy.objspace.std import longobject
- from pypy.objspace.std import noneobject
- from pypy.objspace.std import iterobject
- from pypy.objspace.std import unicodeobject
- from pypy.objspace.std import dictproxyobject
- from pypy.objspace.std import proxyobject
- from pypy.objspace.std import bufferobject
- from pypy.objspace.std import memoryobject
-
-
- self.pythontypes = []
- self.pythontypes.append(objectobject.W_ObjectObject.typedef)
- self.pythontypes.append(typeobject.W_TypeObject.typedef)
- self.pythontypes.append(noneobject.W_NoneObject.typedef)
- self.pythontypes.append(tupleobject.W_TupleObject.typedef)
- self.pythontypes.append(listobject.W_ListObject.typedef)
- self.pythontypes.append(dictmultiobject.W_DictMultiObject.typedef)
- self.pythontypes.append(setobject.W_SetObject.typedef)
- self.pythontypes.append(setobject.W_FrozensetObject.typedef)
- self.pythontypes.append(iterobject.W_AbstractSeqIterObject.typedef)
- self.pythontypes.append(basestringtype.basestring_typedef)
- self.pythontypes.append(bytesobject.W_BytesObject.typedef)
- self.pythontypes.append(bytearrayobject.W_BytearrayObject.typedef)
- self.pythontypes.append(unicodeobject.W_UnicodeObject.typedef)
- self.pythontypes.append(intobject.W_IntObject.typedef)
- self.pythontypes.append(boolobject.W_BoolObject.typedef)
- self.pythontypes.append(longobject.W_LongObject.typedef)
- self.pythontypes.append(floatobject.W_FloatObject.typedef)
- self.pythontypes.append(complexobject.W_ComplexObject.typedef)
- self.pythontypes.append(sliceobject.W_SliceObject.typedef)
- self.pythontypes.append(bufferobject.W_Buffer.typedef)
- self.pythontypes.append(memoryobject.W_MemoryView.typedef)
-
- # the set of implementation types
- self.typeorder = {
- objectobject.W_ObjectObject: [],
- # XXX: Bool/Int/Long are pythontypes but still included here
- # for delegation to Float/Complex
- boolobject.W_BoolObject: [],
- intobject.W_IntObject: [],
- floatobject.W_FloatObject: [],
- typeobject.W_TypeObject: [],
- sliceobject.W_SliceObject: [],
- longobject.W_LongObject: [],
- noneobject.W_NoneObject: [],
- complexobject.W_ComplexObject: [],
- pypy.interpreter.pycode.PyCode: [],
- pypy.interpreter.special.Ellipsis: [],
- }
-
- self.imported_but_not_registered = {
- bytesobject.W_BytesObject: True,
- }
- for option, value in config.objspace.std:
- if option.startswith("with") and option in option_to_typename:
- for classname in option_to_typename[option]:
- modname = classname[:classname.index('.')]
- classname = classname[classname.index('.')+1:]
- d = {}
- exec "from pypy.objspace.std.%s import %s" % (
- modname, classname) in d
- implcls = d[classname]
- if value:
- self.typeorder[implcls] = []
- else:
- self.imported_but_not_registered[implcls] = True
-
- # check if we missed implementations
- for implcls in _registered_implementations:
- if hasattr(implcls, 'register'):
- implcls.register(self.typeorder)
- assert (implcls in self.typeorder or
- implcls in self.imported_but_not_registered), (
- "please add %r in StdTypeModel.typeorder" % (implcls,))
-
-
- for type in self.typeorder:
- self.typeorder[type].append((type, None))
-
- # register the order in which types are converted into each others
- # when trying to dispatch multimethods.
- # XXX build these lists a bit more automatically later
-
- if config.objspace.std.withsmalllong:
- from pypy.objspace.std import smalllongobject
- self.typeorder[smalllongobject.W_SmallLongObject] += [
- (floatobject.W_FloatObject, smalllongobject.delegate_SmallLong2Float),
- (complexobject.W_ComplexObject, smalllongobject.delegate_SmallLong2Complex),
- ]
-
- if config.objspace.std.withstrbuf:
- from pypy.objspace.std import strbufobject
-
- # put W_Root everywhere
- self.typeorder[W_Root] = []
- for type in self.typeorder:
- from pypy.objspace.std import stdtypedef
- if type is not W_Root and isinstance(type.typedef, stdtypedef.StdTypeDef):
- self.typeorder[type].append((type.typedef.any, None))
- self.typeorder[type].append((W_Root, None))
-
- self._typeorder_with_empty_usersubcls = None
-
- # ____________________________________________________________
- # Prebuilt common integer values
-
- if config.objspace.std.withprebuiltint:
- intobject.W_IntObject.PREBUILT = []
- for i in range(config.objspace.std.prebuiltintfrom,
- config.objspace.std.prebuiltintto):
- intobject.W_IntObject.PREBUILT.append(intobject.W_IntObject(i))
- del i
- else:
- intobject.W_IntObject.PREBUILT = None
-
- # ____________________________________________________________
-
- def get_typeorder_with_empty_usersubcls(self):
- if self._typeorder_with_empty_usersubcls is None:
- from pypy.interpreter.typedef import enum_interplevel_subclasses
- from pypy.objspace.std import stdtypedef
- result = self.typeorder.copy()
- for cls in self.typeorder:
- if (hasattr(cls, 'typedef') and cls.typedef is not None and
- cls.typedef.acceptable_as_base_class):
- subclslist = enum_interplevel_subclasses(self.config, cls)
- for subcls in subclslist:
- if cls in subcls.__bases__: # only direct subclasses
- # for user subclasses we only accept "generic"
- # matches: "typedef.any" is the applevel-type-based
- # matching, and "W_Root" is ANY.
- matches = []
- if isinstance(cls.typedef, stdtypedef.StdTypeDef):
- matches.append((cls.typedef.any, None))
- matches.append((W_Root, None))
- result[subcls] = matches
- self._typeorder_with_empty_usersubcls = result
- return self._typeorder_with_empty_usersubcls
-
-def _op_negated(function):
- def op(space, w_1, w_2):
- return space.not_(function(space, w_1, w_2))
- return op
-
-def _op_swapped(function):
- def op(space, w_1, w_2):
- return function(space, w_2, w_1)
- return op
-
-def _op_swapped_negated(function):
- def op(space, w_1, w_2):
- return space.not_(function(space, w_2, w_1))
- return op
-
-
-CMP_OPS = dict(lt='<', le='<=', eq='==', ne='!=', gt='>', ge='>=')
-CMP_CORRESPONDANCES = [
- ('eq', 'ne', _op_negated),
- ('lt', 'gt', _op_swapped),
- ('le', 'ge', _op_swapped),
- ('lt', 'ge', _op_negated),
- ('le', 'gt', _op_negated),
- ('lt', 'le', _op_swapped_negated),
- ('gt', 'ge', _op_swapped_negated),
- ]
-for op1, op2, value in CMP_CORRESPONDANCES[:]:
- i = CMP_CORRESPONDANCES.index((op1, op2, value))
- CMP_CORRESPONDANCES.insert(i+1, (op2, op1, value))
-BINARY_BITWISE_OPS = {'and': '&', 'lshift': '<<', 'or': '|', 'rshift': '>>',
- 'xor': '^'}
-BINARY_OPS = dict(add='+', div='/', floordiv='//', mod='%', mul='*', sub='-',
- truediv='/', **BINARY_BITWISE_OPS)
-COMMUTATIVE_OPS = ('add', 'mul', 'and', 'or', 'xor')
-
-def add_extra_comparisons():
- """
- Add the missing comparison operators if they were not explicitly
- defined: eq <-> ne and lt <-> le <-> gt <-> ge.
- We try to add them in the order defined by the CMP_CORRESPONDANCES
- table, thus favouring swapping the arguments over negating the result.
- """
- originalentries = {}
- for op in CMP_OPS.iterkeys():
- originalentries[op] = getattr(MM, op).signatures()
-
- for op1, op2, correspondance in CMP_CORRESPONDANCES:
- mirrorfunc = getattr(MM, op2)
- for types in originalentries[op1]:
- t1, t2 = types
- if t1 is t2:
- if not mirrorfunc.has_signature(types):
- functions = getattr(MM, op1).getfunctions(types)
- assert len(functions) == 1, ('Automatic'
- ' registration of comparison functions'
- ' only work when there is a single method for'
- ' the operation.')
- mirrorfunc.register(correspondance(functions[0]), *types)
-
-
-# ____________________________________________________________
-
-W_ANY = W_Root
-
-class W_Object(W_Root):
- "Parent base class for wrapped objects provided by the StdObjSpace."
- # Note that not all wrapped objects in the interpreter inherit from
- # W_Object. (They inherit from W_Root.)
- __slots__ = ()
-
- def __repr__(self):
- name = getattr(self, 'name', '')
- if not isinstance(name, str):
- name = ''
- s = '%s(%s)' % (self.__class__.__name__, name)
- w_cls = getattr(self, 'w__class__', None)
- if w_cls is not None and w_cls is not self:
- s += ' instance of %s' % self.w__class__
- return '<%s>' % s
-
-
-class UnwrapError(Exception):
- pass
-
-
-class StdObjSpaceMultiMethod(MultiMethodTable):
-
- def __init__(self, operatorsymbol, arity, specialnames=None, **extras):
- """NOT_RPYTHON: cannot create new multimethods dynamically.
- """
- MultiMethodTable.__init__(self, arity, W_ANY,
- argnames_before = ['space'])
- self.operatorsymbol = operatorsymbol
- if specialnames is None:
- specialnames = [operatorsymbol]
- assert isinstance(specialnames, list)
- self.specialnames = specialnames # e.g. ['__xxx__', '__rxxx__']
- self.extras = extras
- # transform '+' => 'add' etc.
- for line in ObjSpace.MethodTable:
- realname, symbolname = line[:2]
- if symbolname == operatorsymbol:
- self.name = realname
- break
- else:
- self.name = operatorsymbol
-
- if extras.get('general__args__', False):
- self.argnames_after = ['__args__']
- if extras.get('varargs_w', False):
- self.argnames_after = ['args_w']
- self.argnames_after += extras.get('extra_args', [])
-
- def install_not_sliced(self, typeorder, baked_perform_call=True):
- return self.install(prefix = '__mm_' + self.name,
- list_of_typeorders = [typeorder]*self.arity,
- baked_perform_call=baked_perform_call)
-
- def merge_with(self, other):
- # Make a new 'merged' multimethod including the union of the two
- # tables. In case of conflict, pick the entry from 'self'.
- if self.arity != other.arity:
- return self # XXX that's the case of '**'
- operatorsymbol = '%s_merge_%s' % (self.name, other.name)
- assert self.extras == other.extras
- mm = StdObjSpaceMultiMethod(operatorsymbol, self.arity, **self.extras)
- #
- def merge(node1, node2):
- assert type(node1) is type(node2)
- if isinstance(node1, dict):
- d = node1.copy()
- d.update(node2)
- for key in node1:
- if key in node2:
- d[key] = merge(node1[key], node2[key])
- return d
- else:
- assert isinstance(node1, list)
- assert node1
- return node1 # pick the entry from 'self'
- #
- mm.dispatch_tree = merge(self.dispatch_tree, other.dispatch_tree)
- return mm
-
-NOT_MULTIMETHODS = set(
- ['delattr', 'delete', 'get', 'id', 'inplace_div', 'inplace_floordiv',
- 'inplace_lshift', 'inplace_mod', 'inplace_pow', 'inplace_rshift',
- 'inplace_truediv', 'is_', 'set', 'setattr', 'type', 'userdel',
- 'isinstance', 'issubtype', 'int', 'ord'])
-# XXX should we just remove those from the method table or we're happy
-# with just not having multimethods?
-
-class MM:
- """StdObjSpace multimethods"""
-
- call = StdObjSpaceMultiMethod('call', 1, ['__call__'],
- general__args__=True)
- init = StdObjSpaceMultiMethod('__init__', 1, general__args__=True)
- getnewargs = StdObjSpaceMultiMethod('__getnewargs__', 1)
-
- # add all regular multimethods here
- for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable:
- if _name not in locals() and _name not in NOT_MULTIMETHODS:
- mm = StdObjSpaceMultiMethod(_symbol, _arity, _specialnames)
- locals()[_name] = mm
- del mm
-
- pow.extras['defaults'] = (None,)
diff --git a/pypy/objspace/std/multimethod.py b/pypy/objspace/std/multimethod.py
deleted file mode 100644
--- a/pypy/objspace/std/multimethod.py
+++ /dev/null
@@ -1,972 +0,0 @@
-
-from rpython.tool.sourcetools import compile2
-
-# This provide two compatible implementations of "multimethods". A
-# multimethod is a callable object which chooses and calls a real
-# function from a table of pre-registered functions. The choice depends
-# on the '__class__' of all arguments. For example usages see
-# test_multimethod.
-
-# These multimethods support delegation: for each class A we must
-# provide a "typeorder", which is list of pairs (B, converter) where B
-# is a class and 'converter' is a function that can convert from an
-# instance of A to an instance of B. If 'converter' is None it is
-# assumed that the instance needs no conversion. The first entry in the
-# typeorder of a class A must almost always be (A, None).
-
-# A slightly non-standard feature of PyPy's multimethods is the way in
-# which they interact with normal subclassing. Basically, they don't.
-# Suppose that A is a parent class of B. Then a function registered for
-# an argument class A only accepts an instance whose __class__ is A, not
-# B. To make it accept an instance of B, the typeorder for B must
-# contain (A, None). An exception to this strict rule is if C is
-# another subclass of A which is not mentioned at all in the typeorder;
-# in this case C is considered to be equivalent to A.
-
-
-class FailedToImplement(Exception):
- def __new__(cls, *args):
- if cls is FailedToImplement:
- assert not args, "use FailedToImplementArgs!"
- return Exception.__new__(cls, *args)
-
- def get_w_value(self, space):
- return None
-
- def get_w_type(self, space):
- return None
-
- def __str__(self):
- return '<FailedToImplement(None, None)>'
-
-class FailedToImplementArgs(FailedToImplement):
- def __init__(self, w_type=None, w_value=None):
- self.w_type = w_type
- self.w_value = w_value
-
- def get_w_value(self, space):
- # convenience: same semantics as with OperationError
- return self.w_value
-
- def get_w_type(self, space):
- return self.w_type
-
- def __str__(self):
- return '<FailedToImplement(%s, %s)>' % (self.w_type, self.w_value)
-
-
-
-def raiseFailedToImplement():
- raise FailedToImplement
-
-
-class MultiMethodTable:
-
- def __init__(self, arity, root_class, argnames_before=[], argnames_after=[]):
- """NOT_RPYTHON: cannot create new multimethods dynamically.
- MultiMethod-maker dispatching on exactly 'arity' arguments.
- """
- if arity < 1:
- raise ValueError, "multimethods cannot dispatch on nothing"
- self.arity = arity
- self.root_class = root_class
- self.dispatch_tree = {}
- self.argnames_before = list(argnames_before)
- self.argnames_after = list(argnames_after)
-
- def register(self, function, *types, **kwds):
- assert len(types) == self.arity
- assert kwds.keys() == [] or kwds.keys() == ['order']
- order = kwds.get('order', 0)
- node = self.dispatch_tree
- for type in types[:-1]:
- node = node.setdefault(type, {})
- lst = node.setdefault(types[-1], [])
- if order >= len(lst):
- lst += [None] * (order+1 - len(lst))
- assert lst[order] is None, "duplicate function for %r@%d" % (
- types, order)
- lst[order] = function
-
- def install(self, prefix, list_of_typeorders, baked_perform_call=True,
- base_typeorder=None, installercls=None):
- "NOT_RPYTHON: initialization-time only"
- assert len(list_of_typeorders) == self.arity
- installercls = installercls or Installer
- installer = installercls(self, prefix, list_of_typeorders,
- baked_perform_call=baked_perform_call,
- base_typeorder=base_typeorder)
- return installer.install()
-
- def install_if_not_empty(self, prefix, list_of_typeorders,
- base_typeorder=None, installercls=None):
- "NOT_RPYTHON: initialization-time only"
- assert len(list_of_typeorders) == self.arity
- installercls = installercls or Installer
- installer = installercls(self, prefix, list_of_typeorders,
- base_typeorder=base_typeorder)
- if installer.is_empty():
- return None
- else:
- return installer.install()
-
-
-
- # ____________________________________________________________
- # limited dict-like interface to the dispatch table
-
- def getfunctions(self, types):
- assert len(types) == self.arity
- node = self.dispatch_tree
- for type in types:
- node = node[type]
- return [fn for fn in node if fn is not None]
-
- def has_signature(self, types):
- try:
- self.getfunctions(types)
- except KeyError:
- return False
- else:
- return True
-
- def signatures(self):
- """NOT_RPYTHON"""
- result = []
- def enum_keys(types_so_far, node):
- for type, subnode in node.items():
- next_types = types_so_far+(type,)
- if isinstance(subnode, dict):
- enum_keys(next_types, subnode)
- else:
- assert len(next_types) == self.arity
- result.append(next_types)
- enum_keys((), self.dispatch_tree)
- return result
-
-# ____________________________________________________________
-# Installer version 1
-
-class InstallerVersion1:
- """NOT_RPYTHON"""
-
- instance_counter = 0
-
- mmfunccache = {}
-
- prefix_memo = {}
-
- def __init__(self, multimethod, prefix, list_of_typeorders,
- baked_perform_call=True, base_typeorder=None):
- self.__class__.instance_counter += 1
- self.multimethod = multimethod
- # avoid prefix clashes, user code should supply different prefixes
- # itself for nice names in tracebacks
- base_prefix = prefix
- n = 1
- while prefix in self.prefix_memo:
- n += 1
- prefix = "%s%d" % (base_prefix, n)
- self.prefix = prefix
- self.prefix_memo[prefix] = 1
- self.list_of_typeorders = list_of_typeorders
- self.check_typeorders()
- self.subtree_cache = {}
- self.to_install = []
- self.non_empty = self.build_tree([], multimethod.dispatch_tree)
-
- self.baked_perform_call = baked_perform_call
-
- if self.non_empty:
- perform = [(None, prefix, 0)]
- else:
- perform = []
-
- self.perform_call = self.build_function(None, prefix+'_perform_call',
- None, perform)
-
- def check_typeorders(self):
- # xxx we use a '__'-separated list of the '__name__' of the types
- # in build_single_method(), so types with the same __name__ or
- # with '__' in them would obscurely break this logic
- for typeorder in self.list_of_typeorders:
- for type in typeorder:
- assert '__' not in type.__name__, (
- "avoid '__' in the name of %r" % (type,))
- names = dict.fromkeys([type.__name__ for type in typeorder])
- assert len(names) == len(typeorder), (
- "duplicate type.__name__ in %r" % (typeorder,))
-
- def is_empty(self):
- return not self.non_empty
-
- def install(self):
- #f = open('LOGFILE', 'a')
- #print >> f, '_'*60
- #import pprint
- #pprint.pprint(self.list_of_typeorders, f)
-
- def class_key(cls):
- "Returns an object such that class_key(subcls) > class_key(cls)."
- return len(cls.__mro__)
-
- # Sort 'to_install' so that base classes come first, which is
- # necessary for the 'parentfunc' logic in the loop below to work.
- # Moreover, 'to_install' can contain two functions with the same
- # name for the root class: the default fallback one and the real
- # one. So we have to sort the real one just after the default one
- # so that the default one gets overridden.
- def key(target, funcname, func, source, fallback):
- if target is None:
- return ()
- return (class_key(target), not fallback)
- self.to_install.sort(lambda a, b: cmp(key(*a), key(*b)))
-
- for target, funcname, func, source, fallback in self.to_install:
- if target is not None:
- # If the parent class provides a method of the same
- # name which is actually the same 'func', we don't need
- # to install it again. Useful with fallback functions.
- parentfunc = getattr(target, funcname, None)
- parentfunc = getattr(parentfunc, 'im_func', None)
- if parentfunc is func:
- continue
- #print >> f, target.__name__, funcname
- #if source:
- # print >> f, source
- #else:
- # print >> f, '*\n'
- setattr(target, funcname, func)
- #f.close()
- return self.perform_call
-
- def build_tree(self, types_so_far, dispatch_node):
- key = tuple(types_so_far)
- if key in self.subtree_cache:
- return self.subtree_cache[key]
- non_empty = False
- typeorder = self.list_of_typeorders[len(types_so_far)]
- for next_type in typeorder:
- if self.build_single_method(typeorder, types_so_far, next_type,
- dispatch_node):
- non_empty = True
- self.subtree_cache[key] = non_empty
- return non_empty
-
- def build_single_method(self, typeorder, types_so_far, next_type,
- dispatch_node):
- funcname = '__'.join([self.prefix] + [t.__name__ for t in types_so_far])
-
- order = typeorder[next_type]
- #order = [(next_type, None)] + order
-
- things_to_call = []
- for type, conversion in order:
- if type not in dispatch_node:
- # there is no possible completion of types_so_far+[type]
- # that could lead to a registered function.
- continue
- match = dispatch_node[type]
- if isinstance(match, dict):
- if self.build_tree(types_so_far+[type], match):
- call = funcname + '__' + type.__name__
- call_selfarg_index = len(types_so_far) + 1
- things_to_call.append((conversion, call,
- call_selfarg_index))
- else:
- for func in match: # list of functions
- if func is not None:
- things_to_call.append((conversion, func, None))
-
- funcname = intern(funcname)
- self.build_function(next_type, funcname, len(types_so_far),
- things_to_call)
- return bool(things_to_call)
-
- def build_function(self, target, funcname, func_selfarg_index,
- things_to_call):
- # support for inventing names for the entries in things_to_call
- # which are real function objects instead of strings
- miniglobals = {'FailedToImplement': FailedToImplement, '__name__': __name__}
- def invent_name(obj):
- if isinstance(obj, str):
- return obj
- name = obj.__name__
- n = 1
- while name in miniglobals:
- n += 1
- name = '%s%d' % (obj.__name__, n)
- miniglobals[name] = obj
- return name
-
- funcargs = ['arg%d' % i for i in range(self.multimethod.arity)]
-
- bodylines = []
- for conversion, call, call_selfarg_index in things_to_call:
- callargs = funcargs[:]
- if conversion is not None:
- to_convert = func_selfarg_index
- convert_callargs = (self.multimethod.argnames_before +
- [callargs[to_convert]])
- callargs[to_convert] = '%s(%s)' % (
- invent_name(conversion), ', '.join(convert_callargs))
- callname = invent_name(call)
- if call_selfarg_index is not None:
- # fallback on root_class
- self.build_function(self.multimethod.root_class,
- callname, call_selfarg_index, [])
- callname = '%s.%s' % (callargs.pop(call_selfarg_index), callname)
- callargs = (self.multimethod.argnames_before +
- callargs + self.multimethod.argnames_after)
- bodylines.append('return %s(%s)' % (callname, ', '.join(callargs)))
-
- fallback = False
- if not bodylines:
- miniglobals['raiseFailedToImplement'] = raiseFailedToImplement
- bodylines = ['return raiseFailedToImplement()']
- fallback = True
- # NB. make sure that there is only one fallback function object,
- # i.e. the key used in the mmfunccache below is always the same
- # for all functions with the same name and an empty bodylines.
-
- # protect all lines apart from the last one by a try:except:
- for i in range(len(bodylines)-2, -1, -1):
- bodylines[i:i+1] = ['try:',
- ' ' + bodylines[i],
- 'except FailedToImplement:',
- ' pass']
-
- if func_selfarg_index is not None:
- selfargs = [funcargs.pop(func_selfarg_index)]
- else:
- selfargs = []
- funcargs = (selfargs + self.multimethod.argnames_before +
- funcargs + self.multimethod.argnames_after)
-
- if target is None and not self.baked_perform_call:
- return funcargs, bodylines[0][len('return '):], miniglobals, fallback
-
- # indent mode
- bodylines = [' ' + line for line in bodylines]
-
- bodylines.insert(0, 'def %s(%s):' % (funcname, ', '.join(funcargs)))
- bodylines.append('')
- source = '\n'.join(bodylines)
-
- # XXX find a better place (or way) to avoid duplicate functions
- l = miniglobals.items()
- l.sort()
- l = tuple(l)
- key = (source, l)
- try:
- func = self.mmfunccache[key]
- except KeyError:
- exec compile2(source) in miniglobals
- func = miniglobals[funcname]
- self.mmfunccache[key] = func
- #else:
- # print "avoided duplicate function", func
- self.to_install.append((target, funcname, func, source, fallback))
- return func
-
-# ____________________________________________________________
-# Installer version 2
-
-class MMDispatcher(object):
- """NOT_RPYTHON
- Explicit dispatcher class. The __call__ and dispatch() methods
- are only present for documentation purposes. The InstallerVersion2
- uses the expressions() method to precompute fast RPython-friendly
- dispatch tables.
- """
- _revcache = None
-
- def __init__(self, multimethod, list_of_typeorders):
- self.multimethod = multimethod
- self.list_of_typeorders = list_of_typeorders
-
- def __call__(self, *args):
- # for testing only: this is slow
- i = len(self.multimethod.argnames_before)
- j = i + self.multimethod.arity
- k = j + len(self.multimethod.argnames_after)
- assert len(args) == k
- prefixargs = args[:i]
- dispatchargs = args[i:j]
- suffixargs = args[j:]
- return self.dispatch([x.__class__ for x in dispatchargs],
- prefixargs,
- dispatchargs,
- suffixargs)
-
- def dispatch(self, argtypes, prefixargs, args, suffixargs):
- # for testing only: this is slow
- def expr(v):
- if isinstance(v, Call):
- return v.function(*[expr(w) for w in v.arguments])
- else:
- return v
- # XXX this is incomplete: for each type in argtypes but not
- # in the typeorder, we should look for the first base class
- # that is in the typeorder.
- e = None
- for v in self.expressions(argtypes, prefixargs, args, suffixargs):
- try:
- return expr(v)
- except FailedToImplement, e:
- pass
- else:
- raise e or FailedToImplement()
-
- def expressions(self, argtypes, prefixargs, args, suffixargs):
- """Lists the possible expressions that call the appropriate
- function for the given argument types. Each expression is a Call
- object. The intent is that at run-time the first Call that doesn't
- cause FailedToImplement to be raised is the good one.
- """
- prefixargs = tuple(prefixargs)
- suffixargs = tuple(suffixargs)
-
- def walktree(node, args_so_far):
- if isinstance(node, list):
- for func in node:
- if func is not None:
- result.append(Call(func, prefixargs +
- args_so_far +
- suffixargs))
- else:
- index = len(args_so_far)
- typeorder = self.list_of_typeorders[index]
- next_type = argtypes[index]
- for target_type, converter in typeorder[next_type]:
- if target_type not in node:
- continue
- next_arg = args[index]
- if converter:
- next_arg = Call(converter, prefixargs + (next_arg,))
- walktree(node[target_type], args_so_far + (next_arg,))
-
- result = []
- walktree(self.multimethod.dispatch_tree, ())
- return result
-
- def anychance(self, typesprefix):
- # is there any chance that a list of types starting with typesprefix
- # could lead to a successful dispatch?
- # (START-UP TIME OPTIMIZATION ONLY)
- if self._revcache is None:
-
- def build_tree(types_so_far, dispatch_node):
- non_empty = False
- typeorder = self.list_of_typeorders[len(types_so_far)]
- for next_type in typeorder:
- if build_single_method(typeorder, types_so_far, next_type,
- dispatch_node):
- non_empty = True
- if non_empty:
- self._revcache[types_so_far] = True
- return non_empty
-
- def build_single_method(typeorder, types_so_far, next_type,
- dispatch_node):
- order = typeorder[next_type]
- things_to_call = False
- for type, conversion in order:
- if type not in dispatch_node:
- # there is no possible completion of
- # types_so_far+[type] that could lead to a
- # registered function.
- continue
- match = dispatch_node[type]
- if isinstance(match, dict):
- if build_tree(types_so_far+(next_type,), match):
- things_to_call = True
- elif match:
- things_to_call = True
- return things_to_call
-
- self._revcache = {}
- build_tree((), self.multimethod.dispatch_tree)
- return tuple(typesprefix) in self._revcache
-
-
-class Call(object):
- """ Represents a call expression.
- The arguments may themselves be Call objects.
- """
- def __init__(self, function, arguments):
- self.function = function
- self.arguments = arguments
-
-
-class CompressedArray(object):
- def __init__(self, null_value):
- self.null_value = null_value
- self.items = [null_value]
-
- def ensure_length(self, newlen):
- if newlen > len(self.items):
- self.items.extend([self.null_value] * (newlen - len(self.items)))
-
- def insert_subarray(self, array):
- # insert the given array of numbers into the indexlist,
- # allowing null values to become non-null
- if array.count(self.null_value) == len(array):
- return 0
- test = 1
- while True:
- self.ensure_length(test+len(array))
- for i in xrange(len(array)):
- if not (array[i] == self.items[test+i] or
- array[i] == self.null_value or
- self.items[test+i] == self.null_value):
- break
- else:
- # success
- for i in range(len(array)):
- if array[i] != self.null_value:
- self.items[test+i] = array[i]
- return test
- test += 1
-
- def _freeze_(self):
- return True
-
-
-class MRDTable(object):
- # Multi-Method Dispatch Using Multiple Row Displacement,
- # Candy Pang, Wade Holst, Yuri Leontiev, and Duane Szafron
- # University of Alberta, Edmonton AB T6G 2H1 Canada
- # can be found on http://web.cs.ualberta.ca/~yuri/publ.htm
-
- Counter = 0
-
- def __init__(self, list_of_types):
- self.id = MRDTable.Counter
- MRDTable.Counter += 1
- self.list_of_types = list_of_types
- self.typenum = dict(zip(list_of_types, range(len(list_of_types))))
- self.attrname = '__mrd%d_typenum' % self.id
- for t1, num in self.typenum.items():
- setattr(t1, self.attrname, num)
- self.indexarray = CompressedArray(0)
-
- def get_typenum(self, cls):
- return self.typenum[cls]
-
- def is_anti_range(self, typenums):
- # NB. typenums should be sorted. Returns (a, b) if typenums contains
- # at least half of all typenums and its complement is range(a, b).
- # Returns (None, None) otherwise. Returns (0, 0) if typenums contains
- # everything.
- n = len(self.list_of_types)
- if len(typenums) <= n // 2:
- return (None, None)
- typenums = dict.fromkeys(typenums)
- complement = [typenum for typenum in range(n)
- if typenum not in typenums]
- if not complement:
- return (0, 0)
- a = min(complement)
- b = max(complement) + 1
- if complement == range(a, b):
- return (a, b)
- else:
- return (None, None)
-
- def normalize_length(self, next_array):
- # make sure that the indexarray is not smaller than any funcarray
- self.indexarray.ensure_length(len(next_array.items))
-
-
-def invent_name(miniglobals, obj):
- if isinstance(obj, str):
- return obj
- name = obj.__name__
- n = 1
- while name in miniglobals:
- n += 1
- name = '%s%d' % (obj.__name__, n)
- miniglobals[name] = obj
- return name
-
-
-class FuncEntry(object):
-
- def __init__(self, bodylines, miniglobals, fallback):
- self.body = '\n '.join(bodylines)
- self.miniglobals = miniglobals
- self.fallback = fallback
- self.possiblenames = []
- self.typetree = {}
- self._function = None
-
- def key(self):
- lst = self.miniglobals.items()
- lst.sort()
- return self.body, tuple(lst)
-
- def get_function_name(self):
- # pick a name consistently based on self.possiblenames
- length = min([len(parts) for parts in self.possiblenames])
- result = []
- for i in range(length):
- choices = {}
- for parts in self.possiblenames:
- choices[parts[i]] = True
- parts = choices.keys()
- res = str(len(parts))
- for part in parts:
- if type(part) is str: # there is a string at this pos
- if '0_fail' in choices:
- res = '0_fail'
- elif len(parts) == 1:
- res = part
- break
- else:
- # only types at this location, try to find a common base
- basecls = parts[0]
- for cls in parts[1:]:
- if issubclass(basecls, cls):
- basecls = cls
- for cls in parts[1:]:
- if not issubclass(cls, basecls):
- break # no common base
- else:
- res = basecls.__name__
- result.append(res)
- return '_'.join(result)
-
- def make_function(self, fnargs, nbargs_before, mrdtable):
- if self._function is not None:
- return self._function
- name = self.get_function_name()
- self.compress_typechecks(mrdtable)
- checklines = self.generate_typechecks(mrdtable, fnargs[nbargs_before:])
- if not checklines:
- body = self.body
- else:
- checklines.append(self.body)
- body = '\n '.join(checklines)
- source = 'def %s(%s):\n %s\n' % (name, ', '.join(fnargs), body)
- self.debug_dump(source)
- exec compile2(source) in self.miniglobals
- self._function = self.miniglobals[name]
- return self._function
-
- def debug_dump(self, source):
- if 0: # for debugging the generated mm sources
- name = self.get_function_name()
- f = open('/tmp/mm-source/%s' % name, 'a')
- for possiblename in self.possiblenames:
- print >> f, '#',
- for part in possiblename:
- print >> f, getattr(part, '__name__', part),
- print >> f
- print >> f
- print >> f, source
- f.close()
-
- def register_valid_types(self, types):
- node = self.typetree
- for t1 in types[:-1]:
- if node is True:
- return
- node = node.setdefault(t1, {})
- if node is True:
- return
- node[types[-1]] = True
-
- def no_typecheck(self):
- self.typetree = True
-
- def compress_typechecks(self, mrdtable):
- def full(node):
- if node is True:
- return 1
- fulls = 0
- for key, subnode in node.items():
- if full(subnode):
- node[key] = True
- fulls += 1
- if fulls == types_total:
- return 1
- return 0
-
- types_total = len(mrdtable.list_of_types)
- if full(self.typetree):
- self.typetree = True
-
- def generate_typechecks(self, mrdtable, args):
- attrname = mrdtable.attrname
- possibletypes = [{} for _ in args]
- any_type_is_ok = [False for _ in args]
-
- def generate(node, level=0):
- # this generates type-checking code like the following:
- #
- # _argtypenum = arg1.__typenum
- # if _argtypenum == 5:
- # ...
- # elif _argtypenum == 6 or _argtypenum == 8:
- # ...
- # else:
- # _failedtoimplement = True
- #
- # or, in the common particular case of an "anti-range", we optimize it to:
- #
- # _argtypenum = arg1.__typenum
- # if _argtypenum < 5 or _argtypenum >= 10:
- # ...
- # else:
- # _failedtoimplement = True
- #
- result = []
- indent = ' '*level
- if node is True:
- for i in range(level, len(args)):
- any_type_is_ok[i] = True
- result.append('%s_failedtoimplement = False' % (indent,))
- return result
- if not node:
- result.append('%s_failedtoimplement = True' % (indent,))
- return result
- result.append('%s_argtypenum = %s.%s' % (indent, args[level],
- attrname))
- cases = {}
- for key, subnode in node.items():
- possibletypes[level][key] = True
- casebody = tuple(generate(subnode, level+1))
- typenum = mrdtable.get_typenum(key)
- cases.setdefault(casebody, []).append(typenum)
- for casebody, typenums in cases.items():
- typenums.sort()
More information about the pypy-commit
mailing list