[pypy-svn] r8969 - in pypy/dist/pypy: interpreter module objspace/std objspace/std/test
pedronis at codespeak.net
pedronis at codespeak.net
Mon Feb 7 20:26:08 CET 2005
Author: pedronis
Date: Mon Feb 7 20:26:07 2005
New Revision: 8969
Added:
pypy/dist/pypy/objspace/std/model.py (props changed)
- copied unchanged from r8967, pypy/branch/dist-simpler-multimethods/pypy/objspace/std/model.py
Modified:
pypy/dist/pypy/interpreter/gateway.py
pypy/dist/pypy/interpreter/pycode.py
pypy/dist/pypy/module/__builtin__interp.py
pypy/dist/pypy/objspace/std/boolobject.py
pypy/dist/pypy/objspace/std/booltype.py
pypy/dist/pypy/objspace/std/default.py
pypy/dist/pypy/objspace/std/dictobject.py
pypy/dist/pypy/objspace/std/dicttype.py
pypy/dist/pypy/objspace/std/fake.py
pypy/dist/pypy/objspace/std/floatobject.py
pypy/dist/pypy/objspace/std/floattype.py
pypy/dist/pypy/objspace/std/intobject.py
pypy/dist/pypy/objspace/std/inttype.py
pypy/dist/pypy/objspace/std/itertype.py
pypy/dist/pypy/objspace/std/listobject.py
pypy/dist/pypy/objspace/std/longobject.py
pypy/dist/pypy/objspace/std/longtype.py
pypy/dist/pypy/objspace/std/multimethod.py
pypy/dist/pypy/objspace/std/noneobject.py
pypy/dist/pypy/objspace/std/objspace.py
pypy/dist/pypy/objspace/std/register_all.py
pypy/dist/pypy/objspace/std/sliceobject.py
pypy/dist/pypy/objspace/std/stdtypedef.py
pypy/dist/pypy/objspace/std/stringobject.py
pypy/dist/pypy/objspace/std/stringtype.py
pypy/dist/pypy/objspace/std/test/test_multimethod.py
pypy/dist/pypy/objspace/std/tupleobject.py
pypy/dist/pypy/objspace/std/tupletype.py
pypy/dist/pypy/objspace/std/typeobject.py
pypy/dist/pypy/objspace/std/unicodeobject.py
Log:
merged dist-simpler-multimethods branch.
Modified: pypy/dist/pypy/interpreter/gateway.py
==============================================================================
--- pypy/dist/pypy/interpreter/gateway.py (original)
+++ pypy/dist/pypy/interpreter/gateway.py Mon Feb 7 20:26:07 2005
@@ -14,12 +14,14 @@
from pypy.tool import hack
from pypy.interpreter.error import OperationError
-from pypy.interpreter import eval, pycode
+from pypy.interpreter import eval
from pypy.interpreter.function import Function, Method
from pypy.interpreter.baseobjspace import W_Root,ObjSpace,Wrappable
from pypy.interpreter.argument import Arguments
from pypy.tool.cache import Cache
+NoneNotWrapped = object()
+
class Signature:
def __init__(self, func=None, argnames=None, varargname=None,
kwargname=None, name = None):
@@ -127,7 +129,16 @@
assert new_sig.varargname is None,(
"built-in function %r has conflicting rest args specs" % orig_sig.func)
new_sig.varargname = argname[:-2]
-
+
+def unwrap_spec_check_w_args(orig_sig, new_sig):
+ argname = orig_sig.next()
+ assert argname.startswith('w_'), (
+ "rest arguments arg %s of built-in function %r should start 'w_'" %
+ (argname, orig_sig.func))
+ assert new_sig.varargname is None,(
+ "built-in function %r has conflicting rest args specs" % orig_sig.func)
+ new_sig.varargname = argname[2:]
+
# recipes for checking interp2app func argumes wrt unwrap_spec
unwrap_spec_checks = {
ObjSpace: unwrap_spec_check_space,
@@ -136,6 +147,7 @@
Arguments: unwrap_spec_check_arguments,
'*': unwrap_spec_check_starargs,
'args_w': unwrap_spec_check_args_w,
+ 'w_args': unwrap_spec_check_w_args,
}
def unwrap_spec_emit_space(orig_sig, new_sig):
@@ -178,6 +190,13 @@
(new_sig.through_scope_w))
new_sig.through_scope_w += 1
new_sig.run_args.append("self.args_w")
+
+def unwrap_spec_emit_w_args(orig_sig, new_sig):
+ cur = new_sig.through_scope_w
+ new_sig.setfastscope.append(
+ "self.w_args = scope_w[%d]" % cur)
+ new_sig.through_scope_w += 1
+ new_sig.run_args.append("self.w_args")
# recipes for emitting unwrapping code for arguments of a interp2app func
# wrt a unwrap_spec
@@ -188,6 +207,7 @@
Arguments: unwrap_spec_emit_arguments,
'*': unwrap_spec_emit_starargs,
'args_w': unwrap_spec_emit_args_w,
+ 'w_args': unwrap_spec_emit_w_args,
}
# unwrap_spec_check/emit for str,int,float
@@ -257,10 +277,12 @@
# 'self' is used to specify a self method argument
# baseobjspace.W_Root is for wrapped arguments to keep wrapped
# argument.Arguments is for a final rest arguments Arguments object
- # 'args_w' for unpacktuple applied rest arguments
+ # 'args_w' for unpacktuple applied to rest arguments
+ # 'w_args' for rest arguments passed as wrapped tuple
# str,int,float: unwrap argument as such type
# First extract the signature from the (CPython-level) code object
+ from pypy.interpreter import pycode
argnames, varargname, kwargname = pycode.cpython_code_signature(func.func_code)
if unwrap_spec is None:
@@ -459,6 +481,7 @@
raise ValueError, ("function name must start with 'app_'; "
"%r does not" % app.func_name)
app_name = app.func_name[4:]
+ self.__name__ = app.func_name
self.name = app_name
self._staticcode = app.func_code
self._staticglobals = app.func_globals
@@ -466,6 +489,7 @@
def getcode(self, space):
"NOT_RPYTHON"
+ from pypy.interpreter import pycode
code = pycode.PyCode(space)
code._from_code(self._staticcode)
return code
@@ -518,6 +542,7 @@
self._code = BuiltinCode(f, ismethod=ismethod,
spacearg=spacearg,
unwrap_spec=unwrap_spec)
+ self.__name__ = f.func_name
self.name = app_name
self._staticdefs = list(f.func_defaults or ())
#if self._staticdefs:
@@ -531,8 +556,8 @@
"NOT_RPYTHON"
defs_w = []
for val in self._staticdefs:
- if val is None:
- defs_w.append(val)
+ if val is NoneNotWrapped:
+ defs_w.append(None)
else:
defs_w.append(space.wrap(val))
return defs_w
Modified: pypy/dist/pypy/interpreter/pycode.py
==============================================================================
--- pypy/dist/pypy/interpreter/pycode.py (original)
+++ pypy/dist/pypy/interpreter/pycode.py Mon Feb 7 20:26:07 2005
@@ -6,6 +6,7 @@
import dis
from pypy.interpreter import eval
+from pypy.interpreter.gateway import NoneNotWrapped
from pypy.tool.cache import Cache
# helper
@@ -194,7 +195,8 @@
w_argcount, w_nlocals, w_stacksize, w_flags,
w_codestring, w_constants, w_names,
w_varnames, w_filename, w_name, w_firstlineno,
- w_lnotab, w_freevars=None, w_cellvars=None):
+ w_lnotab, w_freevars=NoneNotWrapped,
+ w_cellvars=NoneNotWrapped):
code = space.allocate_instance(PyCode, w_subtype)
code.__init__(space)
# XXX typechecking everywhere!
Modified: pypy/dist/pypy/module/__builtin__interp.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__interp.py (original)
+++ pypy/dist/pypy/module/__builtin__interp.py Mon Feb 7 20:26:07 2005
@@ -5,6 +5,7 @@
from pypy.interpreter.pycode import PyCode
from pypy.interpreter.error import OperationError
from pypy.interpreter.baseobjspace import BaseWrappable, W_Root
+from pypy.interpreter.gateway import NoneNotWrapped
import __builtin__ as cpy_builtin
@@ -225,7 +226,7 @@
compile.unwrap_spec = [str,str,str,int,int]
-def eval(w_source, w_globals=None, w_locals=None):
+def eval(w_source, w_globals=NoneNotWrapped, w_locals=NoneNotWrapped):
w = space.wrap
if space.is_true(space.isinstance(w_source, space.w_str)):
@@ -259,7 +260,7 @@
space.delattr(w_object, w_name)
return space.w_None
-def getattr(w_object, w_name, w_defvalue=None):
+def getattr(w_object, w_name, w_defvalue=NoneNotWrapped):
try:
return space.getattr(w_object, w_name)
except OperationError, e:
@@ -278,9 +279,7 @@
def hex(w_val):
return space.hex(w_val)
-def round(w_val, w_n=None):
- if w_n is None:
- w_n = space.wrap(0)
+def round(w_val, w_n=0):
return space.round(w_val, w_n)
def id(w_object):
@@ -295,7 +294,7 @@
def _issubtype(w_cls1, w_cls2):
return space.issubtype(w_cls1, w_cls2)
-def iter(w_collection_or_callable, w_sentinel=None):
+def iter(w_collection_or_callable, w_sentinel=NoneNotWrapped):
if w_sentinel is None:
return space.iter(w_collection_or_callable)
else:
@@ -308,8 +307,6 @@
return space.ord(w_val)
def pow(w_base, w_exponent, w_modulus=None):
- if w_modulus is None:
- w_modulus = space.w_None
return space.pow(w_base, w_exponent, w_modulus)
def repr(w_object):
Modified: pypy/dist/pypy/objspace/std/boolobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/boolobject.py (original)
+++ pypy/dist/pypy/objspace/std/boolobject.py Mon Feb 7 20:26:07 2005
@@ -16,22 +16,20 @@
""" representation for debugging purposes """
return "%s(%s)" % (w_self.__class__.__name__, w_self.boolval)
+ def unwrap(w_self):
+ return w_self.boolval
+
registerimplementation(W_BoolObject)
# bool-to-int delegation requires translating the .boolvar attribute
# to an .intval one
-def delegate__Bool(space, w_bool):
- return intobject.W_IntObject(space, int(w_bool.boolval))
-delegate__Bool.result_class = intobject.W_IntObject
-delegate__Bool.priority = PRIORITY_PARENT_TYPE
+def delegate_Bool2Int(w_bool):
+ return intobject.W_IntObject(w_bool.space, int(w_bool.boolval))
def nonzero__Bool(space, w_bool):
return w_bool
-def unwrap__Bool(space, w_bool):
- return w_bool.boolval
-
def repr__Bool(space, w_bool):
if w_bool.boolval:
return space.wrap('True')
Modified: pypy/dist/pypy/objspace/std/booltype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/booltype.py (original)
+++ pypy/dist/pypy/objspace/std/booltype.py Mon Feb 7 20:26:07 2005
@@ -5,7 +5,7 @@
def descr__new__(space, w_booltype, w_obj=None):
- if w_obj is not None and space.is_true(w_obj):
+ if space.is_true(w_obj):
return space.w_True
else:
return space.w_False
Modified: pypy/dist/pypy/objspace/std/default.py
==============================================================================
--- pypy/dist/pypy/objspace/std/default.py (original)
+++ pypy/dist/pypy/objspace/std/default.py Mon Feb 7 20:26:07 2005
@@ -13,7 +13,7 @@
# __init__ should succeed if called internally as a multimethod
-def init__ANY(space, w_obj, w_args, w_kwds):
+def init__ANY(space, w_obj, __args__):
pass
@@ -216,9 +216,6 @@
# ugh
-class UnwrapError(Exception):
- pass
-
def typed_unwrap_error_msg(space, expected, w_obj):
w = space.wrap
type_name = space.str_w(space.getattr(space.type(w_obj),w("__name__")))
@@ -236,11 +233,5 @@
raise OperationError(space.w_TypeError,
typed_unwrap_error_msg(space, "float", w_obj))
-def unwrap__ANY(space, w_obj):
- if isinstance(w_obj, BaseWrappable):
- return w_obj
- else:
- raise UnwrapError, 'cannot unwrap %r' % (w_obj,)
-
register_all(vars())
Modified: pypy/dist/pypy/objspace/std/dictobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/dictobject.py (original)
+++ pypy/dist/pypy/objspace/std/dictobject.py Mon Feb 7 20:26:07 2005
@@ -98,40 +98,40 @@
freeslot = entry
perturb >>= 5
-registerimplementation(W_DictObject)
+ def unwrap(w_dict):
+ space = w_dict.space
+ result = {}
+ for entry in w_dict.non_empties():
+ # XXX generic mixed types unwrap
+ result[space.unwrap(entry.w_key)] = space.unwrap(entry.w_value)
+ return result
+registerimplementation(W_DictObject)
-def unwrap__Dict(space, w_dict):
- result = {}
- for entry in w_dict.non_empties():
- result[space.unwrap(entry.w_key)] = space.unwrap(entry.w_value) # XXX generic mixed types unwrap
- return result
-def init__Dict(space, w_dict, w_args, w_kwds):
+def init__Dict(space, w_dict, __args__):
+ w_src, w_kwds = __args__.parse('dict',
+ (['seq_or_map'], None, 'kwargs'), # signature
+ [W_DictObject(space, [])]) # default argument
dict_clear__Dict(space, w_dict)
- args = space.unpackiterable(w_args)
- if len(args) == 0:
- pass
- elif len(args) == 1:
- # XXX do dict({...}) with dict_update__Dict_Dict()
- try:
- space.getattr(args[0], space.wrap("keys"))
- except OperationError:
- list_of_w_pairs = space.unpackiterable(args[0])
- for w_pair in list_of_w_pairs:
- pair = space.unpackiterable(w_pair)
- if len(pair)!=2:
- raise OperationError(space.w_ValueError,
- space.wrap("dict() takes a sequence of pairs"))
- w_k, w_v = pair
- setitem__Dict_ANY_ANY(space, w_dict, w_k, w_v)
- else:
- from pypy.objspace.std.dicttype import dict_update__ANY_ANY
- dict_update__ANY_ANY(space, w_dict, args[0])
+ # XXX do dict({...}) with dict_update__Dict_Dict()
+ try:
+ space.getattr(w_src, space.wrap("keys"))
+ except OperationError:
+ list_of_w_pairs = space.unpackiterable(w_src)
+ for w_pair in list_of_w_pairs:
+ pair = space.unpackiterable(w_pair)
+ if len(pair)!=2:
+ raise OperationError(space.w_ValueError,
+ space.wrap("dict() takes a sequence of pairs"))
+ w_k, w_v = pair
+ setitem__Dict_ANY_ANY(space, w_dict, w_k, w_v)
else:
- raise OperationError(space.w_TypeError,
- space.wrap("dict() takes at most 1 argument"))
- space.call_method(w_dict, 'update', w_kwds)
+ if space.is_true(w_src):
+ from pypy.objspace.std.dicttype import dict_update__ANY_ANY
+ dict_update__ANY_ANY(space, w_dict, w_src)
+ if space.is_true(w_kwds):
+ space.call_method(w_dict, 'update', w_kwds)
def getitem__Dict_ANY(space, w_dict, w_lookup):
entry = w_dict.lookdict(w_dict.hash(w_lookup), w_lookup)
Modified: pypy/dist/pypy/objspace/std/dicttype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/dicttype.py (original)
+++ pypy/dist/pypy/objspace/std/dicttype.py Mon Feb 7 20:26:07 2005
@@ -8,7 +8,7 @@
dict_has_key = MultiMethod('has_key', 2)
dict_clear = MultiMethod('clear', 1)
dict_get = MultiMethod('get', 3, defaults=(None,))
-dict_pop = MultiMethod('pop', 2, varargs=True)
+dict_pop = MultiMethod('pop', 2, w_varargs=True)
dict_popitem = MultiMethod('popitem', 1)
dict_setdefault = MultiMethod('setdefault', 3, defaults=(None,))
dict_update = MultiMethod('update', 2)
Modified: pypy/dist/pypy/objspace/std/fake.py
==============================================================================
--- pypy/dist/pypy/objspace/std/fake.py (original)
+++ pypy/dist/pypy/objspace/std/fake.py Mon Feb 7 20:26:07 2005
@@ -4,7 +4,7 @@
from pypy.interpreter.function import Function
from pypy.objspace.std.stdtypedef import *
from pypy.objspace.std.objspace import W_Object, StdObjSpace
-from pypy.objspace.std.default import UnwrapError
+from pypy.objspace.std.model import UnwrapError
from pypy.tool.cache import Cache
# this file automatically generates non-reimplementations of CPython
@@ -83,13 +83,12 @@
def __init__(w_self, space, val):
W_Object.__init__(w_self, space)
w_self.val = val
+ def unwrap(w_self):
+ return w_self.val
# cannot write to W_Fake.__name__ in Python 2.2!
W_Fake = type(W_Object)('W_Fake%s'%(cpy_type.__name__.capitalize()),
(W_Object,),
dict(W_Fake.__dict__.items()))
- def fake_unwrap(space, w_obj):
- return w_obj.val
- StdObjSpace.unwrap.register(fake_unwrap, W_Fake)
W_Fake.typedef.fakedcpytype = cpy_type
return W_Fake
Modified: pypy/dist/pypy/objspace/std/floatobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/floatobject.py (original)
+++ pypy/dist/pypy/objspace/std/floatobject.py Mon Feb 7 20:26:07 2005
@@ -21,14 +21,19 @@
W_Object.__init__(w_self, space)
w_self.floatval = floatval
+ def unwrap(w_self):
+ return w_self.floatval
+
registerimplementation(W_FloatObject)
+# bool-to-float delegation
+def delegate_Bool2Float(w_bool):
+ return W_FloatObject(w_bool.space, float(w_bool.boolval))
+
# int-to-float delegation
-def delegate__Int(space, w_intobj):
- return W_FloatObject(space, float(w_intobj.intval))
-delegate__Int.result_class = W_FloatObject
-delegate__Int.priority = PRIORITY_CHANGE_TYPE
+def delegate_Int2Float(w_intobj):
+ return W_FloatObject(w_intobj.space, float(w_intobj.intval))
# float__Float is supposed to do nothing, unless it has
@@ -49,9 +54,6 @@
def float_w__Float(space, w_float):
return w_float.floatval
-def unwrap__Float(space, w_float):
- return w_float.floatval
-
def app_repr__Float(f):
r = "%.17g"%f
for c in r:
Modified: pypy/dist/pypy/objspace/std/floattype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/floattype.py (original)
+++ pypy/dist/pypy/objspace/std/floattype.py Mon Feb 7 20:26:07 2005
@@ -1,11 +1,9 @@
from pypy.objspace.std.stdtypedef import *
from pypy.interpreter.error import OperationError
-def descr__new__(space, w_floattype, w_value=None):
+def descr__new__(space, w_floattype, w_value=0.0):
from pypy.objspace.std.floatobject import W_FloatObject
- if w_value is None:
- value = 0.0
- elif space.is_true(space.isinstance(w_value, space.w_str)):
+ if space.is_true(space.isinstance(w_value, space.w_str)):
try:
value = float(space.str_w(w_value))
except ValueError, e:
Modified: pypy/dist/pypy/objspace/std/intobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/intobject.py (original)
+++ pypy/dist/pypy/objspace/std/intobject.py Mon Feb 7 20:26:07 2005
@@ -28,6 +28,9 @@
""" representation for debugging purposes """
return "%s(%d)" % (w_self.__class__.__name__, w_self.intval)
+ def unwrap(w_self):
+ return int(w_self.intval)
+
registerimplementation(W_IntObject)
@@ -43,9 +46,6 @@
def int_w__Int(space, w_int1):
return int(w_int1.intval)
-def unwrap__Int(space, w_int1):
- return int(w_int1.intval)
-
def repr__Int(space, w_int1):
a = w_int1.intval
res = str(a)
Modified: pypy/dist/pypy/objspace/std/inttype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/inttype.py (original)
+++ pypy/dist/pypy/objspace/std/inttype.py Mon Feb 7 20:26:07 2005
@@ -1,14 +1,13 @@
from pypy.objspace.std.stdtypedef import *
from pypy.objspace.std.strutil import string_to_int
from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import NoneNotWrapped
-def descr__new__(space, w_inttype, w_value=None, w_base=None):
+def descr__new__(space, w_inttype, w_value=0, w_base=NoneNotWrapped):
from pypy.objspace.std.intobject import W_IntObject
if w_base is None:
# check for easy cases
- if w_value is None:
- value = 0
- elif isinstance(w_value, W_IntObject):
+ if isinstance(w_value, W_IntObject):
value = w_value.intval
elif space.is_true(space.isinstance(w_value, space.w_str)):
try:
Modified: pypy/dist/pypy/objspace/std/itertype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/itertype.py (original)
+++ pypy/dist/pypy/objspace/std/itertype.py Mon Feb 7 20:26:07 2005
@@ -2,5 +2,5 @@
# ____________________________________________________________
-iter_typedef = StdTypeDef("sequence-iterator",
+iter_typedef = StdTypeDef("sequenceiterator",
)
Modified: pypy/dist/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/listobject.py (original)
+++ pypy/dist/pypy/objspace/std/listobject.py Mon Feb 7 20:26:07 2005
@@ -29,52 +29,47 @@
reprlist = [repr(w_item) for w_item in w_self.ob_item[:w_self.ob_size]]
return "%s(%s)" % (w_self.__class__.__name__, ', '.join(reprlist))
+ def unwrap(w_list):
+ space = w_list.space
+ items = [space.unwrap(w_item) for w_item in w_list.ob_item[:w_list.ob_size]]# XXX generic mixed types unwrap
+ return list(items)
+
registerimplementation(W_ListObject)
-def unwrap__List(space, w_list):
- items = [space.unwrap(w_item) for w_item in w_list.ob_item[:w_list.ob_size]]# XXX generic mixed types unwrap
- return list(items)
-
-def init__List(space, w_list, w_args, w_kwds):
- if space.is_true(w_kwds):
- raise OperationError(space.w_TypeError,
- space.wrap("no keyword arguments expected"))
+def init__List(space, w_list, __args__):
+ w_iterable, = __args__.parse('list',
+ (['sequence'], None, None), # signature
+ [W_ListObject(space, [])]) # default argument
w_list.ob_size = 0 # XXX think about it later
- args = space.unpackiterable(w_args)
- if len(args) == 0:
- pass # empty list
- elif len(args) == 1:
- w_iterable = args[0]
- length = 0
+
+ length = 0
+ try:
+ length = space.int_w(space.len(w_iterable))
+ if length < 0:
+ length = 8
+ except OperationError, e:
+ pass # for now
+ _list_resize(w_list, length)
+ w_iterator = space.iter(w_iterable)
+ while True:
try:
- length = space.int_w(space.len(w_iterable))
- if length < 0:
- length = 8
+ w_item = space.next(w_iterator)
except OperationError, e:
- pass # for now
- _list_resize(w_list, length)
- w_iterator = space.iter(w_iterable)
- while True:
- try:
- w_item = space.next(w_iterator)
- except OperationError, e:
- if not e.match(space, space.w_StopIteration):
- raise
- break # done
- _ins1(w_list, w_list.ob_size, w_item)
- else:
- raise OperationError(space.w_TypeError,
- space.wrap("list() takes at most 1 argument"))
+ if not e.match(space, space.w_StopIteration):
+ raise
+ break # done
+ _ins1(w_list, w_list.ob_size, w_item)
+
def len__List(space, w_list):
result = w_list.ob_size
return W_IntObject(space, result)
-def getitem__List_Int(space, w_list, w_index):
+def getitem__List_ANY(space, w_list, w_index):
items = w_list.ob_item
- idx = w_index.intval
+ idx = space.int_w(w_index)
if idx < 0:
idx += w_list.ob_size
if idx < 0 or idx >= w_list.ob_size:
@@ -129,9 +124,8 @@
list_extend__List_ANY(space, w_list1, w_iterable2)
return w_list1
-def mul__List_Int(space, w_list, w_int):
+def mul_list_times(space, w_list, times):
w_res = W_ListObject(space, [])
- times = w_int.intval
src = w_list.ob_item
size = w_list.ob_size
newlen = size * times # XXX check overflow
@@ -145,8 +139,11 @@
w_res.ob_size = p
return w_res
-def mul__Int_List(space, w_int, w_list):
- return mul__List_Int(space, w_list, w_int)
+def mul__List_ANY(space, w_list, w_times):
+ return mul_list_times(space, w_list, space.int_w(w_times))
+
+def mul__ANY_List(space, w_times, w_list):
+ return mul_list_times(space, w_list, space.int_w(w_times))
def eq__List_List(space, w_list1, w_list2):
items1 = w_list1.ob_item
@@ -188,8 +185,8 @@
# upto here, lists are nearly identical to tuples, despite the
# fact that we now support over-allocation!
-def delitem__List_Int(space, w_list, w_idx):
- i = w_idx.intval
+def delitem__List_ANY(space, w_list, w_idx):
+ i = space.int_w(w_idx)
if i < 0:
i += w_list.ob_size
if i < 0 or i >= w_list.ob_size:
@@ -217,9 +214,9 @@
_del_slice(w_list, i, i+1)
return space.w_None
-def setitem__List_Int_ANY(space, w_list, w_index, w_any):
+def setitem__List_ANY_ANY(space, w_list, w_index, w_any):
items = w_list.ob_item
- idx = w_index.intval
+ idx = space.int_w(w_index)
if idx < 0:
idx += w_list.ob_size
if idx < 0 or idx >= w_list.ob_size:
Modified: pypy/dist/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/longobject.py (original)
+++ pypy/dist/pypy/objspace/std/longobject.py Mon Feb 7 20:26:07 2005
@@ -17,9 +17,25 @@
assert isinstance(longval, long)
w_self.longval = longval
+ def unwrap(w_self):
+ return w_self.longval
+
registerimplementation(W_LongObject)
+# bool-to-long
+def delegate_Bool2Long(w_bool):
+ return W_LongObject(w_bool.space, long(w_bool.boolval))
+
+# int-to-long delegation
+def delegate_Int2Long(w_intobj):
+ return W_LongObject(w_intobj.space, long(w_intobj.intval))
+
+# long-to-float delegation
+def delegate_Long2Float(w_longobj):
+ return W_FloatObject(w_longobj.space, float(w_longobj.longval))
+
+
# long__Long is supposed to do nothing, unless it has
# a derived long object, where it should return
# an exact one.
@@ -56,9 +72,6 @@
raise OperationError(space.w_OverflowError,
space.wrap("long int too large to convert to int"))
-def unwrap__Long(space, w_long):
- return w_long.longval
-
def repr__Long(space, w_long):
return space.wrap(repr(w_long.longval))
@@ -223,35 +236,47 @@
register_all(vars())
-# delegations must be registered manually because we have more than one
-# long-to-something delegation
+# register implementations of ops that recover int op overflows
-# int-to-long delegation
-def delegate_from_int(space, w_intobj):
- return W_LongObject(space, long(w_intobj.intval))
-delegate_from_int.result_class = W_LongObject
-delegate_from_int.priority = PRIORITY_CHANGE_TYPE
-
-StdObjSpace.delegate.register(delegate_from_int, W_IntObject)
-
-# long-to-int delegation
-def delegate_to_int(space, w_longobj):
- if -sys.maxint-1 <= w_longobj.longval <= sys.maxint:
- return W_IntObject(space, int(w_longobj.longval))
- else:
- # note the 'return' here -- hack
- return FailedToImplement(space.w_OverflowError,
- space.wrap("long int too large to convert to int"))
-delegate_to_int.result_class = W_IntObject
-delegate_to_int.priority = PRIORITY_CHANGE_TYPE
-delegate_to_int.can_fail = True
-
-StdObjSpace.delegate.register(delegate_to_int, W_LongObject)
-
-# long-to-float delegation
-def delegate_to_float(space, w_longobj):
- return W_FloatObject(space, float(w_longobj.longval))
-delegate_to_float.result_class = W_FloatObject
-delegate_to_float.priority = PRIORITY_CHANGE_TYPE
+# binary ops
+for opname in ['add', 'sub', 'mul', 'div', 'floordiv', 'truediv', 'mod', 'divmod']:
+ exec """
+def %(opname)s_ovr__Int_Int(space, w_int1, w_int2):
+ w_long1 = delegate_Int2Long(w_int1)
+ w_long2 = delegate_Int2Long(w_int2)
+ return %(opname)s__Long_Long(space, w_long1, w_long2)
+""" % {'opname': opname}
+
+ getattr(StdObjSpace.MM, opname).register(globals()['%s_ovr__Int_Int' %opname], W_IntObject, W_IntObject, order=1)
+
+# unary ops
+for opname in ['neg', 'abs']:
+ exec """
+def %(opname)s_ovr__Int(space, w_int1):
+ w_long1 = delegate_Int2Long(w_int1)
+ return %(opname)s__Long(space, w_long1)
+""" % {'opname': opname}
+
+ getattr(StdObjSpace.MM, opname).register(globals()['%s_ovr__Int' %opname], W_IntObject, order=1)
+
+# lshift
+def lshift_ovr__Int_Int(space, w_int1, w_cnt):
+ w_long1 = delegate_Int2Long(w_int1)
+ return lshift__Long_Int(space, w_long1, w_cnt)
+
+StdObjSpace.MM.lshift.register(lshift_ovr__Int_Int, W_IntObject, W_IntObject, order=1)
+
+# pow
+def pow_ovr__Int_Int_None(space, w_int1, w_int2, w_none3):
+ w_long1 = delegate_Int2Long(w_int1)
+ w_long2 = delegate_Int2Long(w_int2)
+ return pow__Long_Long_None(space, w_long1, w_long2, w_none3)
+
+def pow_ovr__Int_Int_Int(space, w_int1, w_int2, w_int3):
+ w_long1 = delegate_Int2Long(w_int1)
+ w_long2 = delegate_Int2Long(w_int2)
+ w_long3 = delegate_Int2Long(w_int3)
+ return pow__Long_Long_Long(space, w_long1, w_long2, w_long3)
-StdObjSpace.delegate.register(delegate_to_float, W_LongObject)
+StdObjSpace.MM.pow.register(pow_ovr__Int_Int_None, W_IntObject, W_IntObject, W_NoneObject, order=1)
+StdObjSpace.MM.pow.register(pow_ovr__Int_Int_Int , W_IntObject, W_IntObject, W_IntObject, order=1)
Modified: pypy/dist/pypy/objspace/std/longtype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/longtype.py (original)
+++ pypy/dist/pypy/objspace/std/longtype.py Mon Feb 7 20:26:07 2005
@@ -2,14 +2,13 @@
from pypy.objspace.std.strutil import string_to_long
from pypy.interpreter.error import OperationError
from pypy.objspace.std.inttype import int_typedef
+from pypy.interpreter.gateway import NoneNotWrapped
-def descr__new__(space, w_longtype, w_value=None, w_base=None):
+def descr__new__(space, w_longtype, w_value=0, w_base=NoneNotWrapped):
from pypy.objspace.std.longobject import W_LongObject
if w_base is None:
# check for easy cases
- if w_value is None:
- value = 0L
- elif isinstance(w_value, W_LongObject):
+ if isinstance(w_value, W_LongObject):
value = w_value.longval
elif space.is_true(space.isinstance(w_value, space.w_str)):
try:
Modified: pypy/dist/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/multimethod.py (original)
+++ pypy/dist/pypy/objspace/std/multimethod.py Mon Feb 7 20:26:07 2005
@@ -1,507 +1,260 @@
-from pypy.interpreter.baseobjspace import OperationError
-from pypy.tool.cache import Cache
-class FailedToImplement(Exception):
- "Signals the dispatcher to try harder."
-
-class W_ANY:
- "Catch-all in case multimethods don't find anything else."
- typedef = None
-
-
-# This file defines three major classes:
-#
-# MultiMethod is the class you instantiate explicitly.
-# It is essentially just a collection of registered functions.
-# If xxx is a MultiMethod, StdObjSpace.xxx is xxx again,
-# and space.xxx is a BoundMultiMethod.
-#
-# UnboundMultiMethod is a MultiMethod on which one argument
-# (typically the first one) has been restricted to be of some
-# statically known type. It is obtained by the syntax
-# W_XxxType.yyy, where W_XxxType is the static type class,
-# or explicitly by calling 'xxx.slice(typeclass, arg_position)'.
-# Its dispatch table is always a subset of the original MultiMethod's
-# dispatch table.
-#
-# The registration of a new function to a MultiMethod will be propagated
-# to all of its matching UnboundMultiMethod instances. The registration of
-# a function directly to an UnboundMultiMethod will register the function
-# to its base MultiMethod and invoke the same behavior.
-#
-# BoundMultiMethod is a MultiMethod or UnboundMultiMethod which
-# has been bound to a specific object space. It is obtained by
-# 'space.xxx' or explicitly by calling 'xxx.get(space)'.
-
-class AbstractMultiMethod(object):
- """Abstract base class for MultiMethod and UnboundMultiMethod
- i.e. the classes that are not bound to a specific space instance."""
- def __init__(self, operatorsymbol, arity):
- "NOT_RPYTHON: cannot create new multimethods dynamically"
- self.arity = arity
- self.operatorsymbol = operatorsymbol
- self.dispatch_table = {}
- self.cache_table = Cache()
- self.compilation_cache_table = {}
- self.cache_delegator_key = None
- self.dispatch_arity = 0
-
- def __repr__(self):
- return '<%s %s>' % (self.__class__.__name__, self.operatorsymbol)
-
- def register(self, function, *types):
- """NOT_RPYTHON: cannot register new multimethod
- implementations dynamically"""
- assert len(types) == self.arity
- functions = self.dispatch_table.setdefault(types, [])
- if function in functions:
- return False
- functions.append(function)
- self.cache_table.clear()
- self.compilation_cache_table.clear()
- self.adjust_dispatch_arity(types)
- return True
-
- def adjust_dispatch_arity(self, types):
- "NOT_RPYTHON"
- width = len(types)
- while width > self.dispatch_arity and types[width-1] is W_ANY:
- width -= 1
- self.dispatch_arity = width
-
- def compile_calllist(self, argclasses, delegate):
- """Compile a list of calls to try for the given classes of the
- arguments. Return a function that should be called with the
- actual arguments."""
- if delegate.key is not self.cache_delegator_key:
- self.cache_table.clear()
- self.compilation_cache_table.clear()
- self.cache_delegator_key = delegate.key
- return self.cache_table.getorbuild(argclasses,
- self.do_compile_calllist,
- delegate)
-
- def do_compile_calllist(self, argclasses, delegate):
- "NOT_RPYTHON"
- calllist = []
- self.internal_buildcalllist(argclasses, delegate, calllist)
- calllist = tuple(calllist)
- try:
- result = self.compilation_cache_table[calllist]
- except KeyError:
- result = self.internal_compilecalllist(calllist)
- self.compilation_cache_table[calllist] = result
- return result
-
- def internal_compilecalllist(self, calllist):
- "NOT_RPYTHON"
- source, glob = self.internal_sourcecalllist(calllist)
- # compile the function
- exec source in glob
- return glob['do']
-
- def internal_sourcecalllist(self, calllist):
- """NOT_RPYTHON
- Translate a call list into the source of a Python function
- which is optimized and doesn't do repeated conversions on the
- same arguments."""
- if len(calllist) == 1:
- fn, conversions = calllist[0]
- if conversions == ((),) * len(conversions):
- # no conversion, just calling a single function: return
- # that function directly
- return '', {'do': fn}
-
- #print '**** compile **** ', self.operatorsymbol, [
- # t.__name__ for t in argclasses]
- arglist = ['a%d'%i for i in range(self.dispatch_arity)] + ['*extraargs']
- source = ['def do(space,%s):' % ','.join(arglist)]
- converted = [{(): ('a%d'%i, False)} for i in range(self.dispatch_arity)]
-
- def make_conversion(argi, convtuple):
- if convtuple in converted[argi]:
- return converted[argi][convtuple]
- else:
- prev, can_fail = make_conversion(argi, convtuple[:-1])
- new = '%s_%d' % (prev, len(converted[argi]))
- fname = all_functions.setdefault(convtuple[-1],
- 'd%d' % len(all_functions))
- if can_fail:
- source.append(' if isinstance(%s, FailedToImplement):' % prev)
- source.append(' %s = %s' % (new, prev))
- source.append(' else:')
- indent = ' '
- else:
- indent = ' '
- source.append('%s%s = %s(space,%s)' % (indent, new, fname, prev))
- can_fail = can_fail or getattr(convtuple[-1], 'can_fail', False)
- converted[argi][convtuple] = new, can_fail
- return new, can_fail
-
- all_functions = {}
- has_firstfailure = False
- for fn, conversions in calllist:
- # make the required conversions
- fname = all_functions.setdefault(fn, 'f%d' % len(all_functions))
- arglist = []
- failcheck = []
- for i in range(self.dispatch_arity):
- argname, can_fail = make_conversion(i, conversions[i])
- arglist.append(argname)
- if can_fail:
- failcheck.append(argname)
- arglist.append('*extraargs')
- source.append( ' try:')
- for argname in failcheck:
- source.append(' if isinstance(%s, FailedToImplement):' % argname)
- source.append(' raise %s' % argname)
- source.append( ' return %s(space,%s)' % (
- fname, ','.join(arglist)))
- if has_firstfailure:
- source.append(' except FailedToImplement:')
- else:
- source.append(' except FailedToImplement, firstfailure:')
- has_firstfailure = True
- source.append( ' pass')
-
- # complete exhaustion
- if has_firstfailure:
- source.append(' raise firstfailure')
- else:
- source.append(' raise FailedToImplement()')
- source.append('')
-
- glob = {'FailedToImplement': FailedToImplement}
- for fn, fname in all_functions.items():
- glob[fname] = fn
- return '\n'.join(source), glob
-
- def internal_buildcalllist(self, argclasses, delegate, calllist):
- """NOT_RPYTHON
- Build a list of calls to try for the given classes of the
- arguments. The list contains 'calls' of the following form:
- (function-to-call, list-of-list-of-converters)
- The list of converters contains a list of converter functions per
- argument, with [] meaning that no conversion is needed for
- that argument."""
- # look for an exact match first
- arity = self.dispatch_arity
- assert arity == len(argclasses)
- dispatchclasses = tuple([(c,) for c in argclasses])
- choicelist = self.buildchoices(dispatchclasses)
- seen_functions = {}
- no_conversion = [()] * arity
- for signature, function in choicelist:
- calllist.append((function, tuple(no_conversion)))
- seen_functions[function] = 1
-
- # proceed by expanding the last argument by delegation, step by step
- # until no longer possible, and then the previous argument, and so on.
- expanded_args = ()
- expanded_dispcls = ()
-
- for argi in range(arity-1, -1, -1):
- # growing tuple of dispatch classes we can delegate to
- curdispcls = dispatchclasses[argi]
- assert len(curdispcls) == 1
- # maps each dispatch class to a list of converters
- curargs = {curdispcls[0]: []}
- # reduce dispatchclasses to the arguments before this one
- # (on which no delegation has been tried yet)
- dispatchclasses = dispatchclasses[:argi]
- no_conversion = no_conversion[:argi]
-
- while 1:
- choicelist = delegate.buildchoices((curdispcls,))
- # the list is sorted by priority
- progress = False
- for (t,), function in choicelist:
- if function is None:
- # this marks a decrease in the priority.
- # Don't try delegators with lower priority if
- # we have already progressed.
- if progress:
- break
- else:
- assert hasattr(function, 'result_class'), (
- "delegator %r must have a result_class" % function)
- nt = function.result_class
- if nt not in curargs:
- curdispcls += (nt,)
- srcconvs = curargs[t]
- if not getattr(function, 'trivial_delegation',False):
- srcconvs = srcconvs + [function]
- curargs[nt] = srcconvs
- progress = True
- else:
- if not progress:
- break # no progress, and delegators list exhausted
-
- # progress: try again to dispatch with this new set of types
- choicelist = self.buildchoices(
- dispatchclasses + (curdispcls,) + expanded_dispcls)
- for signature, function in choicelist:
- if function not in seen_functions:
- seen_functions[function] = 1
- # collect arguments: arguments after position argi...
- after_argi = [tuple(expanded_args[j][signature[j]])
- for j in range(argi+1-arity, 0)] # nb. j<0
- # collect arguments: argument argi...
- arg_argi = tuple(curargs[signature[argi]])
- # collect all arguments
- newargs = no_conversion + [arg_argi] + after_argi
- # record the call
- calllist.append((function, tuple(newargs)))
- # end of while 1: try on delegating the same argument i
-
- # proceed to the next argument
- expanded_args = (curargs,) + expanded_args
- expanded_dispcls = (curdispcls,) + expanded_dispcls
-
- def buildchoices(self, allowedtypes):
- """NOT_RPYTHON
- Build a list of all possible implementations we can dispatch to,
- sorted best-first, ignoring delegation."""
- # 'types' is a tuple of tuples of classes, one tuple of classes per
- # argument. (After delegation, we need to call buildchoice() with
- # more than one possible class for a single argument.)
- result = []
- self.internal_buildchoices(allowedtypes, (), result)
- self.postprocessresult(allowedtypes, result)
- #print self.operatorsymbol, allowedtypes, result
- # the result is a list a tuples (function, signature).
- return result
-
- def postprocessresult(self, allowedtypes, result):
- "NOT_RPYTHON"
+class FailedToImplement(Exception):
+ pass
- def internal_buildchoices(self, initialtypes, currenttypes, result):
- "NOT_RPYTHON"
- if len(currenttypes) == self.dispatch_arity:
- currenttypes += (W_ANY,) * (self.arity - self.dispatch_arity)
- for func in self.dispatch_table.get(currenttypes, []):
- if func not in result: # ignore duplicates
- result.append((currenttypes, func))
- else:
- classtuple = initialtypes[len(currenttypes)]
- for nexttype in classtuple:
- self.internal_buildchoices(initialtypes,
- currenttypes + (nexttype,),
- result)
- def is_empty(self):
- return not self.dispatch_table
+def raiseFailedToImplement():
+ raise FailedToImplement
-class MultiMethod(AbstractMultiMethod):
+class MultiMethodTable:
- def __init__(self, operatorsymbol, arity, specialnames=None, **extras):
+ def __init__(self, arity, root_class, argnames_before=[], argnames_after=[]):
"""NOT_RPYTHON: cannot create new multimethods dynamically.
- MultiMethod dispatching on the first 'arity' arguments.
+ MultiMethod-maker dispatching on exactly 'arity' arguments.
"""
- AbstractMultiMethod.__init__(self, operatorsymbol, arity)
if arity < 1:
raise ValueError, "multimethods cannot dispatch on nothing"
- if specialnames is None:
- specialnames = [operatorsymbol]
- self.specialnames = specialnames # e.g. ['__xxx__', '__rxxx__']
- self.extras = extras
- self.unbound_versions = {}
-
+ self.arity = arity
+ self.root_class = root_class
+ self.dispatch_tree = {}
+ self.argnames_before = argnames_before
+ self.argnames_after = argnames_after
- def __get__(self, space, cls=None):
- if space is None:
- return self
+ def register(self, function, *types, **kwds):
+ try:
+ order = kwds.pop('order')
+ except KeyError:
+ order = 0
+ assert not kwds
+ assert len(types) == self.arity
+ 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):
+ "NOT_RPYTHON: initialization-time only"
+ assert len(list_of_typeorders) == self.arity
+ installer = Installer(self, prefix, list_of_typeorders,
+ baked_perform_call=baked_perform_call)
+ return installer.install()
+
+ def install_if_not_empty(self, prefix, list_of_typeorders):
+ "NOT_RPYTHON: initialization-time only"
+ assert len(list_of_typeorders) == self.arity
+ installer = Installer(self, prefix, list_of_typeorders)
+ if installer.is_empty():
+ return None
else:
- return BoundMultiMethod(space, self)
+ return installer.install()
+
+
+
+ # ____________________________________________________________
+ # limited dict-like interface to the dispatch table
- get = __get__
+ 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 slice(self, typeclass, bound_position=0):
- "NOT_RPYTHON"
+ def has_signature(self, types):
try:
- return self.unbound_versions[typeclass, bound_position]
+ self.getfunctions(types)
except KeyError:
- m = UnboundMultiMethod(self, typeclass, bound_position)
- self.unbound_versions[typeclass, bound_position] = m
- return m
-
- def register(self, function, *types):
- """NOT_RPYTHON: cannot register new multimethod
- implementations dynamically"""
- if not AbstractMultiMethod.register(self, function, *types):
return False
- # register the function into unbound versions that match
- for m in self.unbound_versions.values():
- if m.match(types):
- AbstractMultiMethod.register(m, function, *types)
- return True
-
-
-class DelegateMultiMethod(MultiMethod):
-
- def __init__(self):
- "NOT_RPYTHON: cannot create new multimethods dynamically."
- MultiMethod.__init__(self, 'delegate', 1, [])
- self.key = object()
-
- def register(self, function, *types):
- """NOT_RPYTHON: cannot register new multimethod
- implementations dynamically"""
- if not AbstractMultiMethod.register(self, function, *types):
- return False
- self.key = object() # change the key to force recomputation
- return True
-
- def postprocessresult(self, allowedtypes, result):
- "NOT_RPYTHON"
- # add delegation from a class to the *first* immediate parent class
- # and to W_ANY
- arg1types, = allowedtypes
- for t in arg1types:
- if t.__bases__:
- base = t.__bases__[0]
- def delegate_to_parent_class(space, a):
- return a
- delegate_to_parent_class.trivial_delegation = True
- delegate_to_parent_class.result_class = base
- delegate_to_parent_class.priority = 0
- # hard-wire it at priority 0
- result.append(((t,), delegate_to_parent_class))
-
- def delegate_to_any(space, a):
- return a
- delegate_to_any.trivial_delegation = True
- delegate_to_any.result_class = W_ANY
- delegate_to_any.priority = -999
- # hard-wire it at priority -999
- result.append(((t,), delegate_to_any))
-
- # sort the results in priority order, and insert None marks
- # between jumps in the priority values. Higher priority values
- # first.
- by_priority = {} # classify delegators by priority
- for signature, function in result:
- assert hasattr(function, 'priority'), (
- "delegator %r must have a priority" % function)
- sublist = by_priority.setdefault(function.priority, [])
- sublist.append((signature, function))
- delegators = by_priority.items()
- delegators.sort()
- delegators.reverse()
- del result[:]
- for priority, sublist in delegators:
- if result:
- result.append(((None,), None))
- result += sublist
-
-
-class UnboundMultiMethod(AbstractMultiMethod):
-
- def __init__(self, basemultimethod, typeclass, bound_position=0):
- "NOT_RPYTHON: cannot create new multimethods dynamically."
- AbstractMultiMethod.__init__(self,
- basemultimethod.operatorsymbol,
- basemultimethod.arity)
- self.basemultimethod = basemultimethod
- self.typeclass = typeclass
- self.bound_position = bound_position
- # get all the already-registered matching functions from parent
- for types, functions in basemultimethod.dispatch_table.iteritems():
- if self.match(types):
- self.dispatch_table[types] = functions
- self.adjust_dispatch_arity(types)
- #print basemultimethod.operatorsymbol, typeclass, self.dispatch_table
-
- def register(self, function, *types):
- """NOT_RPYTHON: cannot register new multimethod
- implementations dynamically"""
- if not AbstractMultiMethod.register(self, function, *types):
- return False
- # propagate the function registeration to the base multimethod
- # and possibly other UnboundMultiMethods
- self.basemultimethod.register(function, *types)
- return True
-
- def match(self, types):
- "NOT_RPYTHON"
- # check if the 'types' signature statically corresponds to the
- # restriction of the present UnboundMultiMethod.
- # Only accept an exact match; having merely subclass should
- # be taken care of by the general look-up rules.
- t = types[self.bound_position].typedef
- return t is self.typeclass or (
- getattr(t, 'could_also_match', None) is self.typeclass)
-
- def __get__(self, space, cls=None):
- if space is None:
- return self
else:
- return BoundMultiMethod(space, self)
+ return True
+
+ def signatures(self):
+ 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
+
- get = __get__
+# ____________________________________________________________
+class Installer:
-class BoundMultiMethod:
- ASSERT_BASE_TYPE = object
+ prefix_memo = {}
- def __init__(self, space, multimethod):
- self.space = space
+ def __init__(self, multimethod, prefix, list_of_typeorders, baked_perform_call=True):
self.multimethod = multimethod
+ # avoid prefix clashes, user code should supply different prefixes
+ # itself for nice names in tracebacks
+ n = 1
+ while prefix in self.prefix_memo:
+ n += 1
+ prefix = "%s%d" % (prefix,n)
+ self.prefix = prefix
+ self.prefix_memo[prefix] = 1
+ self.list_of_typeorders = list_of_typeorders
+ self.subtree_cache = {}
+ self.to_install = []
+ self.non_empty = self.build_tree([], multimethod.dispatch_tree)
- def __eq__(self, other):
- return (self.__class__ == other.__class__ and
- self.space == other.space and
- self.multimethod == other.multimethod)
-
- def __ne__(self, other):
- return self != other
-
- def __hash__(self):
- return hash((self.__class__, self.space, self.multimethod))
-
- def __call__(self, *args):
- if len(args) < self.multimethod.arity:
- raise TypeError, ("multimethod needs at least %d arguments" %
- self.multimethod.arity)
- try:
- return self.perform_call(*args)
- except FailedToImplement, e:
- if e.args:
- raise OperationError(e.args[0], e.args[1])
- else:
- # raise a TypeError for a FailedToImplement
- initialtypes = [a.__class__
- for a in args[:self.multimethod.dispatch_arity]]
- if len(initialtypes) <= 1:
- plural = ""
- else:
- plural = "s"
- debugtypenames = [t.__name__ for t in initialtypes]
- message = "unsupported operand type%s for %s (%s)" % (
- plural, self.multimethod.operatorsymbol,
- ', '.join(debugtypenames))
- w_value = self.space.wrap(message)
- raise OperationError(self.space.w_TypeError, w_value)
-
- def perform_call(self, *args):
- for a in args:
- assert isinstance(a, self.ASSERT_BASE_TYPE), (
- "'%s' multimethod got a non-wrapped argument: %r" % (
- self.multimethod.operatorsymbol, a))
- arity = self.multimethod.dispatch_arity
- argclasses = tuple([a.__class__ for a in args[:arity]])
- delegate = self.space.delegate.multimethod
- fn = self.multimethod.compile_calllist(argclasses, delegate)
- return fn(self.space, *args)
+ 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 is_empty(self):
- return self.multimethod.is_empty()
+ return not self.non_empty
- def __repr__(self):
- return '<Bound %r>'%(self.multimethod,)
+ def install(self):
+ #f = open('LOGFILE', 'a')
+ #print >> f, '_'*60
+ #import pprint
+ #pprint.pprint(self.list_of_typeorders, f)
+ for target, funcname, func, source, fallback in self.to_install:
+ if target is not None:
+ if hasattr(target, funcname) and fallback:
+ 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))
+
+ if things_to_call:
+ funcname = intern(funcname)
+ self.build_function(next_type, funcname, len(types_so_far),
+ things_to_call)
+ return True
+ else:
+ return False
+ 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}
+ 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
+ callargs[to_convert] = '%s(%s)' % (
+ invent_name(conversion), callargs[to_convert])
+ 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
+
+
+ # 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']
-class error(Exception):
- "Thrown to you when you do something wrong with multimethods."
+ 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)
+ #print source
+ #print "*"*60
+ exec source in miniglobals
+ func = miniglobals[funcname]
+ self.to_install.append((target, funcname, func, source, fallback))
+ return func
Modified: pypy/dist/pypy/objspace/std/noneobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/noneobject.py (original)
+++ pypy/dist/pypy/objspace/std/noneobject.py Mon Feb 7 20:26:07 2005
@@ -8,10 +8,11 @@
class W_NoneObject(W_Object):
from pypy.objspace.std.nonetype import none_typedef as typedef
-registerimplementation(W_NoneObject)
-def unwrap__None(space, w_none):
- return None
+ def unwrap(w_self):
+ return None
+
+registerimplementation(W_NoneObject)
def nonzero__None(space, w_none):
return space.w_False
Modified: pypy/dist/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objspace.py (original)
+++ pypy/dist/pypy/objspace/std/objspace.py Mon Feb 7 20:26:07 2005
@@ -1,36 +1,15 @@
from pypy.objspace.std.register_all import register_all
-from pypy.interpreter.baseobjspace import *
+from pypy.interpreter.baseobjspace import ObjSpace, BaseWrappable
+from pypy.interpreter.error import OperationError
from pypy.interpreter.typedef import get_unique_interplevel_subclass
from pypy.interpreter.typedef import instantiate
from pypy.tool.cache import Cache
-from pypy.objspace.std.multimethod import *
+from pypy.objspace.std.model import W_Object, W_ANY, MultiMethod, StdTypeModel
+from pypy.objspace.std.multimethod import FailedToImplement
from pypy.objspace.descroperation import DescrOperation
from pypy.objspace.std import stdtypedef
import types
-class W_Object(W_Root, object):
- "Parent base class for wrapped objects."
- typedef = None
-
- def __init__(w_self, space):
- w_self.space = space # XXX not sure this is ever used any more
-
- def __repr__(self):
- s = '%s(%s)' % (
- self.__class__.__name__,
- #', '.join(['%s=%r' % keyvalue for keyvalue in self.__dict__.items()])
- getattr(self, 'name', '')
- )
- if hasattr(self, 'w__class__'):
- s += ' instance of %s' % self.w__class__
- return '<%s>' % s
-
-# delegation priorities
-PRIORITY_SAME_TYPE = 2 # converting between several impls of the same type
-PRIORITY_PARENT_TYPE = 1 # converting to a base type (e.g. bool -> int)
-PRIORITY_PARENT_IMPL = 0 # hard-wired in multimethod.py (W_IntObject->W_Object)
-PRIORITY_CHANGE_TYPE = -1 # changing type altogether (e.g. int -> float)
-PRIORITY_ANY = -999 # hard-wired in multimethod.py (... -> W_ANY)
def registerimplementation(implcls):
# this function should ultimately register the implementation class somewhere
@@ -47,139 +26,31 @@
PACKAGE_PATH = 'objspace.std'
- def standard_types(self):
- "NOT_RPYTHON: only for initializing the space."
- class result:
- "Import here the types you want to have appear in __builtin__."
-
- from pypy.objspace.std.objecttype import object_typedef
- from pypy.objspace.std.booltype import bool_typedef
- from pypy.objspace.std.inttype import int_typedef
- from pypy.objspace.std.floattype import float_typedef
- from pypy.objspace.std.tupletype import tuple_typedef
- from pypy.objspace.std.listtype import list_typedef
- from pypy.objspace.std.dicttype import dict_typedef
- from pypy.objspace.std.basestringtype import basestring_typedef
- from pypy.objspace.std.stringtype import str_typedef
- from pypy.objspace.std.typetype import type_typedef
- from pypy.objspace.std.slicetype import slice_typedef
- from pypy.objspace.std.longtype import long_typedef
- from pypy.objspace.std.unicodetype import unicode_typedef
- return [value for key, value in result.__dict__.items()
- if not key.startswith('_')] # don't look
-
- def clone_exception_hierarchy(self):
- "NOT_RPYTHON: only for initializing the space."
- from pypy.objspace.std.typeobject import W_TypeObject
- from pypy.interpreter import gateway
- w = self.wrap
- def app___init__(self, *args):
- self.args = args
- w_init = w(gateway.app2interp(app___init__))
- def app___str__(self):
- l = len(self.args)
- if l == 0:
- return ''
- elif l == 1:
- return str(self.args[0])
- else:
- return str(self.args)
- w_str = w(gateway.app2interp(app___str__))
- import exceptions
-
- # to create types, we should call the standard type object;
- # but being able to do that depends on the existence of some
- # of the exceptions...
-
- self.w_Exception = W_TypeObject(
- self,
- 'Exception',
- [self.w_object],
- {'__init__': w_init,
- '__str__': w_str},
- )
- done = {'Exception': self.w_Exception}
-
- # some of the complexity of the following is due to the fact
- # that we need to create the tree root first, but the only
- # connections we have go in the inconvenient direction...
-
- for k in dir(exceptions):
- if k not in done:
- v = getattr(exceptions, k)
- if not isinstance(v, type(Exception)):
- continue
- if not issubclass(v, Exception):
- continue
- stack = [k]
- while stack:
- next = stack[-1]
- if next not in done:
- v = getattr(exceptions, next)
- b = v.__bases__[0]
- if b.__name__ not in done:
- stack.append(b.__name__)
- continue
- else:
- base = done[b.__name__]
- newtype = W_TypeObject(
- self,
- next,
- [base],
- {},
- )
- setattr(self,
- 'w_' + next,
- newtype)
- done[next] = newtype
- stack.pop()
- else:
- stack.pop()
- return done
-
def initialize(self):
"NOT_RPYTHON: only for initializing the space."
self._typecache = Cache()
- # 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 tupleobject
- from pypy.objspace.std import listobject
- from pypy.objspace.std import dictobject
- from pypy.objspace.std import stringobject
- 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 fake
+ # Import all the object types and implementations
+ self.model = StdTypeModel()
+
+ # install all the MultiMethods into the space instance
+ for name, mm in self.MM.__dict__.items():
+ if isinstance(mm, MultiMethod) and not hasattr(self, name):
+ exprargs, expr, miniglobals, fallback = (
+ mm.install_not_sliced(self.model.typeorder, baked_perform_call=False))
+
+ func = stdtypedef.make_perform_trampoline('__mm_'+name,
+ exprargs, expr, miniglobals,
+ mm)
+
+ # e.g. add(space, w_x, w_y)
+ boundmethod = func.__get__(self) # bind the 'space' argument
+ setattr(self, name, boundmethod) # store into 'space' instance
+
# hack to avoid imports in the time-critical functions below
- global W_ObjectObject, W_BoolObject, W_IntObject, W_FloatObject
- global W_TupleObject, W_ListObject, W_DictObject, W_StringObject
- global W_TypeObject, W_SliceObject, W_LongObject, W_NoneObject
- global W_SeqIterObject, W_UnicodeObject, fake_type
- W_ObjectObject = objectobject.W_ObjectObject
- W_BoolObject = boolobject.W_BoolObject
- W_IntObject = intobject.W_IntObject
- W_FloatObject = floatobject.W_FloatObject
- W_TupleObject = tupleobject.W_TupleObject
- W_ListObject = listobject.W_ListObject
- W_DictObject = dictobject.W_DictObject
- W_StringObject = stringobject.W_StringObject
- W_TypeObject = typeobject.W_TypeObject
- W_SliceObject = sliceobject.W_SliceObject
- W_LongObject = longobject.W_LongObject
- W_NoneObject = noneobject.W_NoneObject
- W_SeqIterObject = iterobject.W_SeqIterObject
- W_UnicodeObject = unicodeobject.W_UnicodeObject
- fake_type = fake.fake_type
- # end of hacks
+ for cls in self.model.typeorder:
+ globals()[cls.__name__] = cls
+
# singletons
self.w_None = W_NoneObject(self)
self.w_False = W_BoolObject(self, False)
@@ -193,12 +64,11 @@
"None" : self.w_None,
"NotImplemented": self.w_NotImplemented,
"Ellipsis": self.w_Ellipsis,
-# "long": self.wrap(long), # XXX temporary
}
# types
self.types_w = {}
- for typedef in self.standard_types():
+ for typedef in self.model.pythontypes:
w_type = self.gettypeobject(typedef)
setattr(self, 'w_' + typedef.name, w_type)
for_builtins[typedef.name] = w_type
@@ -206,9 +76,17 @@
# dummy old-style classes types
self.w_classobj = W_TypeObject(self, 'classobj', [self.w_object], {})
self.w_instance = W_TypeObject(self, 'instance', [self.w_object], {})
-
+
# exceptions
- ##for_builtins.update(self.clone_exception_hierarchy())
+ mod = self.setup_exceptions(for_builtins)
+
+ # install things in the __builtin__ module
+ self.make_builtins(for_builtins)
+
+ w_exceptions = self.wrap(mod)
+ self.sys.setbuiltinmodule(w_exceptions, 'exceptions')
+
+ def setup_exceptions(self, for_builtins):
## hacking things in
from pypy.module import exceptionsinterp as ex
def call(w_type, w_args):
@@ -237,15 +115,10 @@
self.setitem(w_dic, self.wrap("__doc__"), ex.__doc__)
finally:
del self.call # revert to the class' method
-
- self.make_builtins(for_builtins)
# XXX refine things, clean up, create a builtin module...
# but for now, we do a regular one.
from pypy.interpreter.module import Module
-
- m = Module(self, self.wrap("exceptions"), w_dic)
- w_exceptions = self.wrap(m)
- self.sys.setbuiltinmodule(w_exceptions, 'exceptions')
+ return Module(self, self.wrap("exceptions"), w_dic)
def gettypeobject(self, typedef):
# types_w maps each StdTypeDef instance to its
@@ -298,7 +171,8 @@
if hasattr(self, 'w_' + x.__name__):
w_result = getattr(self, 'w_' + x.__name__)
assert isinstance(w_result, W_TypeObject)
- return w_result
+ return w_result
+ from fake import fake_type
if isinstance(x, type):
ft = fake_type(x)
return self.gettypeobject(ft.typedef)
@@ -306,6 +180,11 @@
return ft(self, x)
wrap._specialize_ = "argtypes"
+ def unwrap(self, w_obj):
+ if isinstance(w_obj, BaseWrappable):
+ return w_obj
+ return w_obj.unwrap()
+
def newint(self, intval):
return W_IntObject(self, intval)
@@ -367,31 +246,6 @@
len(t), expected_length)
return t
-
- class MM:
- "Container for multimethods."
- #is_data_descr = MultiMethod('is_data_descr', 1, []) # returns an unwrapped bool
- #getdict = MultiMethod('getdict', 1, []) # get '.__dict__' attribute
- next = MultiMethod('next', 1, ['next']) # iterator interface
- call = MultiMethod('call', 1, ['__call__'], varargs=True, keywords=True)
- #getattribute = MultiMethod('getattr', 2, ['__getattribute__']) # XXX hack
- # special visible multimethods
- delegate = DelegateMultiMethod() # delegators
- int_w = MultiMethod('int_w', 1, []) # returns an unwrapped int
- str_w = MultiMethod('str_w', 1, []) # returns an unwrapped string
- float_w = MultiMethod('float_w', 1, []) # returns an unwrapped float
- unwrap = MultiMethod('unwrap', 1, []) # returns an unwrapped object
- issubtype = MultiMethod('issubtype', 2, [])
- id = MultiMethod('id', 1, [])
- init = MultiMethod('__init__', 1, varargs=True, keywords=True)
-
- int_w = MM.int_w
- str_w = MM.str_w
- float_w = MM.float_w
- unwrap = MM.unwrap
- delegate = MM.delegate
- #is_true = MM.is_true
-
def is_(self, w_one, w_two):
# XXX a bit of hacking to gain more speed
if w_one is w_two:
@@ -405,20 +259,21 @@
else:
return DescrOperation.is_true(self, w_obj)
-# add all regular multimethods to StdObjSpace
-for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable:
- if not hasattr(StdObjSpace.MM, _name):
- if _name == 'pow':
- mm = MultiMethod(_symbol, _arity, _specialnames, defaults=(None,))
- else:
- mm = MultiMethod(_symbol, _arity, _specialnames)
- setattr(StdObjSpace.MM, _name, mm)
- if not hasattr(StdObjSpace, _name):
- setattr(StdObjSpace, _name, getattr(StdObjSpace.MM, _name))
-
-# import the common base W_ObjectObject as well as
-# default implementations of some multimethods for all objects
-# that don't explicitly override them or that raise FailedToImplement
-from pypy.objspace.std.register_all import register_all
-import pypy.objspace.std.objectobject
-import pypy.objspace.std.default
+
+ class MM:
+ "Container for multimethods."
+ call = MultiMethod('call', 1, ['__call__'], general__args__=True)
+ init = MultiMethod('__init__', 1, general__args__=True)
+ # special visible multimethods
+ int_w = MultiMethod('int_w', 1, []) # returns an unwrapped int
+ str_w = MultiMethod('str_w', 1, []) # returns an unwrapped string
+ float_w = MultiMethod('float_w', 1, []) # returns an unwrapped float
+
+ # add all regular multimethods here
+ for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable:
+ if _name not in locals():
+ mm = MultiMethod(_symbol, _arity, _specialnames)
+ locals()[_name] = mm
+ del mm
+
+ pow.extras['defaults'] = (None,)
Modified: pypy/dist/pypy/objspace/std/register_all.py
==============================================================================
--- pypy/dist/pypy/objspace/std/register_all.py (original)
+++ pypy/dist/pypy/objspace/std/register_all.py Mon Feb 7 20:26:07 2005
@@ -74,17 +74,17 @@
def op_negated(function):
- def op(space, w_1, w_2, function=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, function=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, function=function):
+ def op(space, w_1, w_2):
return space.not_(function(space, w_2, w_1))
return op
@@ -110,16 +110,17 @@
table, thus favouring swapping the arguments over negating the result.
"""
from pypy.objspace.std.objspace import StdObjSpace, W_ANY
- originaltable = {}
+ originalentries = {}
for op in OPERATORS:
- originaltable[op] = getattr(StdObjSpace.MM, op).dispatch_table.copy()
+ originalentries[op] = getattr(StdObjSpace.MM, op).signatures()
for op1, op2, correspondance in OP_CORRESPONDANCES:
mirrorfunc = getattr(StdObjSpace.MM, op2)
- for types, functions in originaltable[op1].iteritems():
+ for types in originalentries[op1]:
t1, t2 = types
if t1 is t2:
- if types not in mirrorfunc.dispatch_table:
+ if not mirrorfunc.has_signature(types):
+ functions = getattr(StdObjSpace.MM, op1).getfunctions(types)
assert len(functions) == 1, ('Automatic'
' registration of comparison functions'
' only work when there is a single method for'
Modified: pypy/dist/pypy/objspace/std/sliceobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/sliceobject.py (original)
+++ pypy/dist/pypy/objspace/std/sliceobject.py Mon Feb 7 20:26:07 2005
@@ -18,6 +18,10 @@
w_self.w_stop = w_stop
w_self.w_step = w_step
+ def unwrap(w_slice):
+ space = w_slice.space
+ return slice(space.unwrap(w_slice.w_start), space.unwrap(w_slice.w_stop), space.unwrap(w_slice.w_step))
+
registerimplementation(W_SliceObject)
def app_repr__Slice(aslice):
@@ -43,7 +47,4 @@
raise OperationError(space.w_TypeError,
space.wrap("unhashable type"))
-def unwrap__Slice(space, w_slice):
- return slice(space.unwrap(w_slice.w_start), space.unwrap(w_slice.w_stop), space.unwrap(w_slice.w_step))
-
register_all(vars())
Modified: pypy/dist/pypy/objspace/std/stdtypedef.py
==============================================================================
--- pypy/dist/pypy/objspace/std/stdtypedef.py (original)
+++ pypy/dist/pypy/objspace/std/stdtypedef.py Mon Feb 7 20:26:07 2005
@@ -1,7 +1,7 @@
from pypy.interpreter import eval, function, gateway
from pypy.interpreter.error import OperationError
from pypy.interpreter.typedef import TypeDef, GetSetProperty, Member
-from pypy.objspace.std.multimethod import MultiMethod, FailedToImplement
+from pypy.objspace.std.model import MultiMethod, FailedToImplement
__all__ = ['StdTypeDef', 'newmethod', 'gateway',
'GetSetProperty', 'Member', 'attrproperty', 'attrproperty_w',
@@ -24,9 +24,9 @@
if b is object_typedef:
return True
while a is not b:
- a = a.base
if a is None:
return False
+ a = a.base
return True
def attrproperty(name):
@@ -77,16 +77,11 @@
if isinstance(typedef, StdTypeDef):
# get all the sliced multimethods
- multimethods = slicemultimethods(space.__class__, typedef)
- for name, code in multimethods.items():
- # compute the slice and ignore the multimethod if empty
- if not code.computeslice(space):
- continue
- # create a Function around the sliced multimethod code
- fn = function.Function(space, code, defs_w=code.getdefaults(space))
+ multimethods = slicemultimethods(space, typedef)
+ for name, gateway in multimethods.items():
assert name not in rawdict, 'name clash: %s in %s_typedef' % (
name, typedef.name)
- rawdict[name] = fn
+ rawdict[name] = gateway
# compute the bases
if typedef is object_typedef:
@@ -111,150 +106,266 @@
result.append(value)
return result
-def make_frameclass_for_arity(arity, varargs, keywords, isspecial):
- argnames = []
- for i in range(arity):
- argnames.append('arg%dof%d'%(i+1, arity))
- if varargs:
- argnames.append('var_args')
- if keywords:
- argnames.append('kw_args')
- self_args_assigning = []
- for i in range(len(argnames)):
- self_args_assigning.append(' self.%s = args[%i]'%(argnames[i], i))
- self_args_assigning = "\n".join(self_args_assigning)
- self_args = ", ".join(['self.'+ a for a in argnames])
- name = 'MmFrameOfArity%d'%arity
- if varargs:
- name += "Var"
- if keywords:
- name += "KW"
- if isspecial:
- name = "Special" + name
- d = locals()
- template = mmtemplate
- if isspecial:
- template += specialmmruntemplate
+##def make_frameclass_for_arity(arity, varargs, keywords, isspecial):
+## argnames = []
+## for i in range(arity):
+## argnames.append('arg%dof%d'%(i+1, arity))
+## if varargs:
+## argnames.append('var_args')
+## if keywords:
+## argnames.append('kw_args')
+## self_args_assigning = []
+## for i in range(len(argnames)):
+## self_args_assigning.append(' self.%s = args[%i]'%(argnames[i], i))
+## self_args_assigning = "\n".join(self_args_assigning)
+## self_args = ", ".join(['self.'+ a for a in argnames])
+## name = 'MmFrameOfArity%d'%arity
+## if varargs:
+## name += "Var"
+## if keywords:
+## name += "KW"
+## if isspecial:
+## name = "Special" + name
+## d = locals()
+## template = mmtemplate
+## if isspecial:
+## template += specialmmruntemplate
+## else:
+## template += mmruntemplate
+### print template%d
+## exec template%d in globals(), d
+## return d[name]
+##
+##_frameclass_for_arity_cache = {}
+##def frameclass_for_arity(arity, varargs, keywords, isspecial):
+## try:
+## return _frameclass_for_arity_cache[(arity, varargs, keywords, isspecial)]
+## except KeyError:
+## r = _frameclass_for_arity_cache[(arity, varargs, keywords, isspecial)] = \
+## make_frameclass_for_arity(arity, varargs, keywords, isspecial)
+## return r
+
+
+def sliced_typeorders(typeorder, multimethod, typedef, i, local=False):
+ list_of_typeorders = [typeorder] * multimethod.arity
+ prefix = '_mm_' + multimethod.name
+ if not local:
+ # slice
+ sliced_typeorder = {}
+ for type, order in typeorder.items():
+ thistypedef = getattr(type, 'typedef', None)
+ if issubtypedef(thistypedef, typedef):
+ lst = []
+ for target_type, conversion in order:
+ targettypedef = getattr(target_type, 'typedef', None)
+ if targettypedef == typedef:
+ lst.append((target_type, conversion))
+ sliced_typeorder[type] = lst
+ list_of_typeorders[i] = sliced_typeorder
+ prefix += '_%sS%d' % (typedef.name, i)
+ else:
+ prefix = typedef.name +'_mth'+prefix
+ return prefix, list_of_typeorders
+
+def typeerrormsg(space, operatorsymbol, args_w):
+ type_names = [ space.type(w_arg).name for w_arg in args_w ]
+ if len(args_w) > 1:
+ plural = 's'
else:
- template += mmruntemplate
-# print template%d
- exec template%d in globals(), d
- return d[name]
+ plural = ''
+ msg = "unsupported operand type%s for %s (%s)" % (
+ plural, operatorsymbol,
+ ', '.join(type_names))
+ return space.wrap(msg)
+
+def make_perform_trampoline(prefix, exprargs, expr, miniglobals, multimethod, selfindex=0,
+ allow_NotImplemented_results=False):
+ # mess to figure out how to put a gateway around executing expr
+ argnames = ['_%d'%(i+1) for i in range(multimethod.arity)]
+ explicit_argnames = multimethod.extras.get('argnames', [])
+ argnames[len(argnames)-len(explicit_argnames):] = explicit_argnames
+ solid_arglist = ['w_'+name for name in argnames]
+ wrapper_arglist = solid_arglist[:]
+ if multimethod.extras.get('varargs_w', False):
+ wrapper_arglist.append('args_w')
+ if multimethod.extras.get('w_varargs', False):
+ wrapper_arglist.append('w_args')
+ if multimethod.extras.get('keywords', False):
+ raise Exception, "no longer supported, use __args__"
+ if multimethod.extras.get('general__args__', False):
+ wrapper_arglist.append('__args__')
+
+ miniglobals.update({ 'OperationError': OperationError,
+ 'typeerrormsg': typeerrormsg})
-_frameclass_for_arity_cache = {}
-def frameclass_for_arity(arity, varargs, keywords, isspecial):
- try:
- return _frameclass_for_arity_cache[(arity, varargs, keywords, isspecial)]
- except KeyError:
- r = _frameclass_for_arity_cache[(arity, varargs, keywords, isspecial)] = \
- make_frameclass_for_arity(arity, varargs, keywords, isspecial)
- return r
+ app_defaults = multimethod.extras.get('defaults', ())
+ i = len(argnames) - len(app_defaults)
+ wrapper_signature = wrapper_arglist[:]
+ for app_default in app_defaults:
+ name = wrapper_signature[i]
+ wrapper_signature[i] = '%s=%s' % (name, name)
+ miniglobals[name] = app_default
+ i += 1
+
+ wrapper_signature.insert(0, wrapper_signature.pop(selfindex))
+ wrapper_sig = ', '.join(wrapper_signature)
+
+ src = []
+ dest = []
+ for wrapper_arg,expr_arg in zip(['space']+wrapper_arglist, exprargs):
+ if wrapper_arg != expr_arg:
+ src.append(wrapper_arg)
+ dest.append(expr_arg)
+ renaming = ', '.join(dest) +" = "+', '.join(src)
+
+ if allow_NotImplemented_results and len(multimethod.specialnames) > 1:
+ # turn FailedToImplement into NotImplemented
+ code = """def %s_perform_call(space, %s):
+ %s
+ try:
+ return %s
+ except FailedToImplement, e:
+ if e.args:
+ raise OperationError(e.args[0], e.args[1])
+ else:
+ return space.w_NotImplemented
+""" % (prefix, wrapper_sig, renaming, expr)
+ else:
+ # turn FailedToImplement into nice TypeErrors
+ code = """def %s_perform_call(space, %s):
+ %s
+ try:
+ w_res = %s
+ except FailedToImplement, e:
+ if e.args:
+ raise OperationError(e.args[0], e.args[1])
+ else:
+ raise OperationError(space.w_TypeError,
+ typeerrormsg(space, %r, [%s]))
+ if w_res is None:
+ w_res = space.w_None
+ return w_res
+""" % (prefix, wrapper_sig, renaming, expr,
+ multimethod.operatorsymbol, ', '.join(solid_arglist))
+ exec code in miniglobals
+ return miniglobals["%s_perform_call" % prefix]
+
+def wrap_trampoline_in_gateway(func, methname, multimethod):
+ unwrap_spec = [gateway.ObjSpace] + [gateway.W_Root]*multimethod.arity
+ if multimethod.extras.get('varargs_w', False):
+ unwrap_spec.append('args_w')
+ if multimethod.extras.get('w_varargs', False):
+ unwrap_spec.append('w_args')
+ if multimethod.extras.get('general__args__', False):
+ unwrap_spec.append(gateway.Arguments)
+ return gateway.interp2app(func, app_name=methname, unwrap_spec=unwrap_spec)
-def slicemultimethod(multimethod, typeclass, result):
+def slicemultimethod(space, multimethod, typedef, result, local=False):
+ from pypy.objspace.std.objecttype import object_typedef
for i in range(len(multimethod.specialnames)):
# each MultimethodCode embeds a multimethod
- name = multimethod.specialnames[i]
- if name in result:
+ methname = multimethod.specialnames[i]
+ if methname in result:
# conflict between e.g. __lt__ and
# __lt__-as-reversed-version-of-__gt__
- code = result[name]
- if code.bound_position < i:
+ gw = result[methname]
+ if gw.bound_position < i:
continue
- mmframeclass = frameclass_for_arity(multimethod.arity,
- multimethod.extras.get('varargs', False),
- multimethod.extras.get('keywords', False),
- len(multimethod.specialnames) > 1)
- code = MultimethodCode(multimethod, mmframeclass, typeclass, i)
- result[name] = code
-def slicemultimethods(spaceclass, typeclass):
+ prefix, list_of_typeorders = sliced_typeorders(
+ space.model.typeorder, multimethod, typedef, i, local=local)
+ exprargs, expr, miniglobals, fallback = multimethod.install(prefix, list_of_typeorders,
+ baked_perform_call=False)
+ if fallback:
+ continue # skip empty multimethods
+ trampoline = make_perform_trampoline(prefix, exprargs, expr, miniglobals,
+ multimethod, i,
+ allow_NotImplemented_results=True)
+ gw = wrap_trampoline_in_gateway(trampoline, methname, multimethod)
+ gw.bound_position = i # for the check above
+ result[methname] = gw
+
+def slicemultimethods(space, typedef):
result = {}
# import and slice all multimethods of the space.MM container
- for multimethod in hack_out_multimethods(spaceclass.MM.__dict__):
- slicemultimethod(multimethod, typeclass, result)
+ for multimethod in hack_out_multimethods(space.MM.__dict__):
+ slicemultimethod(space, multimethod, typedef, result)
# import all multimethods defined directly on the type without slicing
- for multimethod in typeclass.local_multimethods:
- slicemultimethod(multimethod, None, result)
+ for multimethod in typedef.local_multimethods:
+ slicemultimethod(space, multimethod, typedef, result, local=True)
return result
-class MultimethodCode(eval.Code):
- """A code object that invokes a multimethod."""
+##class MultimethodCode(eval.Code):
+## """A code object that invokes a multimethod."""
- def __init__(self, multimethod, framecls, typeclass, bound_position=0):
- "NOT_RPYTHON: initialization-time only."
- eval.Code.__init__(self, multimethod.operatorsymbol)
- self.basemultimethod = multimethod
- self.typeclass = typeclass
- self.bound_position = bound_position
- self.framecls = framecls
- argnames = ['_%d'%(i+1) for i in range(multimethod.arity)]
- explicit_argnames = multimethod.extras.get('argnames', [])
- argnames[len(argnames)-len(explicit_argnames):] = explicit_argnames
- varargname = kwargname = None
- # XXX do something about __call__ and __init__ which still use
- # XXX packed arguments: w_args, w_kwds instead of *args_w, **kwds_w
- if multimethod.extras.get('varargs', False):
- varargname = 'args'
- if multimethod.extras.get('keywords', False):
- kwargname = 'keywords'
- self.sig = argnames, varargname, kwargname
-
- def computeslice(self, space):
- "NOT_RPYTHON: initialization-time only."
- if self.typeclass is None:
- slice = self.basemultimethod
- else:
- slice = self.basemultimethod.slice(self.typeclass,
- self.bound_position)
- if slice.is_empty():
- return False
- else:
- self.mm = slice.get(space)
- return True
-
- def signature(self):
- return self.sig
-
- def getdefaults(self, space):
- return [space.wrap(x)
- for x in self.basemultimethod.extras.get('defaults', ())]
-
- def create_frame(self, space, w_globals, closure=None):
- return self.framecls(space, self)
-
-mmtemplate = """
-class %(name)s(eval.Frame):
-
- def setfastscope(self, scope_w):
- args = list(scope_w)
- args.insert(0, args.pop(self.code.bound_position))
-%(self_args_assigning)s
-
- def getfastscope(self):
- raise OperationError(self.space.w_TypeError,
- self.space.wrap("cannot get fastscope of a MmFrame"))
-"""
-
-mmruntemplate = """
- def run(self):
- "Call the multimethod, raising a TypeError if not implemented."
- w_result = self.code.mm(%(self_args)s)
- # we accept a real None from operations with no return value
- if w_result is None:
- w_result = self.space.w_None
- return w_result
-"""
-
-specialmmruntemplate = """
-
- def run(self):
- "Call the multimethods, possibly returning a NotImplemented."
- try:
- return self.code.mm.perform_call(%(self_args)s)
- except FailedToImplement, e:
- if e.args:
- raise OperationError(e.args[0], e.args[1])
- else:
- return self.space.w_NotImplemented
+## def __init__(self, multimethod, framecls, typeclass, bound_position=0):
+## "NOT_RPYTHON: initialization-time only."
+## eval.Code.__init__(self, multimethod.operatorsymbol)
+## self.basemultimethod = multimethod
+## self.typeclass = typeclass
+## self.bound_position = bound_position
+## self.framecls = framecls
+## argnames = ['_%d'%(i+1) for i in range(multimethod.arity)]
+## explicit_argnames = multimethod.extras.get('argnames', [])
+## argnames[len(argnames)-len(explicit_argnames):] = explicit_argnames
+## varargname = kwargname = None
+## # XXX do something about __call__ and __init__ which still use
+## # XXX packed arguments: w_args, w_kwds instead of *args_w, **kwds_w
+## if multimethod.extras.get('varargs', False):
+## varargname = 'args'
+## if multimethod.extras.get('keywords', False):
+## kwargname = 'keywords'
+## self.sig = argnames, varargname, kwargname
+
+## def computeslice(self, space):
+## "NOT_RPYTHON: initialization-time only."
+## self.mm = self.basemultimethod.__get__(space, slice=(
+## self.typeclass, self.bound_position))
+## return not self.mm.is_empty()
+
+## def signature(self):
+## return self.sig
+
+## def getdefaults(self, space):
+## return [space.wrap(x)
+## for x in self.basemultimethod.extras.get('defaults', ())]
+
+## def create_frame(self, space, w_globals, closure=None):
+## return self.framecls(space, self)
+
+##mmtemplate = """
+##class %(name)s(eval.Frame):
+
+## def setfastscope(self, scope_w):
+## args = list(scope_w)
+## args.insert(0, args.pop(self.code.bound_position))
+##%(self_args_assigning)s
+
+## def getfastscope(self):
+## raise OperationError(self.space.w_TypeError,
+## self.space.wrap("cannot get fastscope of a MmFrame"))
+##"""
+
+##mmruntemplate = """
+## def run(self):
+## "Call the multimethod, raising a TypeError if not implemented."
+## w_result = self.code.mm(%(self_args)s)
+## # we accept a real None from operations with no return value
+## if w_result is None:
+## w_result = self.space.w_None
+## return w_result
+##"""
+
+##specialmmruntemplate = """
+
+## def run(self):
+## "Call the multimethods, possibly returning a NotImplemented."
+## try:
+## return self.code.mm.perform_call(%(self_args)s)
+## except FailedToImplement, e:
+## if e.args:
+## raise OperationError(e.args[0], e.args[1])
+## else:
+## return self.space.w_NotImplemented
-"""
+##"""
Modified: pypy/dist/pypy/objspace/std/stringobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/stringobject.py (original)
+++ pypy/dist/pypy/objspace/std/stringobject.py Mon Feb 7 20:26:07 2005
@@ -14,7 +14,6 @@
def ord__String(space, w_str):
def string_richcompare(space, w_str1, w_str2, op):
def str_w__String(space, w_str):
- def unwrap__String(space, w_str):
__add__ def add__String_String(space, w_left, w_right):
__class__
__contains__
@@ -23,7 +22,7 @@
__eq__ def eq__String_String(space, w_str1, w_str2):
__ge__ def ge__String_String(space, w_str1, w_str2):
__getattribute__
-__getitem__ def getitem__String_Int(space, w_str, w_int): def getitem__String_Slice(space, w_str, w_slice):
+__getitem__ def getitem__String_ANY(space, w_str, w_int): def getitem__String_Slice(space, w_str, w_slice):
__getslice__
__gt__ def gt__String_String(space, w_str1, w_str2):
__hash__ def hash__String(space, w_str):
@@ -40,12 +39,12 @@
__setattr__
__str__ def str__String(space, w_str):
capitalize def str_capitalize__String(space, w_self):
-center def str_center__String_Int(space, w_self):
-count def str_count__String_String_Int_Int(space, w_self): [optional arguments not supported now]
+center def str_center__String_ANY(space, w_self):
+count def str_count__String_String_ANY_ANY(space, w_self): [optional arguments not supported now]
decode !Unicode not supported now
encode !Unicode not supported now
endswith str_endswith__String_String [optional arguments not supported now]
-expandtabs str_expandtabs__String_Int
+expandtabs str_expandtabs__String_ANY
find OK
index OK
isalnum def str_isalnum__String(space, w_self): def _isalnum(ch):
@@ -64,7 +63,7 @@
rindex OK
rjust def str_rjust__String_ANY(space, w_self, w_arg):
rstrip def str_rstrip__String_String(space, w_self, w_chars):
-split def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1):def str_split__String_String_Int(space, w_self, w_by, w_maxsplit=-1):
+split def str_split__String_None_ANY(space, w_self, w_none, w_maxsplit=-1):def str_split__String_String_ANY(space, w_self, w_by, w_maxsplit=-1):
splitlines def str_splitlines__String_String(space, w_self, w_keepends):
startswith str_startswith__String_String [optional arguments not supported now]
strip def str_strip__String_String(space, w_self, w_chars):
@@ -100,6 +99,9 @@
""" representation for debugging purposes """
return "%s(%r)" % (w_self.__class__.__name__, w_self._value)
+ def unwrap(w_self):
+ return w_self._value
+
registerimplementation(W_StringObject)
@@ -767,9 +769,6 @@
def str_w__String(space, w_str):
return w_str._value
-
-def unwrap__String(space, w_str):
- return w_str._value
def hash__String(space, w_str):
w_hash = w_str.w_hash
@@ -891,8 +890,8 @@
else:
return space.w_False
-def getitem__String_Int(space, w_str, w_int):
- ival = space.int_w(w_int)
+def getitem__String_ANY(space, w_str, w_index):
+ ival = space.int_w(w_index)
str = w_str._value
slen = len(str)
if ival < 0:
@@ -913,9 +912,8 @@
w_empty = space.newstring([])
return str_join__String_ANY(space, w_empty, w_r)
-def mul__String_Int(space, w_str, w_mul):
+def mul_string_times(space, w_str, mul):
input = w_str._value
- mul = space.int_w(w_mul)
if mul < 0:
return space.wrap("")
input_len = len(input)
@@ -932,8 +930,11 @@
return space.wrap("".join(buffer))
-def mul__Int_String(space, w_mul, w_str):
- return mul__String_Int(space, w_str, w_mul)
+def mul__String_ANY(space, w_str, w_times):
+ return mul_string_times(space, w_str, space.int_w(w_times))
+
+def mul__ANY_String(space, w_mul, w_str):
+ return mul_string_times(space, w_str, space.int_w(w_times))
def add__String_String(space, w_left, w_right):
right = w_right._value
Modified: pypy/dist/pypy/objspace/std/stringtype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/stringtype.py (original)
+++ pypy/dist/pypy/objspace/std/stringtype.py Mon Feb 7 20:26:07 2005
@@ -39,15 +39,12 @@
# ____________________________________________________________
-def descr__new__(space, w_stringtype, w_obj=None):
+def descr__new__(space, w_stringtype, w_obj=''):
from pypy.objspace.std.stringobject import W_StringObject
- if w_obj is None:
- value = ''
- else:
- w_obj = space.str(w_obj)
- if space.is_true(space.is_(w_stringtype, space.w_str)):
- return w_obj # XXX might be reworked when space.str() typechecks
- value = space.str_w(w_obj)
+ w_obj = space.str(w_obj)
+ if space.is_true(space.is_(w_stringtype, space.w_str)):
+ return w_obj # XXX might be reworked when space.str() typechecks
+ value = space.str_w(w_obj)
w_obj = space.allocate_instance(W_StringObject, w_stringtype)
w_obj.__init__(space, value)
return w_obj
Modified: pypy/dist/pypy/objspace/std/test/test_multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_multimethod.py (original)
+++ pypy/dist/pypy/objspace/std/test/test_multimethod.py Mon Feb 7 20:26:07 2005
@@ -1,145 +1,94 @@
import autopath
+from py.test import raises
from pypy.objspace.std.multimethod import *
-BoundMultiMethod.ASSERT_BASE_TYPE = object
+class W_Root(object):
+ pass
-objspacename = 'std'
+class W_IntObject(W_Root):
+ pass
-class X:
- def __init__(self, value):
- self.value = value
- def __repr__(self):
- return '<X %r>' % self.value
+class W_BoolObject(W_Root):
+ pass
-def from_y_to_x(space, yinstance):
- return X(yinstance)
-
-from_y_to_x.result_class = X
-from_y_to_x.priority = 2
-
-def from_x_to_str(space, xinstance):
- #if xinstance.value:
- return w('!' + repr(xinstance.value))
- #else:
- # return []
-
-from_x_to_str.result_class = str
-from_x_to_str.priority = 2
-
-
-class Y:
- def __init__(self, value):
- self.value = value
- def __repr__(self):
- return '<Y %r>' % self.value
- def __nonzero__(self):
- return self.value != 666
-
-
-def add_x_x(space, x1, x2):
- return "add_x_x", x1, x2
-
-def add_x_y(space, x1, y2):
- if x1.value < 0:
- raise FailedToImplement(ValueError, 'not good')
- return "add_x_y", x1, y2
-
-def add_y_y(space, y1, y2):
- return "add_y_y", y1, y2
-
-def add_string_string(space, x, y):
- return "add_string_string", x, y
-
-def add_int_string(space, x, y):
- return "add_int_string", x, y
-
-def add_int_any(space, y1, o2):
- return "add_int_any", y1, o2
-
-class FakeObjSpace:
- add = MultiMethod('+', 2, [])
- add.register(add_x_x, X, X)
- add.register(add_x_y, X, Y)
- add.register(add_y_y, Y, Y)
- add.register(add_string_string, str, str)
- add.register(add_int_string, int, str)
- add.register(add_int_any, int, object)
-
- delegate = DelegateMultiMethod()
- delegate.register(from_y_to_x, Y)
- delegate.register(from_x_to_str, X)
+class W_StringObject(W_Root):
+ pass
+
+def delegate_b2i(w_x):
+ assert isinstance(w_x, W_BoolObject)
+ return W_IntObject()
+
+add = MultiMethodTable(2, root_class=W_Root, argnames_before=['space'])
+
+def add__Int_Int(space, w_x, w_y):
+ assert space == 'space'
+ assert isinstance(w_x, W_IntObject)
+ assert isinstance(w_y, W_IntObject)
+ return 'fine'
+
+add.register(add__Int_Int, W_IntObject, W_IntObject)
+
+
+def setup_module(mod):
+ typeorder = {
+ W_IntObject: [(W_IntObject, None)],
+ W_BoolObject: [(W_BoolObject, None), (W_IntObject, delegate_b2i)],
+ W_StringObject: [(W_StringObject, None)],
+ }
+ mod.typeorder = typeorder
+ mod.add1 = add.install('__add', [typeorder, typeorder])
+
+
+def test_simple():
+ space = 'space'
+ w_x = W_IntObject()
+ w_y = W_IntObject()
+ assert add1(space, w_x, w_y) == 'fine'
+
+def test_failtoimplement():
+ space = 'space'
+ w_x = W_IntObject()
+ w_s = W_StringObject()
+ raises(FailedToImplement, "add1(space, w_x, w_s)")
+ raises(FailedToImplement, "add1(space, w_s, w_x)")
+
+def test_delegate():
+ space = 'space'
+ w_x = W_IntObject()
+ w_s = W_StringObject()
+ w_b = W_BoolObject()
+ assert add1(space, w_x, w_b) == 'fine'
+ assert add1(space, w_b, w_x) == 'fine'
+ assert add1(space, w_b, w_b) == 'fine'
+ raises(FailedToImplement, "add1(space, w_b, w_s)")
+ raises(FailedToImplement, "add1(space, w_s, w_b)")
+
+def test_not_baked():
+ add2 = add.install('__add2', [typeorder, typeorder],baked_perform_call=False)
+ assert add2[0] == ['space', 'arg0', 'arg1']
+ assert add2[1] == 'arg0.__add2(space, arg1)'
+ assert isinstance(add2[2], dict)
+ assert not add2[3]
+
+def test_empty():
+ add3_installer = Installer(add, '__add3', [{},{}])
+ assert add3_installer.is_empty()
+ assert len(add3_installer.to_install) == 1
+ assert add3_installer.to_install[0][0] is None
+
+def test_empty_direct():
+ assert not add.install_if_not_empty('__add4', [{},{}])
+
+
+def test_empty_not_baked():
+ add5_installer = Installer(add, '__add5', [{},{}], baked_perform_call=False)
+ assert add5_installer.is_empty()
+ assert len(add5_installer.to_install) == 0
+ add5 = add5_installer.install()
+ assert add5[0] == ['space', 'arg0', 'arg1']
+ assert add5[1] == 'raiseFailedToImplement()'
+ assert isinstance(add5[2], dict)
+ assert add5[3]
- def wrap(self, x):
- return '<wrapped %r>' % (x,)
- w_TypeError = 'w_TypeError'
-
-##def w(x, cache={}):
-## if type(x) in cache:
-## Stub = cache[type(x)]
-## else:
-## Stub = type(type(x))('%s_stub' % type(x).__name__, (type(x),), {})
-## Stub.dispatchclass = Stub
-## cache[type(x)] = Stub
-## return Stub(x)
-
-##X.dispatchclass = X
-##Y.dispatchclass = Y
-
-def w(x):
- return x
-
-
-class TestMultiMethod:
- def setup_method(self,method):
- # only run when testing stdobjectspace
- #XXX removed: self.space
- self.space = FakeObjSpace()
-
- def test_non_delegate(self):
- space = self.space
-
- r = space.add(X(2), X(5))
- assert repr(r) == "('add_x_x', <X 2>, <X 5>)"
-
- r = space.add(X(3), Y(4))
- assert repr(r) == "('add_x_y', <X 3>, <Y 4>)"
-
- r = space.add(Y(0), Y(20))
- assert repr(r) == "('add_y_y', <Y 0>, <Y 20>)"
-
- r = space.add(w(-3), w([7,6,5]))
- assert repr(r) == "('add_int_any', -3, [7, 6, 5])"
-
- r = space.add(w(5), w("test"))
- assert repr(r) == "('add_int_string', 5, 'test')"
-
- r = space.add(w("x"), w("y"))
- assert repr(r) == "('add_string_string', 'x', 'y')"
-
- def test_delegate_y_to_x(self):
- space = self.space
- r = space.add(Y(-1), X(7))
- assert repr(r) == "('add_x_x', <X <Y -1>>, <X 7>)"
-
- r = space.add(Y(1), X(7))
- assert repr(r) == "('add_x_x', <X <Y 1>>, <X 7>)"
-
- r = space.add(X(-3), Y(20))
- assert repr(r) == "('add_x_x', <X -3>, <X <Y 20>>)"
-
- def test_no_operation_defined(self):
- space = self.space
- raises(OperationError, space.add, w([3]), w(4))
- raises(OperationError, space.add, w(3.0), w('bla'))
- #raises(OperationError, space.add, X(0), w("spam"))
- #raises(OperationError, space.add, Y(666), w("egg"))
-
- def test_delegate_x_to_str(self):
- space = self.space
- r = space.add(X(42), w("spam"))
- assert repr(r) == "('add_string_string', '!42', 'spam')"
-
- r = space.add(Y(20), w("egg"))
- assert repr(r) == "('add_string_string', '!<Y 20>', 'egg')"
Modified: pypy/dist/pypy/objspace/std/tupleobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/tupleobject.py (original)
+++ pypy/dist/pypy/objspace/std/tupleobject.py Mon Feb 7 20:26:07 2005
@@ -16,22 +16,23 @@
reprlist = [repr(w_item) for w_item in w_self.wrappeditems]
return "%s(%s)" % (w_self.__class__.__name__, ', '.join(reprlist))
+ def unwrap(w_tuple):
+ space = w_tuple.space
+ items = [space.unwrap(w_item) for w_item in w_tuple.wrappeditems] # XXX generic mixed types unwrap
+ return tuple(items)
-registerimplementation(W_TupleObject)
+registerimplementation(W_TupleObject)
-def unwrap__Tuple(space, w_tuple):
- items = [space.unwrap(w_item) for w_item in w_tuple.wrappeditems] # XXX generic mixed types unwrap
- return tuple(items)
def len__Tuple(space, w_tuple):
result = len(w_tuple.wrappeditems)
return W_IntObject(space, result)
-def getitem__Tuple_Int(space, w_tuple, w_index):
+def getitem__Tuple_ANY(space, w_tuple, w_index):
items = w_tuple.wrappeditems
try:
- w_item = items[w_index.intval]
+ w_item = items[space.int_w(w_index)]
except IndexError:
raise OperationError(space.w_IndexError,
space.wrap("tuple index out of range"))
@@ -63,14 +64,15 @@
items2 = w_tuple2.wrappeditems
return W_TupleObject(space, items1 + items2)
-def mul__Tuple_Int(space, w_tuple, w_int):
+def mul_tuple_times(space, w_tuple, times):
items = w_tuple.wrappeditems
- times = w_int.intval
- return W_TupleObject(space, items * times)
+ return W_TupleObject(space, items * times)
+def mul__Tuple_ANY(space, w_tuple, w_times):
+ return mul_tuple_times(space, w_tuple, space.int_w(w_times))
-def mul__Int_Tuple(space, w_int, w_tuple):
- return mul__Tuple_Int(space, w_tuple, w_int)
+def mul__ANY_Tuple(space, w_times, w_tuple):
+ return mul_tuple_times(space, w_tuple, space.int_w(w_times))
def eq__Tuple_Tuple(space, w_tuple1, w_tuple2):
items1 = w_tuple1.wrappeditems
Modified: pypy/dist/pypy/objspace/std/tupletype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/tupletype.py (original)
+++ pypy/dist/pypy/objspace/std/tupletype.py Mon Feb 7 20:26:07 2005
@@ -1,7 +1,7 @@
from pypy.objspace.std.stdtypedef import *
+from pypy.interpreter.gateway import NoneNotWrapped
-
-def descr__new__(space, w_tupletype, w_items=None):
+def descr__new__(space, w_tupletype, w_items=NoneNotWrapped):
from pypy.objspace.std.tupleobject import W_TupleObject
if w_items is None:
tuple_w = []
Modified: pypy/dist/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/typeobject.py (original)
+++ pypy/dist/pypy/objspace/std/typeobject.py Mon Feb 7 20:26:07 2005
@@ -170,24 +170,29 @@
space.wrap("attribute '__dict__' of type objects "
"is not writable"))
+ def unwrap(w_self):
+ if hasattr(w_self.instancetypedef, 'fakedcpytype'):
+ return w_self.instancetypedef.fakedcpytype
+ from pypy.objspace.std.model import UnwrapError
+ raise UnwrapError(w_self)
-def call__Type(space, w_type, w_args, w_kwds):
- args = Arguments.frompacked(space, w_args, w_kwds)
+
+def call__Type(space, w_type, __args__):
# special case for type(x)
if space.is_true(space.is_(w_type, space.w_type)):
try:
- w_obj, = args.fixedunpack(1)
+ w_obj, = __args__.fixedunpack(1)
except ValueError:
pass
else:
return space.type(w_obj)
# invoke the __new__ of the type
w_newfunc = space.getattr(w_type, space.wrap('__new__'))
- w_newobject = space.call_args(w_newfunc, args.prepend(w_type))
+ w_newobject = space.call_args(w_newfunc, __args__.prepend(w_type))
# maybe invoke the __init__ of the type
if space.is_true(space.isinstance(w_newobject, w_type)):
w_descr = space.lookup(w_newobject, '__init__')
- space.get_and_call_args(w_descr, w_newobject, args)
+ space.get_and_call_args(w_descr, w_newobject, __args__)
return w_newobject
def issubtype__Type_Type(space, w_type1, w_type2):
@@ -229,11 +234,6 @@
# XXX __delattr__
# XXX __hash__ ??
-def unwrap__Type(space, w_type):
- if hasattr(w_type.instancetypedef, 'fakedcpytype'):
- return w_type.instancetypedef.fakedcpytype
- raise FailedToImplement
-
# ____________________________________________________________
Modified: pypy/dist/pypy/objspace/std/unicodeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/unicodeobject.py (original)
+++ pypy/dist/pypy/objspace/std/unicodeobject.py Mon Feb 7 20:26:07 2005
@@ -5,10 +5,10 @@
W_UnicodeObject = fake_type(unicode)
# string-to-unicode delegation
-def delegate__String(space, w_str):
+def delegate_String2Unicode(w_str):
+ space = w_str.space
return W_UnicodeObject(space, unicode(space.str_w(w_str)))
-delegate__String.result_class = W_UnicodeObject
-delegate__String.priority = PRIORITY_CHANGE_TYPE
+
def eq__Unicode_ANY(space, w_uni, w_other):
try:
More information about the Pypy-commit
mailing list