summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorIvan Levkivskyi <levkivskyi@gmail.com>2019-01-22 11:18:22 (GMT)
committerGitHub <noreply@github.com>2019-01-22 11:18:22 (GMT)
commit9932a22897ef9905161dac7476e6976370e13515 (patch)
tree5cfbec44c7ecb01f4817274280881a74ec15c605 /Python
parent7a2368063f25746d4008a74aca0dc0b82f86ff7b (diff)
downloadcpython-9932a22897ef9905161dac7476e6976370e13515.zip
cpython-9932a22897ef9905161dac7476e6976370e13515.tar.gz
cpython-9932a22897ef9905161dac7476e6976370e13515.tar.bz2
bpo-33416: Add end positions to Python AST (GH-11605)
The majority of this PR is tediously passing `end_lineno` and `end_col_offset` everywhere. Here are non-trivial points: * It is not possible to reconstruct end positions in AST "on the fly", some information is lost after an AST node is constructed, so we need two more attributes for every AST node `end_lineno` and `end_col_offset`. * I add end position information to both CST and AST. Although it may be technically possible to avoid adding end positions to CST, the code becomes more cumbersome and less efficient. * Since the end position is not known for non-leaf CST nodes while the next token is added, this requires a bit of extra care (see `_PyNode_FinalizeEndPos`). Unless I made some mistake, the algorithm should be linear. * For statements, I "trim" the end position of suites to not include the terminal newlines and dedent (this seems to be what people would expect), for example in ```python class C: pass pass ``` the end line and end column for the class definition is (2, 8). * For `end_col_offset` I use the common Python convention for indexing, for example for `pass` the `end_col_offset` is 4 (not 3), so that `[0:4]` gives one the source code that corresponds to the node. * I added a helper function `ast.get_source_segment()`, to get source text segment corresponding to a given AST node. It is also useful for testing. An (inevitable) downside of this PR is that AST now takes almost 25% more memory. I think however it is probably justified by the benefits.
Diffstat (limited to 'Python')
-rw-r--r--Python/Python-ast.c578
-rw-r--r--Python/ast.c346
-rw-r--r--Python/ast_opt.c3
-rw-r--r--Python/compile.c6
4 files changed, 712 insertions, 221 deletions
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
index bbe8e69..e6c5bfe 100644
--- a/Python/Python-ast.c
+++ b/Python/Python-ast.c
@@ -28,9 +28,13 @@ static char *Suite_fields[]={
static PyTypeObject *stmt_type;
_Py_IDENTIFIER(lineno);
_Py_IDENTIFIER(col_offset);
+_Py_IDENTIFIER(end_lineno);
+_Py_IDENTIFIER(end_col_offset);
static char *stmt_attributes[] = {
"lineno",
"col_offset",
+ "end_lineno",
+ "end_col_offset",
};
static PyObject* ast2obj_stmt(void*);
static PyTypeObject *FunctionDef_type;
@@ -189,6 +193,8 @@ static PyTypeObject *expr_type;
static char *expr_attributes[] = {
"lineno",
"col_offset",
+ "end_lineno",
+ "end_col_offset",
};
static PyObject* ast2obj_expr(void*);
static PyTypeObject *BoolOp_type;
@@ -427,6 +433,8 @@ static PyTypeObject *excepthandler_type;
static char *excepthandler_attributes[] = {
"lineno",
"col_offset",
+ "end_lineno",
+ "end_col_offset",
};
static PyObject* ast2obj_excepthandler(void*);
static PyTypeObject *ExceptHandler_type;
@@ -456,6 +464,8 @@ static PyObject* ast2obj_arg(void*);
static char *arg_attributes[] = {
"lineno",
"col_offset",
+ "end_lineno",
+ "end_col_offset",
};
_Py_IDENTIFIER(arg);
static char *arg_fields[]={
@@ -804,7 +814,7 @@ static int init_types(void)
if (!Suite_type) return 0;
stmt_type = make_type("stmt", &AST_type, NULL, 0);
if (!stmt_type) return 0;
- if (!add_attributes(stmt_type, stmt_attributes, 2)) return 0;
+ if (!add_attributes(stmt_type, stmt_attributes, 4)) return 0;
FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields,
5);
if (!FunctionDef_type) return 0;
@@ -859,7 +869,7 @@ static int init_types(void)
if (!Continue_type) return 0;
expr_type = make_type("expr", &AST_type, NULL, 0);
if (!expr_type) return 0;
- if (!add_attributes(expr_type, expr_attributes, 2)) return 0;
+ if (!add_attributes(expr_type, expr_attributes, 4)) return 0;
BoolOp_type = make_type("BoolOp", expr_type, BoolOp_fields, 2);
if (!BoolOp_type) return 0;
BinOp_type = make_type("BinOp", expr_type, BinOp_fields, 3);
@@ -1082,7 +1092,7 @@ static int init_types(void)
if (!add_attributes(comprehension_type, NULL, 0)) return 0;
excepthandler_type = make_type("excepthandler", &AST_type, NULL, 0);
if (!excepthandler_type) return 0;
- if (!add_attributes(excepthandler_type, excepthandler_attributes, 2))
+ if (!add_attributes(excepthandler_type, excepthandler_attributes, 4))
return 0;
ExceptHandler_type = make_type("ExceptHandler", excepthandler_type,
ExceptHandler_fields, 3);
@@ -1092,7 +1102,7 @@ static int init_types(void)
if (!add_attributes(arguments_type, NULL, 0)) return 0;
arg_type = make_type("arg", &AST_type, arg_fields, 2);
if (!arg_type) return 0;
- if (!add_attributes(arg_type, arg_attributes, 2)) return 0;
+ if (!add_attributes(arg_type, arg_attributes, 4)) return 0;
keyword_type = make_type("keyword", &AST_type, keyword_fields, 2);
if (!keyword_type) return 0;
if (!add_attributes(keyword_type, NULL, 0)) return 0;
@@ -1181,8 +1191,8 @@ Suite(asdl_seq * body, PyArena *arena)
stmt_ty
FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
- decorator_list, expr_ty returns, int lineno, int col_offset,
- PyArena *arena)
+ decorator_list, expr_ty returns, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
if (!name) {
@@ -1206,13 +1216,15 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
p->v.FunctionDef.returns = returns;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq
* decorator_list, expr_ty returns, int lineno, int col_offset,
- PyArena *arena)
+ int end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
if (!name) {
@@ -1236,13 +1248,15 @@ AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq
p->v.AsyncFunctionDef.returns = returns;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq *
- body, asdl_seq * decorator_list, int lineno, int col_offset, PyArena
- *arena)
+ body, asdl_seq * decorator_list, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
if (!name) {
@@ -1261,11 +1275,14 @@ ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq *
p->v.ClassDef.decorator_list = decorator_list;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Return(expr_ty value, int lineno, int col_offset, PyArena *arena)
+Return(expr_ty value, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1275,11 +1292,14 @@ Return(expr_ty value, int lineno, int col_offset, PyArena *arena)
p->v.Return.value = value;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Delete(asdl_seq * targets, int lineno, int col_offset, PyArena *arena)
+Delete(asdl_seq * targets, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1289,12 +1309,14 @@ Delete(asdl_seq * targets, int lineno, int col_offset, PyArena *arena)
p->v.Delete.targets = targets;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Assign(asdl_seq * targets, expr_ty value, int lineno, int col_offset, PyArena
- *arena)
+Assign(asdl_seq * targets, expr_ty value, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
if (!value) {
@@ -1310,12 +1332,14 @@ Assign(asdl_seq * targets, expr_ty value, int lineno, int col_offset, PyArena
p->v.Assign.value = value;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno, int
- col_offset, PyArena *arena)
+ col_offset, int end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
if (!target) {
@@ -1342,12 +1366,15 @@ AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno, int
p->v.AugAssign.value = value;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
AnnAssign(expr_ty target, expr_ty annotation, expr_ty value, int simple, int
- lineno, int col_offset, PyArena *arena)
+ lineno, int col_offset, int end_lineno, int end_col_offset, PyArena
+ *arena)
{
stmt_ty p;
if (!target) {
@@ -1370,12 +1397,14 @@ AnnAssign(expr_ty target, expr_ty annotation, expr_ty value, int simple, int
p->v.AnnAssign.simple = simple;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int
- lineno, int col_offset, PyArena *arena)
+ lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
if (!target) {
@@ -1398,12 +1427,15 @@ For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int
p->v.For.orelse = orelse;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
AsyncFor(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int
- lineno, int col_offset, PyArena *arena)
+ lineno, int col_offset, int end_lineno, int end_col_offset, PyArena
+ *arena)
{
stmt_ty p;
if (!target) {
@@ -1426,12 +1458,14 @@ AsyncFor(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int
p->v.AsyncFor.orelse = orelse;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int
- col_offset, PyArena *arena)
+ col_offset, int end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
if (!test) {
@@ -1448,12 +1482,14 @@ While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int
p->v.While.orelse = orelse;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int
- col_offset, PyArena *arena)
+ col_offset, int end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
if (!test) {
@@ -1470,12 +1506,14 @@ If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int
p->v.If.orelse = orelse;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-With(asdl_seq * items, asdl_seq * body, int lineno, int col_offset, PyArena
- *arena)
+With(asdl_seq * items, asdl_seq * body, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1486,12 +1524,14 @@ With(asdl_seq * items, asdl_seq * body, int lineno, int col_offset, PyArena
p->v.With.body = body;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-AsyncWith(asdl_seq * items, asdl_seq * body, int lineno, int col_offset,
- PyArena *arena)
+AsyncWith(asdl_seq * items, asdl_seq * body, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1502,11 +1542,14 @@ AsyncWith(asdl_seq * items, asdl_seq * body, int lineno, int col_offset,
p->v.AsyncWith.body = body;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, PyArena *arena)
+Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, int end_lineno,
+ int end_col_offset, PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1517,12 +1560,15 @@ Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, PyArena *arena)
p->v.Raise.cause = cause;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
Try(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, asdl_seq *
- finalbody, int lineno, int col_offset, PyArena *arena)
+ finalbody, int lineno, int col_offset, int end_lineno, int end_col_offset,
+ PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1535,11 +1581,14 @@ Try(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, asdl_seq *
p->v.Try.finalbody = finalbody;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, PyArena *arena)
+Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, int end_lineno,
+ int end_col_offset, PyArena *arena)
{
stmt_ty p;
if (!test) {
@@ -1555,11 +1604,14 @@ Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, PyArena *arena)
p->v.Assert.msg = msg;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Import(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
+Import(asdl_seq * names, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1569,12 +1621,14 @@ Import(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
p->v.Import.names = names;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
ImportFrom(identifier module, asdl_seq * names, int level, int lineno, int
- col_offset, PyArena *arena)
+ col_offset, int end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1586,11 +1640,14 @@ ImportFrom(identifier module, asdl_seq * names, int level, int lineno, int
p->v.ImportFrom.level = level;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Global(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
+Global(asdl_seq * names, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1600,11 +1657,14 @@ Global(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
p->v.Global.names = names;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Nonlocal(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
+Nonlocal(asdl_seq * names, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1614,11 +1674,14 @@ Nonlocal(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
p->v.Nonlocal.names = names;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Expr(expr_ty value, int lineno, int col_offset, PyArena *arena)
+Expr(expr_ty value, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
stmt_ty p;
if (!value) {
@@ -1633,11 +1696,14 @@ Expr(expr_ty value, int lineno, int col_offset, PyArena *arena)
p->v.Expr.value = value;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Pass(int lineno, int col_offset, PyArena *arena)
+Pass(int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena
+ *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1646,11 +1712,14 @@ Pass(int lineno, int col_offset, PyArena *arena)
p->kind = Pass_kind;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Break(int lineno, int col_offset, PyArena *arena)
+Break(int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena
+ *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1659,11 +1728,14 @@ Break(int lineno, int col_offset, PyArena *arena)
p->kind = Break_kind;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
stmt_ty
-Continue(int lineno, int col_offset, PyArena *arena)
+Continue(int lineno, int col_offset, int end_lineno, int end_col_offset,
+ PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1672,12 +1744,14 @@ Continue(int lineno, int col_offset, PyArena *arena)
p->kind = Continue_kind;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-BoolOp(boolop_ty op, asdl_seq * values, int lineno, int col_offset, PyArena
- *arena)
+BoolOp(boolop_ty op, asdl_seq * values, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!op) {
@@ -1693,12 +1767,14 @@ BoolOp(boolop_ty op, asdl_seq * values, int lineno, int col_offset, PyArena
p->v.BoolOp.values = values;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno, int col_offset,
- PyArena *arena)
+ int end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!left) {
@@ -1725,12 +1801,14 @@ BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno, int col_offset,
p->v.BinOp.right = right;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-UnaryOp(unaryop_ty op, expr_ty operand, int lineno, int col_offset, PyArena
- *arena)
+UnaryOp(unaryop_ty op, expr_ty operand, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!op) {
@@ -1751,12 +1829,14 @@ UnaryOp(unaryop_ty op, expr_ty operand, int lineno, int col_offset, PyArena
p->v.UnaryOp.operand = operand;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-Lambda(arguments_ty args, expr_ty body, int lineno, int col_offset, PyArena
- *arena)
+Lambda(arguments_ty args, expr_ty body, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!args) {
@@ -1777,12 +1857,14 @@ Lambda(arguments_ty args, expr_ty body, int lineno, int col_offset, PyArena
p->v.Lambda.body = body;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno, int col_offset,
- PyArena *arena)
+ int end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!test) {
@@ -1809,12 +1891,14 @@ IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno, int col_offset,
p->v.IfExp.orelse = orelse;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-Dict(asdl_seq * keys, asdl_seq * values, int lineno, int col_offset, PyArena
- *arena)
+Dict(asdl_seq * keys, asdl_seq * values, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1825,11 +1909,14 @@ Dict(asdl_seq * keys, asdl_seq * values, int lineno, int col_offset, PyArena
p->v.Dict.values = values;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-Set(asdl_seq * elts, int lineno, int col_offset, PyArena *arena)
+Set(asdl_seq * elts, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
expr_ty p;
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1839,12 +1926,14 @@ Set(asdl_seq * elts, int lineno, int col_offset, PyArena *arena)
p->v.Set.elts = elts;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-ListComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
- PyArena *arena)
+ListComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!elt) {
@@ -1860,12 +1949,14 @@ ListComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
p->v.ListComp.generators = generators;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-SetComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena
- *arena)
+SetComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!elt) {
@@ -1881,12 +1972,14 @@ SetComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena
p->v.SetComp.generators = generators;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
DictComp(expr_ty key, expr_ty value, asdl_seq * generators, int lineno, int
- col_offset, PyArena *arena)
+ col_offset, int end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!key) {
@@ -1908,12 +2001,14 @@ DictComp(expr_ty key, expr_ty value, asdl_seq * generators, int lineno, int
p->v.DictComp.generators = generators;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
- PyArena *arena)
+ int end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!elt) {
@@ -1929,11 +2024,14 @@ GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
p->v.GeneratorExp.generators = generators;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-Await(expr_ty value, int lineno, int col_offset, PyArena *arena)
+Await(expr_ty value, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
expr_ty p;
if (!value) {
@@ -1948,11 +2046,14 @@ Await(expr_ty value, int lineno, int col_offset, PyArena *arena)
p->v.Await.value = value;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-Yield(expr_ty value, int lineno, int col_offset, PyArena *arena)
+Yield(expr_ty value, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
expr_ty p;
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -1962,11 +2063,14 @@ Yield(expr_ty value, int lineno, int col_offset, PyArena *arena)
p->v.Yield.value = value;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-YieldFrom(expr_ty value, int lineno, int col_offset, PyArena *arena)
+YieldFrom(expr_ty value, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
expr_ty p;
if (!value) {
@@ -1981,12 +2085,14 @@ YieldFrom(expr_ty value, int lineno, int col_offset, PyArena *arena)
p->v.YieldFrom.value = value;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, int lineno,
- int col_offset, PyArena *arena)
+ int col_offset, int end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!left) {
@@ -2003,12 +2109,14 @@ Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, int lineno,
p->v.Compare.comparators = comparators;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int lineno, int
- col_offset, PyArena *arena)
+ col_offset, int end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!func) {
@@ -2025,12 +2133,15 @@ Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int lineno, int
p->v.Call.keywords = keywords;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
FormattedValue(expr_ty value, int conversion, expr_ty format_spec, int lineno,
- int col_offset, PyArena *arena)
+ int col_offset, int end_lineno, int end_col_offset, PyArena
+ *arena)
{
expr_ty p;
if (!value) {
@@ -2047,11 +2158,14 @@ FormattedValue(expr_ty value, int conversion, expr_ty format_spec, int lineno,
p->v.FormattedValue.format_spec = format_spec;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-JoinedStr(asdl_seq * values, int lineno, int col_offset, PyArena *arena)
+JoinedStr(asdl_seq * values, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
expr_ty p;
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -2061,11 +2175,14 @@ JoinedStr(asdl_seq * values, int lineno, int col_offset, PyArena *arena)
p->v.JoinedStr.values = values;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-Constant(constant value, int lineno, int col_offset, PyArena *arena)
+Constant(constant value, int lineno, int col_offset, int end_lineno, int
+ end_col_offset, PyArena *arena)
{
expr_ty p;
if (!value) {
@@ -2080,12 +2197,14 @@ Constant(constant value, int lineno, int col_offset, PyArena *arena)
p->v.Constant.value = value;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int lineno, int
- col_offset, PyArena *arena)
+ col_offset, int end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!value) {
@@ -2112,12 +2231,14 @@ Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int lineno, int
p->v.Attribute.ctx = ctx;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
Subscript(expr_ty value, slice_ty slice, expr_context_ty ctx, int lineno, int
- col_offset, PyArena *arena)
+ col_offset, int end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!value) {
@@ -2144,12 +2265,14 @@ Subscript(expr_ty value, slice_ty slice, expr_context_ty ctx, int lineno, int
p->v.Subscript.ctx = ctx;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-Starred(expr_ty value, expr_context_ty ctx, int lineno, int col_offset, PyArena
- *arena)
+Starred(expr_ty value, expr_context_ty ctx, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!value) {
@@ -2170,12 +2293,14 @@ Starred(expr_ty value, expr_context_ty ctx, int lineno, int col_offset, PyArena
p->v.Starred.ctx = ctx;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-Name(identifier id, expr_context_ty ctx, int lineno, int col_offset, PyArena
- *arena)
+Name(identifier id, expr_context_ty ctx, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!id) {
@@ -2196,12 +2321,14 @@ Name(identifier id, expr_context_ty ctx, int lineno, int col_offset, PyArena
p->v.Name.ctx = ctx;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-List(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena
- *arena)
+List(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!ctx) {
@@ -2217,12 +2344,14 @@ List(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena
p->v.List.ctx = ctx;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
expr_ty
-Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena
- *arena)
+Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
expr_ty p;
if (!ctx) {
@@ -2238,6 +2367,8 @@ Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena
p->v.Tuple.ctx = ctx;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
@@ -2311,7 +2442,7 @@ comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, int is_async,
excepthandler_ty
ExceptHandler(expr_ty type, identifier name, asdl_seq * body, int lineno, int
- col_offset, PyArena *arena)
+ col_offset, int end_lineno, int end_col_offset, PyArena *arena)
{
excepthandler_ty p;
p = (excepthandler_ty)PyArena_Malloc(arena, sizeof(*p));
@@ -2323,6 +2454,8 @@ ExceptHandler(expr_ty type, identifier name, asdl_seq * body, int lineno, int
p->v.ExceptHandler.body = body;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
@@ -2344,8 +2477,8 @@ arguments(asdl_seq * args, arg_ty vararg, asdl_seq * kwonlyargs, asdl_seq *
}
arg_ty
-arg(identifier arg, expr_ty annotation, int lineno, int col_offset, PyArena
- *arena)
+arg(identifier arg, expr_ty annotation, int lineno, int col_offset, int
+ end_lineno, int end_col_offset, PyArena *arena)
{
arg_ty p;
if (!arg) {
@@ -2360,6 +2493,8 @@ arg(identifier arg, expr_ty annotation, int lineno, int col_offset, PyArena
p->annotation = annotation;
p->lineno = lineno;
p->col_offset = col_offset;
+ p->end_lineno = end_lineno;
+ p->end_col_offset = end_col_offset;
return p;
}
@@ -2886,6 +3021,16 @@ ast2obj_stmt(void* _o)
if (_PyObject_SetAttrId(result, &PyId_col_offset, value) < 0)
goto failed;
Py_DECREF(value);
+ value = ast2obj_int(o->end_lineno);
+ if (!value) goto failed;
+ if (_PyObject_SetAttrId(result, &PyId_end_lineno, value) < 0)
+ goto failed;
+ Py_DECREF(value);
+ value = ast2obj_int(o->end_col_offset);
+ if (!value) goto failed;
+ if (_PyObject_SetAttrId(result, &PyId_end_col_offset, value) < 0)
+ goto failed;
+ Py_DECREF(value);
return result;
failed:
Py_XDECREF(value);
@@ -3281,6 +3426,16 @@ ast2obj_expr(void* _o)
if (_PyObject_SetAttrId(result, &PyId_col_offset, value) < 0)
goto failed;
Py_DECREF(value);
+ value = ast2obj_int(o->end_lineno);
+ if (!value) goto failed;
+ if (_PyObject_SetAttrId(result, &PyId_end_lineno, value) < 0)
+ goto failed;
+ Py_DECREF(value);
+ value = ast2obj_int(o->end_col_offset);
+ if (!value) goto failed;
+ if (_PyObject_SetAttrId(result, &PyId_end_col_offset, value) < 0)
+ goto failed;
+ Py_DECREF(value);
return result;
failed:
Py_XDECREF(value);
@@ -3571,6 +3726,16 @@ ast2obj_excepthandler(void* _o)
if (_PyObject_SetAttrId(result, &PyId_col_offset, value) < 0)
goto failed;
Py_DECREF(value);
+ value = ast2obj_int(o->end_lineno);
+ if (!value) goto failed;
+ if (_PyObject_SetAttrId(result, &PyId_end_lineno, value) < 0)
+ goto failed;
+ Py_DECREF(value);
+ value = ast2obj_int(o->end_col_offset);
+ if (!value) goto failed;
+ if (_PyObject_SetAttrId(result, &PyId_end_col_offset, value) < 0)
+ goto failed;
+ Py_DECREF(value);
return result;
failed:
Py_XDECREF(value);
@@ -3657,6 +3822,16 @@ ast2obj_arg(void* _o)
if (_PyObject_SetAttrId(result, &PyId_col_offset, value) < 0)
goto failed;
Py_DECREF(value);
+ value = ast2obj_int(o->end_lineno);
+ if (!value) goto failed;
+ if (_PyObject_SetAttrId(result, &PyId_end_lineno, value) < 0)
+ goto failed;
+ Py_DECREF(value);
+ value = ast2obj_int(o->end_col_offset);
+ if (!value) goto failed;
+ if (_PyObject_SetAttrId(result, &PyId_end_col_offset, value) < 0)
+ goto failed;
+ Py_DECREF(value);
return result;
failed:
Py_XDECREF(value);
@@ -3922,6 +4097,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
PyObject *tmp = NULL;
int lineno;
int col_offset;
+ int end_lineno;
+ int end_col_offset;
if (obj == Py_None) {
*out = NULL;
@@ -3953,6 +4130,32 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
+ if (_PyObject_LookupAttrId(obj, &PyId_end_lineno, &tmp) < 0) {
+ return 1;
+ }
+ if (tmp == NULL || tmp == Py_None) {
+ Py_CLEAR(tmp);
+ end_lineno = 0;
+ }
+ else {
+ int res;
+ res = obj2ast_int(tmp, &end_lineno, arena);
+ if (res != 0) goto failed;
+ Py_CLEAR(tmp);
+ }
+ if (_PyObject_LookupAttrId(obj, &PyId_end_col_offset, &tmp) < 0) {
+ return 1;
+ }
+ if (tmp == NULL || tmp == Py_None) {
+ Py_CLEAR(tmp);
+ end_col_offset = 0;
+ }
+ else {
+ int res;
+ res = obj2ast_int(tmp, &end_col_offset, arena);
+ if (res != 0) goto failed;
+ Py_CLEAR(tmp);
+ }
isinstance = PyObject_IsInstance(obj, (PyObject*)FunctionDef_type);
if (isinstance == -1) {
return 1;
@@ -4064,7 +4267,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
Py_CLEAR(tmp);
}
*out = FunctionDef(name, args, body, decorator_list, returns, lineno,
- col_offset, arena);
+ col_offset, end_lineno, end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -4179,7 +4382,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
Py_CLEAR(tmp);
}
*out = AsyncFunctionDef(name, args, body, decorator_list, returns,
- lineno, col_offset, arena);
+ lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -4328,7 +4532,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
Py_CLEAR(tmp);
}
*out = ClassDef(name, bases, keywords, body, decorator_list, lineno,
- col_offset, arena);
+ col_offset, end_lineno, end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -4352,7 +4556,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Return(value, lineno, col_offset, arena);
+ *out = Return(value, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -4393,7 +4598,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = Delete(targets, lineno, col_offset, arena);
+ *out = Delete(targets, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -4448,7 +4654,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Assign(targets, value, lineno, col_offset, arena);
+ *out = Assign(targets, value, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -4500,7 +4707,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = AugAssign(target, op, value, lineno, col_offset, arena);
+ *out = AugAssign(target, op, value, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -4567,7 +4775,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
Py_CLEAR(tmp);
}
*out = AnnAssign(target, annotation, value, simple, lineno, col_offset,
- arena);
+ end_lineno, end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -4667,7 +4875,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = For(target, iter, body, orelse, lineno, col_offset, arena);
+ *out = For(target, iter, body, orelse, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -4767,7 +4976,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = AsyncFor(target, iter, body, orelse, lineno, col_offset, arena);
+ *out = AsyncFor(target, iter, body, orelse, lineno, col_offset,
+ end_lineno, end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -4853,7 +5063,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = While(test, body, orelse, lineno, col_offset, arena);
+ *out = While(test, body, orelse, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -4939,7 +5150,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = If(test, body, orelse, lineno, col_offset, arena);
+ *out = If(test, body, orelse, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5011,7 +5223,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = With(items, body, lineno, col_offset, arena);
+ *out = With(items, body, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5083,7 +5296,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = AsyncWith(items, body, lineno, col_offset, arena);
+ *out = AsyncWith(items, body, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5121,7 +5335,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Raise(exc, cause, lineno, col_offset, arena);
+ *out = Raise(exc, cause, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5256,7 +5471,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
Py_CLEAR(tmp);
}
*out = Try(body, handlers, orelse, finalbody, lineno, col_offset,
- arena);
+ end_lineno, end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5294,7 +5509,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Assert(test, msg, lineno, col_offset, arena);
+ *out = Assert(test, msg, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5335,7 +5551,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = Import(names, lineno, col_offset, arena);
+ *out = Import(names, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5404,7 +5621,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = ImportFrom(module, names, level, lineno, col_offset, arena);
+ *out = ImportFrom(module, names, level, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5445,7 +5663,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = Global(names, lineno, col_offset, arena);
+ *out = Global(names, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5486,7 +5705,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = Nonlocal(names, lineno, col_offset, arena);
+ *out = Nonlocal(names, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5510,7 +5730,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Expr(value, lineno, col_offset, arena);
+ *out = Expr(value, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5520,7 +5741,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
if (isinstance) {
- *out = Pass(lineno, col_offset, arena);
+ *out = Pass(lineno, col_offset, end_lineno, end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5530,7 +5751,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
if (isinstance) {
- *out = Break(lineno, col_offset, arena);
+ *out = Break(lineno, col_offset, end_lineno, end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5540,7 +5761,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
}
if (isinstance) {
- *out = Continue(lineno, col_offset, arena);
+ *out = Continue(lineno, col_offset, end_lineno, end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5559,6 +5780,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
PyObject *tmp = NULL;
int lineno;
int col_offset;
+ int end_lineno;
+ int end_col_offset;
if (obj == Py_None) {
*out = NULL;
@@ -5590,6 +5813,32 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
+ if (_PyObject_LookupAttrId(obj, &PyId_end_lineno, &tmp) < 0) {
+ return 1;
+ }
+ if (tmp == NULL || tmp == Py_None) {
+ Py_CLEAR(tmp);
+ end_lineno = 0;
+ }
+ else {
+ int res;
+ res = obj2ast_int(tmp, &end_lineno, arena);
+ if (res != 0) goto failed;
+ Py_CLEAR(tmp);
+ }
+ if (_PyObject_LookupAttrId(obj, &PyId_end_col_offset, &tmp) < 0) {
+ return 1;
+ }
+ if (tmp == NULL || tmp == Py_None) {
+ Py_CLEAR(tmp);
+ end_col_offset = 0;
+ }
+ else {
+ int res;
+ res = obj2ast_int(tmp, &end_col_offset, arena);
+ if (res != 0) goto failed;
+ Py_CLEAR(tmp);
+ }
isinstance = PyObject_IsInstance(obj, (PyObject*)BoolOp_type);
if (isinstance == -1) {
return 1;
@@ -5641,7 +5890,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = BoolOp(op, values, lineno, col_offset, arena);
+ *out = BoolOp(op, values, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5693,7 +5943,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = BinOp(left, op, right, lineno, col_offset, arena);
+ *out = BinOp(left, op, right, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5731,7 +5982,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = UnaryOp(op, operand, lineno, col_offset, arena);
+ *out = UnaryOp(op, operand, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5769,7 +6021,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Lambda(args, body, lineno, col_offset, arena);
+ *out = Lambda(args, body, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5821,7 +6074,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = IfExp(test, body, orelse, lineno, col_offset, arena);
+ *out = IfExp(test, body, orelse, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5893,7 +6147,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = Dict(keys, values, lineno, col_offset, arena);
+ *out = Dict(keys, values, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5934,7 +6189,7 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = Set(elts, lineno, col_offset, arena);
+ *out = Set(elts, lineno, col_offset, end_lineno, end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -5989,7 +6244,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = ListComp(elt, generators, lineno, col_offset, arena);
+ *out = ListComp(elt, generators, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6044,7 +6300,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = SetComp(elt, generators, lineno, col_offset, arena);
+ *out = SetComp(elt, generators, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6113,7 +6370,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = DictComp(key, value, generators, lineno, col_offset, arena);
+ *out = DictComp(key, value, generators, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6168,7 +6426,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = GeneratorExp(elt, generators, lineno, col_offset, arena);
+ *out = GeneratorExp(elt, generators, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6192,7 +6451,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Await(value, lineno, col_offset, arena);
+ *out = Await(value, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6216,7 +6476,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Yield(value, lineno, col_offset, arena);
+ *out = Yield(value, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6240,7 +6501,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = YieldFrom(value, lineno, col_offset, arena);
+ *out = YieldFrom(value, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6326,7 +6588,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = Compare(left, ops, comparators, lineno, col_offset, arena);
+ *out = Compare(left, ops, comparators, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6412,7 +6675,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = Call(func, args, keywords, lineno, col_offset, arena);
+ *out = Call(func, args, keywords, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6465,7 +6729,7 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
Py_CLEAR(tmp);
}
*out = FormattedValue(value, conversion, format_spec, lineno,
- col_offset, arena);
+ col_offset, end_lineno, end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6506,7 +6770,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = JoinedStr(values, lineno, col_offset, arena);
+ *out = JoinedStr(values, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6530,7 +6795,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Constant(value, lineno, col_offset, arena);
+ *out = Constant(value, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6582,7 +6848,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Attribute(value, attr, ctx, lineno, col_offset, arena);
+ *out = Attribute(value, attr, ctx, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6634,7 +6901,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Subscript(value, slice, ctx, lineno, col_offset, arena);
+ *out = Subscript(value, slice, ctx, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6672,7 +6940,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Starred(value, ctx, lineno, col_offset, arena);
+ *out = Starred(value, ctx, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6710,7 +6979,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Name(id, ctx, lineno, col_offset, arena);
+ *out = Name(id, ctx, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6765,7 +7035,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = List(elts, ctx, lineno, col_offset, arena);
+ *out = List(elts, ctx, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6820,7 +7091,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = Tuple(elts, ctx, lineno, col_offset, arena);
+ *out = Tuple(elts, ctx, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -7389,6 +7661,8 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena)
PyObject *tmp = NULL;
int lineno;
int col_offset;
+ int end_lineno;
+ int end_col_offset;
if (obj == Py_None) {
*out = NULL;
@@ -7420,6 +7694,32 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
+ if (_PyObject_LookupAttrId(obj, &PyId_end_lineno, &tmp) < 0) {
+ return 1;
+ }
+ if (tmp == NULL || tmp == Py_None) {
+ Py_CLEAR(tmp);
+ end_lineno = 0;
+ }
+ else {
+ int res;
+ res = obj2ast_int(tmp, &end_lineno, arena);
+ if (res != 0) goto failed;
+ Py_CLEAR(tmp);
+ }
+ if (_PyObject_LookupAttrId(obj, &PyId_end_col_offset, &tmp) < 0) {
+ return 1;
+ }
+ if (tmp == NULL || tmp == Py_None) {
+ Py_CLEAR(tmp);
+ end_col_offset = 0;
+ }
+ else {
+ int res;
+ res = obj2ast_int(tmp, &end_col_offset, arena);
+ if (res != 0) goto failed;
+ Py_CLEAR(tmp);
+ }
isinstance = PyObject_IsInstance(obj, (PyObject*)ExceptHandler_type);
if (isinstance == -1) {
return 1;
@@ -7485,7 +7785,8 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena)
}
Py_CLEAR(tmp);
}
- *out = ExceptHandler(type, name, body, lineno, col_offset, arena);
+ *out = ExceptHandler(type, name, body, lineno, col_offset, end_lineno,
+ end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -7669,6 +7970,8 @@ obj2ast_arg(PyObject* obj, arg_ty* out, PyArena* arena)
expr_ty annotation;
int lineno;
int col_offset;
+ int end_lineno;
+ int end_col_offset;
if (_PyObject_LookupAttrId(obj, &PyId_arg, &tmp) < 0) {
return 1;
@@ -7722,7 +8025,34 @@ obj2ast_arg(PyObject* obj, arg_ty* out, PyArena* arena)
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
- *out = arg(arg, annotation, lineno, col_offset, arena);
+ if (_PyObject_LookupAttrId(obj, &PyId_end_lineno, &tmp) < 0) {
+ return 1;
+ }
+ if (tmp == NULL || tmp == Py_None) {
+ Py_CLEAR(tmp);
+ end_lineno = 0;
+ }
+ else {
+ int res;
+ res = obj2ast_int(tmp, &end_lineno, arena);
+ if (res != 0) goto failed;
+ Py_CLEAR(tmp);
+ }
+ if (_PyObject_LookupAttrId(obj, &PyId_end_col_offset, &tmp) < 0) {
+ return 1;
+ }
+ if (tmp == NULL || tmp == Py_None) {
+ Py_CLEAR(tmp);
+ end_col_offset = 0;
+ }
+ else {
+ int res;
+ res = obj2ast_int(tmp, &end_col_offset, arena);
+ if (res != 0) goto failed;
+ Py_CLEAR(tmp);
+ }
+ *out = arg(arg, annotation, lineno, col_offset, end_lineno, end_col_offset,
+ arena);
return 0;
failed:
Py_XDECREF(tmp);
diff --git a/Python/ast.c b/Python/ast.c
index d71f44a..855acca 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -580,10 +580,11 @@ static stmt_ty ast_for_for_stmt(struct compiling *, const node *, bool);
/* Note different signature for ast_for_call */
static expr_ty ast_for_call(struct compiling *, const node *, expr_ty,
- const node *);
+ const node *, const node *);
static PyObject *parsenumber(struct compiling *, const char *);
static expr_ty parsestrplus(struct compiling *, const node *n);
+static void get_last_end_pos(asdl_seq *, int *, int *);
#define COMP_GENEXP 0
#define COMP_LISTCOMP 1
@@ -810,6 +811,7 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags,
if (!stmts)
goto out;
asdl_seq_SET(stmts, 0, Pass(n->n_lineno, n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset,
arena));
if (!asdl_seq_GET(stmts, 0))
goto out;
@@ -940,6 +942,8 @@ copy_location(expr_ty e, const node *n)
if (e) {
e->lineno = LINENO(n);
e->col_offset = n->n_col_offset;
+ e->end_lineno = n->n_end_lineno;
+ e->end_col_offset = n->n_end_col_offset;
}
return e;
}
@@ -1228,7 +1232,8 @@ ast_for_arg(struct compiling *c, const node *n)
return NULL;
}
- ret = arg(name, annotation, LINENO(n), n->n_col_offset, c->c_arena);
+ ret = arg(name, annotation, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
if (!ret)
return NULL;
return ret;
@@ -1287,6 +1292,7 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
if (forbidden_name(c, argname, ch, 0))
goto error;
arg = arg(argname, annotation, LINENO(ch), ch->n_col_offset,
+ ch->n_end_lineno, ch->n_end_col_offset,
c->c_arena);
if (!arg)
goto error;
@@ -1480,16 +1486,19 @@ ast_for_dotted_name(struct compiling *c, const node *n)
identifier id;
int lineno, col_offset;
int i;
+ node *ch;
REQ(n, dotted_name);
lineno = LINENO(n);
col_offset = n->n_col_offset;
- id = NEW_IDENTIFIER(CHILD(n, 0));
+ ch = CHILD(n, 0);
+ id = NEW_IDENTIFIER(ch);
if (!id)
return NULL;
- e = Name(id, Load, lineno, col_offset, c->c_arena);
+ e = Name(id, Load, lineno, col_offset,
+ ch->n_end_lineno, ch->n_end_col_offset, c->c_arena);
if (!e)
return NULL;
@@ -1497,7 +1506,8 @@ ast_for_dotted_name(struct compiling *c, const node *n)
id = NEW_IDENTIFIER(CHILD(n, i));
if (!id)
return NULL;
- e = Attribute(e, id, Load, lineno, col_offset, c->c_arena);
+ e = Attribute(e, id, Load, lineno, col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
if (!e)
return NULL;
}
@@ -1526,13 +1536,13 @@ ast_for_decorator(struct compiling *c, const node *n)
}
else if (NCH(n) == 5) { /* Call with no arguments */
d = Call(name_expr, NULL, NULL, LINENO(n),
- n->n_col_offset, c->c_arena);
+ n->n_col_offset, n->n_end_lineno, n->n_end_col_offset, c->c_arena);
if (!d)
return NULL;
name_expr = NULL;
}
else {
- d = ast_for_call(c, CHILD(n, 3), name_expr, CHILD(n, 2));
+ d = ast_for_call(c, CHILD(n, 3), name_expr, CHILD(n, 2), CHILD(n, 4));
if (!d)
return NULL;
name_expr = NULL;
@@ -1573,6 +1583,7 @@ ast_for_funcdef_impl(struct compiling *c, const node *n0,
asdl_seq *body;
expr_ty returns = NULL;
int name_i = 1;
+ int end_lineno, end_col_offset;
REQ(n, funcdef);
@@ -1593,13 +1604,14 @@ ast_for_funcdef_impl(struct compiling *c, const node *n0,
body = ast_for_suite(c, CHILD(n, name_i + 3));
if (!body)
return NULL;
+ get_last_end_pos(body, &end_lineno, &end_col_offset);
if (is_async)
return AsyncFunctionDef(name, args, body, decorator_seq, returns,
- LINENO(n0), n0->n_col_offset, c->c_arena);
+ LINENO(n0), n0->n_col_offset, end_lineno, end_col_offset, c->c_arena);
else
return FunctionDef(name, args, body, decorator_seq, returns,
- LINENO(n), n->n_col_offset, c->c_arena);
+ LINENO(n), n->n_col_offset, end_lineno, end_col_offset, c->c_arena);
}
static stmt_ty
@@ -1704,7 +1716,8 @@ ast_for_lambdef(struct compiling *c, const node *n)
return NULL;
}
- return Lambda(args, expression, LINENO(n), n->n_col_offset, c->c_arena);
+ return Lambda(args, expression, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
static expr_ty
@@ -1724,6 +1737,7 @@ ast_for_ifexpr(struct compiling *c, const node *n)
if (!orelse)
return NULL;
return IfExp(expression, body, orelse, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset,
c->c_arena);
}
@@ -1852,8 +1866,9 @@ ast_for_comprehension(struct compiling *c, const node *n)
comp = comprehension(first, expression, NULL,
is_async, c->c_arena);
else
- comp = comprehension(Tuple(t, Store, first->lineno,
- first->col_offset, c->c_arena),
+ comp = comprehension(Tuple(t, Store, first->lineno, first->col_offset,
+ for_ch->n_end_lineno, for_ch->n_end_col_offset,
+ c->c_arena),
expression, NULL, is_async, c->c_arena);
if (!comp)
return NULL;
@@ -1918,11 +1933,14 @@ ast_for_itercomp(struct compiling *c, const node *n, int type)
return NULL;
if (type == COMP_GENEXP)
- return GeneratorExp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);
+ return GeneratorExp(elt, comps, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
else if (type == COMP_LISTCOMP)
- return ListComp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);
+ return ListComp(elt, comps, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
else if (type == COMP_SETCOMP)
- return SetComp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);
+ return SetComp(elt, comps, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
else
/* Should never happen */
return NULL;
@@ -1984,7 +2002,8 @@ ast_for_dictcomp(struct compiling *c, const node *n)
if (!comps)
return NULL;
- return DictComp(key, value, comps, LINENO(n), n->n_col_offset, c->c_arena);
+ return DictComp(key, value, comps, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
static expr_ty
@@ -2017,7 +2036,8 @@ ast_for_dictdisplay(struct compiling *c, const node *n)
}
keys->size = j;
values->size = j;
- return Dict(keys, values, LINENO(n), n->n_col_offset, c->c_arena);
+ return Dict(keys, values, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
static expr_ty
@@ -2060,7 +2080,8 @@ ast_for_setdisplay(struct compiling *c, const node *n)
return NULL;
asdl_seq_SET(elts, i / 2, expression);
}
- return Set(elts, LINENO(n), n->n_col_offset, c->c_arena);
+ return Set(elts, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
static expr_ty
@@ -2079,17 +2100,21 @@ 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, c->c_arena);
+ return Constant(Py_None, 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, c->c_arena);
+ return Constant(Py_True, 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, c->c_arena);
+ return Constant(Py_False, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
name = new_identifier(s, c);
if (!name)
return NULL;
/* All names start in Load context, but may later be changed. */
- return Name(name, Load, LINENO(n), n->n_col_offset, c->c_arena);
+ return Name(name, Load, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
case STRING: {
expr_ty str = parsestrplus(c, n);
@@ -2128,15 +2153,18 @@ ast_for_atom(struct compiling *c, const node *n)
Py_DECREF(pynum);
return NULL;
}
- return Constant(pynum, LINENO(n), n->n_col_offset, c->c_arena);
+ return Constant(pynum, 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, c->c_arena);
+ return Constant(Py_Ellipsis, 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);
if (TYPE(ch) == RPAR)
- return Tuple(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena);
+ return Tuple(NULL, Load, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
if (TYPE(ch) == yield_expr)
return ast_for_expr(c, ch);
@@ -2156,7 +2184,8 @@ ast_for_atom(struct compiling *c, const node *n)
ch = CHILD(n, 1);
if (TYPE(ch) == RSQB)
- return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena);
+ return List(NULL, Load, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
REQ(ch, testlist_comp);
if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {
@@ -2164,7 +2193,8 @@ ast_for_atom(struct compiling *c, const node *n)
if (!elts)
return NULL;
- return List(elts, Load, LINENO(n), n->n_col_offset, c->c_arena);
+ return List(elts, Load, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
else {
return copy_location(ast_for_listcomp(c, ch), n);
@@ -2178,7 +2208,8 @@ ast_for_atom(struct compiling *c, const node *n)
ch = CHILD(n, 1);
if (TYPE(ch) == RBRACE) {
/* It's an empty dict. */
- return Dict(NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena);
+ return Dict(NULL, NULL, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
else {
int is_dict = (TYPE(CHILD(ch, 0)) == DOUBLESTAR);
@@ -2306,6 +2337,7 @@ ast_for_binop(struct compiling *c, const node *n)
return NULL;
result = BinOp(expr1, newoperator, expr2, LINENO(n), n->n_col_offset,
+ CHILD(n, 2)->n_end_lineno, CHILD(n, 2)->n_end_col_offset,
c->c_arena);
if (!result)
return NULL;
@@ -2325,6 +2357,8 @@ ast_for_binop(struct compiling *c, const node *n)
tmp_result = BinOp(result, newoperator, tmp,
LINENO(next_oper), next_oper->n_col_offset,
+ CHILD(n, i * 2 + 2)->n_end_lineno,
+ CHILD(n, i * 2 + 2)->n_end_col_offset,
c->c_arena);
if (!tmp_result)
return NULL;
@@ -2340,20 +2374,22 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
subscriptlist: subscript (',' subscript)* [',']
subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
*/
+ const node *n_copy = n;
REQ(n, trailer);
if (TYPE(CHILD(n, 0)) == LPAR) {
if (NCH(n) == 2)
- return Call(left_expr, NULL, NULL, LINENO(n),
- n->n_col_offset, c->c_arena);
+ return Call(left_expr, NULL, NULL, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
else
- return ast_for_call(c, CHILD(n, 1), left_expr, CHILD(n, 0));
+ return ast_for_call(c, CHILD(n, 1), left_expr, CHILD(n, 0), CHILD(n, 2));
}
else if (TYPE(CHILD(n, 0)) == DOT) {
PyObject *attr_id = NEW_IDENTIFIER(CHILD(n, 1));
if (!attr_id)
return NULL;
return Attribute(left_expr, attr_id, Load,
- LINENO(n), n->n_col_offset, c->c_arena);
+ LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
else {
REQ(CHILD(n, 0), LSQB);
@@ -2364,6 +2400,7 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
if (!slc)
return NULL;
return Subscript(left_expr, slc, Load, LINENO(n), n->n_col_offset,
+ n_copy->n_end_lineno, n_copy->n_end_col_offset,
c->c_arena);
}
else {
@@ -2389,7 +2426,8 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
}
if (!simple) {
return Subscript(left_expr, ExtSlice(slices, c->c_arena),
- Load, LINENO(n), n->n_col_offset, c->c_arena);
+ Load, LINENO(n), n->n_col_offset,
+ n_copy->n_end_lineno, n_copy->n_end_col_offset, c->c_arena);
}
/* extract Index values and put them in a Tuple */
elts = _Py_asdl_seq_new(asdl_seq_LEN(slices), c->c_arena);
@@ -2400,11 +2438,13 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
assert(slc->kind == Index_kind && slc->v.Index.value);
asdl_seq_SET(elts, j, slc->v.Index.value);
}
- e = Tuple(elts, Load, LINENO(n), n->n_col_offset, c->c_arena);
+ e = Tuple(elts, Load, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
if (!e)
return NULL;
return Subscript(left_expr, Index(e, c->c_arena),
- Load, LINENO(n), n->n_col_offset, c->c_arena);
+ Load, LINENO(n), n->n_col_offset,
+ n_copy->n_end_lineno, n_copy->n_end_col_offset, c->c_arena);
}
}
}
@@ -2421,13 +2461,16 @@ ast_for_factor(struct compiling *c, const node *n)
switch (TYPE(CHILD(n, 0))) {
case PLUS:
return UnaryOp(UAdd, expression, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset,
c->c_arena);
case MINUS:
return UnaryOp(USub, expression, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset,
c->c_arena);
case TILDE:
- return UnaryOp(Invert, expression, LINENO(n),
- n->n_col_offset, c->c_arena);
+ return UnaryOp(Invert, expression, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset,
+ c->c_arena);
}
PyErr_Format(PyExc_SystemError, "unhandled factor: %d",
TYPE(CHILD(n, 0)));
@@ -2454,7 +2497,8 @@ ast_for_atom_expr(struct compiling *c, const node *n)
if (nch == 1)
return e;
if (start && nch == 2) {
- return Await(e, LINENO(n), n->n_col_offset, c->c_arena);
+ return Await(e, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
for (i = start + 1; i < nch; i++) {
@@ -2471,7 +2515,8 @@ ast_for_atom_expr(struct compiling *c, const node *n)
if (start) {
/* there was an 'await' */
- return Await(e, LINENO(n), n->n_col_offset, c->c_arena);
+ return Await(e, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
else {
return e;
@@ -2494,7 +2539,8 @@ ast_for_power(struct compiling *c, const node *n)
expr_ty f = ast_for_expr(c, CHILD(n, NCH(n) - 1));
if (!f)
return NULL;
- e = BinOp(e, Pow, f, LINENO(n), n->n_col_offset, c->c_arena);
+ e = BinOp(e, Pow, f, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
return e;
}
@@ -2510,7 +2556,8 @@ ast_for_starred(struct compiling *c, const node *n)
return NULL;
/* The Load context is changed later. */
- return Starred(tmp, Load, LINENO(n), n->n_col_offset, c->c_arena);
+ return Starred(tmp, Load, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
@@ -2569,9 +2616,11 @@ ast_for_expr(struct compiling *c, const node *n)
}
if (!strcmp(STR(CHILD(n, 1)), "and"))
return BoolOp(And, seq, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset,
c->c_arena);
assert(!strcmp(STR(CHILD(n, 1)), "or"));
- return BoolOp(Or, seq, LINENO(n), n->n_col_offset, c->c_arena);
+ return BoolOp(Or, seq, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
case not_test:
if (NCH(n) == 1) {
n = CHILD(n, 0);
@@ -2583,6 +2632,7 @@ ast_for_expr(struct compiling *c, const node *n)
return NULL;
return UnaryOp(Not, expression, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset,
c->c_arena);
}
case comparison:
@@ -2622,8 +2672,8 @@ ast_for_expr(struct compiling *c, const node *n)
return NULL;
}
- return Compare(expression, ops, cmps, LINENO(n),
- n->n_col_offset, c->c_arena);
+ return Compare(expression, ops, cmps, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
break;
@@ -2663,8 +2713,10 @@ ast_for_expr(struct compiling *c, const node *n)
return NULL;
}
if (is_from)
- return YieldFrom(exp, LINENO(n), n->n_col_offset, c->c_arena);
- return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena);
+ return YieldFrom(exp, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
+ return Yield(exp, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
case factor:
if (NCH(n) == 1) {
@@ -2684,7 +2736,7 @@ ast_for_expr(struct compiling *c, const node *n)
static expr_ty
ast_for_call(struct compiling *c, const node *n, expr_ty func,
- const node *maybegenbeg)
+ const node *maybegenbeg, const node *closepar)
{
/*
arglist: argument (',' argument)* [',']
@@ -2773,6 +2825,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func,
return NULL;
starred = Starred(e, Load, LINENO(chch),
chch->n_col_offset,
+ chch->n_end_lineno, chch->n_end_col_offset,
c->c_arena);
if (!starred)
return NULL;
@@ -2864,7 +2917,8 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func,
}
}
- return Call(func, args, keywords, func->lineno, func->col_offset, c->c_arena);
+ return Call(func, args, keywords, func->lineno, func->col_offset,
+ closepar->n_end_lineno, closepar->n_end_col_offset, c->c_arena);
}
static expr_ty
@@ -2887,7 +2941,8 @@ ast_for_testlist(struct compiling *c, const node* n)
asdl_seq *tmp = seq_for_testlist(c, n);
if (!tmp)
return NULL;
- return Tuple(tmp, Load, LINENO(n), n->n_col_offset, c->c_arena);
+ return Tuple(tmp, Load, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
}
@@ -2909,7 +2964,8 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
if (!e)
return NULL;
- return Expr(e, LINENO(n), n->n_col_offset, c->c_arena);
+ return Expr(e, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
else if (TYPE(CHILD(n, 1)) == augassign) {
expr_ty expr1, expr2;
@@ -2947,7 +3003,8 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
if (!newoperator)
return NULL;
- return AugAssign(expr1, newoperator, expr2, LINENO(n), n->n_col_offset, c->c_arena);
+ return AugAssign(expr1, newoperator, expr2, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
else if (TYPE(CHILD(n, 1)) == annassign) {
expr_ty expr1, expr2, expr3;
@@ -3007,7 +3064,8 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
}
if (NCH(ann) == 2) {
return AnnAssign(expr1, expr2, NULL, simple,
- LINENO(n), n->n_col_offset, c->c_arena);
+ LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
else {
ch = CHILD(ann, 3);
@@ -3016,7 +3074,8 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
return NULL;
}
return AnnAssign(expr1, expr2, expr3, simple,
- LINENO(n), n->n_col_offset, c->c_arena);
+ LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
}
else {
@@ -3054,7 +3113,8 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
expression = ast_for_expr(c, value);
if (!expression)
return NULL;
- return Assign(targets, expression, LINENO(n), n->n_col_offset, c->c_arena);
+ return Assign(targets, expression, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
}
@@ -3093,7 +3153,8 @@ ast_for_del_stmt(struct compiling *c, const node *n)
expr_list = ast_for_exprlist(c, CHILD(n, 1), Del);
if (!expr_list)
return NULL;
- return Delete(expr_list, LINENO(n), n->n_col_offset, c->c_arena);
+ return Delete(expr_list, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
static stmt_ty
@@ -3115,27 +3176,33 @@ ast_for_flow_stmt(struct compiling *c, const node *n)
ch = CHILD(n, 0);
switch (TYPE(ch)) {
case break_stmt:
- return Break(LINENO(n), n->n_col_offset, c->c_arena);
+ return Break(LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
case continue_stmt:
- return Continue(LINENO(n), n->n_col_offset, c->c_arena);
+ return Continue(LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
case yield_stmt: { /* will reduce to yield_expr */
expr_ty exp = ast_for_expr(c, CHILD(ch, 0));
if (!exp)
return NULL;
- return Expr(exp, LINENO(n), n->n_col_offset, c->c_arena);
+ return Expr(exp, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
case return_stmt:
if (NCH(ch) == 1)
- return Return(NULL, LINENO(n), n->n_col_offset, c->c_arena);
+ return Return(NULL, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
else {
expr_ty expression = ast_for_testlist(c, CHILD(ch, 1));
if (!expression)
return NULL;
- return Return(expression, LINENO(n), n->n_col_offset, c->c_arena);
+ return Return(expression, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
case raise_stmt:
if (NCH(ch) == 1)
- return Raise(NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena);
+ return Raise(NULL, NULL, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
else if (NCH(ch) >= 2) {
expr_ty cause = NULL;
expr_ty expression = ast_for_expr(c, CHILD(ch, 1));
@@ -3146,7 +3213,8 @@ ast_for_flow_stmt(struct compiling *c, const node *n)
if (!cause)
return NULL;
}
- return Raise(expression, cause, LINENO(n), n->n_col_offset, c->c_arena);
+ return Raise(expression, cause, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
/* fall through */
default:
@@ -3307,11 +3375,14 @@ ast_for_import_stmt(struct compiling *c, const node *n)
return NULL;
asdl_seq_SET(aliases, i / 2, import_alias);
}
- return Import(aliases, lineno, col_offset, c->c_arena);
+ // Even though n is modified above, the end position is not changed
+ return Import(aliases, lineno, col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
else if (TYPE(n) == import_from) {
int n_children;
int idx, ndots = 0;
+ const node *n_copy = n;
alias_ty mod = NULL;
identifier modname = NULL;
@@ -3382,6 +3453,7 @@ ast_for_import_stmt(struct compiling *c, const node *n)
if (mod != NULL)
modname = mod->name;
return ImportFrom(modname, aliases, ndots, lineno, col_offset,
+ n_copy->n_end_lineno, n_copy->n_end_col_offset,
c->c_arena);
}
PyErr_Format(PyExc_SystemError,
@@ -3408,7 +3480,8 @@ ast_for_global_stmt(struct compiling *c, const node *n)
return NULL;
asdl_seq_SET(s, i / 2, name);
}
- return Global(s, LINENO(n), n->n_col_offset, c->c_arena);
+ return Global(s, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
static stmt_ty
@@ -3429,7 +3502,8 @@ ast_for_nonlocal_stmt(struct compiling *c, const node *n)
return NULL;
asdl_seq_SET(s, i / 2, name);
}
- return Nonlocal(s, LINENO(n), n->n_col_offset, c->c_arena);
+ return Nonlocal(s, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
static stmt_ty
@@ -3441,7 +3515,8 @@ ast_for_assert_stmt(struct compiling *c, const node *n)
expr_ty expression = ast_for_expr(c, CHILD(n, 1));
if (!expression)
return NULL;
- return Assert(expression, NULL, LINENO(n), n->n_col_offset, c->c_arena);
+ return Assert(expression, NULL, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
else if (NCH(n) == 4) {
expr_ty expr1, expr2;
@@ -3453,7 +3528,8 @@ ast_for_assert_stmt(struct compiling *c, const node *n)
if (!expr2)
return NULL;
- return Assert(expr1, expr2, LINENO(n), n->n_col_offset, c->c_arena);
+ return Assert(expr1, expr2, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
PyErr_Format(PyExc_SystemError,
"improper number of parts to 'assert' statement: %d",
@@ -3527,6 +3603,20 @@ ast_for_suite(struct compiling *c, const node *n)
return seq;
}
+static void
+get_last_end_pos(asdl_seq *s, int *end_lineno, int *end_col_offset)
+{
+ int tot = asdl_seq_LEN(s);
+ // Suite should not be empty, but it is safe to just ignore it
+ // if it will ever occur.
+ if (!tot) {
+ return;
+ }
+ stmt_ty last = asdl_seq_GET(s, tot - 1);
+ *end_lineno = last->end_lineno;
+ *end_col_offset = last->end_col_offset;
+}
+
static stmt_ty
ast_for_if_stmt(struct compiling *c, const node *n)
{
@@ -3534,6 +3624,7 @@ ast_for_if_stmt(struct compiling *c, const node *n)
['else' ':' suite]
*/
char *s;
+ int end_lineno, end_col_offset;
REQ(n, if_stmt);
@@ -3547,9 +3638,10 @@ ast_for_if_stmt(struct compiling *c, const node *n)
suite_seq = ast_for_suite(c, CHILD(n, 3));
if (!suite_seq)
return NULL;
+ get_last_end_pos(suite_seq, &end_lineno, &end_col_offset);
return If(expression, suite_seq, NULL, LINENO(n), n->n_col_offset,
- c->c_arena);
+ end_lineno, end_col_offset, c->c_arena);
}
s = STR(CHILD(n, 4));
@@ -3570,9 +3662,10 @@ ast_for_if_stmt(struct compiling *c, const node *n)
seq2 = ast_for_suite(c, CHILD(n, 6));
if (!seq2)
return NULL;
+ get_last_end_pos(seq2, &end_lineno, &end_col_offset);
return If(expression, seq1, seq2, LINENO(n), n->n_col_offset,
- c->c_arena);
+ end_lineno, end_col_offset, c->c_arena);
}
else if (s[2] == 'i') {
int i, n_elif, has_else = 0;
@@ -3604,12 +3697,13 @@ ast_for_if_stmt(struct compiling *c, const node *n)
suite_seq2 = ast_for_suite(c, CHILD(n, NCH(n) - 1));
if (!suite_seq2)
return NULL;
+ get_last_end_pos(suite_seq2, &end_lineno, &end_col_offset);
asdl_seq_SET(orelse, 0,
If(expression, suite_seq, suite_seq2,
LINENO(CHILD(n, NCH(n) - 6)),
CHILD(n, NCH(n) - 6)->n_col_offset,
- c->c_arena));
+ end_lineno, end_col_offset, c->c_arena));
/* the just-created orelse handled the last elif */
n_elif--;
}
@@ -3626,10 +3720,16 @@ ast_for_if_stmt(struct compiling *c, const node *n)
if (!suite_seq)
return NULL;
+ if (orelse != NULL) {
+ get_last_end_pos(orelse, &end_lineno, &end_col_offset);
+ } else {
+ get_last_end_pos(suite_seq, &end_lineno, &end_col_offset);
+ }
asdl_seq_SET(newobj, 0,
If(expression, suite_seq, orelse,
LINENO(CHILD(n, off)),
- CHILD(n, off)->n_col_offset, c->c_arena));
+ CHILD(n, off)->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena));
orelse = newobj;
}
expression = ast_for_expr(c, CHILD(n, 1));
@@ -3638,8 +3738,10 @@ ast_for_if_stmt(struct compiling *c, const node *n)
suite_seq = ast_for_suite(c, CHILD(n, 3));
if (!suite_seq)
return NULL;
+ get_last_end_pos(orelse, &end_lineno, &end_col_offset);
return If(expression, suite_seq, orelse,
- LINENO(n), n->n_col_offset, c->c_arena);
+ LINENO(n), n->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
}
PyErr_Format(PyExc_SystemError,
@@ -3652,6 +3754,7 @@ ast_for_while_stmt(struct compiling *c, const node *n)
{
/* while_stmt: 'while' test ':' suite ['else' ':' suite] */
REQ(n, while_stmt);
+ int end_lineno, end_col_offset;
if (NCH(n) == 4) {
expr_ty expression;
@@ -3663,7 +3766,9 @@ ast_for_while_stmt(struct compiling *c, const node *n)
suite_seq = ast_for_suite(c, CHILD(n, 3));
if (!suite_seq)
return NULL;
- return While(expression, suite_seq, NULL, LINENO(n), n->n_col_offset, c->c_arena);
+ get_last_end_pos(suite_seq, &end_lineno, &end_col_offset);
+ return While(expression, suite_seq, NULL, LINENO(n), n->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
}
else if (NCH(n) == 7) {
expr_ty expression;
@@ -3678,8 +3783,10 @@ ast_for_while_stmt(struct compiling *c, const node *n)
seq2 = ast_for_suite(c, CHILD(n, 6));
if (!seq2)
return NULL;
+ get_last_end_pos(seq2, &end_lineno, &end_col_offset);
- return While(expression, seq1, seq2, LINENO(n), n->n_col_offset, c->c_arena);
+ return While(expression, seq1, seq2, LINENO(n), n->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
}
PyErr_Format(PyExc_SystemError,
@@ -3696,6 +3803,7 @@ ast_for_for_stmt(struct compiling *c, const node *n0, bool is_async)
expr_ty expression;
expr_ty target, first;
const node *node_target;
+ int end_lineno, end_col_offset;
/* for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] */
REQ(n, for_stmt);
@@ -3715,7 +3823,9 @@ ast_for_for_stmt(struct compiling *c, const node *n0, bool is_async)
if (NCH(node_target) == 1)
target = first;
else
- target = Tuple(_target, Store, first->lineno, first->col_offset, c->c_arena);
+ target = Tuple(_target, Store, first->lineno, first->col_offset,
+ node_target->n_end_lineno, node_target->n_end_col_offset,
+ c->c_arena);
expression = ast_for_testlist(c, CHILD(n, 3));
if (!expression)
@@ -3724,20 +3834,26 @@ ast_for_for_stmt(struct compiling *c, const node *n0, bool is_async)
if (!suite_seq)
return NULL;
+ if (seq != NULL) {
+ get_last_end_pos(seq, &end_lineno, &end_col_offset);
+ } else {
+ get_last_end_pos(suite_seq, &end_lineno, &end_col_offset);
+ }
if (is_async)
return AsyncFor(target, expression, suite_seq, seq,
LINENO(n0), n0->n_col_offset,
- c->c_arena);
+ end_lineno, end_col_offset, c->c_arena);
else
return For(target, expression, suite_seq, seq,
LINENO(n), n->n_col_offset,
- c->c_arena);
+ end_lineno, end_col_offset, c->c_arena);
}
static excepthandler_ty
ast_for_except_clause(struct compiling *c, const node *exc, node *body)
{
/* except_clause: 'except' [test ['as' test]] */
+ int end_lineno, end_col_offset;
REQ(exc, except_clause);
REQ(body, suite);
@@ -3745,9 +3861,11 @@ ast_for_except_clause(struct compiling *c, const node *exc, node *body)
asdl_seq *suite_seq = ast_for_suite(c, body);
if (!suite_seq)
return NULL;
+ get_last_end_pos(suite_seq, &end_lineno, &end_col_offset);
return ExceptHandler(NULL, NULL, suite_seq, LINENO(exc),
- exc->n_col_offset, c->c_arena);
+ exc->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
}
else if (NCH(exc) == 2) {
expr_ty expression;
@@ -3759,9 +3877,11 @@ ast_for_except_clause(struct compiling *c, const node *exc, node *body)
suite_seq = ast_for_suite(c, body);
if (!suite_seq)
return NULL;
+ get_last_end_pos(suite_seq, &end_lineno, &end_col_offset);
return ExceptHandler(expression, NULL, suite_seq, LINENO(exc),
- exc->n_col_offset, c->c_arena);
+ exc->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
}
else if (NCH(exc) == 4) {
asdl_seq *suite_seq;
@@ -3777,9 +3897,11 @@ ast_for_except_clause(struct compiling *c, const node *exc, node *body)
suite_seq = ast_for_suite(c, body);
if (!suite_seq)
return NULL;
+ get_last_end_pos(suite_seq, &end_lineno, &end_col_offset);
return ExceptHandler(expression, e, suite_seq, LINENO(exc),
- exc->n_col_offset, c->c_arena);
+ exc->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
}
PyErr_Format(PyExc_SystemError,
@@ -3792,8 +3914,9 @@ static stmt_ty
ast_for_try_stmt(struct compiling *c, const node *n)
{
const int nch = NCH(n);
- int n_except = (nch - 3)/3;
+ int end_lineno, end_col_offset, n_except = (nch - 3)/3;
asdl_seq *body, *handlers = NULL, *orelse = NULL, *finally = NULL;
+ excepthandler_ty last_handler;
REQ(n, try_stmt);
@@ -3849,7 +3972,20 @@ ast_for_try_stmt(struct compiling *c, const node *n)
}
assert(finally != NULL || asdl_seq_LEN(handlers));
- return Try(body, handlers, orelse, finally, LINENO(n), n->n_col_offset, c->c_arena);
+ if (finally != NULL) {
+ // finally is always last
+ get_last_end_pos(finally, &end_lineno, &end_col_offset);
+ } else if (orelse != NULL) {
+ // otherwise else is last
+ get_last_end_pos(orelse, &end_lineno, &end_col_offset);
+ } else {
+ // inline the get_last_end_pos logic due to layout mismatch
+ last_handler = (excepthandler_ty) asdl_seq_GET(handlers, n_except - 1);
+ end_lineno = last_handler->end_lineno;
+ end_col_offset = last_handler->end_col_offset;
+ }
+ return Try(body, handlers, orelse, finally, LINENO(n), n->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
}
/* with_item: test ['as' expr] */
@@ -3881,7 +4017,7 @@ static stmt_ty
ast_for_with_stmt(struct compiling *c, const node *n0, bool is_async)
{
const node * const n = is_async ? CHILD(n0, 1) : n0;
- int i, n_items;
+ int i, n_items, end_lineno, end_col_offset;
asdl_seq *items, *body;
REQ(n, with_stmt);
@@ -3900,11 +4036,14 @@ ast_for_with_stmt(struct compiling *c, const node *n0, bool is_async)
body = ast_for_suite(c, CHILD(n, NCH(n) - 1));
if (!body)
return NULL;
+ get_last_end_pos(body, &end_lineno, &end_col_offset);
if (is_async)
- return AsyncWith(items, body, LINENO(n0), n0->n_col_offset, c->c_arena);
+ return AsyncWith(items, body, LINENO(n0), n0->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
else
- return With(items, body, LINENO(n), n->n_col_offset, c->c_arena);
+ return With(items, body, LINENO(n), n->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
}
static stmt_ty
@@ -3914,6 +4053,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
PyObject *classname;
asdl_seq *s;
expr_ty call;
+ int end_lineno, end_col_offset;
REQ(n, classdef);
@@ -3921,26 +4061,32 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
s = ast_for_suite(c, CHILD(n, 3));
if (!s)
return NULL;
+ get_last_end_pos(s, &end_lineno, &end_col_offset);
+
classname = NEW_IDENTIFIER(CHILD(n, 1));
if (!classname)
return NULL;
if (forbidden_name(c, classname, CHILD(n, 3), 0))
return NULL;
return ClassDef(classname, NULL, NULL, s, decorator_seq,
- LINENO(n), n->n_col_offset, c->c_arena);
+ LINENO(n), n->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
}
if (TYPE(CHILD(n, 3)) == RPAR) { /* class NAME '(' ')' ':' suite */
s = ast_for_suite(c, CHILD(n, 5));
if (!s)
return NULL;
+ get_last_end_pos(s, &end_lineno, &end_col_offset);
+
classname = NEW_IDENTIFIER(CHILD(n, 1));
if (!classname)
return NULL;
if (forbidden_name(c, classname, CHILD(n, 3), 0))
return NULL;
return ClassDef(classname, NULL, NULL, s, decorator_seq,
- LINENO(n), n->n_col_offset, c->c_arena);
+ LINENO(n), n->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
}
/* class NAME '(' arglist ')' ':' suite */
@@ -3951,14 +4097,18 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
dummy_name = NEW_IDENTIFIER(CHILD(n, 1));
if (!dummy_name)
return NULL;
- dummy = Name(dummy_name, Load, LINENO(n), n->n_col_offset, c->c_arena);
- call = ast_for_call(c, CHILD(n, 3), dummy, NULL);
+ dummy = Name(dummy_name, Load, LINENO(n), n->n_col_offset,
+ CHILD(n, 1)->n_end_lineno, CHILD(n, 1)->n_end_col_offset,
+ c->c_arena);
+ call = ast_for_call(c, CHILD(n, 3), dummy, NULL, CHILD(n, 4));
if (!call)
return NULL;
}
s = ast_for_suite(c, CHILD(n, 6));
if (!s)
return NULL;
+ get_last_end_pos(s, &end_lineno, &end_col_offset);
+
classname = NEW_IDENTIFIER(CHILD(n, 1));
if (!classname)
return NULL;
@@ -3966,7 +4116,8 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
return NULL;
return ClassDef(classname, call->v.Call.args, call->v.Call.keywords, s,
- decorator_seq, LINENO(n), n->n_col_offset, c->c_arena);
+ decorator_seq, LINENO(n), n->n_col_offset,
+ end_lineno, end_col_offset, c->c_arena);
}
static stmt_ty
@@ -3991,7 +4142,8 @@ ast_for_stmt(struct compiling *c, const node *n)
case del_stmt:
return ast_for_del_stmt(c, n);
case pass_stmt:
- return Pass(LINENO(n), n->n_col_offset, c->c_arena);
+ return Pass(LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
case flow_stmt:
return ast_for_flow_stmt(c, n);
case import_stmt:
@@ -4248,6 +4400,7 @@ decode_bytes_with_escapes(struct compiling *c, const node *n, const char *s,
static void fstring_shift_node_locations(node *n, int lineno, int col_offset)
{
n->n_col_offset = n->n_col_offset + col_offset;
+ n->n_end_col_offset = n->n_end_col_offset + col_offset;
for (int i = 0; i < NCH(n); ++i) {
if (n->n_lineno && n->n_lineno < CHILD(n, i)->n_lineno) {
/* Shifting column offsets unnecessary if there's been newlines. */
@@ -4256,6 +4409,7 @@ static void fstring_shift_node_locations(node *n, int lineno, int col_offset)
fstring_shift_node_locations(CHILD(n, i), lineno, col_offset);
}
n->n_lineno = n->n_lineno + lineno;
+ n->n_end_lineno = n->n_end_lineno + lineno;
}
/* Fix locations for the given node and its children.
@@ -4672,6 +4826,7 @@ fstring_find_expr(const char **str, const char *end, int raw, int recurse_lvl,
entire expression with the conversion and format spec. */
*expression = FormattedValue(simple_expression, conversion,
format_spec, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset,
c->c_arena);
if (!*expression)
return -1;
@@ -4918,7 +5073,8 @@ make_str_node_and_del(PyObject **str, struct compiling *c, const node* n)
Py_DECREF(s);
return NULL;
}
- return Constant(s, LINENO(n), n->n_col_offset, c->c_arena);
+ return Constant(s, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
/* Add a non-f-string (that is, a regular literal string). str is
@@ -5073,7 +5229,8 @@ FstringParser_Finish(FstringParser *state, struct compiling *c,
if (!seq)
goto error;
- return JoinedStr(seq, LINENO(n), n->n_col_offset, c->c_arena);
+ return JoinedStr(seq, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
error:
FstringParser_Dealloc(state);
@@ -5283,7 +5440,8 @@ 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, c->c_arena);
+ return Constant(bytes_str, LINENO(n), n->n_col_offset,
+ n->n_end_lineno, n->n_end_col_offset, c->c_arena);
}
/* We're not a bytes string, bytes_str should never have been set. */
diff --git a/Python/ast_opt.c b/Python/ast_opt.c
index 6f72a7f..96c766f 100644
--- a/Python/ast_opt.c
+++ b/Python/ast_opt.c
@@ -439,7 +439,8 @@ astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_)
return 0;
}
asdl_seq_SET(values, 0, st->v.Expr.value);
- expr_ty expr = JoinedStr(values, st->lineno, st->col_offset, ctx_);
+ expr_ty expr = JoinedStr(values, st->lineno, st->col_offset,
+ st->end_lineno, st->end_col_offset, ctx_);
if (!expr) {
return 0;
}
diff --git a/Python/compile.c b/Python/compile.c
index 5aebda0..9713bfc 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -4757,7 +4757,8 @@ compiler_augassign(struct compiler *c, stmt_ty s)
switch (e->kind) {
case Attribute_kind:
auge = Attribute(e->v.Attribute.value, e->v.Attribute.attr,
- AugLoad, e->lineno, e->col_offset, c->c_arena);
+ AugLoad, e->lineno, e->col_offset,
+ e->end_lineno, e->end_col_offset, c->c_arena);
if (auge == NULL)
return 0;
VISIT(c, expr, auge);
@@ -4768,7 +4769,8 @@ compiler_augassign(struct compiler *c, stmt_ty s)
break;
case Subscript_kind:
auge = Subscript(e->v.Subscript.value, e->v.Subscript.slice,
- AugLoad, e->lineno, e->col_offset, c->c_arena);
+ AugLoad, e->lineno, e->col_offset,
+ e->end_lineno, e->end_col_offset, c->c_arena);
if (auge == NULL)
return 0;
VISIT(c, expr, auge);