1.1 --- a/micropython/ast.py Sun Apr 18 21:28:56 2010 +0200
1.2 +++ b/micropython/ast.py Mon Apr 19 01:14:59 2010 +0200
1.3 @@ -193,9 +193,6 @@
1.4 def default(self, node, *args):
1.5 raise TranslateError(self.module.full_name(), node, "Node class %r is not supported." % node.__class__)
1.6
1.7 - def dispatch(self, node, *args):
1.8 - return ASTVisitor.dispatch(self, node, *args)
1.9 -
1.10 # Concrete visitor methods.
1.11
1.12 # Binary operators.
3.1 --- a/micropython/inspect.py Sun Apr 18 21:28:56 2010 +0200
3.2 +++ b/micropython/inspect.py Mon Apr 19 01:14:59 2010 +0200
3.3 @@ -366,9 +366,6 @@
3.4 def default(self, node, *args):
3.5 raise InspectError(self.full_name(), node, "Node class %r is not supported." % node.__class__)
3.6
3.7 - def dispatch(self, node, *args):
3.8 - return ASTVisitor.dispatch(self, node, *args)
3.9 -
3.10 def NOP(self, node):
3.11 for n in node.getChildNodes():
3.12 self.dispatch(n)
4.1 --- a/micropython/report.py Sun Apr 18 21:28:56 2010 +0200
4.2 +++ b/micropython/report.py Mon Apr 19 01:14:59 2010 +0200
4.3 @@ -158,9 +158,6 @@
4.4 def _url(self, url):
4.5 return self._attr(url).replace("#", "%23").replace("-", "%2d")
4.6
4.7 - def _summary_link(self, module_name, name):
4.8 - return "<a href='%s-summary%sxhtml#%s'>%s</a>" % (module_name, os.path.extsep, self._attr(name), self._text(name))
4.9 -
4.10 # Methods which write to the stream.
4.11
4.12 def _comment(self, comment):
4.13 @@ -181,9 +178,25 @@
4.14 def _name(self, name):
4.15 self.stream.write("<span class='name'>%s</span>\n" % name)
4.16
4.17 + def _name_link(self, module_name, full_name, name):
4.18 + self.stream.write("<a class='name' href='%s%sxhtml#%s'>%s</a>" % (
4.19 + module_name, os.path.extsep, self._attr(full_name), self._text(name)))
4.20 +
4.21 + def _summary_link(self, module_name, full_name, name):
4.22 + self.stream.write("<a class='name' href='%s-summary%sxhtml#%s'>%s</a>" % (
4.23 + module_name, os.path.extsep, self._attr(full_name), self._text(name)))
4.24 +
4.25 + def _object_name_def(self, module, obj):
4.26 +
4.27 + """
4.28 + Link to the summary for 'module' using 'obj'.
4.29 + """
4.30 +
4.31 + self._summary_link(module.full_name(), obj.full_name(), obj.name)
4.32 +
4.33 # Summary classes.
4.34
4.35 -class Summariser(Writer):
4.36 +class Summary(Writer):
4.37
4.38 "Summarise classes and attributes in modules."
4.39
4.40 @@ -253,13 +266,277 @@
4.41 self.attribute_names = list(names)
4.42 self.attribute_names.sort()
4.43
4.44 +# Source code classes.
4.45 +
4.46 +class AnnotatedSource(ASTVisitor, Writer):
4.47 +
4.48 + "A module source code browser."
4.49 +
4.50 + def __init__(self, module):
4.51 + ASTVisitor.__init__(self)
4.52 + self.visitor = self
4.53 + self.module = module
4.54 +
4.55 + def to_stream(self, stream):
4.56 +
4.57 + "Write the annotated code to the given 'stream'."
4.58 +
4.59 + self.stream = stream
4.60 + self.stream.write(html_header)
4.61 + self.dispatch(self.module.module)
4.62 + self.stream.write(html_footer)
4.63 +
4.64 + def visitModule(self, node):
4.65 + self.default(node)
4.66 +
4.67 + # Statements.
4.68 +
4.69 + def visitAssert(self, node):
4.70 + self.stream.write("<div class='assert nowrap'>\n")
4.71 + self._keyword("assert")
4.72 + self.dispatch(node.test)
4.73 + if node.fail:
4.74 + self.stream.write(", ")
4.75 + self.dispatch(node.fail)
4.76 + self.stream.write("</div>\n")
4.77 +
4.78 + def visitAssign(self, node):
4.79 + self.stream.write("<div class='assign nowrap'>\n")
4.80 + for lvalue in node.nodes:
4.81 + self.dispatch(lvalue)
4.82 + self.stream.write("= ")
4.83 + self.dispatch(node.expr)
4.84 + self.stream.write("</div>\n")
4.85 +
4.86 + def visitAugAssign(self, node):
4.87 + self.stream.write("<div class='augassign nowrap'>\n")
4.88 + self.dispatch(node.node)
4.89 + self.stream.write("%s " % node.op)
4.90 + self.dispatch(node.expr)
4.91 + self.stream.write("</div>\n")
4.92 +
4.93 + def visitBreak(self, node):
4.94 + self.stream.write("<div class='break nowrap'>\n")
4.95 + self._keyword("break")
4.96 + self.stream.write("</div>\n")
4.97 +
4.98 + def visitClass(self, node):
4.99 +
4.100 + # Use inspected details where possible.
4.101 +
4.102 + if hasattr(node, "_def"):
4.103 + cls = node._def
4.104 + bases = cls.bases
4.105 + self.stream.write("<div class='class nowrap' id='%s'>\n" % cls.full_name())
4.106 + else:
4.107 + print "Warning: class %s not recognised!" % node.name
4.108 + return
4.109 +
4.110 + # Write the declaration line.
4.111 +
4.112 + self.stream.write("<div>\n")
4.113 + self._keyword("class")
4.114 + self._object_name_def(self.module, cls)
4.115 +
4.116 + # Suppress the "object" class appearing alone.
4.117 +
4.118 + if bases and not (len(bases) == 1 and bases[0].name == "object"):
4.119 + self.stream.write("(")
4.120 + first = 1
4.121 + for base in bases:
4.122 + if not first:
4.123 + self.stream.write(",\n")
4.124 +
4.125 + self._object_name_def(base.module, base)
4.126 +
4.127 + first = 0
4.128 + self.stream.write(")")
4.129 +
4.130 + self.stream.write(":\n")
4.131 + self.stream.write("</div>\n")
4.132 +
4.133 + # Write the docstring and class body.
4.134 +
4.135 + self.stream.write("<div class='body nowrap'>\n")
4.136 + self._doc(node)
4.137 + self.dispatch(node.code)
4.138 + self.stream.write("</div>\n")
4.139 + self.stream.write("</div>\n")
4.140 +
4.141 + def visitContinue(self, node):
4.142 + self.stream.write("<div class='continue nowrap'>\n")
4.143 + self._keyword("continue")
4.144 + self.stream.write("</div>\n")
4.145 +
4.146 + def visitDiscard(self, node):
4.147 + self.stream.write("<div class='discard nowrap'>\n")
4.148 + self.default(node)
4.149 + self.stream.write("</div>\n")
4.150 +
4.151 + def visitFor(self, node):
4.152 + self.stream.write("<div class='if nowrap'>\n")
4.153 + self.stream.write("<div>\n")
4.154 + self._keyword("for")
4.155 + self.dispatch(node.assign)
4.156 + self._keyword("in")
4.157 + self.dispatch(node.list)
4.158 + self.stream.write(":\n")
4.159 + self.stream.write("</div>\n")
4.160 + self.stream.write("<div class='body nowrap'>\n")
4.161 + self.dispatch(node.body)
4.162 + self.stream.write("</div>\n")
4.163 + if node.else_ is not None:
4.164 + self.stream.write("<div>\n")
4.165 + self._keyword("else")
4.166 + self.stream.write(":\n")
4.167 + self.stream.write("</div>\n")
4.168 + self.stream.write("<div class='body nowrap'>\n")
4.169 + self.dispatch(node.else_)
4.170 + self.stream.write("</div>\n")
4.171 + self.stream.write("</div>\n")
4.172 +
4.173 + def visitFrom(self, node):
4.174 + self.stream.write("<div class='from nowrap'>\n")
4.175 + self._keyword("from")
4.176 + self._name(node.modname)
4.177 + self._keyword("import")
4.178 + first = 1
4.179 + for (name, alias), _name in map(None, node.names, node._names):
4.180 + if not first:
4.181 + self.stream.write(",\n")
4.182 + if alias:
4.183 + self.stream.write(name + " ")
4.184 + self._keyword("as")
4.185 + self._name(alias or name)
4.186 + first = 0
4.187 + self.stream.write("</div>\n")
4.188 +
4.189 + def visitFunction(self, node):
4.190 + if hasattr(node, "_def"):
4.191 + fn = node._def
4.192 + self.stream.write("<div class='function nowrap' id='%s'>\n" % fn.full_name())
4.193 + else:
4.194 + print "Warning: function %s not recognised!" % node.name
4.195 + return
4.196 +
4.197 + # Write the declaration line.
4.198 +
4.199 + self.stream.write("<div>\n")
4.200 + self._keyword("def")
4.201 + self._object_name_def(self.module, fn)
4.202 +
4.203 + self.stream.write("(")
4.204 + self._parameters(fn)
4.205 + self.stream.write(")")
4.206 + self.stream.write(":\n")
4.207 + self.stream.write("</div>\n")
4.208 +
4.209 + self.stream.write("<div class='body nowrap'>\n")
4.210 + self._doc(node)
4.211 + self.dispatch(node.code)
4.212 + self.stream.write("</div>\n")
4.213 + self.stream.write("</div>\n")
4.214 +
4.215 + def visitGlobal(self, node):
4.216 + self.stream.write("<div class='global nowrap'>\n")
4.217 + self._keyword("global")
4.218 + first = 1
4.219 + for name in node.names:
4.220 + if not first:
4.221 + self.stream.write(",\n")
4.222 + self.stream.write(name)
4.223 + first = 0
4.224 + self.stream.write("</div>\n")
4.225 +
4.226 + def visitIf(self, node):
4.227 + self.stream.write("<div class='if nowrap'>\n")
4.228 + first = 1
4.229 + for compare, stmt in node.tests:
4.230 + self.stream.write("<div>\n")
4.231 + if first:
4.232 + self._keyword("if")
4.233 + else:
4.234 + self._keyword("elif")
4.235 + self.dispatch(compare)
4.236 + self.stream.write(":\n")
4.237 + self.stream.write("</div>\n")
4.238 + self.stream.write("<div class='body nowrap'>\n")
4.239 + self.dispatch(stmt)
4.240 + self.stream.write("</div>\n")
4.241 + first = 0
4.242 + if node.else_ is not None:
4.243 + self.stream.write("<div>\n")
4.244 + self._keyword("else")
4.245 + self.stream.write(":\n")
4.246 + self.stream.write("</div>\n")
4.247 + self.stream.write("<div class='body nowrap'>\n")
4.248 + self.dispatch(node.else_)
4.249 + self.stream.write("</div>\n")
4.250 + self.stream.write("</div>\n")
4.251 +
4.252 + # Output preparation methods.
4.253 +
4.254 + def _sequence(self, node):
4.255 + first = 1
4.256 + for n in node.nodes:
4.257 + if not first:
4.258 + self.stream.write(",\n")
4.259 + self.dispatch(n)
4.260 + first = 0
4.261 +
4.262 + def _mapping(self, node):
4.263 + first = 1
4.264 + for k, v in node.items:
4.265 + if not first:
4.266 + self.stream.write(",\n")
4.267 + self.dispatch(k)
4.268 + self.stream.write(":\n")
4.269 + self.dispatch(v)
4.270 + first = 0
4.271 +
4.272 + def _parameters(self, fn):
4.273 + first = 1
4.274 + nparams = len(fn.positional_names)
4.275 + ndefaults = len(fn.defaults)
4.276 + first_with_default = nparams - ndefaults
4.277 +
4.278 + for n, param in enumerate(fn.positional_names):
4.279 + if not first:
4.280 + self.stream.write(",\n")
4.281 + self._name(param)
4.282 + n_default = n - first_with_default
4.283 + if n_default >= 0:
4.284 + self._default(fn.defaults[n_default])
4.285 +
4.286 + if fn.has_star:
4.287 + if not first:
4.288 + self.stream.write(", *\n")
4.289 + self._name(fn.star_name)
4.290 +
4.291 + if fn.has_dstar:
4.292 + if not first:
4.293 + self.stream.write(", **\n")
4.294 + self._name(fn.dstar_name)
4.295 +
4.296 + def _default(self, default):
4.297 + self.stream.write("=\n")
4.298 + self.dispatch(default)
4.299 +
4.300 # Convenience functions.
4.301
4.302 -def summary(module, filename):
4.303 +def summarise(module, filename):
4.304 stream = open(filename, "wb")
4.305 try:
4.306 - summariser = Summariser(module)
4.307 - summariser.to_stream(stream)
4.308 + summary = Summary(module)
4.309 + summary.to_stream(stream)
4.310 + finally:
4.311 + stream.close()
4.312 +
4.313 +def annotate(module, filename):
4.314 + stream = open(filename, "wb")
4.315 + try:
4.316 + source = AnnotatedSource(module)
4.317 + source.to_stream(stream)
4.318 finally:
4.319 stream.close()
4.320