1.1 --- a/micropython/common.py Tue Aug 10 23:18:42 2010 +0200
1.2 +++ b/micropython/common.py Wed Aug 11 00:04:11 2010 +0200
1.3 @@ -26,13 +26,16 @@
1.4 except NameError:
1.5 from sets import Set as set
1.6
1.7 -# Visitors.
1.8 +# Visitors and activities related to node annotations.
1.9
1.10 class ASTVisitor(compiler.visitor.ASTVisitor):
1.11
1.12 "A base class for visitors."
1.13
1.14 def dispatch(self, node, *args):
1.15 +
1.16 + "Dispatch using 'node', annotating any raised exceptions."
1.17 +
1.18 try:
1.19 return compiler.visitor.ASTVisitor.dispatch(self, node, *args)
1.20 except NodeProcessingError, exc:
1.21 @@ -47,6 +50,25 @@
1.22 exc.unit_name = self.full_name()
1.23 raise
1.24
1.25 + def possible_accessor_types(self, node):
1.26 +
1.27 + """
1.28 + Given annotations made during the inspection process, return all possible
1.29 + types for a 'node' involved in attribute access, or return None if no
1.30 + annotations are available.
1.31 + """
1.32 +
1.33 + if hasattr(node, "_attrusers"):
1.34 + target_names = set()
1.35 +
1.36 + for user in node._attrusers:
1.37 + target_names.update(self.objtable.all_possible_objects(user._attrnames[node._username]))
1.38 +
1.39 + return target_names
1.40 +
1.41 + else:
1.42 + return None
1.43 +
1.44 def used_by_unit(node):
1.45
1.46 """
2.1 --- a/micropython/report.py Tue Aug 10 23:18:42 2010 +0200
2.2 +++ b/micropython/report.py Wed Aug 11 00:04:11 2010 +0200
2.3 @@ -73,12 +73,24 @@
2.4 z-index: 3;
2.5 }
2.6
2.7 + .types-popup {
2.8 + display: none;
2.9 + position: absolute;
2.10 + bottom: 3ex; left: 0;
2.11 + color: white;
2.12 + border-bottom: 0.5ex solid #000;
2.13 + border-right: 0.5ex solid #000;
2.14 + z-index: 3;
2.15 + }
2.16 +
2.17 + .accessor,
2.18 .name {
2.19 position: relative;
2.20 background-color: #300;
2.21 color: white;
2.22 }
2.23
2.24 + .accessor:hover,
2.25 .name:hover {
2.26 background-color: #500;
2.27 padding-top: 0.5ex;
2.28 @@ -86,11 +98,13 @@
2.29 z-index: 2;
2.30 }
2.31
2.32 + .accessor:hover .types-popup,
2.33 .name:hover .popup {
2.34 display: block;
2.35 }
2.36
2.37 .attrnames,
2.38 + .typenames,
2.39 .scope {
2.40 padding: 0.5em;
2.41 background-color: #700;
2.42 @@ -157,8 +171,8 @@
2.43 self.stream.write(self._text(name))
2.44 self._name_end()
2.45
2.46 - def _popup_start(self):
2.47 - self._span_start("popup")
2.48 + def _popup_start(self, classes=None):
2.49 + self._span_start(classes or "popup")
2.50
2.51 _popup_end = _span_end
2.52
2.53 @@ -222,27 +236,47 @@
2.54 self._span(name)
2.55 self._span_end()
2.56
2.57 - def _attrnames(self, attrnames):
2.58 - if not attrnames:
2.59 + def _names_list(self, names, label, classes):
2.60 + if not names:
2.61 return
2.62 + names = list(names)
2.63 + names.sort()
2.64
2.65 - self.stream.write("<div class='attrnames'><span class='label'>attributes</span><br />")
2.66 + self.stream.write("<div class='%s'><span class='label'>%s</span><br />" % (classes, label))
2.67 first = 1
2.68 - for attrname in attrnames:
2.69 + for name in names:
2.70 if not first:
2.71 self.stream.write("<br />")
2.72 - self.stream.write(attrname)
2.73 + self.stream.write(name)
2.74 first = 0
2.75 self.stream.write("</div>\n")
2.76
2.77 + def _attrnames(self, attrnames):
2.78 + self._names_list(attrnames, "attributes", "attrnames")
2.79 +
2.80 + def _typenames(self, typenames):
2.81 + self._names_list(typenames, "types", "typenames")
2.82 +
2.83 + def _accessor_start(self, target_names):
2.84 + if target_names is not None:
2.85 + self._span_start("accessor")
2.86 + self._popup_start("types-popup")
2.87 + self._typenames(target_names)
2.88 + self._popup_end()
2.89 +
2.90 + def _accessor_end(self, target_names):
2.91 + if target_names is not None:
2.92 + self._span_end()
2.93 +
2.94 # Summary classes.
2.95
2.96 class Summary(Writer):
2.97
2.98 "Summarise classes and attributes in modules."
2.99
2.100 - def __init__(self, module):
2.101 + def __init__(self, module, program):
2.102 self.module = module
2.103 + self.program = program
2.104
2.105 def to_stream(self, stream):
2.106
2.107 @@ -313,10 +347,13 @@
2.108
2.109 "A module source code browser."
2.110
2.111 - def __init__(self, module):
2.112 + def __init__(self, module, program):
2.113 ASTVisitor.__init__(self)
2.114 self.visitor = self
2.115 self.module = module
2.116 + self.program = program
2.117 + self.objtable = self.program.get_object_table()
2.118 + self.paramtable = self.program.get_parameter_table()
2.119
2.120 def to_stream(self, stream):
2.121
2.122 @@ -780,8 +817,11 @@
2.123 self._visitBinary(node, "floordiv", "//")
2.124
2.125 def visitGetattr(self, node):
2.126 + target_names = self.possible_accessor_types(node)
2.127 self._span_start("getattr")
2.128 + self._accessor_start(target_names)
2.129 self.dispatch(node.expr)
2.130 + self._accessor_end(target_names)
2.131 self._span_start("attr")
2.132 self.stream.write(".")
2.133 self._span(node.attrname, "attrname")
2.134 @@ -913,28 +953,28 @@
2.135
2.136 # Convenience functions.
2.137
2.138 -def summarise(module, filename):
2.139 +def summarise(module, program, filename):
2.140 stream = open(filename, "wb")
2.141 try:
2.142 - summary = Summary(module)
2.143 + summary = Summary(module, program)
2.144 summary.to_stream(stream)
2.145 finally:
2.146 stream.close()
2.147
2.148 -def annotate(module, filename):
2.149 +def annotate(module, program, filename):
2.150 stream = open(filename, "wb")
2.151 try:
2.152 - source = AnnotatedSource(module)
2.153 + source = AnnotatedSource(module, program)
2.154 source.to_stream(stream)
2.155 finally:
2.156 stream.close()
2.157
2.158 -def report(importer, directory):
2.159 +def report(program, directory):
2.160 if not exists(directory):
2.161 os.mkdir(directory)
2.162
2.163 - for module in importer.get_modules():
2.164 - annotate(module, join(directory, "%s%sxhtml" % (module.full_name(), extsep)))
2.165 - summarise(module, join(directory, "%s-summary%sxhtml" % (module.full_name(), extsep)))
2.166 + for module in program.get_importer().get_modules():
2.167 + annotate(module, program, join(directory, "%s%sxhtml" % (module.full_name(), extsep)))
2.168 + summarise(module, program, join(directory, "%s-summary%sxhtml" % (module.full_name(), extsep)))
2.169
2.170 # vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/micropython/trans.py Tue Aug 10 23:18:42 2010 +0200
3.2 +++ b/micropython/trans.py Wed Aug 11 00:04:11 2010 +0200
3.3 @@ -511,36 +511,32 @@
3.4
3.5 elif self.optimiser.should_optimise_accesses_by_attribute_usage():
3.6
3.7 - if hasattr(node, "_attrusers"):
3.8 - target_names = set()
3.9 + target_names = self.possible_accessor_types(node)
3.10
3.11 - for user in node._attrusers:
3.12 - target_names.update(self.objtable.all_possible_objects(user._attrnames[node._username]))
3.13 + if target_names is not None and len(target_names) == 1:
3.14 + target_name = list(target_names)[0]
3.15
3.16 - if len(target_names) == 1:
3.17 - target_name = list(target_names)[0]
3.18 + # Access the object table to get the attribute.
3.19
3.20 - # Access the object table to get the attribute.
3.21 + try:
3.22 + attr = self.objtable.access(target_name, attrname)
3.23
3.24 - try:
3.25 - attr = self.objtable.access(target_name, attrname)
3.26 + # Disallow non-class/instance optimisations.
3.27
3.28 - # Disallow non-class/instance optimisations.
3.29 + except TableError, exc:
3.30 + print "Possible optimisation for", target_name, "not permissable."
3.31 +
3.32 + # Produce a suitable instruction.
3.33
3.34 - except TableError, exc:
3.35 - print "Possible optimisation for", target_name, "not permissable."
3.36 -
3.37 - # Produce a suitable instruction.
3.38 -
3.39 + else:
3.40 + if AddressContextCondInstruction is not None and attr.is_static_attribute():
3.41 + self.new_op(AddressContextCondInstruction(attr))
3.42 + elif AttrInstruction is not None and not attr.is_static_attribute():
3.43 + self.new_op(AttrInstruction(attr))
3.44 else:
3.45 - if AddressContextCondInstruction is not None and attr.is_static_attribute():
3.46 - self.new_op(AddressContextCondInstruction(attr))
3.47 - elif AttrInstruction is not None and not attr.is_static_attribute():
3.48 - self.new_op(AttrInstruction(attr))
3.49 - else:
3.50 - raise TranslateError("Storing of class or module attribute %r via an object is not permitted." % attrname)
3.51 + raise TranslateError("Storing of class or module attribute %r via an object is not permitted." % attrname)
3.52
3.53 - return
3.54 + return
3.55
3.56 # Otherwise, perform a normal operation.
3.57