"""The full list of which Python types and which implementation we wantto provide in this version of PyPy, along with conversion rules."""frompypy.objspace.std.multimethodimportMultiMethodTable,FailedToImplementfrompypy.interpreter.baseobjspaceimportW_Root,ObjSpaceimportpypy.interpreter.pycodeimportpypy.interpreter.special_registered_implementations=set()defregisterimplementation(implcls):"""Hint to objspace.std.model to register the implementation class."""assertissubclass(implcls,W_Object)_registered_implementations.add(implcls)option_to_typename={"withsmalllong":["smalllongobject.W_SmallLongObject"],"withstrbuf":["strbufobject.W_StringBufferObject"],}IDTAG_INT=1IDTAG_LONG=3IDTAG_FLOAT=5IDTAG_COMPLEX=7classStdTypeModel:def__init__(self,config):"""NOT_RPYTHON: inititialization only"""self.config=config# All the Python types that we want to provide in this StdObjSpaceclassresult:frompypy.objspace.std.objecttypeimportobject_typedeffrompypy.objspace.std.floattypeimportfloat_typedeffrompypy.objspace.std.complextypeimportcomplex_typedeffrompypy.objspace.std.typeobjectimporttype_typedeffrompypy.objspace.std.slicetypeimportslice_typedeffrompypy.objspace.std.nonetypeimportnone_typedefself.pythontypes=[valueforkey,valueinresult.__dict__.items()ifnotkey.startswith('_')]# don't look# 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.frompypy.objspace.stdimportobjectobjectfrompypy.objspace.stdimportboolobjectfrompypy.objspace.stdimportintobjectfrompypy.objspace.stdimportfloatobjectfrompypy.objspace.stdimportcomplexobjectfrompypy.objspace.stdimporttupleobjectfrompypy.objspace.stdimportlistobjectfrompypy.objspace.stdimportdictmultiobjectfrompypy.objspace.stdimportsetobjectfrompypy.objspace.stdimportbasestringtypefrompypy.objspace.stdimportbytesobjectfrompypy.objspace.stdimportbytearrayobjectfrompypy.objspace.stdimporttypeobjectfrompypy.objspace.stdimportsliceobjectfrompypy.objspace.stdimportlongobjectfrompypy.objspace.stdimportnoneobjectfrompypy.objspace.stdimportiterobjectfrompypy.objspace.stdimportunicodeobjectfrompypy.objspace.stdimportdictproxyobjectfrompypy.objspace.stdimportproxyobjectimportpypy.objspace.std.default# register a few catch-all multimethodsimportpypy.objspace.std.marshal_impl# install marshal multimethods# not-multimethod based typesself.pythontypes.append(tupleobject.W_TupleObject.typedef)self.pythontypes.append(listobject.W_ListObject.typedef)self.pythontypes.append(dictmultiobject.W_DictMultiObject.typedef)self.pythontypes.append(setobject.W_SetObject.typedef)self.pythontypes.append(setobject.W_FrozensetObject.typedef)self.pythontypes.append(iterobject.W_AbstractSeqIterObject.typedef)self.pythontypes.append(basestringtype.basestring_typedef)self.pythontypes.append(bytesobject.W_BytesObject.typedef)self.pythontypes.append(bytearrayobject.W_BytearrayObject.typedef)self.pythontypes.append(unicodeobject.W_UnicodeObject.typedef)self.pythontypes.append(intobject.W_IntObject.typedef)self.pythontypes.append(boolobject.W_BoolObject.typedef)self.pythontypes.append(longobject.W_LongObject.typedef)# the set of implementation typesself.typeorder={objectobject.W_ObjectObject:[],# XXX: Bool/Int/Long are pythontypes but still included here# for delegation to Float/Complexboolobject.W_BoolObject:[],intobject.W_IntObject:[],floatobject.W_FloatObject:[],typeobject.W_TypeObject:[],sliceobject.W_SliceObject:[],longobject.W_LongObject:[],noneobject.W_NoneObject:[],complexobject.W_ComplexObject:[],pypy.interpreter.pycode.PyCode:[],pypy.interpreter.special.Ellipsis:[],}self.imported_but_not_registered={bytesobject.W_BytesObject:True,}foroption,valueinconfig.objspace.std:ifoption.startswith("with")andoptioninoption_to_typename:forclassnameinoption_to_typename[option]:modname=classname[:classname.index('.')]classname=classname[classname.index('.')+1:]d={}exec"from pypy.objspace.std.%s import %s"%(modname,classname)indimplcls=d[classname]ifvalue:self.typeorder[implcls]=[]else:self.imported_but_not_registered[implcls]=True# check if we missed implementationsforimplclsin_registered_implementations:ifhasattr(implcls,'register'):implcls.register(self.typeorder)assert(implclsinself.typeorderorimplclsinself.imported_but_not_registered),("please add %r in StdTypeModel.typeorder"%(implcls,))fortypeinself.typeorder:self.typeorder[type].append((type,None))# register the order in which types are converted into each others# when trying to dispatch multimethods.# XXX build these lists a bit more automatically laterself.typeorder[boolobject.W_BoolObject]+=[(floatobject.W_FloatObject,floatobject.delegate_Bool2Float),(complexobject.W_ComplexObject,complexobject.delegate_Bool2Complex),]self.typeorder[intobject.W_IntObject]+=[(floatobject.W_FloatObject,floatobject.delegate_Int2Float),(complexobject.W_ComplexObject,complexobject.delegate_Int2Complex),]ifconfig.objspace.std.withsmalllong:frompypy.objspace.stdimportsmalllongobjectself.typeorder[smalllongobject.W_SmallLongObject]+=[(floatobject.W_FloatObject,smalllongobject.delegate_SmallLong2Float),(complexobject.W_ComplexObject,smalllongobject.delegate_SmallLong2Complex),]self.typeorder[longobject.W_LongObject]+=[(floatobject.W_FloatObject,floatobject.delegate_Long2Float),(complexobject.W_ComplexObject,complexobject.delegate_Long2Complex),]self.typeorder[floatobject.W_FloatObject]+=[(complexobject.W_ComplexObject,complexobject.delegate_Float2Complex),]ifconfig.objspace.std.withstrbuf:frompypy.objspace.stdimportstrbufobject# put W_Root everywhereself.typeorder[W_Root]=[]fortypeinself.typeorder:frompypy.objspace.stdimportstdtypedefiftypeisnotW_Rootandisinstance(type.typedef,stdtypedef.StdTypeDef):self.typeorder[type].append((type.typedef.any,None))self.typeorder[type].append((W_Root,None))self._typeorder_with_empty_usersubcls=None# ____________________________________________________________# Prebuilt common integer valuesifconfig.objspace.std.withprebuiltint:intobject.W_IntObject.PREBUILT=[]foriinrange(config.objspace.std.prebuiltintfrom,config.objspace.std.prebuiltintto):intobject.W_IntObject.PREBUILT.append(intobject.W_IntObject(i))delielse:intobject.W_IntObject.PREBUILT=None# ____________________________________________________________defget_typeorder_with_empty_usersubcls(self):ifself._typeorder_with_empty_usersubclsisNone:frompypy.interpreter.typedefimportenum_interplevel_subclassesfrompypy.objspace.stdimportstdtypedefresult=self.typeorder.copy()forclsinself.typeorder:if(hasattr(cls,'typedef')andcls.typedefisnotNoneandcls.typedef.acceptable_as_base_class):subclslist=enum_interplevel_subclasses(self.config,cls)forsubclsinsubclslist:ifclsinsubcls.__bases__:# only direct subclasses# for user subclasses we only accept "generic"# matches: "typedef.any" is the applevel-type-based# matching, and "W_Root" is ANY.matches=[]ifisinstance(cls.typedef,stdtypedef.StdTypeDef):matches.append((cls.typedef.any,None))matches.append((W_Root,None))result[subcls]=matchesself._typeorder_with_empty_usersubcls=resultreturnself._typeorder_with_empty_usersubclsdef_op_negated(function):defop(space,w_1,w_2):returnspace.not_(function(space,w_1,w_2))returnopdef_op_swapped(function):defop(space,w_1,w_2):returnfunction(space,w_2,w_1)returnopdef_op_swapped_negated(function):defop(space,w_1,w_2):returnspace.not_(function(space,w_2,w_1))returnopCMP_OPS=dict(lt='<',le='<=',eq='==',ne='!=',gt='>',ge='>=')CMP_CORRESPONDANCES=[('eq','ne',_op_negated),('lt','gt',_op_swapped),('le','ge',_op_swapped),('lt','ge',_op_negated),('le','gt',_op_negated),('lt','le',_op_swapped_negated),('gt','ge',_op_swapped_negated),]forop1,op2,valueinCMP_CORRESPONDANCES[:]:i=CMP_CORRESPONDANCES.index((op1,op2,value))CMP_CORRESPONDANCES.insert(i+1,(op2,op1,value))BINARY_BITWISE_OPS={'and':'&','lshift':'<<','or':'|','rshift':'>>','xor':'^'}BINARY_OPS=dict(add='+',div='/',floordiv='//',mod='%',mul='*',sub='-',truediv='/',**BINARY_BITWISE_OPS)COMMUTATIVE_OPS=('add','mul','and','or','xor')defadd_extra_comparisons():""" Add the missing comparison operators if they were not explicitly defined: eq <-> ne and lt <-> le <-> gt <-> ge. We try to add them in the order defined by the CMP_CORRESPONDANCES table, thus favouring swapping the arguments over negating the result. """originalentries={}foropinCMP_OPS.iterkeys():originalentries[op]=getattr(MM,op).signatures()forop1,op2,correspondanceinCMP_CORRESPONDANCES:mirrorfunc=getattr(MM,op2)fortypesinoriginalentries[op1]:t1,t2=typesift1ist2:ifnotmirrorfunc.has_signature(types):functions=getattr(MM,op1).getfunctions(types)assertlen(functions)==1,('Automatic'' registration of comparison functions'' only work when there is a single method for'' the operation.')mirrorfunc.register(correspondance(functions[0]),*types)# ____________________________________________________________W_ANY=W_RootclassW_Object(W_Root):"Parent base class for wrapped objects provided by the StdObjSpace."# Note that not all wrapped objects in the interpreter inherit from# W_Object. (They inherit from W_Root.)__slots__=()def__repr__(self):name=getattr(self,'name','')ifnotisinstance(name,str):name=''s='%s(%s)'%(self.__class__.__name__,name)w_cls=getattr(self,'w__class__',None)ifw_clsisnotNoneandw_clsisnotself:s+=' instance of %s'%self.w__class__return'<%s>'%sclassUnwrapError(Exception):passclassStdObjSpaceMultiMethod(MultiMethodTable):def__init__(self,operatorsymbol,arity,specialnames=None,**extras):"""NOT_RPYTHON: cannot create new multimethods dynamically. """MultiMethodTable.__init__(self,arity,W_ANY,argnames_before=['space'])self.operatorsymbol=operatorsymbolifspecialnamesisNone:specialnames=[operatorsymbol]assertisinstance(specialnames,list)self.specialnames=specialnames# e.g. ['__xxx__', '__rxxx__']self.extras=extras# transform '+' => 'add' etc.forlineinObjSpace.MethodTable:realname,symbolname=line[:2]ifsymbolname==operatorsymbol:self.name=realnamebreakelse:self.name=operatorsymbolifextras.get('general__args__',False):self.argnames_after=['__args__']ifextras.get('varargs_w',False):self.argnames_after=['args_w']self.argnames_after+=extras.get('extra_args',[])definstall_not_sliced(self,typeorder,baked_perform_call=True):returnself.install(prefix='__mm_'+self.name,list_of_typeorders=[typeorder]*self.arity,baked_perform_call=baked_perform_call)defmerge_with(self,other):# Make a new 'merged' multimethod including the union of the two# tables. In case of conflict, pick the entry from 'self'.ifself.arity!=other.arity:returnself# XXX that's the case of '**'operatorsymbol='%s_merge_%s'%(self.name,other.name)assertself.extras==other.extrasmm=StdObjSpaceMultiMethod(operatorsymbol,self.arity,**self.extras)#defmerge(node1,node2):asserttype(node1)istype(node2)ifisinstance(node1,dict):d=node1.copy()d.update(node2)forkeyinnode1:ifkeyinnode2:d[key]=merge(node1[key],node2[key])returndelse:assertisinstance(node1,list)assertnode1returnnode1# pick the entry from 'self'#mm.dispatch_tree=merge(self.dispatch_tree,other.dispatch_tree)returnmmNOT_MULTIMETHODS=set(['delattr','delete','get','id','inplace_div','inplace_floordiv','inplace_lshift','inplace_mod','inplace_pow','inplace_rshift','inplace_truediv','is_','set','setattr','type','userdel','isinstance','issubtype','int','ord'])# XXX should we just remove those from the method table or we're happy# with just not having multimethods?classMM:"""StdObjSpace multimethods"""call=StdObjSpaceMultiMethod('call',1,['__call__'],general__args__=True)init=StdObjSpaceMultiMethod('__init__',1,general__args__=True)getnewargs=StdObjSpaceMultiMethod('__getnewargs__',1)# special visible multimethods# NOTE: when adding more sometype_w() methods, you need to write a# stub in default.py to raise a space.w_TypeErrormarshal_w=StdObjSpaceMultiMethod('marshal_w',1,[],extra_args=['marshaller'])# add all regular multimethods herefor_name,_symbol,_arity,_specialnamesinObjSpace.MethodTable:if_namenotinlocals()and_namenotinNOT_MULTIMETHODS:mm=StdObjSpaceMultiMethod(_symbol,_arity,_specialnames)locals()[_name]=mmdelmmpow.extras['defaults']=(None,)