Skip to content

Commit

Permalink
gh-102371: move _Py_Mangle from compile.c to symtable.c (#102372)
Browse files Browse the repository at this point in the history
  • Loading branch information
iritkatriel authored Mar 2, 2023
1 parent 7325000 commit 71db5db
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 76 deletions.
6 changes: 0 additions & 6 deletions Include/internal/pycore_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ PyAPI_FUNC(PyCodeObject*) _PyAST_Compile(
int optimize,
struct _arena *arena);

int _PyFuture_FromAST(
struct _mod * mod,
PyObject *filename,
PyFutureFeatures* futures);

extern PyObject* _Py_Mangle(PyObject *p, PyObject *name);

typedef struct {
int optimize;
Expand Down
7 changes: 7 additions & 0 deletions Include/internal/pycore_symtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ PyAPI_FUNC(PySTEntryObject *) PySymtable_Lookup(struct symtable *, void *);

extern void _PySymtable_Free(struct symtable *);

extern PyObject* _Py_Mangle(PyObject *p, PyObject *name);

/* Flags for def-use information */

#define DEF_GLOBAL 1 /* global stmt */
Expand Down Expand Up @@ -128,6 +130,11 @@ extern struct symtable* _Py_SymtableStringObjectFlags(
int start,
PyCompilerFlags *flags);

int _PyFuture_FromAST(
struct _mod * mod,
PyObject *filename,
PyFutureFeatures* futures);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "Python.h"
#include "pycore_call.h"
#include "pycore_code.h" // CO_FAST_FREE
#include "pycore_compile.h" // _Py_Mangle()
#include "pycore_symtable.h" // _Py_Mangle()
#include "pycore_dict.h" // _PyDict_KeysSize()
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_moduleobject.h" // _PyModule_GetDef()
Expand Down
70 changes: 2 additions & 68 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@
#include "Python.h"
#include "pycore_ast.h" // _PyAST_GetDocString()
#include "pycore_code.h" // _PyCode_New()
#include "pycore_compile.h" // _PyFuture_FromAST()
#include "pycore_compile.h"
#include "pycore_intrinsics.h"
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_opcode.h" // _PyOpcode_Caches
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
#include "pycore_symtable.h" // PySTEntryObject
#include "pycore_symtable.h" // PySTEntryObject, _PyFuture_FromAST()

#include "opcode_metadata.h" // _PyOpcode_opcode_metadata, _PyOpcode_num_popped/pushed

Expand Down Expand Up @@ -569,72 +569,6 @@ static PyCodeObject *assemble(struct compiler *, int addNone);

#define CAPSULE_NAME "compile.c compiler unit"

PyObject *
_Py_Mangle(PyObject *privateobj, PyObject *ident)
{
/* Name mangling: __private becomes _classname__private.
This is independent from how the name is used. */
PyObject *result;
size_t nlen, plen, ipriv;
Py_UCS4 maxchar;
if (privateobj == NULL || !PyUnicode_Check(privateobj) ||
PyUnicode_READ_CHAR(ident, 0) != '_' ||
PyUnicode_READ_CHAR(ident, 1) != '_') {
return Py_NewRef(ident);
}
nlen = PyUnicode_GET_LENGTH(ident);
plen = PyUnicode_GET_LENGTH(privateobj);
/* Don't mangle __id__ or names with dots.
The only time a name with a dot can occur is when
we are compiling an import statement that has a
package name.
TODO(jhylton): Decide whether we want to support
mangling of the module name, e.g. __M.X.
*/
if ((PyUnicode_READ_CHAR(ident, nlen-1) == '_' &&
PyUnicode_READ_CHAR(ident, nlen-2) == '_') ||
PyUnicode_FindChar(ident, '.', 0, nlen, 1) != -1) {
return Py_NewRef(ident); /* Don't mangle __whatever__ */
}
/* Strip leading underscores from class name */
ipriv = 0;
while (PyUnicode_READ_CHAR(privateobj, ipriv) == '_')
ipriv++;
if (ipriv == plen) {
return Py_NewRef(ident); /* Don't mangle if class is just underscores */
}
plen -= ipriv;

if (plen + nlen >= PY_SSIZE_T_MAX - 1) {
PyErr_SetString(PyExc_OverflowError,
"private identifier too large to be mangled");
return NULL;
}

maxchar = PyUnicode_MAX_CHAR_VALUE(ident);
if (PyUnicode_MAX_CHAR_VALUE(privateobj) > maxchar)
maxchar = PyUnicode_MAX_CHAR_VALUE(privateobj);

result = PyUnicode_New(1 + nlen + plen, maxchar);
if (!result) {
return NULL;
}
/* ident = "_" + priv[ipriv:] + ident # i.e. 1+plen+nlen bytes */
PyUnicode_WRITE(PyUnicode_KIND(result), PyUnicode_DATA(result), 0, '_');
if (PyUnicode_CopyCharacters(result, 1, privateobj, ipriv, plen) < 0) {
Py_DECREF(result);
return NULL;
}
if (PyUnicode_CopyCharacters(result, plen+1, ident, 0, nlen) < 0) {
Py_DECREF(result);
return NULL;
}
assert(_PyUnicode_CheckConsistency(result, 1));
return result;
}


static int
compiler_setup(struct compiler *c, mod_ty mod, PyObject *filename,
Expand Down
67 changes: 66 additions & 1 deletion Python/symtable.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "Python.h"
#include "pycore_ast.h" // identifier, stmt_ty
#include "pycore_compile.h" // _Py_Mangle(), _PyFuture_FromAST()
#include "pycore_parser.h" // _PyParser_ASTFromString()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_symtable.h" // PySTEntryObject
Expand Down Expand Up @@ -2152,3 +2151,69 @@ _Py_SymtableStringObjectFlags(const char *str, PyObject *filename,
_PyArena_Free(arena);
return st;
}

PyObject *
_Py_Mangle(PyObject *privateobj, PyObject *ident)
{
/* Name mangling: __private becomes _classname__private.
This is independent from how the name is used. */
if (privateobj == NULL || !PyUnicode_Check(privateobj) ||
PyUnicode_READ_CHAR(ident, 0) != '_' ||
PyUnicode_READ_CHAR(ident, 1) != '_') {
return Py_NewRef(ident);
}
size_t nlen = PyUnicode_GET_LENGTH(ident);
size_t plen = PyUnicode_GET_LENGTH(privateobj);
/* Don't mangle __id__ or names with dots.
The only time a name with a dot can occur is when
we are compiling an import statement that has a
package name.
TODO(jhylton): Decide whether we want to support
mangling of the module name, e.g. __M.X.
*/
if ((PyUnicode_READ_CHAR(ident, nlen-1) == '_' &&
PyUnicode_READ_CHAR(ident, nlen-2) == '_') ||
PyUnicode_FindChar(ident, '.', 0, nlen, 1) != -1) {
return Py_NewRef(ident); /* Don't mangle __whatever__ */
}
/* Strip leading underscores from class name */
size_t ipriv = 0;
while (PyUnicode_READ_CHAR(privateobj, ipriv) == '_') {
ipriv++;
}
if (ipriv == plen) {
return Py_NewRef(ident); /* Don't mangle if class is just underscores */
}
plen -= ipriv;

if (plen + nlen >= PY_SSIZE_T_MAX - 1) {
PyErr_SetString(PyExc_OverflowError,
"private identifier too large to be mangled");
return NULL;
}

Py_UCS4 maxchar = PyUnicode_MAX_CHAR_VALUE(ident);
if (PyUnicode_MAX_CHAR_VALUE(privateobj) > maxchar) {
maxchar = PyUnicode_MAX_CHAR_VALUE(privateobj);
}

PyObject *result = PyUnicode_New(1 + nlen + plen, maxchar);
if (!result) {
return NULL;
}
/* ident = "_" + priv[ipriv:] + ident # i.e. 1+plen+nlen bytes */
PyUnicode_WRITE(PyUnicode_KIND(result), PyUnicode_DATA(result), 0, '_');
if (PyUnicode_CopyCharacters(result, 1, privateobj, ipriv, plen) < 0) {
Py_DECREF(result);
return NULL;
}
if (PyUnicode_CopyCharacters(result, plen+1, ident, 0, nlen) < 0) {
Py_DECREF(result);
return NULL;
}
assert(_PyUnicode_CheckConsistency(result, 1));
return result;
}

0 comments on commit 71db5db

Please sign in to comment.