Example #1
0
    def attach_methods_to_subclasses(self):
        # in ootype, it might happen that a method is defined in the
        # superclass but the annotator discovers that it's always called
        # through instances of a subclass (e.g. because of specialization, see
        # test_rclass.test_method_specialized_with_subclass).  In that cases,
        # we copy the method also in the ootype.Instance of the subclass, so
        # that the type of v_self coincides with the type returned by
        # _lookup().
        assert self.type_system.name == 'ootypesystem'

        def allclasses(TYPE, seen):
            '''Yield TYPE and all its subclasses'''
            if TYPE in seen:
                return
            seen.add(TYPE)
            yield TYPE
            for SUB in TYPE._subclasses:
                for T in allclasses(SUB, seen):
                    yield T

        for TYPE in allclasses(ootype.ROOT, set()):
            for methname, meth in TYPE._methods.iteritems():
                try:
                    graph = meth.graph
                except AttributeError:
                    continue
                SELF = graph.getargs()[0].concretetype
                if TYPE != SELF and ootype.isSubclass(SELF, TYPE):
                    # the annotator found that this method has a more precise
                    # type. Attach it to the proper subclass, so that the type
                    # of 'self' coincides with the type returned by _lookup(),
                    # else we might have type errors
                    if methname not in SELF._methods:
                        ootype.addMethods(SELF, {methname: meth})
Example #2
0
File: rtyper.py Project: ieure/pypy
    def attach_methods_to_subclasses(self):
        # in ootype, it might happen that a method is defined in the
        # superclass but the annotator discovers that it's always called
        # through instances of a subclass (e.g. because of specialization, see
        # test_rclass.test_method_specialized_with_subclass).  In that cases,
        # we copy the method also in the ootype.Instance of the subclass, so
        # that the type of v_self coincides with the type returned by
        # _lookup().
        assert self.type_system.name == 'ootypesystem'
        def allclasses(TYPE, seen):
            '''Yield TYPE and all its subclasses'''
            if TYPE in seen:
                return
            seen.add(TYPE)
            yield TYPE
            for SUB in TYPE._subclasses:
                for T in allclasses(SUB, seen):
                    yield T

        for TYPE in allclasses(ootype.ROOT, set()):
            for methname, meth in TYPE._methods.iteritems():
                try:
                    graph = meth.graph
                except AttributeError:
                    continue
                SELF = graph.getargs()[0].concretetype
                if TYPE != SELF and ootype.isSubclass(SELF, TYPE):
                    # the annotator found that this method has a more precise
                    # type. Attach it to the proper subclass, so that the type
                    # of 'self' coincides with the type returned by _lookup(),
                    # else we might have type errors
                    if methname not in SELF._methods:
                        ootype.addMethods(SELF, {methname: meth})
Example #3
0
    def attach_class_attr_accessor(self, mangled, oovalue):
        def ll_getclassattr(self):
            return oovalue

        M = ootype.Meth([], ootype.typeOf(oovalue))
        ll_getclassattr = func_with_new_name(ll_getclassattr,
                                             'll_get_' + mangled)
        graph = self.rtyper.annotate_helper(ll_getclassattr, [self.lowleveltype])
        m = ootype.meth(M, _name=mangled, _callable=ll_getclassattr,
                        graph=graph)
        ootype.addMethods(self.lowleveltype, {mangled: m})
Example #4
0
def test_checkvirtual_simple():
    A = Instance("A", ROOT)
    B = Instance("B", A)

    addMethods(A, {"foo": meth(Meth([], Void)), "bar": meth(Meth([], Void))})

    addMethods(B, {"foo": meth(Meth([], Void))})

    check_virtual_methods()
    assert A._methods["foo"]._virtual == True
    assert A._methods["bar"]._virtual == False
    assert B._methods["foo"]._virtual == False
Example #5
0
def test_checkvirtual_simple():
    A = Instance("A", ROOT)
    B = Instance("B", A)

    addMethods(A, {"foo": meth(Meth([], Void)),
                   "bar": meth(Meth([], Void))})
    
    addMethods(B, {"foo": meth(Meth([], Void))})

    check_virtual_methods()
    assert A._methods["foo"]._virtual == True
    assert A._methods["bar"]._virtual == False
    assert B._methods["foo"]._virtual == False
Example #6
0
def test_checkvirtual_brother():
    A = Instance("A", ROOT)
    B1 = Instance("B1", A)
    B2 = Instance("B2", A)

    addMethods(A, {"foo": meth(Meth([], Void)), "bar": meth(Meth([], Void))})

    addMethods(B1, {"foo": meth(Meth([], Void))})

    check_virtual_methods()
    assert A._methods["foo"]._virtual == True
    assert A._methods["bar"]._virtual == False
    assert B1._methods["foo"]._virtual == False
    assert "foo" not in B2._methods
Example #7
0
    def attach_class_attr_accessor(self, mangled, oovalue):
        def ll_getclassattr(self):
            return oovalue

        M = ootype.Meth([], ootype.typeOf(oovalue))
        ll_getclassattr = func_with_new_name(ll_getclassattr,
                                             'll_get_' + mangled)
        graph = self.rtyper.annotate_helper(ll_getclassattr,
                                            [self.lowleveltype])
        m = ootype.meth(M,
                        _name=mangled,
                        _callable=ll_getclassattr,
                        graph=graph)
        ootype.addMethods(self.lowleveltype, {mangled: m})
Example #8
0
def test_checkvirtual_deep():
    A = Instance("A", ROOT)
    B = Instance("B", A)
    C = Instance("C", B)

    addMethods(A, {"foo": meth(Meth([], Void)), "bar": meth(Meth([], Void))})

    addMethods(C, {"foo": meth(Meth([], Void))})

    check_virtual_methods()
    assert A._methods["foo"]._virtual == True
    assert A._methods["bar"]._virtual == False
    assert "foo" not in B._methods
    assert C._methods["foo"]._virtual == False
Example #9
0
def test_checkvirtual_brother():
    A = Instance("A", ROOT)
    B1 = Instance("B1", A)
    B2 = Instance("B2", A)

    addMethods(A, {"foo": meth(Meth([], Void)),
                   "bar": meth(Meth([], Void))})
    
    addMethods(B1, {"foo": meth(Meth([], Void))})

    check_virtual_methods()
    assert A._methods["foo"]._virtual == True
    assert A._methods["bar"]._virtual == False
    assert B1._methods["foo"]._virtual == False
    assert "foo" not in B2._methods
Example #10
0
def test_checkvirtual_deep():
    A = Instance("A", ROOT)
    B = Instance("B", A)
    C = Instance("C", B)

    addMethods(A, {"foo": meth(Meth([], Void)),
                   "bar": meth(Meth([], Void))})
    
    addMethods(C, {"foo": meth(Meth([], Void))})

    check_virtual_methods()
    assert A._methods["foo"]._virtual == True
    assert A._methods["bar"]._virtual == False
    assert "foo" not in B._methods
    assert C._methods["foo"]._virtual == False
Example #11
0
    def attach_class_attr_accessor(self, mangled, value, r_value):
        def ll_getclassattr(self):
            return oovalue

        M = ootype.Meth([], r_value.lowleveltype)
        if value is None:
            m = ootype.meth(M, _name=mangled, abstract=True)
        else:
            oovalue = r_value.convert_desc_or_const(value)
            ll_getclassattr = func_with_new_name(ll_getclassattr,
                                                 'll_get_' + mangled)
            graph = self.rtyper.annotate_helper(ll_getclassattr, [self.lowleveltype])
            m = ootype.meth(M, _name=mangled, _callable=ll_getclassattr,
                            graph=graph)

        ootype.addMethods(self.lowleveltype, {mangled: m})
Example #12
0
    def attach_class_attr_accessor(self, mangled, value, r_value):
        def ll_getclassattr(self):
            return oovalue

        M = ootype.Meth([], r_value.lowleveltype)
        if value is None:
            m = ootype.meth(M, _name=mangled, abstract=True)
        else:
            oovalue = r_value.convert_desc_or_const(value)
            ll_getclassattr = func_with_new_name(ll_getclassattr,
                                                 'll_get_' + mangled)
            graph = self.rtyper.annotate_helper(ll_getclassattr,
                                                [self.lowleveltype])
            m = ootype.meth(M,
                            _name=mangled,
                            _callable=ll_getclassattr,
                            graph=graph)

        ootype.addMethods(self.lowleveltype, {mangled: m})
Example #13
0
    def _setup_repr_final(self):
        if self.classdef is None:
            return
        AbstractInstanceRepr._setup_repr_final(self)

        # we attach methods here and not in _setup(), because we want
        # to be sure that all the reprs of the input arguments of all
        # our methods have been computed at this point
        methods = {}
        selfattrs = self.classdef.attrs
        for mangled, (name, s_value) in self.allmethods.iteritems():
            methdescs = s_value.descriptions
            origin = dict([(methdesc.originclassdef, methdesc)
                           for methdesc in methdescs])
            if self.classdef in origin:
                methdesc = origin[self.classdef]
            else:
                if name in selfattrs:
                    for superdef in self.classdef.getmro():
                        if superdef in origin:
                            # put in methods
                            methdesc = origin[superdef]
                            break
                    else:
                        # abstract method
                        methdesc = None
                else:
                    continue
            # get method implementation
            from pypy.rpython.ootypesystem.rpbc import MethodImplementations
            methimpls = MethodImplementations.get(self.rtyper, s_value)
            m_impls = methimpls.get_impl(mangled,
                                         methdesc,
                                         is_finalizer=name == "__del__")
            methods.update(m_impls)
        ootype.addMethods(self.lowleveltype, methods)

        # step 3: provide accessor methods for class attributes that
        # are really overridden in subclasses. Must be done here
        # instead of _setup_repr to avoid recursion problems if class
        # attributes are Instances of self.lowleveltype.

        for mangled, (s_value, value) in self.classattributes.items():
            r = self.rtyper.getrepr(s_value)
            if value is None:
                self.attach_abstract_class_attr_accessor(
                    mangled, r.lowleveltype)
            else:
                oovalue = r.convert_desc_or_const(value)
                self.attach_class_attr_accessor(mangled, oovalue)

        # step 4: do the same with instance fields whose default
        # values are overridden in subclasses. Not sure it's the best
        # way to do it.
        overridden_defaults = {}

        if self.classdef is not None:
            for name, constant in self.classdef.classdesc.classdict.iteritems(
            ):
                # look for the attrdef in the superclasses
                classdef = self.classdef.basedef
                attrdef = None
                while classdef is not None:
                    if name in classdef.attrs:
                        attrdef = classdef.attrs[name]
                        break
                    classdef = classdef.basedef
                if attrdef is not None and not attrdef.readonly:
                    # it means that the default value for this field
                    # is overridden in this subclass. Record we know
                    # about it
                    repr = self.rtyper.getrepr(attrdef.s_value)
                    oot = repr.lowleveltype
                    mangled = mangle(name, self.rtyper.getconfig())
                    value = self.classdef.classdesc.read_attribute(name)
                    default = repr.convert_desc_or_const(value)
                    overridden_defaults[mangled] = oot, default

        ootype.overrideDefaultForFields(self.lowleveltype, overridden_defaults)
Example #14
0
 def attach_abstract_class_attr_accessor(self, mangled, attrtype):
     M = ootype.Meth([], attrtype)
     m = ootype.meth(M, _name=mangled, abstract=True)
     ootype.addMethods(self.lowleveltype, {mangled: m})
Example #15
0
    def _setup_repr_final(self):
        if self.classdef is None:
            return
        AbstractInstanceRepr._setup_repr_final(self)
        
        # we attach methods here and not in _setup(), because we want
        # to be sure that all the reprs of the input arguments of all
        # our methods have been computed at this point
        methods = {}
        selfattrs = self.classdef.attrs
        for mangled, (name, s_value) in self.allmethods.iteritems():
            methdescs = s_value.descriptions
            origin = dict([(methdesc.originclassdef, methdesc) for
                           methdesc in methdescs])
            if self.classdef in origin:
                methdesc = origin[self.classdef]
            else:
                if name in selfattrs:
                    for superdef in self.classdef.getmro():
                        if superdef in origin:
                            # put in methods
                            methdesc = origin[superdef]
                            break
                    else:
                        # abstract method
                        methdesc = None
                else:
                    continue
            # get method implementation
            from pypy.rpython.ootypesystem.rpbc import MethodImplementations
            methimpls = MethodImplementations.get(self.rtyper, s_value)
            m_impls = methimpls.get_impl(mangled, methdesc,
                    is_finalizer=name == "__del__")
            methods.update(m_impls)
        ootype.addMethods(self.lowleveltype, methods)
        
        
        # step 3: provide accessor methods for class attributes that
        # are really overridden in subclasses. Must be done here
        # instead of _setup_repr to avoid recursion problems if class
        # attributes are Instances of self.lowleveltype.
        
        for mangled, (s_value, value) in self.classattributes.items():
            r = self.rtyper.getrepr(s_value)
            if value is None:
                self.attach_abstract_class_attr_accessor(mangled,
                                                         r.lowleveltype)
            else:
                oovalue = r.convert_desc_or_const(value)
                self.attach_class_attr_accessor(mangled, oovalue)

        # step 4: do the same with instance fields whose default
        # values are overridden in subclasses. Not sure it's the best
        # way to do it.
        overridden_defaults = {}

        if self.classdef is not None:
            for name, constant in self.classdef.classdesc.classdict.iteritems():
                # look for the attrdef in the superclasses
                classdef = self.classdef.basedef
                attrdef = None
                while classdef is not None:
                    if name in classdef.attrs:
                        attrdef = classdef.attrs[name]
                        break
                    classdef = classdef.basedef
                if attrdef is not None and not attrdef.readonly:
                    # it means that the default value for this field
                    # is overridden in this subclass. Record we know
                    # about it
                    repr = self.rtyper.getrepr(attrdef.s_value)
                    oot = repr.lowleveltype
                    mangled = mangle(name, self.rtyper.getconfig())
                    value = self.classdef.classdesc.read_attribute(name)
                    default = repr.convert_desc_or_const(value)
                    overridden_defaults[mangled] = oot, default

        ootype.overrideDefaultForFields(self.lowleveltype, overridden_defaults)
Example #16
0
    def _setup_repr(self):
        if self.classdef is None:
            self.allfields = {}
            self.allmethods = {}
            self.allclassattributes = {}
            self.classattributes = {}
            return

        if self.baserepr is not None:
            allfields = self.baserepr.allfields.copy()
            allmethods = self.baserepr.allmethods.copy()
            allclassattributes = self.baserepr.allclassattributes.copy()
        else:
            allfields = {}
            allmethods = {}
            allclassattributes = {}

        fields = {}
        fielddefaults = {}
        
        selfattrs = self.classdef.attrs

        for name, attrdef in selfattrs.iteritems():
            mangled = mangle(name, self.rtyper.getconfig())
            if not attrdef.readonly:
                repr = self.rtyper.getrepr(attrdef.s_value)
                allfields[mangled] = repr
                oot = repr.lowleveltype
                fields[mangled] = oot
                try:
                    value = self.classdef.classdesc.read_attribute(name)
                    fielddefaults[mangled] = repr.convert_desc_or_const(value)
                except AttributeError:
                    pass
            else:
                s_value = attrdef.s_value
                if isinstance(s_value, annmodel.SomePBC):
                    if len(s_value.descriptions) > 0 and s_value.getKind() == description.MethodDesc:
                        # attrdef is for a method
                        if mangled in allclassattributes:
                            raise TyperError("method overrides class attribute")
                        allmethods[mangled] = name, self.classdef.lookup_filter(s_value)
                        continue
                # class attribute
                if mangled in allmethods:
                    raise TyperError("class attribute overrides method")
                allclassattributes[mangled] = name, s_value

        special_methods = ["__init__", "__del__"]
        for meth_name in special_methods:
            if meth_name not in selfattrs and \
                    self.classdef.classdesc.find_source_for(meth_name) is not None:
                s_meth = self.classdef.classdesc.s_get_value(self.classdef,
                        meth_name)
                if isinstance(s_meth, annmodel.SomePBC):
                    mangled = mangle(meth_name, self.rtyper.getconfig())
                    allmethods[mangled] = meth_name, s_meth
                # else: it's the __init__ of a builtin exception
            
        #
        # hash() support
        if self.rtyper.needs_hash_support(self.classdef):
            from pypy.rpython import rint
            allfields['_hash_cache_'] = rint.signed_repr
            fields['_hash_cache_'] = ootype.Signed

        ootype.addFields(self.lowleveltype, fields)

        self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef)
        self.rbase.setup()

        methods = {}
        classattributes = {}
        baseInstance = self.lowleveltype._superclass
        classrepr = getclassrepr(self.rtyper, self.classdef)

        for mangled, (name, s_value) in allmethods.iteritems():
            methdescs = s_value.descriptions
            origin = dict([(methdesc.originclassdef, methdesc) for
                           methdesc in methdescs])
            if self.classdef in origin:
                methdesc = origin[self.classdef]
            else:
                if name in selfattrs:
                    for superdef in self.classdef.getmro():
                        if superdef in origin:
                            # put in methods
                            methdesc = origin[superdef]
                            break
                    else:
                        # abstract method
                        methdesc = None
                else:
                    continue

            # get method implementation
            from pypy.rpython.ootypesystem.rpbc import MethodImplementations
            methimpls = MethodImplementations.get(self.rtyper, s_value)
            m_impls = methimpls.get_impl(mangled, methdesc,
                    is_finalizer=name == "__del__")
            
            methods.update(m_impls)
                                        

        for classdef in self.classdef.getmro():
            for name, attrdef in classdef.attrs.iteritems():
                if not attrdef.readonly:
                    continue
                mangled = mangle(name, self.rtyper.getconfig())
                if mangled in allclassattributes:
                    selfdesc = self.classdef.classdesc
                    if name not in selfattrs:
                        # if the attr was already found in a parent class,
                        # we register it again only if it is overridden.
                        if selfdesc.find_source_for(name) is None:
                            continue
                        value = selfdesc.read_attribute(name)
                    else:
                        # otherwise, for new attrs, we look in all parent
                        # classes to see if it's defined in a parent but only
                        # actually first used in self.classdef.
                        value = selfdesc.read_attribute(name, None)

                    # a non-method class attribute
                    if not attrdef.s_value.is_constant():
                        classattributes[mangled] = attrdef.s_value, value

        ootype.addMethods(self.lowleveltype, methods)
        
        self.allfields = allfields
        self.allmethods = allmethods
        self.allclassattributes = allclassattributes
        self.classattributes = classattributes

        # the following is done after the rest of the initialization because
        # convert_const can require 'self' to be fully initialized.

        # step 2: provide default values for fields
        for mangled, impl in fielddefaults.items():
            oot = fields[mangled]
            ootype.addFields(self.lowleveltype, {mangled: (oot, impl)})
Example #17
0
def test_nonvirtual():
    A = Instance("A", ROOT)
    addMethods(A, {"foo": meth(Meth([], Void))})

    check_virtual_methods()
    assert A._methods["foo"]._virtual == False
Example #18
0
 def attach_abstract_class_attr_accessor(self, mangled, attrtype):
     M = ootype.Meth([], attrtype)
     m = ootype.meth(M, _name=mangled, abstract=True)
     ootype.addMethods(self.lowleveltype, {mangled: m})
Example #19
0
def test_nonvirtual():
    A = Instance("A", ROOT)
    addMethods(A, {"foo": meth(Meth([], Void))})

    check_virtual_methods()
    assert A._methods["foo"]._virtual == False
Example #20
0
    def _setup_repr(self):
        if self.classdef is None:
            self.allfields = {}
            self.allmethods = {}
            self.allclassattributes = {}
            self.classattributes = {}
            return

        if self.baserepr is not None:
            allfields = self.baserepr.allfields.copy()
            allmethods = self.baserepr.allmethods.copy()
            allclassattributes = self.baserepr.allclassattributes.copy()
        else:
            allfields = {}
            allmethods = {}
            allclassattributes = {}

        fields = {}
        fielddefaults = {}

        selfattrs = self.classdef.attrs

        for name, attrdef in selfattrs.iteritems():
            mangled = mangle(name, self.rtyper.getconfig())
            if not attrdef.readonly:
                repr = self.rtyper.getrepr(attrdef.s_value)
                allfields[mangled] = repr
                oot = repr.lowleveltype
                fields[mangled] = oot
                try:
                    value = self.classdef.classdesc.read_attribute(name)
                    fielddefaults[mangled] = repr.convert_desc_or_const(value)
                except AttributeError:
                    pass
            else:
                s_value = attrdef.s_value
                if isinstance(s_value, annmodel.SomePBC):
                    if len(s_value.descriptions) > 0 and s_value.getKind(
                    ) == description.MethodDesc:
                        # attrdef is for a method
                        if mangled in allclassattributes:
                            raise TyperError(
                                "method overrides class attribute")
                        allmethods[
                            mangled] = name, self.classdef.lookup_filter(
                                s_value)
                        continue
                # class attribute
                if mangled in allmethods:
                    raise TyperError("class attribute overrides method")
                allclassattributes[mangled] = name, s_value

        special_methods = ["__init__", "__del__"]
        for meth_name in special_methods:
            if meth_name not in selfattrs and \
                    self.classdef.classdesc.find_source_for(meth_name) is not None:
                s_meth = self.classdef.classdesc.s_get_value(
                    self.classdef, meth_name)
                if isinstance(s_meth, annmodel.SomePBC):
                    mangled = mangle(meth_name, self.rtyper.getconfig())
                    allmethods[mangled] = meth_name, s_meth
                # else: it's the __init__ of a builtin exception

        #
        # hash() support
        if self.rtyper.needs_hash_support(self.classdef):
            from pypy.rpython import rint
            allfields['_hash_cache_'] = rint.signed_repr
            fields['_hash_cache_'] = ootype.Signed

        ootype.addFields(self.lowleveltype, fields)

        self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef)
        self.rbase.setup()

        methods = {}
        classattributes = {}
        baseInstance = self.lowleveltype._superclass
        classrepr = getclassrepr(self.rtyper, self.classdef)

        for mangled, (name, s_value) in allmethods.iteritems():
            methdescs = s_value.descriptions
            origin = dict([(methdesc.originclassdef, methdesc)
                           for methdesc in methdescs])
            if self.classdef in origin:
                methdesc = origin[self.classdef]
            else:
                if name in selfattrs:
                    for superdef in self.classdef.getmro():
                        if superdef in origin:
                            # put in methods
                            methdesc = origin[superdef]
                            break
                    else:
                        # abstract method
                        methdesc = None
                else:
                    continue

            # get method implementation
            from pypy.rpython.ootypesystem.rpbc import MethodImplementations
            methimpls = MethodImplementations.get(self.rtyper, s_value)
            m_impls = methimpls.get_impl(mangled,
                                         methdesc,
                                         is_finalizer=name == "__del__")

            methods.update(m_impls)

        for classdef in self.classdef.getmro():
            for name, attrdef in classdef.attrs.iteritems():
                if not attrdef.readonly:
                    continue
                mangled = mangle(name, self.rtyper.getconfig())
                if mangled in allclassattributes:
                    selfdesc = self.classdef.classdesc
                    if name not in selfattrs:
                        # if the attr was already found in a parent class,
                        # we register it again only if it is overridden.
                        if selfdesc.find_source_for(name) is None:
                            continue
                        value = selfdesc.read_attribute(name)
                    else:
                        # otherwise, for new attrs, we look in all parent
                        # classes to see if it's defined in a parent but only
                        # actually first used in self.classdef.
                        value = selfdesc.read_attribute(name, None)

                    # a non-method class attribute
                    if not attrdef.s_value.is_constant():
                        classattributes[mangled] = attrdef.s_value, value

        ootype.addMethods(self.lowleveltype, methods)

        self.allfields = allfields
        self.allmethods = allmethods
        self.allclassattributes = allclassattributes
        self.classattributes = classattributes

        # the following is done after the rest of the initialization because
        # convert_const can require 'self' to be fully initialized.

        # step 2: provide default values for fields
        for mangled, impl in fielddefaults.items():
            oot = fields[mangled]
            ootype.addFields(self.lowleveltype, {mangled: (oot, impl)})