#include "Python.h"
#include "pycore_ast.h" // expr_ty
#include "pycore_runtime.h" // _Py_ID()
#include // DBL_MAX_10_EXP
#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(open_br, "{");
_Py_DECLARE_STR(dbl_open_br, "{{");
_Py_DECLARE_STR(close_br, "}");
_Py_DECLARE_STR(dbl_close_br, "}}");
static PyObject *_str_replace_inf;
/* 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_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec);
static int
append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e);
static int
append_ast_slice(_PyUnicodeWriter *writer, expr_ty e);
static int
append_charp(_PyUnicodeWriter *writer, const char *charp)
{
return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1);
}
#define APPEND_STR_FINISH(str) do { \
return append_charp(writer, (str)); \
} 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) && Py_IS_INFINITY(PyFloat_AS_DOUBLE(obj))) ||
PyComplex_CheckExact(obj))
{
PyObject *new_repr = PyUnicode_Replace(
repr,
&_Py_ID(inf),
_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, /* '', '==', '>=', '