OILS / asdl / format.py View on Github | oilshell.org

157 lines, 102 significant
1"""
2format.py -- Pretty print an ASDL data structure.
3"""
4from _devbuild.gen.hnode_asdl import hnode, hnode_e, hnode_t
5from _devbuild.gen.pretty_asdl import (doc, doc_e, doc_t, MeasuredDoc,
6 List_Measured)
7from display import pp_hnode
8from display import pretty
9from mycpp import mylib
10from mycpp.mylib import log, tagswitch
11
12from typing import Any, Optional, cast
13
14_ = log
15
16if mylib.PYTHON:
17
18 def PrettyPrint(obj, f=None):
19 # type: (Any, Optional[mylib.Writer]) -> None
20 """Print abbreviated tree in color. For unit tests."""
21 f = f if f else mylib.Stdout()
22 tree = obj.PrettyTree(True)
23 HNodePrettyPrint(tree, f)
24
25
26def _HNodeCount(h):
27 # type: (hnode_t) -> int
28 """
29 Return the size of the tree
30 """
31 UP_h = h
32 with tagswitch(h) as case:
33 if case(hnode_e.AlreadySeen):
34 return 1
35
36 elif case(hnode_e.Leaf):
37 return 1
38
39 elif case(hnode_e.Array):
40 h = cast(hnode.Array, UP_h)
41 n = 1 # 1 for this node
42 for child in h.children:
43 n += _HNodeCount(child)
44 return n
45
46 elif case(hnode_e.Record):
47 h = cast(hnode.Record, UP_h)
48 n = 1 # 1 for this node
49 for field in h.fields:
50 n += _HNodeCount(field.val)
51
52 if h.unnamed_fields is not None:
53 for child in h.unnamed_fields:
54 n += _HNodeCount(child)
55 return n
56
57 else:
58 raise AssertionError()
59
60
61def _DocCount(d):
62 # type: (doc_t) -> int
63 """
64 Return the size of the tree
65 """
66 UP_d = d
67 with tagswitch(d) as case:
68 if case(doc_e.Break):
69 return 1
70
71 elif case(doc_e.Text):
72 return 1
73
74 elif case(doc_e.Indent):
75 d = cast(doc.Indent, UP_d)
76 return 1 + _DocCount(d.mdoc.doc)
77
78 elif case(doc_e.Group):
79 d = cast(MeasuredDoc, UP_d)
80 return 1 + _DocCount(d.doc)
81
82 elif case(doc_e.Flat):
83 d = cast(doc.Flat, UP_d)
84 return 1 + _DocCount(d.mdoc.doc)
85
86 elif case(doc_e.IfFlat):
87 d = cast(doc.IfFlat, UP_d)
88 return 1 + _DocCount(d.flat_mdoc.doc) + _DocCount(
89 d.nonflat_mdoc.doc)
90
91 elif case(doc_e.Concat):
92 d = cast(List_Measured, UP_d)
93 n = 1 # 1 for this node
94 for mdoc in d:
95 n += _DocCount(mdoc.doc)
96 return n
97
98 else:
99 raise AssertionError()
100
101
102def _HNodePrettyPrint(perf_stats, doc_debug, node, f, max_width=80):
103 # type: (bool, bool, hnode_t, mylib.Writer, int) -> None
104
105 mylib.MaybeCollect()
106 if perf_stats:
107 log('___ HNODE COUNT %d', _HNodeCount(node))
108 log('')
109
110 if 0:
111 log('___ GC: after hnode_t conversion')
112 mylib.PrintGcStats()
113 log('')
114
115 enc = pp_hnode.HNodeEncoder()
116 enc.SetUseStyles(f.isatty())
117 enc.SetIndent(2) # save space, compared to 4 spaces
118
119 d = enc.HNode(node)
120
121 mylib.MaybeCollect()
122 if perf_stats:
123 if doc_debug:
124 #if 0:
125 # Pretty print the doc tree itself!
126 p = d.PrettyTree(False)
127 _HNodePrettyPrint(perf_stats, False, p, f)
128
129 log('___ DOC COUNT %d', _DocCount(d))
130 log('')
131
132 if 0:
133 log('___ GC: after doc_t conversion')
134 mylib.PrintGcStats()
135 log('')
136
137 printer = pretty.PrettyPrinter(max_width) # max columns
138
139 buf = mylib.BufWriter()
140 printer.PrintDoc(d, buf)
141
142 f.write(buf.getvalue())
143 f.write('\n')
144
145 mylib.MaybeCollect()
146 if perf_stats:
147 log('___ GC: after printing')
148 mylib.PrintGcStats()
149 log('')
150
151
152def HNodePrettyPrint(node, f, max_width=80):
153 # type: (hnode_t, mylib.Writer, int) -> None
154 """
155 Make sure dependencies aren't a problem
156 """
157 _HNodePrettyPrint(False, True, node, f, max_width=max_width)