11#include "Python.h"
2+ #include "pycore_ast.h" // PyAST_Check()
3+ #include "pycore_pyarena.h" // _PyArena_New()
24#include "pycore_pythonrun.h" // _Py_SourceAsString()
35#include "pycore_symtable.h" // struct symtable
46
@@ -9,6 +11,29 @@ module _symtable
911/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f4685845a7100605]*/
1012
1113
14+ static struct symtable *
15+ symtable_from_ast (PyObject * source , PyObject * filename , int compile_mode )
16+ {
17+ PyArena * arena = _PyArena_New ();
18+ if (arena == NULL ) {
19+ return NULL ;
20+ }
21+ struct symtable * st = NULL ;
22+ mod_ty mod = PyAST_obj2mod (source , arena , compile_mode );
23+ if (mod == NULL || !_PyAST_Validate (mod )) {
24+ goto finally ;
25+ }
26+ _PyFutureFeatures future ;
27+ if (!_PyFuture_FromAST (mod , filename , & future )) {
28+ goto finally ;
29+ }
30+ st = _PySymtable_Build (mod , filename , & future );
31+ finally :
32+ _PyArena_Free (arena );
33+ return st ;
34+ }
35+
36+
1237/*[clinic input]
1338_symtable.symtable
1439
@@ -20,37 +45,29 @@ _symtable.symtable
2045 module as modname: object = None
2146
2247Return symbol and scope dictionaries used internally by compiler.
48+
49+ The source can be a string, a bytes object, or an AST object.
2350[clinic start generated code]*/
2451
2552static PyObject *
2653_symtable_symtable_impl (PyObject * module , PyObject * source ,
2754 PyObject * filename , const char * startstr ,
2855 PyObject * modname )
29- /*[clinic end generated code: output=235ec5a87a9ce178 input=fbf9adaa33c7070d ]*/
56+ /*[clinic end generated code: output=235ec5a87a9ce178 input=6cadac0485f576a7 ]*/
3057{
3158 struct symtable * st ;
3259 PyObject * t ;
33- int start ;
34- PyCompilerFlags cf = _PyCompilerFlags_INIT ;
35- PyObject * source_copy = NULL ;
36-
37- cf .cf_flags = PyCF_SOURCE_IS_UTF8 ;
38-
39- const char * str = _Py_SourceAsString (source , "symtable" , "string or bytes" , & cf , & source_copy );
40- if (str == NULL ) {
41- return NULL ;
42- }
60+ int compile_mode ;
4361
4462 if (strcmp (startstr , "exec" ) == 0 )
45- start = Py_file_input ;
63+ compile_mode = 0 ;
4664 else if (strcmp (startstr , "eval" ) == 0 )
47- start = Py_eval_input ;
65+ compile_mode = 1 ;
4866 else if (strcmp (startstr , "single" ) == 0 )
49- start = Py_single_input ;
67+ compile_mode = 2 ;
5068 else {
5169 PyErr_SetString (PyExc_ValueError ,
5270 "symtable() arg 3 must be 'exec' or 'eval' or 'single'" );
53- Py_XDECREF (source_copy );
5471 return NULL ;
5572 }
5673 if (modname == Py_None ) {
@@ -60,11 +77,30 @@ _symtable_symtable_impl(PyObject *module, PyObject *source,
6077 PyErr_Format (PyExc_TypeError ,
6178 "symtable() argument 'module' must be str or None, not %T" ,
6279 modname );
63- Py_XDECREF (source_copy );
6480 return NULL ;
6581 }
66- st = _Py_SymtableStringObjectFlags (str , filename , start , & cf , modname );
67- Py_XDECREF (source_copy );
82+
83+ if (PyAST_Check (source )) {
84+ st = symtable_from_ast (source , filename , compile_mode );
85+ }
86+ else {
87+ static const int starts [] = {
88+ Py_file_input , Py_eval_input , Py_single_input };
89+ PyCompilerFlags cf = _PyCompilerFlags_INIT ;
90+ PyObject * source_copy = NULL ;
91+
92+ cf .cf_flags = PyCF_SOURCE_IS_UTF8 ;
93+ const char * str = _Py_SourceAsString (source , "symtable" ,
94+ "string, bytes or AST" ,
95+ & cf , & source_copy );
96+ if (str == NULL ) {
97+ return NULL ;
98+ }
99+ st = _Py_SymtableStringObjectFlags (str , filename ,
100+ starts [compile_mode ], & cf ,
101+ modname );
102+ Py_XDECREF (source_copy );
103+ }
68104 if (st == NULL ) {
69105 return NULL ;
70106 }
0 commit comments