# HG changeset patch # User Paul Boddie # Date 1281901787 -7200 # Node ID dcff921447e6d60a17c62adda7ccb546c94b70f5 # Parent 33faeaf83f57b56cbbb93814a7f610272bc746ec Fixed operator module acquisition where the module is acquired in both a normal module and in the builtins. Fixed unary operator inspection so that the operator module is also used for such operators. Fixed instantiator acquisition, preventing attribute usage information from being erased by not supplying the Function initialiser with an AST node and not attempting to initialise attribute users without such a node. Removed the in_init attribute from InspectedModule instances. Simplified the built-in range function implementation. Added support for most remaining AST nodes in the report module. Changed the report summary to show instance attributes in order. Made base classes refer to their definitions in generated reports. Added a "pass" statement to empty classes in generated reports. diff -r 33faeaf83f57 -r dcff921447e6 lib/builtins.py --- a/lib/builtins.py Wed Aug 11 00:04:11 2010 +0200 +++ b/lib/builtins.py Sun Aug 15 21:49:47 2010 +0200 @@ -460,10 +460,7 @@ "Implementation of range." - l = [] - for i in xrange(start_or_end, end, step): - l.append(i) - return l + return list(xrange(start_or_end, end, step)) def raw_input(prompt=None): pass def reduce(function, sequence, initial=None): pass diff -r 33faeaf83f57 -r dcff921447e6 micropython/__init__.py --- a/micropython/__init__.py Wed Aug 11 00:04:11 2010 +0200 +++ b/micropython/__init__.py Sun Aug 15 21:49:47 2010 +0200 @@ -161,7 +161,6 @@ # Generate the instantiator/initialiser. # Append the function code to the image. - instantiator = obj.get_instantiator() code = trans.get_instantiator_code(obj) self.code += code diff -r 33faeaf83f57 -r dcff921447e6 micropython/data.py --- a/micropython/data.py Wed Aug 11 00:04:11 2010 +0200 +++ b/micropython/data.py Sun Aug 15 21:49:47 2010 +0200 @@ -1303,18 +1303,13 @@ # Initialise attribute usage. - for arg in argnames: + if node is not None: + for arg in argnames: - # Define attribute users. + # Define attribute users. - if node is not None: self._define_attribute_user_for_name(node, arg) - # Or just record the usage. - - else: - self.attributes_used[-1][arg] = set() - # Caches. self.localnames = None # cache for locals @@ -1520,7 +1515,7 @@ "Make an instantiator function from a method, keeping all arguments." function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults, - self.has_star, self.has_dstar, self.dynamic_def, self.module, self.astnode) + self.has_star, self.has_dstar, self.dynamic_def, self.module) function.default_attrs = self.default_attrs return function diff -r 33faeaf83f57 -r dcff921447e6 micropython/inspect.py --- a/micropython/inspect.py Wed Aug 11 00:04:11 2010 +0200 +++ b/micropython/inspect.py Sun Aug 15 21:49:47 2010 +0200 @@ -108,7 +108,6 @@ # Namespace state. - self.in_init = 0 # Find instance attributes in __init__ methods. self.in_method = 0 # Find instance attributes in all methods. self.in_function = 0 # Note function presence, affecting definitions. self.in_loop = 0 # Note loop "membership", affecting assignments. @@ -409,28 +408,25 @@ # Generic support for classes of operations. def _ensureOperators(self): - if not self.has_key("$operator"): + attr, scope, namespace = self._get_with_scope("$operator") + if attr is None: module = self.importer.load("operator") self["$operator"] = module - return self["$operator"].get_value() + else: + module = attr.get_value() + return module def _visitUnary(self, node): - "Accounting method for the unary operator 'node'." - - method = unary_methods[node.__class__.__name__] - self.use_name(method, node) - return self.OP(node) - - def _visitBinary(self, node): - - "Accounting method for the binary operator 'node'." + "Accounting method for the operator 'node'." operator_module = self._ensureOperators() operator_fn = operator_functions[node.__class__.__name__] self.use_specific_attribute(operator_module.full_name(), operator_fn) return self.OP(node) + _visitBinary = _visitUnary + def _visitFunction(self, node, name): """ @@ -487,8 +483,6 @@ # Previous namespace is the class. if self.in_class(namespaces): - if namespaces[-1].name == "__init__": - self.in_init = 1 self.in_method = 1 in_function = self.in_function @@ -501,7 +495,6 @@ self.in_loop = in_loop self.in_function = in_function - self.in_init = 0 self.in_method = 0 # Specific handler methods. diff -r 33faeaf83f57 -r dcff921447e6 micropython/report.py --- a/micropython/report.py Wed Aug 11 00:04:11 2010 +0200 +++ b/micropython/report.py Sun Aug 15 21:49:47 2010 +0200 @@ -60,6 +60,7 @@ .comment { color: blue; } .class-name { color: cyan; } .function-name { color: cyan; } + .specific-ref { color: #07F; } .str { color: #FF00FF; } .doc { color: #FF00FF; margin-top: 1em; margin-bottom: 1em; } @@ -202,9 +203,6 @@ self.stream.write('"""') self.stream.write("\n") - def _summary_link(self, module_name, full_name, name, classes=None): - self._name_link("%s-summary" % module_name, full_name, name, classes) - def _object_name_def(self, module, obj, classes=None): """ @@ -214,9 +212,21 @@ self._summary_link(module.full_name(), obj.full_name(), obj.name, classes) + def _object_name_ref(self, module, obj, classes=None): + + """ + Link to the definition for 'module' using 'obj'. The optional 'classes' + can be used to customise the CSS classes employed. + """ + + self._name_link(module.full_name(), obj.full_name(), obj.name, classes) + + def _summary_link(self, module_name, full_name, name, classes=None): + self._name_link("%s-summary" % module_name, full_name, name, classes) + def _name_link(self, module_name, full_name, name, classes=None): self.stream.write("%s" % ( - classes or "name", module_name, os.path.extsep, + classes or "specific-ref", module_name, os.path.extsep, self._attr(full_name), self._text(name))) def _scope(self, scope): @@ -283,7 +293,6 @@ "Write the summary to the given 'stream'." self.stream = stream - self._init_details() self.stream.write(html_header % {"full_name" : self.module.full_name()}) self._write_classes(self.module) self.stream.write(html_footer) @@ -316,31 +325,17 @@ self.stream.write(obj.name) self.stream.write("\n") - # ...and all known attribute names. + # ...and instance attribute names in order. - obj_attributes = obj.all_attribute_names() + attrs = obj.instance_attributes().values() + attrs.sort(cmp=lambda x, y: cmp(x.position, y.position)) - for name in self.attribute_names: - if name in obj_attributes: - self.stream.write("%s\n" % self._text(name)) - else: - self.stream.write("\n") + for attr in attrs: + self.stream.write("%s\n" % self._text(attr.name)) + self.stream.write("\n") - self.stream.write("\n") - def _init_details(self): - names = set() - - # Visit all classes. - - for obj in self.module.all_objects: - if isinstance(obj, Class): - names.update(obj.all_attribute_names()) - - self.attribute_names = list(names) - self.attribute_names.sort() - # Source code classes. class AnnotatedSource(ASTVisitor, Writer): @@ -427,7 +422,7 @@ if not first: self.stream.write(", ") - self._object_name_def(base.module, base) + self._object_name_ref(base.module, base) first = 0 self.stream.write(")") @@ -439,7 +434,18 @@ self.stream.write("
\n") self._doc(node) - self.dispatch(node.code) + + # NOTE: Some streams may not support tell. + + x = self.stream.tell() + + self.default(node.code) + + # Check for no output. + + if x == self.stream.tell(): + self.visitPass(None) + self.stream.write("
\n") self.stream.write("\n") @@ -902,6 +908,71 @@ else: self._span(node.name) + def visitNot(self, node): + self._span_start("not") + self._keyword("not") + self.dispatch(node.expr) + self._span_end() + + def visitOr(self, node): + self._span_start("or") + first = 1 + for n in node.nodes: + if not first: + self._keyword("or", 1) + self.dispatch(n) + first = 0 + self._span_end() + + def visitPower(self, node): + self._visitBinary(node, "power", "**") + + def visitSlice(self, node): + self._span_start("slice") + self.dispatch(node.expr) + self.stream.write("[") + if node.lower: + self.dispatch(node.lower) + self.stream.write(":") + if node.upper: + self.dispatch(node.upper) + # NOTE: Step? + self.stream.write("]") + self._span_end() + + def visitSliceobj(self, node): + self._span_start("sliceobj") + first = 1 + for n in node.nodes: + if not first: + self.stream.write(":") + self.dispatch(n) + self._span_end() + + def visitSub(self, node): + self._visitBinary(node, "sub", "-") + + def visitSubscript(self, node): + self._span_start("subscript") + self.dispatch(node.expr) + self.stream.write("[") + first = 1 + for sub in node.subs: + if not first: + self.stream.write(", ") + self.dispatch(sub) + first = 0 + self.stream.write("]") + self._span_end() + + visitTuple = visitAssTuple + + def visitUnaryAdd(self, node): + self._visitUnary(node, "add", "+") + + def visitUnarySub(self, node): + self._visitUnary(node, "sub", "-") + # Output preparation methods. def _sequence(self, node):