1.1 --- a/annotate.py Mon Oct 16 00:36:34 2006 +0200
1.2 +++ b/annotate.py Mon Oct 16 00:39:44 2006 +0200
1.3 @@ -69,17 +69,16 @@
1.4
1.5 # Exceptions.
1.6
1.7 -class AnnotationError(Exception):
1.8 - def __init__(self, exc, node, *args):
1.9 - Exception.__init__(self, *args)
1.10 - self.nodes = [node]
1.11 - self.exc = exc
1.12 - def add(self, node):
1.13 - self.nodes.append(node)
1.14 - def __str__(self):
1.15 - return "%s, %s" % (self.exc, self.nodes)
1.16 +class AnnotationError(SimplifiedError):
1.17 +
1.18 + "An error in the annotation process."
1.19 +
1.20 + pass
1.21
1.22 class AnnotationMessage(Exception):
1.23 +
1.24 + "A lesser annotation error."
1.25 +
1.26 pass
1.27
1.28 # Annotation.
1.29 @@ -197,11 +196,14 @@
1.30
1.31 return result
1.32
1.33 - def annotate(self, node):
1.34 + def annotate(self, node, types=None):
1.35
1.36 - "Annotate the given 'node' in the system."
1.37 + """
1.38 + Annotate the given 'node' in the system, using either the optional
1.39 + 'types' or the namespace's current type information.
1.40 + """
1.41
1.42 - self.system.annotate(node, self.namespace.types)
1.43 + self.system.annotate(node, types or self.namespace.types)
1.44
1.45 # Visitor methods.
1.46
1.47 @@ -288,12 +290,14 @@
1.48 types.append(attribute)
1.49 if not accesses.has_key(attr.type):
1.50 accesses[attr.type] = []
1.51 - accesses[attr.type].append((attribute, accessor))
1.52 + if not (attribute, accessor) in accesses[attr.type]:
1.53 + accesses[attr.type].append((attribute, accessor))
1.54 else:
1.55 print "Empty attribute", loadattr.name, "via accessor", accessor
1.56 if not non_accesses.has_key(attr.type):
1.57 non_accesses[attr.type] = []
1.58 - non_accesses[attr.type].append((attribute, accessor))
1.59 + if not (attribute, accessor) in non_accesses[attr.type]:
1.60 + non_accesses[attr.type].append((attribute, accessor))
1.61 self.namespace.set_types(types)
1.62 loadattr.accesses = accesses
1.63 loadattr.non_accesses = non_accesses
1.64 @@ -347,9 +351,15 @@
1.65 return return_
1.66
1.67 def visitInvoke(self, invoke):
1.68 +
1.69 + # First find the callables.
1.70 +
1.71 invoke.expr = self.dispatch(invoke.expr)
1.72 invocation_types = self.namespace.types
1.73
1.74 + # Invocation processing starts with making sure that the arguments have
1.75 + # been processed.
1.76 +
1.77 if isinstance(invoke, InvokeFunction):
1.78 self.process_args(invoke)
1.79
1.80 @@ -424,6 +434,9 @@
1.81 self.namespace.set_types([Attribute(None, instance)])
1.82 self.annotate(invoke)
1.83
1.84 + # Remember the invocations that were found, along with the return type
1.85 + # information.
1.86 +
1.87 invoke.invocations = invocations
1.88 self.namespace.set_types(getattr(invoke, "types", []))
1.89 return invoke
1.90 @@ -494,7 +507,9 @@
1.91 for locals in self.returned_locals:
1.92 self.namespace.merge_namespace(locals)
1.93
1.94 - def process_args(self, invoke):
1.95 + def process_args(self, invocation):
1.96 +
1.97 + "Process the arguments associated with an 'invocation'."
1.98
1.99 # NOTE: Consider initialiser invocation for classes.
1.100
1.101 @@ -503,25 +518,25 @@
1.102
1.103 # Get type information for regular arguments.
1.104
1.105 - for arg in invoke.args:
1.106 + for arg in invocation.args:
1.107 args.append(self.dispatch(arg))
1.108 types.append(self.namespace.types)
1.109
1.110 # Get type information for star and dstar arguments.
1.111
1.112 - if invoke.star is not None:
1.113 - param, default = invoke.star
1.114 + if invocation.star is not None:
1.115 + param, default = invocation.star
1.116 default = self.dispatch(default)
1.117 - invoke.star = param, default
1.118 + invocation.star = param, default
1.119 types.append(default.types)
1.120
1.121 - if invoke.dstar is not None:
1.122 - param, default = invoke.dstar
1.123 + if invocation.dstar is not None:
1.124 + param, default = invocation.dstar
1.125 default = self.dispatch(default)
1.126 - invoke.dstar = param, default
1.127 + invocation.dstar = param, default
1.128 types.append(default.types)
1.129
1.130 - invoke.args = args
1.131 + invocation.args = args
1.132
1.133 def make_items(self, invocation, subprogram, context):
1.134
1.135 @@ -587,13 +602,12 @@
1.136 if star_args:
1.137 star_invocation = self.make_star_args(invocation, subprogram, star_args)
1.138 self.dispatch(star_invocation)
1.139 - star_invocation.pprint()
1.140 star_types = star_invocation.types
1.141 else:
1.142 star_types = None
1.143
1.144 if dstar_args:
1.145 - dstar_invocation = self.make_dstar_args(invocation, subprogram, dstar_args)
1.146 + dstar_invocation = self.make_dstar_args(invocation, subprogram, dstar_args) # NOTE: To be written!
1.147 self.dispatch(dstar_invocation)
1.148 dstar_types = dstar_invocation.types
1.149 else:
1.150 @@ -628,6 +642,12 @@
1.151 arg = self.dispatch(default) # NOTE: Review reprocessing.
1.152 items.append((param, arg.types))
1.153
1.154 + # Record the parameter types.
1.155 +
1.156 + subprogram.paramtypes = {}
1.157 + for param, types in items:
1.158 + subprogram.paramtypes[param] = types
1.159 +
1.160 return items
1.161
1.162 def make_star_args(self, invocation, subprogram, star_args):