Commit 10f8ce66 authored by Guido van Rossum's avatar Guido van Rossum Committed by Miss Islington (bot)

bpo-36280: Add Constant.kind field (GH-12295)



The value is a string for string and byte literals, None otherwise.
It is 'u' for u"..." literals, 'b' for b"..." literals, '' for "..." literals.
The 'r' (raw) prefix is ignored.
Does not apply to f-strings.

This appears sufficient to make mypy capable of using the stdlib ast module instead of typed_ast (assuming a mypy patch I'm working on).

WIP: I need to make the tests pass. @ilevkivskyi @serhiy-storchaka 



https://bugs.python.org/issue36280
parent 8b5bdda5
......@@ -338,6 +338,7 @@ struct _expr {
struct {
constant value;
string kind;
} Constant;
struct {
......@@ -642,9 +643,9 @@ expr_ty _Py_FormattedValue(expr_ty value, int conversion, expr_ty format_spec,
#define JoinedStr(a0, a1, a2, a3, a4, a5) _Py_JoinedStr(a0, a1, a2, a3, a4, a5)
expr_ty _Py_JoinedStr(asdl_seq * values, int lineno, int col_offset, int
end_lineno, int end_col_offset, PyArena *arena);
#define Constant(a0, a1, a2, a3, a4, a5) _Py_Constant(a0, a1, a2, a3, a4, a5)
expr_ty _Py_Constant(constant value, int lineno, int col_offset, int
end_lineno, int end_col_offset, PyArena *arena);
#define Constant(a0, a1, a2, a3, a4, a5, a6) _Py_Constant(a0, a1, a2, a3, a4, a5, a6)
expr_ty _Py_Constant(constant value, string kind, int lineno, int col_offset,
int end_lineno, int end_col_offset, PyArena *arena);
#define Attribute(a0, a1, a2, a3, a4, a5, a6, a7) _Py_Attribute(a0, a1, a2, a3, a4, a5, a6, a7)
expr_ty _Py_Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int
lineno, int col_offset, int end_lineno, int
......
This diff is collapsed.
Add a kind field to ast.Constant. It is 'u' if the literal has a 'u' prefix
(i.e. a Python 2 style unicode literal), else None.
......@@ -78,7 +78,7 @@ module Python
| Call(expr func, expr* args, keyword* keywords)
| FormattedValue(expr value, int? conversion, expr? format_spec)
| JoinedStr(expr* values)
| Constant(constant value)
| Constant(constant value, string? kind)
-- the following expression can appear in assignment context
| Attribute(expr value, identifier attr, expr_context ctx)
......
......@@ -324,8 +324,10 @@ static char *JoinedStr_fields[]={
"values",
};
static PyTypeObject *Constant_type;
_Py_IDENTIFIER(kind);
static char *Constant_fields[]={
"value",
"kind",
};
static PyTypeObject *Attribute_type;
_Py_IDENTIFIER(attr);
......@@ -950,7 +952,7 @@ static int init_types(void)
if (!FormattedValue_type) return 0;
JoinedStr_type = make_type("JoinedStr", expr_type, JoinedStr_fields, 1);
if (!JoinedStr_type) return 0;
Constant_type = make_type("Constant", expr_type, Constant_fields, 1);
Constant_type = make_type("Constant", expr_type, Constant_fields, 2);
if (!Constant_type) return 0;
Attribute_type = make_type("Attribute", expr_type, Attribute_fields, 3);
if (!Attribute_type) return 0;
......@@ -2287,8 +2289,8 @@ JoinedStr(asdl_seq * values, int lineno, int col_offset, int end_lineno, int
}
expr_ty
Constant(constant value, int lineno, int col_offset, int end_lineno, int
end_col_offset, PyArena *arena)
Constant(constant value, string kind, int lineno, int col_offset, int
end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!value) {
......@@ -2301,6 +2303,7 @@ Constant(constant value, int lineno, int col_offset, int end_lineno, int
return NULL;
p->kind = Constant_kind;
p->v.Constant.value = value;
p->v.Constant.kind = kind;
p->lineno = lineno;
p->col_offset = col_offset;
p->end_lineno = end_lineno;
......@@ -3507,6 +3510,11 @@ ast2obj_expr(void* _o)
if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
goto failed;
Py_DECREF(value);
value = ast2obj_string(o->v.Constant.kind);
if (!value) goto failed;
if (_PyObject_SetAttrId(result, &PyId_kind, value) == -1)
goto failed;
Py_DECREF(value);
break;
case Attribute_kind:
result = PyType_GenericNew(Attribute_type, NULL, NULL);
......@@ -7224,6 +7232,7 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
}
if (isinstance) {
constant value;
string kind;
if (_PyObject_LookupAttrId(obj, &PyId_value, &tmp) < 0) {
return 1;
......@@ -7238,8 +7247,21 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = Constant(value, lineno, col_offset, end_lineno, end_col_offset,
arena);
if (_PyObject_LookupAttrId(obj, &PyId_kind, &tmp) < 0) {
return 1;
}
if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp);
kind = NULL;
}
else {
int res;
res = obj2ast_string(tmp, &kind, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = Constant(value, kind, lineno, col_offset, end_lineno,
end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
......
......@@ -2313,13 +2313,13 @@ ast_for_atom(struct compiling *c, const node *n)
size_t len = strlen(s);
if (len >= 4 && len <= 5) {
if (!strcmp(s, "None"))
return Constant(Py_None, LINENO(n), n->n_col_offset,
return Constant(Py_None, NULL, LINENO(n), n->n_col_offset,
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
if (!strcmp(s, "True"))
return Constant(Py_True, LINENO(n), n->n_col_offset,
return Constant(Py_True, NULL, LINENO(n), n->n_col_offset,
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
if (!strcmp(s, "False"))
return Constant(Py_False, LINENO(n), n->n_col_offset,
return Constant(Py_False, NULL, LINENO(n), n->n_col_offset,
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
name = new_identifier(s, c);
......@@ -2374,11 +2374,11 @@ ast_for_atom(struct compiling *c, const node *n)
Py_DECREF(pynum);
return NULL;
}
return Constant(pynum, LINENO(n), n->n_col_offset,
return Constant(pynum, NULL, LINENO(n), n->n_col_offset,
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
case ELLIPSIS: /* Ellipsis */
return Constant(Py_Ellipsis, LINENO(n), n->n_col_offset,
return Constant(Py_Ellipsis, NULL, LINENO(n), n->n_col_offset,
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
case LPAR: /* some parenthesized expressions */
ch = CHILD(n, 1);
......@@ -5388,18 +5388,57 @@ FstringParser_Dealloc(FstringParser *state)
ExprList_Dealloc(&state->expr_list);
}
/* Constants for the following */
static PyObject *u_kind;
/* Compute 'kind' field for string Constant (either 'u' or None) */
static PyObject *
make_kind(struct compiling *c, const node *n)
{
char *s = NULL;
PyObject *kind = NULL;
/* Find the first string literal, if any */
while (TYPE(n) != STRING) {
if (NCH(n) == 0)
return NULL;
n = CHILD(n, 0);
}
REQ(n, STRING);
/* If it starts with 'u', return a PyUnicode "u" string */
s = STR(n);
if (s && *s == 'u') {
if (!u_kind) {
u_kind = PyUnicode_InternFromString("u");
if (!u_kind)
return NULL;
}
kind = u_kind;
if (PyArena_AddPyObject(c->c_arena, kind) < 0) {
return NULL;
}
Py_INCREF(kind);
}
return kind;
}
/* Make a Constant node, but decref the PyUnicode object being added. */
static expr_ty
make_str_node_and_del(PyObject **str, struct compiling *c, const node* n)
{
PyObject *s = *str;
PyObject *kind = NULL;
*str = NULL;
assert(PyUnicode_CheckExact(s));
if (PyArena_AddPyObject(c->c_arena, s) < 0) {
Py_DECREF(s);
return NULL;
}
return Constant(s, LINENO(n), n->n_col_offset,
kind = make_kind(c, n);
if (kind == NULL && PyErr_Occurred())
return NULL;
return Constant(s, kind, LINENO(n), n->n_col_offset,
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
......@@ -5774,7 +5813,7 @@ parsestrplus(struct compiling *c, const node *n)
/* Just return the bytes object and we're done. */
if (PyArena_AddPyObject(c->c_arena, bytes_str) < 0)
goto error;
return Constant(bytes_str, LINENO(n), n->n_col_offset,
return Constant(bytes_str, NULL, LINENO(n), n->n_col_offset,
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
......
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