micropython

Changeset

527:830194e3b6ab
2012-06-05 Paul Boddie raw files shortlog changelog graph Reinstated tentative declarations of instance attributes from attribute usage that can be overridden by the declaration of class attributes for classes in the same hierarchy. Thus, "mix-in" classes whose methods employ self-based attribute accesses will not cause instance attributes to be allocated if class attributes are defined in descendant classes making use of such "mix-in" classes.
micropython/data.py (file) micropython/inspect.py (file)
     1.1 --- a/micropython/data.py	Tue Jun 05 01:30:05 2012 +0200
     1.2 +++ b/micropython/data.py	Tue Jun 05 01:54:54 2012 +0200
     1.3 @@ -1303,6 +1303,7 @@
     1.4          self.bases = []
     1.5          self.descendants = set()
     1.6          self.instattr = set()           # instance attributes
     1.7 +        self.instattr_tentative = set() # tentative/suspected instance attributes
     1.8          self.relocated = set()          # attributes which do not have the same
     1.9                                          # position as those of the same name in
    1.10                                          # some superclasses
    1.11 @@ -1446,8 +1447,11 @@
    1.12          self.bases.append(base)
    1.13          base.add_descendant(self)
    1.14  
    1.15 -    def add_instance_attribute(self, name):
    1.16 -        self.instattr.add(name)
    1.17 +    def add_instance_attribute(self, name, tentative=False):
    1.18 +        if tentative:
    1.19 +            self.instattr_tentative.add(name)
    1.20 +        else:
    1.21 +            self.instattr.add(name)
    1.22  
    1.23      def add_descendant(self, cls):
    1.24          self.descendants.add(cls)
    1.25 @@ -1553,6 +1557,21 @@
    1.26  
    1.27          "Make sure that the instance attributes are fully defined."
    1.28  
    1.29 +        # Eliminate tentative instance attributes that are actually class
    1.30 +        # attributes.
    1.31 +
    1.32 +        for attrname in self.all_class_attributes().keys():
    1.33 +            if attrname in self.instattr_tentative:
    1.34 +                self.instattr_tentative.remove(attrname)
    1.35 +
    1.36 +        for cls in self.descendants:
    1.37 +            for attrname in cls.class_attribute_names():
    1.38 +                if attrname in self.instattr_tentative:
    1.39 +                    self.instattr_tentative.remove(attrname)
    1.40 +
    1.41 +        for attrname in self.instattr_tentative:
    1.42 +            self.instattr.add(attrname)
    1.43 +
    1.44          # Cache the attributes by converting the positioned attributes into a
    1.45          # dictionary.
    1.46  
     2.1 --- a/micropython/inspect.py	Tue Jun 05 01:30:05 2012 +0200
     2.2 +++ b/micropython/inspect.py	Tue Jun 05 01:54:54 2012 +0200
     2.3 @@ -327,9 +327,13 @@
     2.4          cls.set(name, self.expr, 0)
     2.5          self.use_specific_attribute(cls.full_name(), name)
     2.6  
     2.7 -    def store_instance_attr(self, name):
     2.8 +    def store_instance_attr(self, name, tentative=False):
     2.9  
    2.10 -        "Record instance attribute 'name' in the current class."
    2.11 +        """
    2.12 +        Record instance attribute 'name' in the current class. If 'tentative' is
    2.13 +        set to a true value, the instance attribute will be discarded if a class
    2.14 +        attribute is observed.
    2.15 +        """
    2.16  
    2.17          if self.in_method:
    2.18  
    2.19 @@ -337,7 +341,7 @@
    2.20              # Previous namespace is the class.
    2.21  
    2.22              cls = self.namespaces[-2]
    2.23 -            cls.add_instance_attribute(name)
    2.24 +            cls.add_instance_attribute(name, tentative)
    2.25  
    2.26              # NOTE: The instance attribute, although defined in a specific
    2.27              # NOTE: class, obviously appears in all descendant classes.
    2.28 @@ -514,6 +518,12 @@
    2.29              # to be an instance.
    2.30  
    2.31              else:
    2.32 +
    2.33 +                # Record any instance attributes.
    2.34 +
    2.35 +                if expr.name == "self":
    2.36 +                    self.store_instance_attr(attrname, tentative=True)
    2.37 +
    2.38                  attr = make_instance()
    2.39  
    2.40                  # Note usage of the attribute where a local is involved.