Commit c5dd10aa authored by Neil Schemenauer's avatar Neil Schemenauer

Write a separate ast_for_testlist_gexp() function instead of overloading

ast_for_testlist().  Also, write a ast_for_class_bases() function and in
the process fix a memory leak.  Add some assertions.
parent c396d9ed
...@@ -35,7 +35,8 @@ static expr_ty ast_for_expr(struct compiling *, const node *); ...@@ -35,7 +35,8 @@ static expr_ty ast_for_expr(struct compiling *, const node *);
static stmt_ty ast_for_stmt(struct compiling *, const node *); static stmt_ty ast_for_stmt(struct compiling *, const node *);
static asdl_seq *ast_for_suite(struct compiling *, const node *); static asdl_seq *ast_for_suite(struct compiling *, const node *);
static asdl_seq *ast_for_exprlist(struct compiling *, const node *, int); static asdl_seq *ast_for_exprlist(struct compiling *, const node *, int);
static expr_ty ast_for_testlist(struct compiling *, const node *, int); static expr_ty ast_for_testlist(struct compiling *, const node *);
static expr_ty ast_for_testlist_gexp(struct compiling *, const node *);
/* Note different signature for ast_for_call */ /* Note different signature for ast_for_call */
static expr_ty ast_for_call(struct compiling *, const node *, expr_ty); static expr_ty ast_for_call(struct compiling *, const node *, expr_ty);
...@@ -251,7 +252,7 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename) ...@@ -251,7 +252,7 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename)
expr_ty testlist_ast; expr_ty testlist_ast;
/* XXX Why not gen_for here? */ /* XXX Why not gen_for here? */
testlist_ast = ast_for_testlist(&c, CHILD(n, 0), 0); testlist_ast = ast_for_testlist(&c, CHILD(n, 0));
if (!testlist_ast) if (!testlist_ast)
goto error; goto error;
return Expression(testlist_ast); return Expression(testlist_ast);
...@@ -980,7 +981,7 @@ ast_for_listcomp(struct compiling *c, const node *n) ...@@ -980,7 +981,7 @@ ast_for_listcomp(struct compiling *c, const node *n)
free_expr(elt); free_expr(elt);
return NULL; return NULL;
} }
expression = ast_for_testlist(c, CHILD(ch, 3), 0); expression = ast_for_testlist(c, CHILD(ch, 3));
if (!expression) { if (!expression) {
asdl_seq_free(t); asdl_seq_free(t);
asdl_seq_free(listcomps); asdl_seq_free(listcomps);
...@@ -1144,7 +1145,7 @@ ast_for_genexp(struct compiling *c, const node *n) ...@@ -1144,7 +1145,7 @@ ast_for_genexp(struct compiling *c, const node *n)
free_expr(elt); free_expr(elt);
return NULL; return NULL;
} }
expression = ast_for_testlist(c, CHILD(ch, 3), 1); expression = ast_for_expr(c, CHILD(ch, 3));
if (!expression) { if (!expression) {
asdl_seq_free(genexps); asdl_seq_free(genexps);
free_expr(elt); free_expr(elt);
...@@ -1184,11 +1185,17 @@ ast_for_genexp(struct compiling *c, const node *n) ...@@ -1184,11 +1185,17 @@ ast_for_genexp(struct compiling *c, const node *n)
} }
for (j = 0; j < n_ifs; j++) { for (j = 0; j < n_ifs; j++) {
expr_ty expression;
REQ(ch, gen_iter); REQ(ch, gen_iter);
ch = CHILD(ch, 0); ch = CHILD(ch, 0);
REQ(ch, gen_if); REQ(ch, gen_if);
asdl_seq_APPEND(ifs, ast_for_expr(c, CHILD(ch, 1))); expression = ast_for_expr(c, CHILD(ch, 1));
if (!expression) {
asdl_seq_free(genexps);
return NULL;
}
asdl_seq_APPEND(ifs, expression);
if (NCH(ch) == 3) if (NCH(ch) == 3)
ch = CHILD(ch, 2); ch = CHILD(ch, 2);
} }
...@@ -1244,7 +1251,7 @@ ast_for_atom(struct compiling *c, const node *n) ...@@ -1244,7 +1251,7 @@ ast_for_atom(struct compiling *c, const node *n)
if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for)) if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for))
return ast_for_genexp(c, ch); return ast_for_genexp(c, ch);
return ast_for_testlist(c, ch, 1); return ast_for_testlist_gexp(c, ch);
case LSQB: /* list (or list comprehension) */ case LSQB: /* list (or list comprehension) */
ch = CHILD(n, 1); ch = CHILD(n, 1);
...@@ -1297,7 +1304,7 @@ ast_for_atom(struct compiling *c, const node *n) ...@@ -1297,7 +1304,7 @@ ast_for_atom(struct compiling *c, const node *n)
return Dict(keys, values, LINENO(n)); return Dict(keys, values, LINENO(n));
} }
case BACKQUOTE: { /* repr */ case BACKQUOTE: { /* repr */
expr_ty expression = ast_for_testlist(c, CHILD(n, 1), 0); expr_ty expression = ast_for_testlist(c, CHILD(n, 1));
if (!expression) if (!expression)
return NULL; return NULL;
...@@ -1552,7 +1559,7 @@ ast_for_expr(struct compiling *c, const node *n) ...@@ -1552,7 +1559,7 @@ ast_for_expr(struct compiling *c, const node *n)
case yield_expr: { case yield_expr: {
expr_ty exp = NULL; expr_ty exp = NULL;
if (NCH(n) == 2) { if (NCH(n) == 2) {
exp = ast_for_testlist(c, CHILD(n, 1), 0); exp = ast_for_testlist(c, CHILD(n, 1));
if (!exp) if (!exp)
return NULL; return NULL;
} }
...@@ -1796,36 +1803,69 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) ...@@ -1796,36 +1803,69 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
return NULL; return NULL;
} }
/* Unlike other ast_for_XXX() functions, this takes a flag that
indicates whether generator expressions are allowed. If gexp is
non-zero, check for testlist_gexp instead of plain testlist.
*/
static expr_ty static expr_ty
ast_for_testlist(struct compiling *c, const node* n, int gexp) ast_for_testlist(struct compiling *c, const node* n)
{ {
/* testlist_gexp: test ( gen_for | (',' test)* [','] ) /* testlist_gexp: test (',' test)* [','] */
testlist: test (',' test)* [','] /* testlist: test (',' test)* [','] */
*/ /* testlist_safe: test (',' test)+ [','] */
/* testlist1: test (',' test)* */
assert(NCH(n) > 0); assert(NCH(n) > 0);
if (TYPE(n) == testlist_gexp) {
if (NCH(n) > 1)
assert(TYPE(CHILD(n, 1)) != gen_for);
}
else {
assert(TYPE(n) == testlist ||
TYPE(n) == testlist_safe ||
TYPE(n) == testlist1);
}
if (NCH(n) == 1) if (NCH(n) == 1)
return ast_for_expr(c, CHILD(n, 0)); return ast_for_expr(c, CHILD(n, 0));
if (TYPE(CHILD(n, 1)) == gen_for) {
if (!gexp) {
ast_error(n, "illegal generator expression");
return NULL;
}
return ast_for_genexp(c, n);
}
else { else {
asdl_seq *tmp = seq_for_testlist(c, n); asdl_seq *tmp = seq_for_testlist(c, n);
if (!tmp) if (!tmp)
return NULL; return NULL;
return Tuple(tmp, Load, LINENO(n)); return Tuple(tmp, Load, LINENO(n));
} }
return NULL; /* unreachable */ }
static expr_ty
ast_for_testlist_gexp(struct compiling *c, const node* n)
{
/* testlist_gexp: test ( gen_for | (',' test)* [','] ) */
/* argument: test [ gen_for ] */
assert(TYPE(n) == testlist_gexp || TYPE(n) == argument);
if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == gen_for) {
return ast_for_genexp(c, n);
}
else
return ast_for_testlist(c, n);
}
/* like ast_for_testlist() but returns a sequence */
static asdl_seq*
ast_for_class_bases(struct compiling *c, const node* n)
{
/* testlist: test (',' test)* [','] */
assert(NCH(n) > 0);
REQ(n, testlist);
if (NCH(n) == 1) {
expr_ty base;
asdl_seq *bases = asdl_seq_new(1);
if (!bases)
return NULL;
base = ast_for_expr(c, CHILD(n, 0));
if (!base) {
asdl_seq_free(bases);
return NULL;
}
asdl_seq_SET(bases, 0, base);
return bases;
}
else {
return seq_for_testlist(c, n);
}
} }
static stmt_ty static stmt_ty
...@@ -1841,7 +1881,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n) ...@@ -1841,7 +1881,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
*/ */
if (NCH(n) == 1) { if (NCH(n) == 1) {
expr_ty e = ast_for_testlist(c, CHILD(n, 0), 0); expr_ty e = ast_for_testlist(c, CHILD(n, 0));
if (!e) if (!e)
return NULL; return NULL;
...@@ -1853,7 +1893,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n) ...@@ -1853,7 +1893,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
node *ch = CHILD(n, 0); node *ch = CHILD(n, 0);
if (TYPE(ch) == testlist) if (TYPE(ch) == testlist)
expr1 = ast_for_testlist(c, ch, 0); expr1 = ast_for_testlist(c, ch);
else else
expr1 = Yield(ast_for_expr(c, CHILD(ch, 0)), LINENO(ch)); expr1 = Yield(ast_for_expr(c, CHILD(ch, 0)), LINENO(ch));
...@@ -1874,7 +1914,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n) ...@@ -1874,7 +1914,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
ch = CHILD(n, 2); ch = CHILD(n, 2);
if (TYPE(ch) == testlist) if (TYPE(ch) == testlist)
expr2 = ast_for_testlist(c, ch, 0); expr2 = ast_for_testlist(c, ch);
else else
expr2 = Yield(ast_for_expr(c, ch), LINENO(ch)); expr2 = Yield(ast_for_expr(c, ch), LINENO(ch));
if (!expr2) if (!expr2)
...@@ -1904,7 +1944,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n) ...@@ -1904,7 +1944,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
ast_error(ch, "assignment to yield expression not possible"); ast_error(ch, "assignment to yield expression not possible");
goto error; goto error;
} }
e = ast_for_testlist(c, ch, 0); e = ast_for_testlist(c, ch);
/* set context to assign */ /* set context to assign */
if (!e) if (!e)
...@@ -1919,7 +1959,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n) ...@@ -1919,7 +1959,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
} }
value = CHILD(n, NCH(n) - 1); value = CHILD(n, NCH(n) - 1);
if (TYPE(value) == testlist) if (TYPE(value) == testlist)
expression = ast_for_testlist(c, value, 0); expression = ast_for_testlist(c, value);
else else
expression = ast_for_expr(c, value); expression = ast_for_expr(c, value);
if (!expression) if (!expression)
...@@ -2041,7 +2081,7 @@ ast_for_flow_stmt(struct compiling *c, const node *n) ...@@ -2041,7 +2081,7 @@ ast_for_flow_stmt(struct compiling *c, const node *n)
if (NCH(ch) == 1) if (NCH(ch) == 1)
return Return(NULL, LINENO(n)); return Return(NULL, LINENO(n));
else { else {
expr_ty expression = ast_for_testlist(c, CHILD(ch, 1), 0); expr_ty expression = ast_for_testlist(c, CHILD(ch, 1));
if (!expression) if (!expression)
return NULL; return NULL;
return Return(expression, LINENO(n)); return Return(expression, LINENO(n));
...@@ -2599,7 +2639,7 @@ ast_for_for_stmt(struct compiling *c, const node *n) ...@@ -2599,7 +2639,7 @@ ast_for_for_stmt(struct compiling *c, const node *n)
else else
target = Tuple(_target, Store, LINENO(n)); target = Tuple(_target, Store, LINENO(n));
expression = ast_for_testlist(c, CHILD(n, 3), 0); expression = ast_for_testlist(c, CHILD(n, 3));
if (!expression) if (!expression)
return NULL; return NULL;
suite_seq = ast_for_suite(c, CHILD(n, 5)); suite_seq = ast_for_suite(c, CHILD(n, 5));
...@@ -2725,7 +2765,6 @@ static stmt_ty ...@@ -2725,7 +2765,6 @@ static stmt_ty
ast_for_classdef(struct compiling *c, const node *n) ast_for_classdef(struct compiling *c, const node *n)
{ {
/* classdef: 'class' NAME ['(' testlist ')'] ':' suite */ /* classdef: 'class' NAME ['(' testlist ')'] ':' suite */
expr_ty _bases;
asdl_seq *bases, *s; asdl_seq *bases, *s;
REQ(n, classdef); REQ(n, classdef);
...@@ -2750,37 +2789,13 @@ ast_for_classdef(struct compiling *c, const node *n) ...@@ -2750,37 +2789,13 @@ ast_for_classdef(struct compiling *c, const node *n)
} }
/* else handle the base class list */ /* else handle the base class list */
_bases = ast_for_testlist(c, CHILD(n, 3), 0); bases = ast_for_class_bases(c, CHILD(n, 3));
if (!_bases) if (!bases)
return NULL; return NULL;
/* XXX: I don't think we can set to diff types here, how to free???
Here's the allocation chain:
Tuple (Python-ast.c:907)
ast_for_testlist (ast.c:1782)
ast_for_classdef (ast.c:2677)
*/
if (_bases->kind == Tuple_kind)
bases = _bases->v.Tuple.elts;
else {
bases = asdl_seq_new(1);
if (!bases) {
free_expr(_bases);
/* XXX: free _bases */
return NULL;
}
asdl_seq_SET(bases, 0, _bases);
}
s = ast_for_suite(c, CHILD(n, 6)); s = ast_for_suite(c, CHILD(n, 6));
if (!s) { if (!s) {
/* XXX: I think this free is correct, but needs to change see above */ asdl_seq_free(bases);
if (_bases->kind == Tuple_kind)
free_expr(_bases);
else {
free_expr(_bases);
asdl_seq_free(bases);
}
return NULL; return NULL;
} }
return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), bases, s, LINENO(n)); return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), bases, s, LINENO(n));
......
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