|
4 | 4 | #include "pycore_pystate.h" // _PyThreadState_GET()
|
5 | 5 | #include "pycore_symtable.h" // PySTEntryObject
|
6 | 6 |
|
| 7 | +// Set this to 1 to dump all symtables to stdout for debugging |
| 8 | +#define _PY_DUMP_SYMTABLE 0 |
7 | 9 |
|
8 | 10 | /* error strings used for warnings */
|
9 | 11 | #define GLOBAL_PARAM \
|
@@ -251,6 +253,109 @@ static int symtable_visit_pattern(struct symtable *st, pattern_ty s);
|
251 | 253 | static int symtable_raise_if_annotation_block(struct symtable *st, const char *, expr_ty);
|
252 | 254 | static int symtable_raise_if_comprehension_block(struct symtable *st, expr_ty);
|
253 | 255 |
|
| 256 | +/* For debugging purposes only */ |
| 257 | +#if _PY_DUMP_SYMTABLE |
| 258 | +static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) |
| 259 | +{ |
| 260 | + const char *blocktype = ""; |
| 261 | + switch (ste->ste_type) { |
| 262 | + case FunctionBlock: blocktype = "FunctionBlock"; break; |
| 263 | + case ClassBlock: blocktype = "ClassBlock"; break; |
| 264 | + case ModuleBlock: blocktype = "ModuleBlock"; break; |
| 265 | + case AnnotationBlock: blocktype = "AnnotationBlock"; break; |
| 266 | + case TypeVarBoundBlock: blocktype = "TypeVarBoundBlock"; break; |
| 267 | + case TypeAliasBlock: blocktype = "TypeAliasBlock"; break; |
| 268 | + case TypeParamBlock: blocktype = "TypeParamBlock"; break; |
| 269 | + } |
| 270 | + const char *comptype = ""; |
| 271 | + switch (ste->ste_comprehension) { |
| 272 | + case ListComprehension: comptype = " ListComprehension"; break; |
| 273 | + case DictComprehension: comptype = " DictComprehension"; break; |
| 274 | + case SetComprehension: comptype = " SetComprehension"; break; |
| 275 | + case GeneratorExpression: comptype = " GeneratorExpression"; break; |
| 276 | + case NoComprehension: break; |
| 277 | + } |
| 278 | + PyObject* msg = PyUnicode_FromFormat( |
| 279 | + ( |
| 280 | + "%U=== Symtable for %U ===\n" |
| 281 | + "%U%s%s\n" |
| 282 | + "%U%s%s%s%s%s%s%s%s%s%s%s%s%s\n" |
| 283 | + "%Ulineno: %d col_offset: %d\n" |
| 284 | + "%U--- Symbols ---\n" |
| 285 | + ), |
| 286 | + prefix, |
| 287 | + ste->ste_name, |
| 288 | + prefix, |
| 289 | + blocktype, |
| 290 | + comptype, |
| 291 | + prefix, |
| 292 | + ste->ste_nested ? " nested" : "", |
| 293 | + ste->ste_free ? " free" : "", |
| 294 | + ste->ste_child_free ? " child_free" : "", |
| 295 | + ste->ste_generator ? " generator" : "", |
| 296 | + ste->ste_coroutine ? " coroutine" : "", |
| 297 | + ste->ste_varargs ? " varargs" : "", |
| 298 | + ste->ste_varkeywords ? " varkeywords" : "", |
| 299 | + ste->ste_returns_value ? " returns_value" : "", |
| 300 | + ste->ste_needs_class_closure ? " needs_class_closure" : "", |
| 301 | + ste->ste_needs_classdict ? " needs_classdict" : "", |
| 302 | + ste->ste_comp_inlined ? " comp_inlined" : "", |
| 303 | + ste->ste_comp_iter_target ? " comp_iter_target" : "", |
| 304 | + ste->ste_can_see_class_scope ? " can_see_class_scope" : "", |
| 305 | + prefix, |
| 306 | + ste->ste_lineno, |
| 307 | + ste->ste_col_offset, |
| 308 | + prefix |
| 309 | + ); |
| 310 | + assert(msg != NULL); |
| 311 | + printf("%s", PyUnicode_AsUTF8(msg)); |
| 312 | + Py_DECREF(msg); |
| 313 | + PyObject *name, *value; |
| 314 | + Py_ssize_t pos = 0; |
| 315 | + while (PyDict_Next(ste->ste_symbols, &pos, &name, &value)) { |
| 316 | + int scope = _PyST_GetScope(ste, name); |
| 317 | + long flags = _PyST_GetSymbol(ste, name); |
| 318 | + printf("%s %s: ", PyUnicode_AsUTF8(prefix), PyUnicode_AsUTF8(name)); |
| 319 | + if (flags & DEF_GLOBAL) printf(" DEF_GLOBAL"); |
| 320 | + if (flags & DEF_LOCAL) printf(" DEF_LOCAL"); |
| 321 | + if (flags & DEF_PARAM) printf(" DEF_PARAM"); |
| 322 | + if (flags & DEF_NONLOCAL) printf(" DEF_NONLOCAL"); |
| 323 | + if (flags & USE) printf(" USE"); |
| 324 | + if (flags & DEF_FREE) printf(" DEF_FREE"); |
| 325 | + if (flags & DEF_FREE_CLASS) printf(" DEF_FREE_CLASS"); |
| 326 | + if (flags & DEF_IMPORT) printf(" DEF_IMPORT"); |
| 327 | + if (flags & DEF_ANNOT) printf(" DEF_ANNOT"); |
| 328 | + if (flags & DEF_COMP_ITER) printf(" DEF_COMP_ITER"); |
| 329 | + if (flags & DEF_TYPE_PARAM) printf(" DEF_TYPE_PARAM"); |
| 330 | + if (flags & DEF_COMP_CELL) printf(" DEF_COMP_CELL"); |
| 331 | + switch (scope) { |
| 332 | + case LOCAL: printf(" LOCAL"); break; |
| 333 | + case GLOBAL_EXPLICIT: printf(" GLOBAL_EXPLICIT"); break; |
| 334 | + case GLOBAL_IMPLICIT: printf(" GLOBAL_IMPLICIT"); break; |
| 335 | + case FREE: printf(" FREE"); break; |
| 336 | + case CELL: printf(" CELL"); break; |
| 337 | + } |
| 338 | + printf("\n"); |
| 339 | + } |
| 340 | + printf("%s--- Children ---\n", PyUnicode_AsUTF8(prefix)); |
| 341 | + PyObject *new_prefix = PyUnicode_FromFormat(" %U", prefix); |
| 342 | + assert(new_prefix != NULL); |
| 343 | + for (Py_ssize_t i = 0; i < PyList_GET_SIZE(ste->ste_children); i++) { |
| 344 | + PyObject *child = PyList_GetItem(ste->ste_children, i); |
| 345 | + assert(child != NULL && PySTEntry_Check(child)); |
| 346 | + _dump_symtable((PySTEntryObject *)child, new_prefix); |
| 347 | + } |
| 348 | + Py_DECREF(new_prefix); |
| 349 | +} |
| 350 | + |
| 351 | +static void dump_symtable(PySTEntryObject* ste) |
| 352 | +{ |
| 353 | + PyObject *empty = PyUnicode_FromString(""); |
| 354 | + assert(empty != NULL); |
| 355 | + _dump_symtable(ste, empty); |
| 356 | + Py_DECREF(empty); |
| 357 | +} |
| 358 | +#endif |
254 | 359 |
|
255 | 360 | #define DUPLICATE_ARGUMENT \
|
256 | 361 | "duplicate argument '%U' in function definition"
|
@@ -360,8 +465,12 @@ _PySymtable_Build(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
|
360 | 465 | return NULL;
|
361 | 466 | }
|
362 | 467 | /* Make the second symbol analysis pass */
|
363 |
| - if (symtable_analyze(st)) |
| 468 | + if (symtable_analyze(st)) { |
| 469 | +#if _PY_DUMP_SYMTABLE |
| 470 | + dump_symtable(st->st_top); |
| 471 | +#endif |
364 | 472 | return st;
|
| 473 | + } |
365 | 474 | _PySymtable_Free(st);
|
366 | 475 | return NULL;
|
367 | 476 | error:
|
|
0 commit comments