From 1506ff16ad0fa203b385d2a7e0a2a300437ec65c Mon Sep 17 00:00:00 2001 From: James King Date: Wed, 10 Apr 2013 15:08:44 -0400 Subject: [PATCH] Added ast pretty printer --- hy/util.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/hy/util.py b/hy/util.py index f2ffdf1..98d5861 100644 --- a/hy/util.py +++ b/hy/util.py @@ -18,6 +18,8 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. +import ast + def flatten_literal_list(entry): for e in entry: @@ -26,3 +28,42 @@ def flatten_literal_list(entry): yield x # needs more yield-from else: yield e + + +def dump(node, annotate_fields=True, include_attributes=False, indent=' '): + """ + Return a formatted dump of the tree in *node*. This is mainly useful for + debugging purposes. The returned string will show the names and the values + for fields. This makes the code impossible to evaluate, so if evaluation is + wanted *annotate_fields* must be set to False. Attributes such as line + numbers and column offsets are not dumped by default. If this is wanted, + *include_attributes* can be set to True. + + Original author: Alex Leone (acleone ~AT~ gmail.com), 2010-01-30 + """ + def _format(node, level=0): + if isinstance(node, ast.AST): + fields = [(a, _format(b, level)) for a, b in ast.iter_fields(node)] + if include_attributes and node._attributes: + fields.extend([(a, _format(getattr(node, a), level)) + for a in node._attributes]) + return ''.join([ + node.__class__.__name__, + '(', + ', '.join(('%s=%s' % field for field in fields) + if annotate_fields else + (b for a, b in fields)), + ')']) + elif isinstance(node, list): + lines = ['['] + lines.extend((indent * (level + 2) + _format(x, level + 2) + ',' + for x in node)) + if len(lines) > 1: + lines.append(indent * (level + 1) + ']') + else: + lines[-1] += ']' + return '\n'.join(lines) + return repr(node) + if not isinstance(node, ast.AST): + raise TypeError('expected AST, got %r' % node.__class__.__name__) + return _format(node)