OILS / mycpp / debug_pass.py View on Github | oilshell.org

465 lines, 311 significant
1"""
2debug.py - Pretty-print the AST
3"""
4from mypy.visitor import ExpressionVisitor, StatementVisitor
5from mypy.nodes import Expression, Statement
6from mypy.types import Type
7
8from typing import overload, Union, Optional, Dict
9
10import mypy
11from mycpp.crash import catch_errors
12from mycpp.util import log
13
14T = None
15
16
17class UnsupportedException(Exception):
18 pass
19
20
21class Print(ExpressionVisitor[T], StatementVisitor[None]):
22
23 def __init__(self, types: Dict[Expression, Type]):
24 self.types = types
25 self.indent = 0
26
27 def log(self, msg, *args):
28 ind_str = self.indent * ' '
29 log(ind_str + msg, *args)
30
31 #
32 # COPIED from IRBuilder
33 #
34
35 @overload
36 def accept(self, node: Expression) -> T:
37 ...
38
39 @overload
40 def accept(self, node: Statement) -> None:
41 ...
42
43 def accept(self, node: Union[Statement, Expression]) -> Optional[T]:
44 with catch_errors(self.module_path, node.line):
45 if isinstance(node, Expression):
46 try:
47 res = node.accept(self)
48 #res = self.coerce(res, self.node_type(node), node.line)
49
50 # If we hit an error during compilation, we want to
51 # keep trying, so we can produce more error
52 # messages. Generate a temp of the right type to keep
53 # from causing more downstream trouble.
54 except UnsupportedException:
55 res = self.alloc_temp(self.node_type(node))
56 return res
57 else:
58 try:
59 node.accept(self)
60 except UnsupportedException:
61 pass
62 return None
63
64 # Not in superclasses:
65
66 def visit_mypy_file(self, o: 'mypy.nodes.MypyFile') -> T:
67 # Skip some stdlib stuff. A lot of it is brought in by 'import
68 # typing'.
69 if o.fullname() in ('__future__', 'sys', 'types', 'typing', 'abc',
70 '_ast', 'ast', '_weakrefset', 'collections',
71 'cStringIO', 're', 'builtins'):
72
73 # These module are special; their contents are currently all
74 # built-in primitives.
75 return
76
77 self.log('')
78 self.log('mypyfile %s', o.fullname())
79
80 self.module_path = o.path
81
82 self.indent += 1
83 for node in o.defs:
84 self.accept(node)
85 self.indent -= 1
86
87 # LITERALS
88
89 def visit_int_expr(self, o: 'mypy.nodes.IntExpr') -> T:
90 self.log('IntExpr %d', o.value)
91
92 def visit_str_expr(self, o: 'mypy.nodes.StrExpr') -> T:
93 pass
94
95 def visit_bytes_expr(self, o: 'mypy.nodes.BytesExpr') -> T:
96 pass
97
98 def visit_unicode_expr(self, o: 'mypy.nodes.UnicodeExpr') -> T:
99 pass
100
101 def visit_float_expr(self, o: 'mypy.nodes.FloatExpr') -> T:
102 pass
103
104 def visit_complex_expr(self, o: 'mypy.nodes.ComplexExpr') -> T:
105 pass
106
107 # Expression
108
109 def visit_ellipsis(self, o: 'mypy.nodes.EllipsisExpr') -> T:
110 pass
111
112 def visit_star_expr(self, o: 'mypy.nodes.StarExpr') -> T:
113 pass
114
115 def visit_name_expr(self, o: 'mypy.nodes.NameExpr') -> T:
116 self.log('NameExpr %s', o.name)
117
118 def visit_member_expr(self, o: 'mypy.nodes.MemberExpr') -> T:
119 self.log('MemberExpr')
120 self.log(' expr %s', o.expr)
121 self.log(' name %s', o.name)
122
123 def visit_yield_from_expr(self, o: 'mypy.nodes.YieldFromExpr') -> T:
124 pass
125
126 def visit_yield_expr(self, o: 'mypy.nodes.YieldExpr') -> T:
127 pass
128
129 def visit_call_expr(self, o: 'mypy.nodes.CallExpr') -> T:
130 self.log('CallExpr')
131 self.accept(o.callee) # could be f() or obj.method()
132
133 self.indent += 1
134 for arg in o.args:
135 self.accept(arg)
136 # The type of each argument
137 #self.log(':: %s', self.types[arg])
138 self.indent -= 1
139 #self.log( 'args %s', o.args)
140
141 self.log(' arg_kinds %s', o.arg_kinds)
142 self.log(' arg_names %s', o.arg_names)
143
144 def visit_op_expr(self, o: 'mypy.nodes.OpExpr') -> T:
145 self.log('OpExpr')
146 self.indent += 1
147 self.accept(o.left)
148 self.accept(o.right)
149 self.indent -= 1
150
151 def visit_comparison_expr(self, o: 'mypy.nodes.ComparisonExpr') -> T:
152 self.log('ComparisonExpr')
153 self.log(' operators %s', o.operators)
154 self.indent += 1
155
156 for operand in o.operands:
157 self.log('operand')
158 self.indent += 1
159 self.accept(operand)
160 self.indent -= 1
161
162 self.indent -= 1
163
164 def visit_cast_expr(self, o: 'mypy.nodes.CastExpr') -> T:
165 pass
166
167 def visit_reveal_expr(self, o: 'mypy.nodes.RevealExpr') -> T:
168 pass
169
170 def visit_super_expr(self, o: 'mypy.nodes.SuperExpr') -> T:
171 pass
172
173 def visit_assignment_expr(self, o: 'mypy.nodes.AssignmentExpr') -> T:
174 pass
175
176 def visit_unary_expr(self, o: 'mypy.nodes.UnaryExpr') -> T:
177 self.log('UnaryExpr %s', o.op)
178 self.indent += 1
179 self.accept(o.expr)
180 self.indent -= 1
181
182 def visit_list_expr(self, o: 'mypy.nodes.ListExpr') -> T:
183 pass
184
185 def visit_dict_expr(self, o: 'mypy.nodes.DictExpr') -> T:
186 pass
187
188 def visit_tuple_expr(self, o: 'mypy.nodes.TupleExpr') -> T:
189 pass
190
191 def visit_set_expr(self, o: 'mypy.nodes.SetExpr') -> T:
192 pass
193
194 def visit_index_expr(self, o: 'mypy.nodes.IndexExpr') -> T:
195 self.log('Index')
196 self.accept(o.base)
197 self.accept(o.index)
198
199 def visit_type_application(self, o: 'mypy.nodes.TypeApplication') -> T:
200 pass
201
202 def visit_lambda_expr(self, o: 'mypy.nodes.LambdaExpr') -> T:
203 pass
204
205 def visit_list_comprehension(self, o: 'mypy.nodes.ListComprehension') -> T:
206 pass
207
208 def visit_set_comprehension(self, o: 'mypy.nodes.SetComprehension') -> T:
209 pass
210
211 def visit_dictionary_comprehension(
212 self, o: 'mypy.nodes.DictionaryComprehension') -> T:
213 pass
214
215 def visit_generator_expr(self, o: 'mypy.nodes.GeneratorExpr') -> T:
216 pass
217
218 def visit_slice_expr(self, o: 'mypy.nodes.SliceExpr') -> T:
219 self.log('Slice')
220 self.indent += 1
221 self.log('begin %s', o.begin_index)
222 self.log('end %s', o.end_index)
223
224 if o.begin_index:
225 self.accept(o.begin_index)
226
227 if o.end_index:
228 self.accept(o.end_index)
229
230 if o.stride:
231 self.accept(o.stride)
232 self.indent -= 1
233
234 def visit_conditional_expr(self, o: 'mypy.nodes.ConditionalExpr') -> T:
235 pass
236
237 def visit_backquote_expr(self, o: 'mypy.nodes.BackquoteExpr') -> T:
238 pass
239
240 def visit_type_var_expr(self, o: 'mypy.nodes.TypeVarExpr') -> T:
241 pass
242
243 def visit_type_alias_expr(self, o: 'mypy.nodes.TypeAliasExpr') -> T:
244 pass
245
246 def visit_namedtuple_expr(self, o: 'mypy.nodes.NamedTupleExpr') -> T:
247 pass
248
249 def visit_enum_call_expr(self, o: 'mypy.nodes.EnumCallExpr') -> T:
250 pass
251
252 def visit_typeddict_expr(self, o: 'mypy.nodes.TypedDictExpr') -> T:
253 pass
254
255 def visit_newtype_expr(self, o: 'mypy.nodes.NewTypeExpr') -> T:
256 pass
257
258 def visit__promote_expr(self, o: 'mypy.nodes.PromoteExpr') -> T:
259 pass
260
261 def visit_await_expr(self, o: 'mypy.nodes.AwaitExpr') -> T:
262 pass
263
264 def visit_temp_node(self, o: 'mypy.nodes.TempNode') -> T:
265 pass
266
267 def visit_assignment_stmt(self, o: 'mypy.nodes.AssignmentStmt') -> T:
268 # How does this get reached??
269
270 # Ah wtf, why is there no type on here!
271 # I thought we did parse_and_typecheck already?
272
273 if 1:
274 self.log('AssignmentStmt')
275 #self.log(' type %s', o.type)
276 #self.log(' unanalyzed_type %s', o.unanalyzed_type)
277
278 # NICE! Got the lvalue
279 for lval in o.lvalues:
280 try:
281 self.log(' lval %s :: %s', lval, self.types[lval])
282 except KeyError: # TODO: handle this
283 pass
284 try:
285 r = self.types[o.rvalue]
286 except KeyError:
287 # This seems to only happen for Ellipsis, I guess in the abc module
288 #log(' NO TYPE FOR RVALUE: %s', o.rvalue)
289 pass
290 else:
291 #self.log(' %s :: %s', o.rvalue, r)
292 self.indent += 1
293 self.log(' rvalue :: %s', r)
294 self.accept(o.rvalue)
295 self.indent -= 1
296 #self.log(' o.rvalue %s', o.rvalue)
297
298 def visit_for_stmt(self, o: 'mypy.nodes.ForStmt') -> T:
299 self.log('ForStmt')
300 self.log(' index_type %s', o.index_type)
301 self.log(' inferred_item_type %s', o.inferred_item_type)
302 self.log(' inferred_iterator_type %s', o.inferred_iterator_type)
303 self.accept(o.index) # index var expression
304 self.accept(o.expr) # the thing being iterated over
305 self.accept(o.body)
306 if o.else_body:
307 self.accept(o.else_body)
308
309 def visit_with_stmt(self, o: 'mypy.nodes.WithStmt') -> T:
310 pass
311
312 def visit_del_stmt(self, o: 'mypy.nodes.DelStmt') -> T:
313 pass
314
315 def visit_func_def(self, o: 'mypy.nodes.FuncDef') -> T:
316 # got the type here, nice!
317 typ = o.type
318 self.log('FuncDef %s :: %s', o.name(), typ)
319 #self.log('%s', type(typ))
320
321 for t, name in zip(typ.arg_types, typ.arg_names):
322 self.log(' arg %s %s', t, name)
323 self.log(' ret %s', o.type.ret_type)
324
325 self.indent += 1
326 for arg in o.arguments:
327 # We can't use __str__ on these Argument objects? That seems like an
328 # oversight
329 #self.log('%r', arg)
330
331 self.log('Argument %s', arg.variable)
332 self.log(' type_annotation %s', arg.type_annotation)
333 # I think these are for default values
334 self.log(' initializer %s', arg.initializer)
335 self.log(' kind %s', arg.kind)
336
337 self.accept(o.body)
338 self.indent -= 1
339
340 def visit_overloaded_func_def(self,
341 o: 'mypy.nodes.OverloadedFuncDef') -> T:
342 pass
343
344 def visit_class_def(self, o: 'mypy.nodes.ClassDef') -> T:
345 # woohoo!!
346 self.log('ClassDef %s', o.name)
347 for b in o.base_type_exprs:
348 self.log(' base_type_expr %s', b)
349 self.indent += 1
350 self.accept(o.defs)
351 self.indent -= 1
352
353 def visit_global_decl(self, o: 'mypy.nodes.GlobalDecl') -> T:
354 pass
355
356 def visit_nonlocal_decl(self, o: 'mypy.nodes.NonlocalDecl') -> T:
357 pass
358
359 def visit_decorator(self, o: 'mypy.nodes.Decorator') -> T:
360 pass
361
362 def visit_var(self, o: 'mypy.nodes.Var') -> T:
363 pass
364
365 # Module structure
366
367 def visit_import(self, o: 'mypy.nodes.Import') -> T:
368 pass
369
370 def visit_import_from(self, o: 'mypy.nodes.ImportFrom') -> T:
371 pass
372
373 def visit_import_all(self, o: 'mypy.nodes.ImportAll') -> T:
374 pass
375
376 # Statements
377
378 def visit_block(self, block: 'mypy.nodes.Block') -> T:
379 self.log('Block')
380 self.indent += 1
381 for stmt in block.body:
382 #log('-- %d', self.indent)
383 self.accept(stmt)
384 self.indent -= 1
385
386 def visit_expression_stmt(self, o: 'mypy.nodes.ExpressionStmt') -> T:
387 self.log('ExpressionStmt')
388 self.indent += 1
389 self.accept(o.expr)
390 self.indent -= 1
391
392 def visit_operator_assignment_stmt(
393 self, o: 'mypy.nodes.OperatorAssignmentStmt') -> T:
394 self.log('OperatorAssignmentStmt %s', o.op)
395 self.indent += 1
396 self.accept(o.lvalue)
397 self.accept(o.rvalue)
398 self.indent -= 1
399
400 def visit_while_stmt(self, o: 'mypy.nodes.WhileStmt') -> T:
401 self.log('WhileStmt')
402 self.accept(o.expr)
403 self.accept(o.body)
404
405 def visit_return_stmt(self, o: 'mypy.nodes.ReturnStmt') -> T:
406 self.log('ReturnStmt')
407 if o.expr:
408 self.indent += 1
409 self.accept(o.expr)
410 self.indent -= 1
411
412 def visit_assert_stmt(self, o: 'mypy.nodes.AssertStmt') -> T:
413 pass
414
415 def visit_if_stmt(self, o: 'mypy.nodes.IfStmt') -> T:
416 self.log('IfStmt')
417 self.indent += 1
418 for e in o.expr:
419 self.accept(e)
420 for node in o.body:
421 self.accept(node)
422 if o.else_body:
423 self.accept(o.else_body)
424 self.indent -= 1
425
426 def visit_break_stmt(self, o: 'mypy.nodes.BreakStmt') -> T:
427 self.log('BreakStmt')
428
429 def visit_continue_stmt(self, o: 'mypy.nodes.ContinueStmt') -> T:
430 self.log('ContinueStmt')
431
432 def visit_pass_stmt(self, o: 'mypy.nodes.PassStmt') -> T:
433 pass
434
435 def visit_raise_stmt(self, o: 'mypy.nodes.RaiseStmt') -> T:
436 self.log('RaiseStmt')
437 if o.expr:
438 self.indent += 1
439 self.accept(o.expr)
440 self.indent -= 1
441
442 def visit_try_stmt(self, o: 'mypy.nodes.TryStmt') -> T:
443 self.log('TryStmt')
444 self.indent += 1
445
446 self.accept(o.body)
447
448 for t, v, handler in zip(o.types, o.vars, o.handlers):
449 self.log('except %s as %s', t, v)
450 self.indent += 1
451 self.accept(handler)
452 self.indent -= 1
453
454 if o.else_body:
455 self.accept(o.else_body)
456 if o.finally_body:
457 self.accept(o.finally_body)
458
459 self.indent -= 1
460
461 def visit_print_stmt(self, o: 'mypy.nodes.PrintStmt') -> T:
462 pass
463
464 def visit_exec_stmt(self, o: 'mypy.nodes.ExecStmt') -> T:
465 pass