GitHub Viewer
#include "Python.h"
#include "pycore_ast.h" // expr_ty
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_runtime.h" // _Py_ID()
#include
/* This limited unparser is used to convert annotations back to strings
* during compilation rather than being a full AST unparser.
* See ast.unparse for a full unparser (written in Python)
*/
_Py_DECLARE_STR(dbl_open_br, "{{");
_Py_DECLARE_STR(dbl_close_br, "}}");
/* Forward declarations for recursion via helper functions. */
static PyObject *
expr_as_unicode(expr_ty e, int level);
static int
append_ast_expr(PyUnicodeWriter *writer, expr_ty e, int level);
static int
append_templatestr(PyUnicodeWriter *writer, expr_ty e);
static int
append_joinedstr(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec);
static int
append_interpolation(PyUnicodeWriter *writer, expr_ty e);
static int
append_formattedvalue(PyUnicodeWriter *writer, expr_ty e);
static int
append_ast_slice(PyUnicodeWriter *writer, expr_ty e);
static int
append_char(PyUnicodeWriter *writer, Py_UCS4 ch)
{
return PyUnicodeWriter_WriteChar(writer, ch);
}
static int
append_charp(PyUnicodeWriter *writer, const char *charp)
{
return PyUnicodeWriter_WriteUTF8(writer, charp, -1);
}
#define APPEND_CHAR_FINISH(ch) do { \
return append_char(writer, (ch)); \
} while (0)
#define APPEND_STR_FINISH(str) do { \
return append_charp(writer, (str)); \
} while (0)
#define APPEND_CHAR(ch) do { \
if (-1 == append_char(writer, (ch))) { \
return -1; \
} \
} while (0)
#define APPEND_STR(str) do { \
if (-1 == append_charp(writer, (str))) { \
return -1; \
} \
} while (0)
#define APPEND_STR_IF(cond, str) do { \
if ((cond) && -1 == append_charp(writer, (str))) { \
return -1; \
} \
} while (0)
#define APPEND_STR_IF_NOT_FIRST(str) do { \
APPEND_STR_IF(!first, (str)); \
first = false; \
} while (0)
#define APPEND_EXPR(expr, pr) do { \
if (-1 == append_ast_expr(writer, (expr), (pr))) { \
return -1; \
} \
} while (0)
#define APPEND(type, value) do { \
if (-1 == append_ast_ ## type(writer, (value))) { \
return -1; \
} \
} while (0)
static int
append_repr(PyUnicodeWriter *writer, PyObject *obj)
{
PyObject *repr = PyObject_Repr(obj);
if (!repr) {
return -1;
}
if ((PyFloat_CheckExact(obj) && isinf(PyFloat_AS_DOUBLE(obj))) ||
PyComplex_CheckExact(obj))
{
_Py_DECLARE_STR(str_replace_inf, "1e309"); // evaluates to inf
PyObject *new_repr = PyUnicode_Replace(
repr,
&_Py_ID(inf),
&_Py_STR(str_replace_inf),
-1
);
Py_DECREF(repr);
if (!new_repr) {
return -1;
}
repr = new_repr;
}
int ret = PyUnicodeWriter_WriteStr(writer, repr);
Py_DECREF(repr);
return ret;
}
/* Priority levels */
enum {
PR_TUPLE,
PR_TEST, /* 'if'-'else', 'lambda' */
PR_OR, /* 'or' */
PR_AND, /* 'and' */
PR_NOT, /* 'not' */
PR_CMP, /* '', '==', '>=', '