Commit 64fddc42 authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by Łukasz Langa

bpo-33475: Fix and improve converting annotations to strings. (GH-6774)

parent d852142c
...@@ -19,9 +19,7 @@ PyAPI_FUNC(mod_ty) PyAST_FromNodeObject( ...@@ -19,9 +19,7 @@ PyAPI_FUNC(mod_ty) PyAST_FromNodeObject(
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
/* _PyAST_ExprAsUnicode is defined in ast_unparse.c */ /* _PyAST_ExprAsUnicode is defined in ast_unparse.c */
PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode( PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode(expr_ty);
expr_ty e,
int omit_parens);
#endif /* !Py_LIMITED_API */ #endif /* !Py_LIMITED_API */
......
...@@ -157,55 +157,76 @@ class AnnotationsFutureTestCase(unittest.TestCase): ...@@ -157,55 +157,76 @@ class AnnotationsFutureTestCase(unittest.TestCase):
eq('True or False or None') eq('True or False or None')
eq('True and False') eq('True and False')
eq('True and False and None') eq('True and False and None')
eq('(Name1 and Name2) or Name3') eq('Name1 and Name2 or Name3')
eq('Name1 or (Name2 and Name3)') eq('Name1 and (Name2 or Name3)')
eq('(Name1 and Name2) or (Name3 and Name4)') eq('Name1 or Name2 and Name3')
eq('Name1 or (Name2 and Name3) or Name4') eq('(Name1 or Name2) and Name3')
eq('Name1 and Name2 or Name3 and Name4')
eq('Name1 or Name2 and Name3 or Name4')
eq('a + b + (c + d)')
eq('a * b * (c * d)')
eq('(a ** b) ** c ** d')
eq('v1 << 2') eq('v1 << 2')
eq('1 >> v2') eq('1 >> v2')
eq(r'1 % finished') eq('1 % finished')
eq('((1 + v2) - (v3 * 4)) ^ (((5 ** v6) / 7) // 8)') eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8')
eq('not great') eq('not great')
eq('not not great')
eq('~great') eq('~great')
eq('+value') eq('+value')
eq('++value')
eq('-1') eq('-1')
eq('(~int) and (not ((v1 ^ (123 + v2)) | True))') eq('~int and not v1 ^ 123 + v2 | True')
eq('a + (not b)')
eq('lambda arg: None') eq('lambda arg: None')
eq('lambda a=True: a') eq('lambda a=True: a')
eq('lambda a, b, c=True: a') eq('lambda a, b, c=True: a')
eq("lambda a, b, c=True, *, d=(1 << v2), e='str': a") eq("lambda a, b, c=True, *, d=1 << v2, e='str': a")
eq("lambda a, b, c=True, *vararg, d=(v1 << 2), e='str', **kwargs: a + b") eq("lambda a, b, c=True, *vararg, d=v1 << 2, e='str', **kwargs: a + b")
eq('lambda x: lambda y: x + y')
eq('1 if True else 2') eq('1 if True else 2')
eq('(str or None) if True else (str or bytes or None)') eq('str or None if int or True else str or bytes or None')
eq('(str or None) if (1 if True else 2) else (str or bytes or None)') eq('str or None if (1 if True else 2) else str or bytes or None')
eq("{'2.7': dead, '3.7': (long_live or die_hard)}") eq("0 if not x else 1 if x > 0 else -1")
eq("{'2.7': dead, '3.7': (long_live or die_hard), **{'3.6': verygood}}") eq("(1 if x > 0 else -1) if x else 0")
eq("{'2.7': dead, '3.7': long_live or die_hard}")
eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}")
eq("{**a, **b, **c}") eq("{**a, **b, **c}")
eq("{'2.7', '3.6', '3.7', '3.8', '3.9', ('4.0' if gilectomy else '3.10')}") eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}")
eq("({'a': 'b'}, (True or False), (+value), 'string', b'bytes') or None") eq("{*a, *b, *c}")
eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None")
eq("()") eq("()")
eq("(1,)") eq("(a,)")
eq("(1, 2)") eq("(a, b)")
eq("(1, 2, 3)") eq("(a, b, c)")
eq("(*a, *b, *c)")
eq("[]") eq("[]")
eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, (10 or A), (11 or B), (12 or C)]") eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
eq("[*a, *b, *c]")
eq("{i for i in (1, 2, 3)}") eq("{i for i in (1, 2, 3)}")
eq("{(i ** 2) for i in (1, 2, 3)}") eq("{i ** 2 for i in (1, 2, 3)}")
eq("{(i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}") eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}")
eq("{((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)}") eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}")
eq("[i for i in (1, 2, 3)]") eq("[i for i in (1, 2, 3)]")
eq("[(i ** 2) for i in (1, 2, 3)]") eq("[i ** 2 for i in (1, 2, 3)]")
eq("[(i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]") eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]")
eq("[((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)]") eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]")
eq(r"{i: 0 for i in (1, 2, 3)}") eq("(i for i in (1, 2, 3))")
eq("(i ** 2 for i in (1, 2, 3))")
eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))")
eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
eq("{i: 0 for i in (1, 2, 3)}")
eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}") eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
eq("[(x, y) for x, y in (a, b)]")
eq("[(x,) for x, in (a,)]")
eq("Python3 > Python2 > COBOL") eq("Python3 > Python2 > COBOL")
eq("Life is Life") eq("Life is Life")
eq("call()") eq("call()")
eq("call(arg)") eq("call(arg)")
eq("call(kwarg='hey')") eq("call(kwarg='hey')")
eq("call(arg, kwarg='hey')") eq("call(arg, kwarg='hey')")
eq("call(arg, another, kwarg='hey', **kwargs)") eq("call(arg, *args, another, kwarg='hey')")
eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')")
eq("lukasz.langa.pl") eq("lukasz.langa.pl")
eq("call.me(maybe)") eq("call.me(maybe)")
eq("1 .real") eq("1 .real")
...@@ -213,6 +234,7 @@ class AnnotationsFutureTestCase(unittest.TestCase): ...@@ -213,6 +234,7 @@ class AnnotationsFutureTestCase(unittest.TestCase):
eq("....__class__") eq("....__class__")
eq("list[str]") eq("list[str]")
eq("dict[str, int]") eq("dict[str, int]")
eq("set[str,]")
eq("tuple[str, ...]") eq("tuple[str, ...]")
eq("tuple[str, int, float, dict[str, int]]") eq("tuple[str, int, float, dict[str, int]]")
eq("slice[0]") eq("slice[0]")
...@@ -222,49 +244,28 @@ class AnnotationsFutureTestCase(unittest.TestCase): ...@@ -222,49 +244,28 @@ class AnnotationsFutureTestCase(unittest.TestCase):
eq("slice[:-1]") eq("slice[:-1]")
eq("slice[1:]") eq("slice[1:]")
eq("slice[::-1]") eq("slice[::-1]")
eq('(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None)') eq("slice[()]")
eq("slice[a, b:c, d:e:f]")
eq("slice[(x for x in a)]")
eq('str or None if sys.version_info[0] > (3,) else str or bytes or None')
eq("f'f-string without formatted values is just a string'") eq("f'f-string without formatted values is just a string'")
eq("f'{{NOT a formatted value}}'") eq("f'{{NOT a formatted value}}'")
eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'") eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'")
eq('''f"{f'{nested} inner'} outer"''') eq('''f"{f'{nested} inner'} outer"''')
eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'") eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'")
eq("f'{(lambda x: x)}'")
def test_annotations_inexact(self): eq("f'{(None if a else lambda x: x)}'")
"""Source formatting is not always preserved
This is due to reconstruction from AST. We *need to* put the parens
in nested expressions because we don't know if the source code
had them in the first place or not.
"""
eq = partial(self.assertAnnotationEqual, drop_parens=True)
eq('Name1 and Name2 or Name3')
eq('Name1 or Name2 and Name3')
eq('Name1 and Name2 or Name3 and Name4')
eq('Name1 or Name2 and Name3 or Name4')
eq('1 + v2 - v3 * 4 ^ v5 ** 6 / 7 // 8')
eq('~int and not v1 ^ 123 + v2 | True')
eq('str or None if True else str or bytes or None')
eq("{'2.7': dead, '3.7': long_live or die_hard}")
eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}")
eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
# Consequently, we always drop unnecessary parens if they were given in
# the outer scope:
some_name = self.getActual("(SomeName)")
self.assertEqual(some_name, 'SomeName')
# Interestingly, in the case of tuples (and generator expressions) the
# parens are *required* by the Python syntax in the annotation context.
# But there's no point storing that detail in __annotations__ so we're
# fine with the parens-less form.
eq = partial(self.assertAnnotationEqual, is_tuple=True)
eq("(Good, Bad, Ugly)")
eq("(i for i in (1, 2, 3))")
eq("((i ** 2) for i in (1, 2, 3))")
eq("((i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))")
eq("(((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3))")
eq("(*starred)")
eq('(yield from outside_of_generator)') eq('(yield from outside_of_generator)')
eq('(yield)') eq('(yield)')
eq('(await some.complicated[0].call(with_args=(True or (1 is not 1))))') eq('(yield a + b)')
eq('await some.complicated[0].call(with_args=True or 1 is not 1)')
eq('[x for x in (a if b else c)]')
eq('[x for x in a if (b if c else d)]')
eq('f(x for x in a)')
eq('f(1, (x for x in a))')
eq('f((x for x in a), 2)')
eq('(((a)))', 'a')
eq('(((a, b)))', '(a, b)')
if __name__ == "__main__": if __name__ == "__main__":
......
Fixed miscellaneous bugs in converting annotations to strings and optimized
parentheses in the string representation.
...@@ -9,13 +9,15 @@ static PyObject *_str_dbl_close_br; ...@@ -9,13 +9,15 @@ static PyObject *_str_dbl_close_br;
/* Forward declarations for recursion via helper functions. */ /* Forward declarations for recursion via helper functions. */
static PyObject * static PyObject *
expr_as_unicode(expr_ty e, bool omit_parens); expr_as_unicode(expr_ty e, int level);
static int static int
append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens); append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level);
static int static int
append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec); append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec);
static int static int
append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec); append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec);
static int
append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice);
static int static int
append_charp(_PyUnicodeWriter *writer, const char *charp) append_charp(_PyUnicodeWriter *writer, const char *charp)
...@@ -23,6 +25,39 @@ append_charp(_PyUnicodeWriter *writer, const char *charp) ...@@ -23,6 +25,39 @@ append_charp(_PyUnicodeWriter *writer, const char *charp)
return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1); 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 static int
append_repr(_PyUnicodeWriter *writer, PyObject *obj) append_repr(_PyUnicodeWriter *writer, PyObject *obj)
{ {
...@@ -37,111 +72,108 @@ append_repr(_PyUnicodeWriter *writer, PyObject *obj) ...@@ -37,111 +72,108 @@ append_repr(_PyUnicodeWriter *writer, PyObject *obj)
return ret; return ret;
} }
static int /* Priority levels */
append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens)
enum {
PR_TUPLE,
PR_TEST, /* 'if'-'else', 'lambda' */
PR_OR, /* 'or' */
PR_AND, /* 'and' */
PR_NOT, /* 'not' */
PR_CMP, /* '<', '>', '==', '>=', '<=', '!=',
'in', 'not in', 'is', 'is not' */
PR_EXPR,
PR_BOR = PR_EXPR, /* '|' */
PR_BXOR, /* '^' */
PR_BAND, /* '&' */
PR_SHIFT, /* '<<', '>>' */
PR_ARITH, /* '+', '-' */
PR_TERM, /* '*', '@', '/', '%', '//' */
PR_FACTOR, /* unary '+', '-', '~' */
PR_POWER, /* '**' */
PR_AWAIT, /* 'await' */
PR_ATOM,
};
static int
append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, int level)
{ {
Py_ssize_t i, value_count; Py_ssize_t i, value_count;
asdl_seq *values; asdl_seq *values;
const char *op = (e->v.BoolOp.op == And) ? " and " : " or ";
int pr = (e->v.BoolOp.op == And) ? PR_AND : PR_OR;
if (!omit_parens && -1 == append_charp(writer, "(")) { APPEND_STR_IF(level > pr, "(");
return -1;
}
values = e->v.BoolOp.values; values = e->v.BoolOp.values;
value_count = asdl_seq_LEN(values) - 1; value_count = asdl_seq_LEN(values);
assert(value_count >= 0);
if (-1 == append_ast_expr(writer, for (i = 0; i < value_count; ++i) {
(expr_ty)asdl_seq_GET(values, 0), APPEND_STR_IF(i > 0, op);
false)) { APPEND_EXPR((expr_ty)asdl_seq_GET(values, i), pr + 1);
return -1;
}
const char *op = (e->v.BoolOp.op == And) ? " and " : " or ";
for (i = 1; i <= value_count; ++i) {
if (-1 == append_charp(writer, op)) {
return -1;
}
if (-1 == append_ast_expr(writer,
(expr_ty)asdl_seq_GET(values, i),
false)) {
return -1;
}
} }
return omit_parens ? 0 : append_charp(writer, ")"); APPEND_STR_IF(level > pr, ")");
return 0;
} }
static int static int
append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, int level)
{ {
const char *op; const char *op;
int pr;
if (!omit_parens && -1 == append_charp(writer, "(")) { bool rassoc = false; /* is right-associative? */
return -1;
} switch (e->v.BinOp.op) {
case Add: op = " + "; pr = PR_ARITH; break;
if (-1 == append_ast_expr(writer, e->v.BinOp.left, false)) { case Sub: op = " - "; pr = PR_ARITH; break;
return -1; case Mult: op = " * "; pr = PR_TERM; break;
} case MatMult: op = " @ "; pr = PR_TERM; break;
case Div: op = " / "; pr = PR_TERM; break;
switch(e->v.BinOp.op) { case Mod: op = " % "; pr = PR_TERM; break;
case Add: op = " + "; break; case LShift: op = " << "; pr = PR_SHIFT; break;
case Sub: op = " - "; break; case RShift: op = " >> "; pr = PR_SHIFT; break;
case Mult: op = " * "; break; case BitOr: op = " | "; pr = PR_BOR; break;
case MatMult: op = " @ "; break; case BitXor: op = " ^ "; pr = PR_BXOR; break;
case Div: op = " / "; break; case BitAnd: op = " & "; pr = PR_BAND; break;
case Mod: op = " % "; break; case FloorDiv: op = " // "; pr = PR_TERM; break;
case LShift: op = " << "; break; case Pow: op = " ** "; pr = PR_POWER; rassoc = true; break;
case RShift: op = " >> "; break;
case BitOr: op = " | "; break;
case BitXor: op = " ^ "; break;
case BitAnd: op = " & "; break;
case FloorDiv: op = " // "; break;
case Pow: op = " ** "; break;
default: default:
Py_UNREACHABLE(); PyErr_SetString(PyExc_SystemError,
} "unknown binary operator");
if (-1 == append_charp(writer, op)) {
return -1;
}
if (-1 == append_ast_expr(writer, e->v.BinOp.right, false)) {
return -1; return -1;
} }
return omit_parens ? 0 : append_charp(writer, ")"); APPEND_STR_IF(level > pr, "(");
APPEND_EXPR(e->v.BinOp.left, pr + rassoc);
APPEND_STR(op);
APPEND_EXPR(e->v.BinOp.right, pr + !rassoc);
APPEND_STR_IF(level > pr, ")");
return 0;
} }
static int static int
append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, int level)
{ {
const char *op; const char *op;
int pr;
if (!omit_parens && -1 == append_charp(writer, "(")) { switch (e->v.UnaryOp.op) {
return -1; case Invert: op = "~"; pr = PR_FACTOR; break;
} case Not: op = "not "; pr = PR_NOT; break;
case UAdd: op = "+"; pr = PR_FACTOR; break;
switch(e->v.UnaryOp.op) { case USub: op = "-"; pr = PR_FACTOR; break;
case Invert: op = "~"; break;
case Not: op = "not "; break;
case UAdd: op = "+"; break;
case USub: op = "-"; break;
default: default:
Py_UNREACHABLE(); PyErr_SetString(PyExc_SystemError,
} "unknown unary operator");
if (-1 == append_charp(writer, op)) {
return -1;
}
if (-1 == append_ast_expr(writer, e->v.UnaryOp.operand, false)) {
return -1; return -1;
} }
return omit_parens ? 0 : append_charp(writer, ")"); APPEND_STR_IF(level > pr, "(");
APPEND_STR(op);
APPEND_EXPR(e->v.UnaryOp.operand, pr);
APPEND_STR_IF(level > pr, ")");
return 0;
} }
static int static int
...@@ -151,12 +183,8 @@ append_ast_arg(_PyUnicodeWriter *writer, arg_ty arg) ...@@ -151,12 +183,8 @@ append_ast_arg(_PyUnicodeWriter *writer, arg_ty arg)
return -1; return -1;
} }
if (arg->annotation) { if (arg->annotation) {
if (-1 == append_charp(writer, ": ")) { APPEND_STR(": ");
return -1; APPEND_EXPR(arg->annotation, PR_TEST);
}
if (-1 == append_ast_expr(writer, arg->annotation, true)) {
return -1;
}
} }
return 0; return 0;
} }
...@@ -166,8 +194,6 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) ...@@ -166,8 +194,6 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args)
{ {
bool first; bool first;
Py_ssize_t i, di, arg_count, default_count; Py_ssize_t i, di, arg_count, default_count;
arg_ty arg;
expr_ty default_;
first = true; first = true;
...@@ -175,47 +201,22 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) ...@@ -175,47 +201,22 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args)
arg_count = asdl_seq_LEN(args->args); arg_count = asdl_seq_LEN(args->args);
default_count = asdl_seq_LEN(args->defaults); default_count = asdl_seq_LEN(args->defaults);
for (i = 0; i < arg_count; i++) { for (i = 0; i < arg_count; i++) {
if (first) { APPEND_STR_IF_NOT_FIRST(", ");
first = false; APPEND(arg, (arg_ty)asdl_seq_GET(args->args, i));
}
else if (-1 == append_charp(writer, ", ")) {
return -1;
}
arg = (arg_ty)asdl_seq_GET(args->args, i);
if (-1 == append_ast_arg(writer, arg)) {
return -1;
}
di = i - arg_count + default_count; di = i - arg_count + default_count;
if (di >= 0) { if (di >= 0) {
if (-1 == append_charp(writer, "=")) { APPEND_STR("=");
return -1; APPEND_EXPR((expr_ty)asdl_seq_GET(args->defaults, di), PR_TEST);
}
default_ = (expr_ty)asdl_seq_GET(args->defaults, di);
if (-1 == append_ast_expr(writer, default_, false)) {
return -1;
}
} }
} }
/* vararg, or bare '*' if no varargs but keyword-only arguments present */ /* vararg, or bare '*' if no varargs but keyword-only arguments present */
if (args->vararg || args->kwonlyargs) { if (args->vararg || args->kwonlyargs) {
if (first) { APPEND_STR_IF_NOT_FIRST(", ");
first = false; APPEND_STR("*");
}
else if (-1 == append_charp(writer, ", ")) {
return -1;
}
if (-1 == append_charp(writer, "*")) {
return -1;
}
if (args->vararg) { if (args->vararg) {
if (-1 == append_ast_arg(writer, args->vararg)) { APPEND(arg, args->vararg);
return -1;
}
} }
} }
...@@ -223,223 +224,127 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) ...@@ -223,223 +224,127 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args)
arg_count = asdl_seq_LEN(args->kwonlyargs); arg_count = asdl_seq_LEN(args->kwonlyargs);
default_count = asdl_seq_LEN(args->kw_defaults); default_count = asdl_seq_LEN(args->kw_defaults);
for (i = 0; i < arg_count; i++) { for (i = 0; i < arg_count; i++) {
if (first) { APPEND_STR_IF_NOT_FIRST(", ");
first = false; APPEND(arg, (arg_ty)asdl_seq_GET(args->kwonlyargs, i));
}
else if (-1 == append_charp(writer, ", ")) {
return -1;
}
arg = (arg_ty)asdl_seq_GET(args->kwonlyargs, i);
if (-1 == append_ast_arg(writer, arg)) {
return -1;
}
di = i - arg_count + default_count; di = i - arg_count + default_count;
if (di >= 0) { if (di >= 0) {
if (-1 == append_charp(writer, "=")) { APPEND_STR("=");
return -1; APPEND_EXPR((expr_ty)asdl_seq_GET(args->kw_defaults, di), PR_TEST);
}
default_ = (expr_ty)asdl_seq_GET(args->kw_defaults, di);
if (-1 == append_ast_expr(writer, default_, false)) {
return -1;
}
} }
} }
/* **kwargs */ /* **kwargs */
if (args->kwarg) { if (args->kwarg) {
if (first) { APPEND_STR_IF_NOT_FIRST(", ");
first = false; APPEND_STR("**");
} APPEND(arg, args->kwarg);
else if (-1 == append_charp(writer, ", ")) {
return -1;
}
if (-1 == append_charp(writer, "**")) {
return -1;
}
if (-1 == append_ast_arg(writer, args->kwarg)) {
return -1;
}
} }
return 0; return 0;
} }
static int static int
append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, int level)
{ {
if (!omit_parens && -1 == append_charp(writer, "(")) { APPEND_STR_IF(level > PR_TEST, "(");
return -1; APPEND_STR("lambda ");
} APPEND(args, e->v.Lambda.args);
APPEND_STR(": ");
if (-1 == append_charp(writer, "lambda ")) { APPEND_EXPR(e->v.Lambda.body, PR_TEST);
return -1; APPEND_STR_IF(level > PR_TEST, ")");
} return 0;
if (-1 == append_ast_args(writer, e->v.Lambda.args)) {
return -1;
}
if (-1 == append_charp(writer, ": ")) {
return -1;
}
if (-1 == append_ast_expr(writer, e->v.Lambda.body, true)) {
return -1;
}
return omit_parens ? 0 : append_charp(writer, ")");
} }
static int static int
append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, int level)
{ {
if (!omit_parens && -1 == append_charp(writer, "(")) { APPEND_STR_IF(level > PR_TEST, "(");
return -1; APPEND_EXPR(e->v.IfExp.body, PR_TEST + 1);
} APPEND_STR(" if ");
APPEND_EXPR(e->v.IfExp.test, PR_TEST + 1);
if (-1 == append_ast_expr(writer, e->v.IfExp.body, false)) { APPEND_STR(" else ");
return -1; APPEND_EXPR(e->v.IfExp.orelse, PR_TEST);
} APPEND_STR_IF(level > PR_TEST, ")");
return 0;
if (-1 == append_charp(writer, " if ")) {
return -1;
}
if (-1 == append_ast_expr(writer, e->v.IfExp.test, false)) {
return -1;
}
if (-1 == append_charp(writer, " else ")) {
return -1;
}
if (-1 == append_ast_expr(writer, e->v.IfExp.orelse, false)) {
return -1;
}
return omit_parens ? 0 : append_charp(writer, ")");
} }
static int static int
append_ast_dict(_PyUnicodeWriter *writer, expr_ty e) append_ast_dict(_PyUnicodeWriter *writer, expr_ty e)
{ {
Py_ssize_t i, value_count; Py_ssize_t i, value_count;
expr_ty key_node, value_node; expr_ty key_node;
if (-1 == append_charp(writer, "{")) {
return -1;
}
APPEND_STR("{");
value_count = asdl_seq_LEN(e->v.Dict.values); value_count = asdl_seq_LEN(e->v.Dict.values);
for (i = 0; i < value_count; i++) { for (i = 0; i < value_count; i++) {
if (i > 0 && -1 == append_charp(writer, ", ")) { APPEND_STR_IF(i > 0, ", ");
return -1;
}
key_node = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i); key_node = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i);
if (key_node != NULL) { if (key_node != NULL) {
if (-1 == append_ast_expr(writer, key_node, false)) { APPEND_EXPR(key_node, PR_TEST);
return -1; APPEND_STR(": ");
} APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_TEST);
if (-1 == append_charp(writer, ": ")) {
return -1;
}
}
else if (-1 == append_charp(writer, "**")) {
return -1;
} }
else {
value_node = (expr_ty)asdl_seq_GET(e->v.Dict.values, i); APPEND_STR("**");
if (-1 == append_ast_expr(writer, value_node, false)) { APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_EXPR);
return -1;
} }
} }
return append_charp(writer, "}"); APPEND_STR_FINISH("}");
} }
static int static int
append_ast_set(_PyUnicodeWriter *writer, expr_ty e) append_ast_set(_PyUnicodeWriter *writer, expr_ty e)
{ {
Py_ssize_t i, elem_count; Py_ssize_t i, elem_count;
expr_ty elem_node;
if (-1 == append_charp(writer, "{")) {
return -1;
}
APPEND_STR("{");
elem_count = asdl_seq_LEN(e->v.Set.elts); elem_count = asdl_seq_LEN(e->v.Set.elts);
for (i = 0; i < elem_count; i++) { for (i = 0; i < elem_count; i++) {
if (i > 0 && -1 == append_charp(writer, ", ")) { APPEND_STR_IF(i > 0, ", ");
return -1; APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Set.elts, i), PR_TEST);
}
elem_node = (expr_ty)asdl_seq_GET(e->v.Set.elts, i);
if (-1 == append_ast_expr(writer, elem_node, false)) {
return -1;
}
} }
return append_charp(writer, "}"); APPEND_STR_FINISH("}");
} }
static int static int
append_ast_list(_PyUnicodeWriter *writer, expr_ty e) append_ast_list(_PyUnicodeWriter *writer, expr_ty e)
{ {
Py_ssize_t i, elem_count; Py_ssize_t i, elem_count;
expr_ty elem_node;
if (-1 == append_charp(writer, "[")) {
return -1;
}
APPEND_STR("[");
elem_count = asdl_seq_LEN(e->v.List.elts); elem_count = asdl_seq_LEN(e->v.List.elts);
for (i = 0; i < elem_count; i++) { for (i = 0; i < elem_count; i++) {
if (i > 0 && -1 == append_charp(writer, ", ")) { APPEND_STR_IF(i > 0, ", ");
return -1; APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.List.elts, i), PR_TEST);
}
elem_node = (expr_ty)asdl_seq_GET(e->v.List.elts, i);
if (-1 == append_ast_expr(writer, elem_node, false)) {
return -1;
}
} }
return append_charp(writer, "]"); APPEND_STR_FINISH("]");
} }
static int static int
append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, int level)
{ {
Py_ssize_t i, elem_count; Py_ssize_t i, elem_count;
expr_ty elem_node;
elem_count = asdl_seq_LEN(e->v.Tuple.elts); elem_count = asdl_seq_LEN(e->v.Tuple.elts);
if (!omit_parens || elem_count < 2) { if (elem_count == 0) {
if (-1 == append_charp(writer, "(")) { APPEND_STR_FINISH("()");
return -1;
}
} }
for (i = 0; i < elem_count; i++) { APPEND_STR_IF(level > PR_TUPLE, "(");
if ((i > 0 || elem_count == 1) && -1 == append_charp(writer, ", ")) {
return -1;
}
elem_node = (expr_ty)asdl_seq_GET(e->v.Tuple.elts, i);
if (-1 == append_ast_expr(writer, elem_node, false)) {
return -1;
}
}
if (!omit_parens || elem_count < 2) { for (i = 0; i < elem_count; i++) {
return append_charp(writer, ")"); APPEND_STR_IF(i > 0, ", ");
APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Tuple.elts, i), PR_TEST);
} }
APPEND_STR_IF(elem_count == 1, ",");
APPEND_STR_IF(level > PR_TUPLE, ")");
return 0; return 0;
} }
...@@ -448,33 +353,15 @@ append_ast_comprehension(_PyUnicodeWriter *writer, comprehension_ty gen) ...@@ -448,33 +353,15 @@ append_ast_comprehension(_PyUnicodeWriter *writer, comprehension_ty gen)
{ {
Py_ssize_t i, if_count; Py_ssize_t i, if_count;
if (-1 == append_charp(writer, gen->is_async ? " async for " : " for ")) { APPEND_STR(gen->is_async ? " async for " : " for ");
return -1; APPEND_EXPR(gen->target, PR_TUPLE);
} APPEND_STR(" in ");
APPEND_EXPR(gen->iter, PR_TEST + 1);
if (-1 == append_ast_expr(writer, gen->target, true)) {
return -1;
}
if (-1 == append_charp(writer, " in ")) {
return -1;
}
if (-1 == append_ast_expr(writer, gen->iter, false)) {
return -1;
}
if_count = asdl_seq_LEN(gen->ifs); if_count = asdl_seq_LEN(gen->ifs);
for (i = 0; i < if_count; i++) { for (i = 0; i < if_count; i++) {
if (-1 == append_charp(writer, " if ")) { APPEND_STR(" if ");
return -1; APPEND_EXPR((expr_ty)asdl_seq_GET(gen->ifs, i), PR_TEST + 1);
}
if (-1 == append_ast_expr(writer,
(expr_ty)asdl_seq_GET(gen->ifs, i),
false)) {
return -1;
}
} }
return 0; return 0;
} }
...@@ -483,110 +370,62 @@ static int ...@@ -483,110 +370,62 @@ static int
append_ast_comprehensions(_PyUnicodeWriter *writer, asdl_seq *comprehensions) append_ast_comprehensions(_PyUnicodeWriter *writer, asdl_seq *comprehensions)
{ {
Py_ssize_t i, gen_count; Py_ssize_t i, gen_count;
comprehension_ty comp_node;
gen_count = asdl_seq_LEN(comprehensions); gen_count = asdl_seq_LEN(comprehensions);
for (i = 0; i < gen_count; i++) { for (i = 0; i < gen_count; i++) {
comp_node = (comprehension_ty)asdl_seq_GET(comprehensions, i); APPEND(comprehension, (comprehension_ty)asdl_seq_GET(comprehensions, i));
if (-1 == append_ast_comprehension(writer, comp_node)) {
return -1;
}
} }
return 0; return 0;
} }
static int static int
append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e)
{ {
if (!omit_parens && -1 == append_charp(writer, "(")) { APPEND_STR("(");
return -1; APPEND_EXPR(e->v.GeneratorExp.elt, PR_TEST);
} APPEND(comprehensions, e->v.GeneratorExp.generators);
APPEND_STR_FINISH(")");
if (-1 == append_ast_expr(writer, e->v.GeneratorExp.elt, false)) {
return -1;
}
if (-1 == append_ast_comprehensions(writer, e->v.GeneratorExp.generators)) {
return -1;
}
return omit_parens ? 0 : append_charp(writer, ")");
} }
static int static int
append_ast_listcomp(_PyUnicodeWriter *writer, expr_ty e) append_ast_listcomp(_PyUnicodeWriter *writer, expr_ty e)
{ {
if (-1 == append_charp(writer, "[")) { APPEND_STR("[");
return -1; APPEND_EXPR(e->v.ListComp.elt, PR_TEST);
} APPEND(comprehensions, e->v.ListComp.generators);
APPEND_STR_FINISH("]");
if (-1 == append_ast_expr(writer, e->v.ListComp.elt, false)) {
return -1;
}
if (-1 == append_ast_comprehensions(writer, e->v.ListComp.generators)) {
return -1;
}
return append_charp(writer, "]");
} }
static int static int
append_ast_setcomp(_PyUnicodeWriter *writer, expr_ty e) append_ast_setcomp(_PyUnicodeWriter *writer, expr_ty e)
{ {
if (-1 == append_charp(writer, "{")) { APPEND_STR("{");
return -1; APPEND_EXPR(e->v.SetComp.elt, PR_TEST);
} APPEND(comprehensions, e->v.SetComp.generators);
APPEND_STR_FINISH("}");
if (-1 == append_ast_expr(writer, e->v.SetComp.elt, false)) {
return -1;
}
if (-1 == append_ast_comprehensions(writer, e->v.SetComp.generators)) {
return -1;
}
return append_charp(writer, "}");
} }
static int static int
append_ast_dictcomp(_PyUnicodeWriter *writer, expr_ty e) append_ast_dictcomp(_PyUnicodeWriter *writer, expr_ty e)
{ {
if (-1 == append_charp(writer, "{")) { APPEND_STR("{");
return -1; APPEND_EXPR(e->v.DictComp.key, PR_TEST);
} APPEND_STR(": ");
APPEND_EXPR(e->v.DictComp.value, PR_TEST);
if (-1 == append_ast_expr(writer, e->v.DictComp.key, false)) { APPEND(comprehensions, e->v.DictComp.generators);
return -1; APPEND_STR_FINISH("}");
}
if (-1 == append_charp(writer, ": ")) {
return -1;
}
if (-1 == append_ast_expr(writer, e->v.DictComp.value, false)) {
return -1;
}
if (-1 == append_ast_comprehensions(writer, e->v.DictComp.generators)) {
return -1;
}
return append_charp(writer, "}");
} }
static int static int
append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, int level)
{ {
const char *op; const char *op;
Py_ssize_t i, comparator_count; Py_ssize_t i, comparator_count;
asdl_seq *comparators; asdl_seq *comparators;
asdl_int_seq *ops; asdl_int_seq *ops;
if (!omit_parens && -1 == append_charp(writer, "(")) { APPEND_STR_IF(level > PR_CMP, "(");
return -1;
}
comparators = e->v.Compare.comparators; comparators = e->v.Compare.comparators;
ops = e->v.Compare.ops; ops = e->v.Compare.ops;
...@@ -594,9 +433,7 @@ append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) ...@@ -594,9 +433,7 @@ append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens)
assert(comparator_count > 0); assert(comparator_count > 0);
assert(comparator_count == asdl_seq_LEN(ops)); assert(comparator_count == asdl_seq_LEN(ops));
if (-1 == append_ast_expr(writer, e->v.Compare.left, false)) { APPEND_EXPR(e->v.Compare.left, PR_CMP + 1);
return -1;
}
for (i = 0; i < comparator_count; i++) { for (i = 0; i < comparator_count; i++) {
switch ((cmpop_ty)asdl_seq_GET(ops, i)) { switch ((cmpop_ty)asdl_seq_GET(ops, i)) {
...@@ -636,39 +473,30 @@ append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) ...@@ -636,39 +473,30 @@ append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens)
return -1; return -1;
} }
if (-1 == append_charp(writer, op)) { APPEND_STR(op);
return -1; APPEND_EXPR((expr_ty)asdl_seq_GET(comparators, i), PR_CMP + 1);
}
if (-1 == append_ast_expr(writer,
(expr_ty)asdl_seq_GET(comparators, i),
false)) {
return -1;
}
} }
return omit_parens ? 0 : append_charp(writer, ")"); APPEND_STR_IF(level > PR_CMP, ")");
return 0;
} }
static int static int
append_ast_keyword(_PyUnicodeWriter *writer, keyword_ty kw) append_ast_keyword(_PyUnicodeWriter *writer, keyword_ty kw)
{ {
if (kw->arg == NULL) { if (kw->arg == NULL) {
if (-1 == append_charp(writer, "**")) { APPEND_STR("**");
return -1;
}
} }
else { else {
if (-1 == _PyUnicodeWriter_WriteStr(writer, kw->arg)) { if (-1 == _PyUnicodeWriter_WriteStr(writer, kw->arg)) {
return -1; return -1;
} }
if (-1 == append_charp(writer, "=")) { APPEND_STR("=");
return -1;
}
} }
return append_ast_expr(writer, kw->value, false); APPEND_EXPR(kw->value, PR_TEST);
return 0;
} }
static int static int
...@@ -677,48 +505,33 @@ append_ast_call(_PyUnicodeWriter *writer, expr_ty e) ...@@ -677,48 +505,33 @@ append_ast_call(_PyUnicodeWriter *writer, expr_ty e)
bool first; bool first;
Py_ssize_t i, arg_count, kw_count; Py_ssize_t i, arg_count, kw_count;
expr_ty expr; expr_ty expr;
keyword_ty kw;
if (-1 == append_ast_expr(writer, e->v.Call.func, false)) { APPEND_EXPR(e->v.Call.func, PR_ATOM);
return -1;
}
if (-1 == append_charp(writer, "(")) { arg_count = asdl_seq_LEN(e->v.Call.args);
return -1; kw_count = asdl_seq_LEN(e->v.Call.keywords);
if (arg_count == 1 && kw_count == 0) {
expr = (expr_ty)asdl_seq_GET(e->v.Call.args, 0);
if (expr->kind == GeneratorExp_kind) {
/* Special case: a single generator expression. */
return append_ast_genexp(writer, expr);
}
} }
APPEND_STR("(");
first = true; first = true;
arg_count = asdl_seq_LEN(e->v.Call.args);
for (i = 0; i < arg_count; i++) { for (i = 0; i < arg_count; i++) {
if (first) { APPEND_STR_IF_NOT_FIRST(", ");
first = false; APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Call.args, i), PR_TEST);
}
else if (-1 == append_charp(writer, ", ")) {
return -1;
}
expr = (expr_ty)asdl_seq_GET(e->v.Call.args, i);
if (-1 == append_ast_expr(writer, expr, false)) {
return -1;
}
} }
kw_count = asdl_seq_LEN(e->v.Call.keywords);
for (i = 0; i < kw_count; i++) { for (i = 0; i < kw_count; i++) {
if (first) { APPEND_STR_IF_NOT_FIRST(", ");
first = false; APPEND(keyword, (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i));
}
else if (-1 == append_charp(writer, ", ")) {
return -1;
}
kw = (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i);
if (-1 == append_ast_keyword(writer, kw)) {
return -1;
}
} }
return append_charp(writer, ")"); APPEND_STR_FINISH(")");
} }
static PyObject * static PyObject *
...@@ -778,9 +591,8 @@ build_fstring_body(asdl_seq *values, bool is_format_spec) ...@@ -778,9 +591,8 @@ build_fstring_body(asdl_seq *values, bool is_format_spec)
body_writer.min_length = 256; body_writer.min_length = 256;
body_writer.overallocate = 1; body_writer.overallocate = 1;
value_count = asdl_seq_LEN(values) - 1; value_count = asdl_seq_LEN(values);
assert(value_count >= 0); for (i = 0; i < value_count; ++i) {
for (i = 0; i <= value_count; ++i) {
if (-1 == append_fstring_element(&body_writer, if (-1 == append_fstring_element(&body_writer,
(expr_ty)asdl_seq_GET(values, i), (expr_ty)asdl_seq_GET(values, i),
is_format_spec is_format_spec
...@@ -819,9 +631,11 @@ append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) ...@@ -819,9 +631,11 @@ append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
static int static int
append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
{ {
char *conversion; const char *conversion;
char *outer_brace = "{"; const char *outer_brace = "{";
PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, true); /* Grammar allows PR_TUPLE, but use >PR_TEST for adding parenthesis
around a lambda with ':' */
PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, PR_TEST + 1);
if (!temp_fv_str) { if (!temp_fv_str) {
return -1; return -1;
} }
...@@ -842,13 +656,13 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) ...@@ -842,13 +656,13 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
if (e->v.FormattedValue.conversion > 0) { if (e->v.FormattedValue.conversion > 0) {
switch (e->v.FormattedValue.conversion) { switch (e->v.FormattedValue.conversion) {
case 97: case 'a':
conversion = "!a"; conversion = "!a";
break; break;
case 114: case 'r':
conversion = "!r"; conversion = "!r";
break; break;
case 115: case 's':
conversion = "!s"; conversion = "!s";
break; break;
default: default:
...@@ -856,9 +670,7 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) ...@@ -856,9 +670,7 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
"unknown f-value conversion kind"); "unknown f-value conversion kind");
return -1; return -1;
} }
if (-1 == append_charp(writer, conversion)) { APPEND_STR(conversion);
return -1;
}
} }
if (e->v.FormattedValue.format_spec) { if (e->v.FormattedValue.format_spec) {
if (-1 == _PyUnicodeWriter_WriteASCIIString(writer, ":", 1) || if (-1 == _PyUnicodeWriter_WriteASCIIString(writer, ":", 1) ||
...@@ -870,16 +682,15 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) ...@@ -870,16 +682,15 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
return -1; return -1;
} }
} }
return append_charp(writer, "}");
APPEND_STR_FINISH("}");
} }
static int static int
append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e) append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e)
{ {
const char *period; const char *period;
if (-1 == append_ast_expr(writer, e->v.Attribute.value, false)) { APPEND_EXPR(e->v.Attribute.value, PR_ATOM);
return -1;
}
/* Special case: integers require a space for attribute access to be /* Special case: integers require a space for attribute access to be
unambiguous. Floats and complex numbers don't but work with it, too. */ unambiguous. Floats and complex numbers don't but work with it, too. */
...@@ -891,9 +702,7 @@ append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e) ...@@ -891,9 +702,7 @@ append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e)
else { else {
period = "."; period = ".";
} }
if (-1 == append_charp(writer, period)) { APPEND_STR(period);
return -1;
}
return _PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr); return _PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr);
} }
...@@ -902,28 +711,18 @@ static int ...@@ -902,28 +711,18 @@ static int
append_ast_simple_slice(_PyUnicodeWriter *writer, slice_ty slice) append_ast_simple_slice(_PyUnicodeWriter *writer, slice_ty slice)
{ {
if (slice->v.Slice.lower) { if (slice->v.Slice.lower) {
if (-1 == append_ast_expr(writer, slice->v.Slice.lower, false)) { APPEND_EXPR(slice->v.Slice.lower, PR_TEST);
return -1;
}
} }
if (-1 == append_charp(writer, ":")) { APPEND_STR(":");
return -1;
}
if (slice->v.Slice.upper) { if (slice->v.Slice.upper) {
if (-1 == append_ast_expr(writer, slice->v.Slice.upper, false)) { APPEND_EXPR(slice->v.Slice.upper, PR_TEST);
return -1;
}
} }
if (slice->v.Slice.step) { if (slice->v.Slice.step) {
if (-1 == append_charp(writer, ":")) { APPEND_STR(":");
return -1; APPEND_EXPR(slice->v.Slice.step, PR_TEST);
}
if (-1 == append_ast_expr(writer, slice->v.Slice.step, false)) {
return -1;
}
} }
return 0; return 0;
} }
...@@ -934,28 +733,23 @@ append_ast_ext_slice(_PyUnicodeWriter *writer, slice_ty slice) ...@@ -934,28 +733,23 @@ append_ast_ext_slice(_PyUnicodeWriter *writer, slice_ty slice)
Py_ssize_t i, dims_count; Py_ssize_t i, dims_count;
dims_count = asdl_seq_LEN(slice->v.ExtSlice.dims); dims_count = asdl_seq_LEN(slice->v.ExtSlice.dims);
for (i = 0; i < dims_count; i++) { for (i = 0; i < dims_count; i++) {
if (i > 0 && -1 == append_charp(writer, ", ")) { APPEND_STR_IF(i > 0, ", ");
return -1; APPEND(slice, (slice_ty)asdl_seq_GET(slice->v.ExtSlice.dims, i));
}
if (-1 == append_ast_expr(writer,
(expr_ty)asdl_seq_GET(slice->v.ExtSlice.dims, i),
false)) {
return -1;
}
} }
return 0; return 0;
} }
static int static int
append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice, bool omit_parens) append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice)
{ {
switch(slice->kind) { switch (slice->kind) {
case Slice_kind: case Slice_kind:
return append_ast_simple_slice(writer, slice); return append_ast_simple_slice(writer, slice);
case ExtSlice_kind: case ExtSlice_kind:
return append_ast_ext_slice(writer, slice); return append_ast_ext_slice(writer, slice);
case Index_kind: case Index_kind:
return append_ast_expr(writer, slice->v.Index.value, omit_parens); APPEND_EXPR(slice->v.Index.value, PR_TUPLE);
return 0;
default: default:
PyErr_SetString(PyExc_SystemError, PyErr_SetString(PyExc_SystemError,
"unexpected slice kind"); "unexpected slice kind");
...@@ -966,109 +760,70 @@ append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice, bool omit_parens) ...@@ -966,109 +760,70 @@ append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice, bool omit_parens)
static int static int
append_ast_subscript(_PyUnicodeWriter *writer, expr_ty e) append_ast_subscript(_PyUnicodeWriter *writer, expr_ty e)
{ {
if (-1 == append_ast_expr(writer, e->v.Subscript.value, false)) { APPEND_EXPR(e->v.Subscript.value, PR_ATOM);
return -1; APPEND_STR("[");
} APPEND(slice, e->v.Subscript.slice);
APPEND_STR_FINISH("]");
if (-1 == append_charp(writer, "[")) {
return -1;
}
if (-1 == append_ast_slice(writer, e->v.Subscript.slice, true)) {
return -1;
}
return append_charp(writer, "]");
} }
static int static int
append_ast_starred(_PyUnicodeWriter *writer, expr_ty e) append_ast_starred(_PyUnicodeWriter *writer, expr_ty e)
{ {
if (-1 == append_charp(writer, "*")) { APPEND_STR("*");
return -1; APPEND_EXPR(e->v.Starred.value, PR_EXPR);
} return 0;
return append_ast_expr(writer, e->v.Starred.value, false);
} }
static int static int
append_ast_yield(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) append_ast_yield(_PyUnicodeWriter *writer, expr_ty e)
{ {
if (!omit_parens && -1 == append_charp(writer, "(")) { if (!e->v.Yield.value) {
return -1; APPEND_STR_FINISH("(yield)");
}
if (-1 == append_charp(writer, e->v.Yield.value ? "yield " : "yield")) {
return -1;
} }
if (e->v.Yield.value) { APPEND_STR("(yield ");
if (-1 == append_ast_expr(writer, e->v.Yield.value, false)) { APPEND_EXPR(e->v.Yield.value, PR_TEST);
return -1; APPEND_STR_FINISH(")");
}
}
return omit_parens ? 0 : append_charp(writer, ")");
} }
static int static int
append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e)
{ {
if (!omit_parens && -1 == append_charp(writer, "(")) { APPEND_STR("(yield from ");
return -1; APPEND_EXPR(e->v.YieldFrom.value, PR_TEST);
} APPEND_STR_FINISH(")");
if (-1 == append_charp(writer,
e->v.YieldFrom.value ? "yield from " : "yield from")) {
return -1;
}
if (e->v.YieldFrom.value) {
if (-1 == append_ast_expr(writer, e->v.YieldFrom.value, false)) {
return -1;
}
}
return omit_parens ? 0 : append_charp(writer, ")");
} }
static int static int
append_ast_await(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) append_ast_await(_PyUnicodeWriter *writer, expr_ty e, int level)
{ {
if (!omit_parens && -1 == append_charp(writer, "(")) { APPEND_STR_IF(level > PR_AWAIT, "(");
return -1; APPEND_STR("await ");
} APPEND_EXPR(e->v.Await.value, PR_ATOM);
APPEND_STR_IF(level > PR_AWAIT, ")");
if (-1 == append_charp(writer, e->v.Await.value ? "await " : "await")) { return 0;
return -1;
}
if (e->v.Await.value) {
if (-1 == append_ast_expr(writer, e->v.Await.value, false)) {
return -1;
}
}
return omit_parens ? 0 : append_charp(writer, ")");
} }
static int static int
append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
{ {
switch (e->kind) { switch (e->kind) {
case BoolOp_kind: case BoolOp_kind:
return append_ast_boolop(writer, e, omit_parens); return append_ast_boolop(writer, e, level);
case BinOp_kind: case BinOp_kind:
return append_ast_binop(writer, e, omit_parens); return append_ast_binop(writer, e, level);
case UnaryOp_kind: case UnaryOp_kind:
return append_ast_unaryop(writer, e, omit_parens); return append_ast_unaryop(writer, e, level);
case Lambda_kind: case Lambda_kind:
return append_ast_lambda(writer, e, omit_parens); return append_ast_lambda(writer, e, level);
case IfExp_kind: case IfExp_kind:
return append_ast_ifexp(writer, e, omit_parens); return append_ast_ifexp(writer, e, level);
case Dict_kind: case Dict_kind:
return append_ast_dict(writer, e); return append_ast_dict(writer, e);
case Set_kind: case Set_kind:
return append_ast_set(writer, e); return append_ast_set(writer, e);
case GeneratorExp_kind: case GeneratorExp_kind:
return append_ast_genexp(writer, e, omit_parens); return append_ast_genexp(writer, e);
case ListComp_kind: case ListComp_kind:
return append_ast_listcomp(writer, e); return append_ast_listcomp(writer, e);
case SetComp_kind: case SetComp_kind:
...@@ -1076,13 +831,13 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) ...@@ -1076,13 +831,13 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens)
case DictComp_kind: case DictComp_kind:
return append_ast_dictcomp(writer, e); return append_ast_dictcomp(writer, e);
case Yield_kind: case Yield_kind:
return append_ast_yield(writer, e, omit_parens); return append_ast_yield(writer, e);
case YieldFrom_kind: case YieldFrom_kind:
return append_ast_yield_from(writer, e, omit_parens); return append_ast_yield_from(writer, e);
case Await_kind: case Await_kind:
return append_ast_await(writer, e, omit_parens); return append_ast_await(writer, e, level);
case Compare_kind: case Compare_kind:
return append_ast_compare(writer, e, omit_parens); return append_ast_compare(writer, e, level);
case Call_kind: case Call_kind:
return append_ast_call(writer, e); return append_ast_call(writer, e);
case Constant_kind: case Constant_kind:
...@@ -1098,7 +853,7 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) ...@@ -1098,7 +853,7 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens)
case Bytes_kind: case Bytes_kind:
return append_repr(writer, e->v.Bytes.s); return append_repr(writer, e->v.Bytes.s);
case Ellipsis_kind: case Ellipsis_kind:
return append_charp(writer, "..."); APPEND_STR_FINISH("...");
case NameConstant_kind: case NameConstant_kind:
return append_repr(writer, e->v.NameConstant.value); return append_repr(writer, e->v.NameConstant.value);
/* The following exprs can be assignment targets. */ /* The following exprs can be assignment targets. */
...@@ -1110,11 +865,10 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) ...@@ -1110,11 +865,10 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens)
return append_ast_starred(writer, e); return append_ast_starred(writer, e);
case Name_kind: case Name_kind:
return _PyUnicodeWriter_WriteStr(writer, e->v.Name.id); return _PyUnicodeWriter_WriteStr(writer, e->v.Name.id);
/* child nodes of List and Tuple will have expr_context set */
case List_kind: case List_kind:
return append_ast_list(writer, e); return append_ast_list(writer, e);
case Tuple_kind: case Tuple_kind:
return append_ast_tuple(writer, e, omit_parens); return append_ast_tuple(writer, e, level);
default: default:
PyErr_SetString(PyExc_SystemError, PyErr_SetString(PyExc_SystemError,
"unknown expression kind"); "unknown expression kind");
...@@ -1145,14 +899,14 @@ maybe_init_static_strings(void) ...@@ -1145,14 +899,14 @@ maybe_init_static_strings(void)
} }
static PyObject * static PyObject *
expr_as_unicode(expr_ty e, bool omit_parens) expr_as_unicode(expr_ty e, int level)
{ {
_PyUnicodeWriter writer; _PyUnicodeWriter writer;
_PyUnicodeWriter_Init(&writer); _PyUnicodeWriter_Init(&writer);
writer.min_length = 256; writer.min_length = 256;
writer.overallocate = 1; writer.overallocate = 1;
if (-1 == maybe_init_static_strings() || if (-1 == maybe_init_static_strings() ||
-1 == append_ast_expr(&writer, e, omit_parens)) -1 == append_ast_expr(&writer, e, level))
{ {
_PyUnicodeWriter_Dealloc(&writer); _PyUnicodeWriter_Dealloc(&writer);
return NULL; return NULL;
...@@ -1161,7 +915,7 @@ expr_as_unicode(expr_ty e, bool omit_parens) ...@@ -1161,7 +915,7 @@ expr_as_unicode(expr_ty e, bool omit_parens)
} }
PyObject * PyObject *
_PyAST_ExprAsUnicode(expr_ty e, bool omit_parens) _PyAST_ExprAsUnicode(expr_ty e)
{ {
return expr_as_unicode(e, omit_parens); return expr_as_unicode(e, PR_TEST);
} }
...@@ -1822,7 +1822,7 @@ error: ...@@ -1822,7 +1822,7 @@ error:
static int static int
compiler_visit_annexpr(struct compiler *c, expr_ty annotation) compiler_visit_annexpr(struct compiler *c, expr_ty annotation)
{ {
ADDOP_LOAD_CONST_NEW(c, _PyAST_ExprAsUnicode(annotation, 1)); ADDOP_LOAD_CONST_NEW(c, _PyAST_ExprAsUnicode(annotation));
return 1; return 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment