\n")
self._keyword("def")
self._name_start(subprogram.name)
self._popup_start()
- self._scopes(definition)
- self._raises(subprogram)
+ self._scopes([definition]) # not dependent on subprograms
+ self._raises(subprograms)
self._popup_end()
self._name_end()
self.stream.write("(")
- self._parameters(subprogram)
+ self._parameters(subprogram, subprograms)
self.stream.write(")")
self.stream.write(":\n")
self._comment(self._text(subprogram.full_name()))
@@ -326,6 +329,7 @@
self.stream.write("
\n")
first = 1
conditional = node._node
+ conditionals = getattr(node, "_nodes", [conditional])
for compare, stmt in node.tests:
self.stream.write("
\n")
self.stream.write("\n")
@@ -371,7 +375,7 @@
self.stream.write("\n")
self.stream.write(alias or name)
self._popup_start()
- self._types(_name)
+ self._types([_name])
self._popup_end()
self.stream.write("\n")
first = 0
@@ -420,11 +424,13 @@
self.stream.write("
\n")
def visitReturn(self, node):
+ value = node._node
+ values = getattr(node, "_nodes", [value])
self.stream.write("
\n")
self.stream.write("
\n")
self._keyword("return")
self._popup_start()
- self._types(node._node)
+ self._types(values)
self._popup_end()
self.stream.write("\n")
self.dispatch(node.value)
@@ -556,13 +562,15 @@
self.stream.write("")
def visitAssAttr(self, node):
+ target = node._node
+ targets = getattr(node, "_nodes", [target])
self.stream.write("
\n")
self.dispatch(node.expr)
self.stream.write("\n")
self.stream.write(".%s\n" % self._text(node.attrname))
self._popup_start()
- self._types(node._node)
- self._scopes(node._node)
+ self._types(targets)
+ self._scopes(targets)
self._popup_end()
self.stream.write("\n")
self.stream.write("\n")
@@ -575,10 +583,12 @@
self.stream.write("\n")
def visitAssName(self, node):
- self._name_start(node._node.name)
+ target = node._node
+ targets = getattr(node, "_nodes", [target])
+ self._name_start(target.name)
self._popup_start()
- self._types(node._node.expr)
- self._scopes(node._node)
+ self._types(targets) # target.expr
+ self._scopes(targets)
self._popup_end()
self._name_end()
@@ -590,12 +600,14 @@
self.stream.write("\n")
def visitCallFunc(self, node):
+ target = node._node
+ targets = getattr(node, "_nodes", [target])
self.stream.write("
\n")
self.dispatch(node.node)
self.stream.write("\n")
self.stream.write("(")
self._popup_start()
- self._invocations(node._node)
+ self._invocations(target)
self._popup_end()
self.stream.write("\n")
first = 1
@@ -633,6 +645,13 @@
def visitConst(self, node):
self.stream.write(repr(node.value))
+ def visitDict(self, node):
+ self.stream.write("\n")
+ self.stream.write("{")
+ self._mapping(node)
+ self.stream.write("}\n")
+ self.stream.write("\n")
+
def visitDiv(self, node):
self._visitBinary(node, "div", "/")
@@ -640,13 +659,15 @@
self._visitBinary(node, "floordiv", "//")
def visitGetattr(self, node):
+ target = node._node
+ targets = getattr(node, "_nodes", [target])
self.stream.write("\n")
self.dispatch(node.expr)
self.stream.write("\n")
self.stream.write(".%s\n" % self._text(node.attrname))
self._popup_start()
- self._types(node._node)
- self._scopes(node._node)
+ self._types(targets)
+ self._scopes(targets)
self._popup_end()
self.stream.write("\n")
self.stream.write("\n")
@@ -660,10 +681,12 @@
def visitLambda(self, node):
definition = node._node
+ definitions = [n for n in getattr(node, "_nodes", [definition]) if not isinstance(n, Subprogram)]
subprogram = definition.expr.ref
+ subprograms = [n for n in getattr(node, "_nodes", [subprogram]) if isinstance(n, Subprogram)]
self.stream.write("\n")
self._keyword("lambda")
- self._parameters(subprogram)
+ self._parameters(subprogram, subprograms)
self.dispatch(node.code)
self.stream.write("\n")
@@ -676,10 +699,12 @@
self._visitBinary(node, "mul", "*")
def visitName(self, node):
- self._name_start(node._node.name)
+ target = node._node
+ targets = getattr(node, "_nodes", [target])
+ self._name_start(target.name)
self._popup_start()
- self._types(node._node)
- self._scopes(node._node)
+ self._types(targets)
+ self._scopes(targets)
self._popup_end()
self._name_end()
@@ -773,33 +798,94 @@
self.dispatch(n)
first = 0
- def _parameters(self, subprogram):
+ def _mapping(self, node):
first = 1
- for param, default in subprogram.params:
+ for k, v in node.items:
if not first:
self.stream.write(",\n")
- self._parameter(subprogram, param, default)
+ self.dispatch(k)
+ self.stream.write(":\n")
+ self.dispatch(v)
first = 0
- if subprogram.star is not None:
+
+ def _parameters(self, subprogram, subprograms):
+
+ # Get all the parameter lists.
+
+ params = []
+ nparams = 0
+ for sub in subprograms:
+ params.append(sub.params)
+ nparams = max(nparams, len(sub.params))
+ stars = []
+ have_star = 0
+ for sub in subprograms:
+ stars.append(sub.star)
+ if sub.star is not None:
+ have_star = 1
+ dstars = []
+ have_dstar = 0
+ for sub in subprograms:
+ dstars.append(sub.dstar)
+ if sub.dstar is not None:
+ have_dstar = 1
+
+ # Traverse the parameter lists, choosing a "column" at a time.
+
+ first = 1
+ for n in range(0, nparams):
+ if not first:
+ self.stream.write(",\n")
+ main_param, main_default = subprogram.params[n]
+ self._name_start(main_param)
+ self._popup_start()
+ self.stream.write("\n")
+ for i in range(0, len(subprograms)):
+ param, default = params[i][n]
+ self._parameter(subprograms[i], param)
+ self.stream.write("
\n")
+ self._popup_end()
+ self._name_end()
+ self._default(main_default)
+ first = 0
+
+ if have_star:
if not first:
self.stream.write(", *\n")
- param, default = subprogram.star
- self._parameter(subprogram, param, default)
+ main_param, main_default = subprogram.star
+ self._name_start(main_param)
+ self._popup_start()
+ self.stream.write("\n")
+ for i in range(0, len(subprograms)):
+ param, default = stars[i]
+ self._parameter(subprograms[i], param)
+ self.stream.write("
\n")
+ self._popup_end()
+ self._name_end()
+ self._default(main_default)
first = 0
- if subprogram.dstar is not None:
+
+ if have_dstar:
if not first:
self.stream.write(", **\n")
- param, default = subprogram.dstar
- self._parameter(subprogram, param, default)
+ main_param, main_default = subprogram.dstar
+ self._name_start(main_param)
+ self._popup_start()
+ self.stream.write("\n")
+ for i in range(0, len(subprograms)):
+ param, default = dstars[i]
+ self._parameter(subprograms[i], param)
+ self.stream.write("
\n")
+ self._popup_end()
+ self._name_end()
+ self._default(main_default)
first = 0
- def _parameter(self, subprogram, param, default):
- self._name_start(param)
+ def _parameter(self, subprogram, param):
if hasattr(subprogram, "paramtypes"):
- self._popup_start()
self._types_list(subprogram.paramtypes[param])
- self._popup_end()
- self._name_end()
+
+ def _default(self, default):
if default is not None and default.original is not None:
self.stream.write("=\n")
self.dispatch(default.original)
@@ -844,7 +930,13 @@
self.stream.write("")
self.stream.write("\n")
- def _types(self, node):
+ def _types(self, nodes):
+ self.stream.write("
\n")
+ for node in nodes:
+ self._type(node)
+ self.stream.write("
\n")
+
+ def _type(self, node):
if hasattr(node, "types"):
if node.types:
self._types_list(node.types)
@@ -856,40 +948,59 @@
else:
self._no_types()
else:
- self.stream.write("
\n")
- self.stream.write("unvisited\n")
- self.stream.write("
\n")
+ self._unvisited()
+
+ def _unvisited(self):
+ self.stream.write("
")
+ self.stream.write("unvisited\n")
+ self.stream.write("
\n")
def _no_types(self):
- self.stream.write("
\n")
+ self.stream.write("
")
self.stream.write("no types\n")
self.stream.write("
\n")
- def _types_list(self, types, style_class="types"):
+ def _types_container(self, types, style_class):
self.stream.write("
\n" % style_class)
+ self._types_list(types)
+ self.stream.write("
\n")
+
+ def _types_list(self, types):
for type in types:
fn = type.type.full_name()
self.stream.write("
")
self.stream.write(self._text(fn))
self.stream.write("
\n")
+
+ def _raises(self, nodes):
+
+ "Output the exception information for the given simplified 'nodes'."
+
+ self.stream.write("
\n")
+ for node in nodes:
+ if hasattr(node, "namespace") and hasattr(node.namespace, "raises") and node.namespace.raises:
+ self._types_list(node.namespace.raises)
self.stream.write("
\n")
- def _raises(self, node):
- if hasattr(node, "namespace") and hasattr(node.namespace, "raises") and node.namespace.raises:
- self._types_list(node.namespace.raises, style_class="raises")
+ def _scopes(self, nodes):
+
+ "Output the scope information for the given simplified 'nodes'."
- def _scopes(self, node):
+ self.stream.write("
\n")
+ for node in nodes:
+ self._scope(node)
+ self.stream.write("
\n")
+
+ def _scope(self, node):
"Output the scope information for the given simplified 'node'."
# Straightforward name loading/storing involves the local scope.
if isinstance(node, StoreName) or isinstance(node, LoadName):
- self.stream.write("
\n")
self.stream.write("
")
self.stream.write("(local)")
self.stream.write("
\n")
- self.stream.write("
\n")
# Other loading/storing involves attributes accessed on modules, classes
# and objects.
@@ -899,7 +1010,6 @@
# Loading...
if hasattr(node, "accesses") and node.accesses:
- self.stream.write("
\n")
for ref, accesses in node.accesses.items():
fn = ref.full_name()
for attr, access in accesses:
@@ -909,28 +1019,25 @@
if ref != access:
self.stream.write(" (via " + self._text(access_fn) + ")")
self.stream.write("
\n")
- self.stream.write("
\n")
# Storing...
if hasattr(node, "writes") and node.writes:
- self.stream.write("
\n")
for ref in node.writes.keys():
fn = ref.full_name()
self.stream.write("
")
self.stream.write(self._text(fn))
self.stream.write("
\n")
- self.stream.write("
\n")
# Non-loading...
if hasattr(node, "non_accesses") and node.non_accesses:
- self._types_list(node.non_accesses, style_class="non-accesses")
+ self._types_container(node.non_accesses, "non-accesses")
# Non-storing...
if hasattr(node, "non_writes") and node.non_writes:
- self._types_list(node.non_writes, style_class="non-writes")
+ self._types_container(node.non_writes, "non-writes")
# Utility functions.