simplify

Changeset

73:3e9914b119fd
2006-10-08 paulb raw files shortlog changelog graph Wrapped __class__ attributes up properly, fixing the attribute traversal code to deal with this. Improved temporary variable error handling. Added a function to combine lists.
annotate.py (file)
     1.1 --- a/annotate.py	Sun Oct 08 23:53:35 2006 +0200
     1.2 +++ b/annotate.py	Sun Oct 08 23:54:56 2006 +0200
     1.3 @@ -253,7 +253,10 @@
     1.4  
     1.5      def visitLoadTemp(self, loadtemp):
     1.6          index = getattr(loadtemp, "index", None)
     1.7 -        self.namespace.set_types(self.namespace.temp[index][-1])
     1.8 +        try:
     1.9 +            self.namespace.set_types(self.namespace.temp[index][-1])
    1.10 +        except KeyError:
    1.11 +            raise AnnotationMessage, "Temporary store index '%s' not defined." % index
    1.12          self.annotate(loadtemp)
    1.13          return loadtemp
    1.14  
    1.15 @@ -267,7 +270,12 @@
    1.16  
    1.17      def visitReleaseTemp(self, releasetemp):
    1.18          index = getattr(releasetemp, "index", None)
    1.19 -        self.namespace.temp[index].pop()
    1.20 +        try:
    1.21 +            self.namespace.temp[index].pop()
    1.22 +        except KeyError:
    1.23 +            raise AnnotationMessage, "Temporary store index '%s' not defined." % index
    1.24 +        except IndexError:
    1.25 +            pass #raise AnnotationMessage, "Temporary store index '%s' is empty." % index
    1.26          return releasetemp
    1.27  
    1.28      def visitLoadAttr(self, loadattr):
    1.29 @@ -329,7 +337,7 @@
    1.30      def visitReturn(self, return_):
    1.31          if hasattr(return_, "expr"):
    1.32              return_.expr = self.dispatch(return_.expr)
    1.33 -            self.namespace.returns += self.namespace.types
    1.34 +            combine(self.namespace.returns, self.namespace.types)
    1.35              self.annotate(return_)
    1.36          self.namespace.snapshot()
    1.37          return return_
    1.38 @@ -385,7 +393,7 @@
    1.39  
    1.40                      instance = Instance()
    1.41                      instance.namespace = Namespace()
    1.42 -                    instance.namespace.store("__class__", [attr.type])
    1.43 +                    instance.namespace.store("__class__", [Attribute(None, attr.type)])
    1.44  
    1.45                      # For instantiations, switch the context.
    1.46  
    1.47 @@ -548,17 +556,45 @@
    1.48              param, default = params[0]
    1.49              if kw_args.has_key(param):
    1.50                  arg = kw_args[param]
    1.51 +                del kw_args[param]
    1.52              elif default is None:
    1.53                  raise AnnotationMessage, "No argument supplied in '%s' for parameter '%s'." % (subprogram, param)
    1.54              items.append((param, arg.types))
    1.55              params = params[1:]
    1.56  
    1.57 +        dstar_args = kw_args
    1.58 +
    1.59 +        # Construct temporary objects.
    1.60 +
    1.61 +        if star_args:
    1.62 +            list_type = self.builtins_namespace.load("list")[0] # NOTE: Hack to get list type.
    1.63 +            star = Instance()
    1.64 +            star.namespace = Namespace()
    1.65 +            star.namespace.store("__class__", [Attribute(None, list_type)])
    1.66 +            star_types = [Attribute(None, star)]
    1.67 +        else:
    1.68 +            star_types = None
    1.69 +
    1.70 +        if dstar_args:
    1.71 +            dict_type = self.builtins_namespace.load("dict")[0] # NOTE: Hack to get dict type.
    1.72 +            dstar = Instance()
    1.73 +            dstar.namespace = Namespace()
    1.74 +            dstar.namespace.store("__class__", [Attribute(None, dict_type)])
    1.75 +            dstar_types = [Attribute(None, dstar)]
    1.76 +        else:
    1.77 +            dstar_types = None
    1.78 +
    1.79 +        # NOTE: Merge the objects properly.
    1.80 +
    1.81 +        star_types = star_types or invocation.star and invocation.star.types
    1.82 +        dstar_types = dstar_types or invocation.dstar and invocation.dstar.types
    1.83 +
    1.84          # Add star and dstar.
    1.85  
    1.86 -        if star_args or invocation.star is not None:
    1.87 +        if star_types is not None:
    1.88              if subprogram.star is not None:
    1.89                  param, default = subprogram.star
    1.90 -                items.append((param, invocation.star.types))
    1.91 +                items.append((param, star_types))
    1.92              else:
    1.93                  raise AnnotationMessage, "Invocation provides unwanted *args."
    1.94          elif subprogram.star is not None:
    1.95 @@ -566,10 +602,10 @@
    1.96              arg = self.dispatch(default) # NOTE: Review reprocessing.
    1.97              items.append((param, arg.types))
    1.98  
    1.99 -        if kw_args or invocation.dstar is not None:
   1.100 +        if dstar_types is not None:
   1.101              if subprogram.dstar is not None:
   1.102                  param, default = subprogram.dstar
   1.103 -                items.append((param, invocation.dstar.types))
   1.104 +                items.append((param, dstar_types))
   1.105              else:
   1.106                  raise AnnotationMessage, "Invocation provides unwanted **args."
   1.107          elif subprogram.dstar is not None:
   1.108 @@ -619,7 +655,8 @@
   1.109  
   1.110      def merge_namespace(self, namespace):
   1.111          self.merge_items(namespace.names.items())
   1.112 -        self.returns += namespace.returns
   1.113 +        combine(self.returns, namespace.returns)
   1.114 +        self.temp = namespace.temp
   1.115  
   1.116      def merge_items(self, items):
   1.117          for name, types in items:
   1.118 @@ -630,9 +667,7 @@
   1.119              self.names[name] = types[:]
   1.120          else:
   1.121              existing = self.names[name]
   1.122 -            for type in types:
   1.123 -                if type not in existing:
   1.124 -                    existing.append(type)
   1.125 +            combine(existing, types)
   1.126  
   1.127      def snapshot(self):
   1.128  
   1.129 @@ -666,6 +701,11 @@
   1.130      def __init__(self, attribute):
   1.131          self.types = [attribute]
   1.132  
   1.133 +def combine(target, additions):
   1.134 +    for addition in additions:
   1.135 +        if addition not in target:
   1.136 +            target.append(addition)
   1.137 +
   1.138  def find_attributes(structure, name):
   1.139  
   1.140      """
   1.141 @@ -693,11 +733,10 @@
   1.142          # Investigate any instance's implementing class.
   1.143  
   1.144          if isinstance(structure, Instance):
   1.145 -            for cls in structure.namespace.load("__class__"):
   1.146 +            for attr in structure.namespace.load("__class__"):
   1.147 +                cls = attr.type
   1.148                  l = get_attributes(cls, name)
   1.149 -                for attribute in l:
   1.150 -                    if attribute not in attributes:
   1.151 -                        attributes.append(attribute)
   1.152 +                combine(attributes, l)
   1.153  
   1.154          # Investigate any class's base classes.
   1.155  
   1.156 @@ -719,11 +758,9 @@
   1.157  
   1.158                  for base_ref in base_refs:
   1.159                      l = get_attributes(base_ref, name)
   1.160 -                    for attribute in l:
   1.161 -                        if attribute not in base_attributes:
   1.162 -                            base_attributes.append(attribute)
   1.163 +                    combine(base_attributes, l)
   1.164  
   1.165 -                attributes += base_attributes
   1.166 +                combine(attributes, base_attributes)
   1.167  
   1.168      return attributes
   1.169