mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Hide list comp variables and support set comprehensions
This commit is contained in:
		
							parent
							
								
									6ef6306dd6
								
							
						
					
					
						commit
						650f0d06d3
					
				
					 29 changed files with 2006 additions and 1323 deletions
				
			
		
							
								
								
									
										366
									
								
								Python/ast.c
									
										
									
									
									
								
							
							
						
						
									
										366
									
								
								Python/ast.c
									
										
									
									
									
								
							|  | @ -27,7 +27,6 @@ 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_exprlist(struct compiling *, const node *, expr_context_ty); | ||||
| 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 */ | ||||
| static expr_ty ast_for_call(struct compiling *, const node *, expr_ty); | ||||
|  | @ -41,6 +40,10 @@ static PyObject *parsestrplus(struct compiling *, const node *n, | |||
| #define LINENO(n)       ((n)->n_lineno) | ||||
| #endif | ||||
| 
 | ||||
| #define COMP_GENEXP   0 | ||||
| #define COMP_LISTCOMP 1 | ||||
| #define COMP_SETCOMP  2 | ||||
| 
 | ||||
| static identifier | ||||
| new_identifier(const char* n, PyArena *arena) { | ||||
|     PyObject* id = PyString_InternFromString(n); | ||||
|  | @ -231,7 +234,7 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, | |||
|         case eval_input: { | ||||
|             expr_ty testlist_ast; | ||||
| 
 | ||||
|             /* XXX Why not gen_for here? */ | ||||
|             /* XXX Why not comp_for here? */ | ||||
|             testlist_ast = ast_for_testlist(&c, CHILD(n, 0)); | ||||
|             if (!testlist_ast) | ||||
|                 goto error; | ||||
|  | @ -530,19 +533,14 @@ seq_for_testlist(struct compiling *c, const node *n) | |||
|     asdl_seq *seq; | ||||
|     expr_ty expression; | ||||
|     int i; | ||||
|     assert(TYPE(n) == testlist | ||||
|            || TYPE(n) == listmaker | ||||
|            || TYPE(n) == testlist_gexp | ||||
|            || TYPE(n) == testlist_safe | ||||
|            || TYPE(n) == testlist1 | ||||
|            ); | ||||
|     assert(TYPE(n) == testlist || TYPE(n) == testlist_comp); | ||||
| 
 | ||||
|     seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena); | ||||
|     if (!seq) | ||||
|         return NULL; | ||||
| 
 | ||||
|     for (i = 0; i < NCH(n); i += 2) { | ||||
|         assert(TYPE(CHILD(n, i)) == test || TYPE(CHILD(n, i)) == old_test); | ||||
|         assert(TYPE(CHILD(n, i)) == test || TYPE(CHILD(n, i)) == test_nocond); | ||||
| 
 | ||||
|         expression = ast_for_expr(c, CHILD(n, i)); | ||||
|         if (!expression) | ||||
|  | @ -1022,7 +1020,8 @@ ast_for_funcdef(struct compiling *c, const node *n) | |||
| static expr_ty | ||||
| ast_for_lambdef(struct compiling *c, const node *n) | ||||
| { | ||||
|     /* lambdef: 'lambda' [varargslist] ':' test */ | ||||
|     /* lambdef: 'lambda' [varargslist] ':' test
 | ||||
|        lambdef_nocond: 'lambda' [varargslist] ':' test_nocond */ | ||||
|     arguments_ty args; | ||||
|     expr_ty expression; | ||||
| 
 | ||||
|  | @ -1067,190 +1066,34 @@ ast_for_ifexpr(struct compiling *c, const node *n) | |||
|                  c->c_arena); | ||||
| } | ||||
| 
 | ||||
| /* XXX(nnorwitz): the listcomp and genexpr code should be refactored
 | ||||
|    so there is only a single version.  Possibly for loops can also re-use | ||||
|    the code. | ||||
| */ | ||||
| 
 | ||||
| /* Count the number of 'for' loop in a list comprehension.
 | ||||
| 
 | ||||
|    Helper for ast_for_listcomp(). | ||||
| */ | ||||
| 
 | ||||
| static int | ||||
| count_list_fors(const node *n) | ||||
| { | ||||
|     int n_fors = 0; | ||||
|     node *ch = CHILD(n, 1); | ||||
| 
 | ||||
|  count_list_for: | ||||
|     n_fors++; | ||||
|     REQ(ch, list_for); | ||||
|     if (NCH(ch) == 5) | ||||
|         ch = CHILD(ch, 4); | ||||
|     else | ||||
|         return n_fors; | ||||
|  count_list_iter: | ||||
|     REQ(ch, list_iter); | ||||
|     ch = CHILD(ch, 0); | ||||
|     if (TYPE(ch) == list_for) | ||||
|         goto count_list_for; | ||||
|     else if (TYPE(ch) == list_if) { | ||||
|         if (NCH(ch) == 3) { | ||||
|             ch = CHILD(ch, 2); | ||||
|             goto count_list_iter; | ||||
|         } | ||||
|         else | ||||
|             return n_fors; | ||||
|     } | ||||
| 
 | ||||
|     /* Should never be reached */ | ||||
|     PyErr_SetString(PyExc_SystemError, "logic error in count_list_fors"); | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| /* Count the number of 'if' statements in a list comprehension.
 | ||||
| 
 | ||||
|    Helper for ast_for_listcomp(). | ||||
| */ | ||||
| 
 | ||||
| static int | ||||
| count_list_ifs(const node *n) | ||||
| { | ||||
|     int n_ifs = 0; | ||||
| 
 | ||||
|  count_list_iter: | ||||
|     REQ(n, list_iter); | ||||
|     if (TYPE(CHILD(n, 0)) == list_for) | ||||
|         return n_ifs; | ||||
|     n = CHILD(n, 0); | ||||
|     REQ(n, list_if); | ||||
|     n_ifs++; | ||||
|     if (NCH(n) == 2) | ||||
|         return n_ifs; | ||||
|     n = CHILD(n, 2); | ||||
|     goto count_list_iter; | ||||
| } | ||||
| 
 | ||||
| static expr_ty | ||||
| ast_for_listcomp(struct compiling *c, const node *n) | ||||
| { | ||||
|     /* listmaker: test ( list_for | (',' test)* [','] )
 | ||||
|        list_for: 'for' exprlist 'in' testlist_safe [list_iter] | ||||
|        list_iter: list_for | list_if | ||||
|        list_if: 'if' test [list_iter] | ||||
|        testlist_safe: test [(',' test)+ [',']] | ||||
|     */ | ||||
|     expr_ty elt; | ||||
|     asdl_seq *listcomps; | ||||
|     int i, n_fors; | ||||
|     node *ch; | ||||
| 
 | ||||
|     REQ(n, listmaker); | ||||
|     assert(NCH(n) > 1); | ||||
| 
 | ||||
|     elt = ast_for_expr(c, CHILD(n, 0)); | ||||
|     if (!elt) | ||||
|         return NULL; | ||||
| 
 | ||||
|     n_fors = count_list_fors(n); | ||||
|     if (n_fors == -1) | ||||
|         return NULL; | ||||
| 
 | ||||
|     listcomps = asdl_seq_new(n_fors, c->c_arena); | ||||
|     if (!listcomps) | ||||
|         return NULL; | ||||
| 
 | ||||
|     ch = CHILD(n, 1); | ||||
|     for (i = 0; i < n_fors; i++) { | ||||
|         comprehension_ty lc; | ||||
|         asdl_seq *t; | ||||
|         expr_ty expression; | ||||
|         node *for_ch; | ||||
| 
 | ||||
|         REQ(ch, list_for); | ||||
| 
 | ||||
|         for_ch = CHILD(ch, 1); | ||||
|         t = ast_for_exprlist(c, for_ch, Store); | ||||
|         if (!t) | ||||
|             return NULL; | ||||
|         expression = ast_for_testlist(c, CHILD(ch, 3)); | ||||
|         if (!expression) | ||||
|             return NULL; | ||||
| 
 | ||||
|         /* Check the # of children rather than the length of t, since
 | ||||
|            [x for x, in ... ] has 1 element in t, but still requires a Tuple. */ | ||||
|         if (NCH(for_ch) == 1) | ||||
|             lc = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, NULL, | ||||
|                                c->c_arena); | ||||
|         else | ||||
|             lc = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, | ||||
|                                      c->c_arena), | ||||
|                                expression, NULL, c->c_arena); | ||||
|         if (!lc) | ||||
|             return NULL; | ||||
| 
 | ||||
|         if (NCH(ch) == 5) { | ||||
|             int j, n_ifs; | ||||
|             asdl_seq *ifs; | ||||
| 
 | ||||
|             ch = CHILD(ch, 4); | ||||
|             n_ifs = count_list_ifs(ch); | ||||
|             if (n_ifs == -1) | ||||
|                 return NULL; | ||||
| 
 | ||||
|             ifs = asdl_seq_new(n_ifs, c->c_arena); | ||||
|             if (!ifs) | ||||
|                 return NULL; | ||||
| 
 | ||||
|             for (j = 0; j < n_ifs; j++) { | ||||
|             REQ(ch, list_iter); | ||||
|                     ch = CHILD(ch, 0); | ||||
|                     REQ(ch, list_if); | ||||
| 
 | ||||
|                 asdl_seq_SET(ifs, j, ast_for_expr(c, CHILD(ch, 1))); | ||||
|                 if (NCH(ch) == 3) | ||||
|                     ch = CHILD(ch, 2); | ||||
|                 } | ||||
|                 /* on exit, must guarantee that ch is a list_for */ | ||||
|                 if (TYPE(ch) == list_iter) | ||||
|                         ch = CHILD(ch, 0); | ||||
|             lc->ifs = ifs; | ||||
|             } | ||||
|             asdl_seq_SET(listcomps, i, lc); | ||||
|     } | ||||
| 
 | ||||
|     return ListComp(elt, listcomps, LINENO(n), n->n_col_offset, c->c_arena); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|    Count the number of 'for' loops in a generator expression. | ||||
|    Count the number of 'for' loops in a comprehension. | ||||
| 
 | ||||
|    Helper for ast_for_genexp(). | ||||
|    Helper for ast_for_comprehension(). | ||||
| */ | ||||
| 
 | ||||
| static int | ||||
| count_gen_fors(const node *n) | ||||
| count_comp_fors(const node *n) | ||||
| { | ||||
|         int n_fors = 0; | ||||
|         node *ch = CHILD(n, 1); | ||||
| 
 | ||||
|  count_gen_for: | ||||
|  count_comp_for: | ||||
|         n_fors++; | ||||
|         REQ(ch, gen_for); | ||||
|         REQ(ch, comp_for); | ||||
|         if (NCH(ch) == 5) | ||||
|                 ch = CHILD(ch, 4); | ||||
|         else | ||||
|                 return n_fors; | ||||
|  count_gen_iter: | ||||
|         REQ(ch, gen_iter); | ||||
|  count_comp_iter: | ||||
|         REQ(ch, comp_iter); | ||||
|         ch = CHILD(ch, 0); | ||||
|         if (TYPE(ch) == gen_for) | ||||
|                 goto count_gen_for; | ||||
|         else if (TYPE(ch) == gen_if) { | ||||
|         if (TYPE(ch) == comp_for) | ||||
|                 goto count_comp_for; | ||||
|         else if (TYPE(ch) == comp_if) { | ||||
|                 if (NCH(ch) == 3) { | ||||
|                         ch = CHILD(ch, 2); | ||||
|                         goto count_gen_iter; | ||||
|                         goto count_comp_iter; | ||||
|                 } | ||||
|                 else | ||||
|                     return n_fors; | ||||
|  | @ -1258,26 +1101,26 @@ count_gen_fors(const node *n) | |||
| 
 | ||||
|         /* Should never be reached */ | ||||
|         PyErr_SetString(PyExc_SystemError, | ||||
|                         "logic error in count_gen_fors"); | ||||
|                         "logic error in count_comp_fors"); | ||||
|         return -1; | ||||
| } | ||||
| 
 | ||||
| /* Count the number of 'if' statements in a generator expression.
 | ||||
| /* Count the number of 'if' statements in a comprehension.
 | ||||
| 
 | ||||
|    Helper for ast_for_genexp(). | ||||
|    Helper for ast_for_comprehension(). | ||||
| */ | ||||
| 
 | ||||
| static int | ||||
| count_gen_ifs(const node *n) | ||||
| count_comp_ifs(const node *n) | ||||
| { | ||||
|         int n_ifs = 0; | ||||
| 
 | ||||
|         while (1) { | ||||
|                 REQ(n, gen_iter); | ||||
|                 if (TYPE(CHILD(n, 0)) == gen_for) | ||||
|                 REQ(n, comp_iter); | ||||
|                 if (TYPE(CHILD(n, 0)) == comp_for) | ||||
|                         return n_ifs; | ||||
|                 n = CHILD(n, 0); | ||||
|                 REQ(n, gen_if); | ||||
|                 REQ(n, comp_if); | ||||
|                 n_ifs++; | ||||
|                 if (NCH(n) == 2) | ||||
|                         return n_ifs; | ||||
|  | @ -1285,40 +1128,38 @@ count_gen_ifs(const node *n) | |||
|         } | ||||
| } | ||||
| 
 | ||||
| /* TODO(jhylton): Combine with list comprehension code? */ | ||||
| static expr_ty | ||||
| ast_for_genexp(struct compiling *c, const node *n) | ||||
| ast_for_comprehension(struct compiling *c, const node *n, int type) | ||||
| { | ||||
|     /* testlist_gexp: test ( gen_for | (',' test)* [','] )
 | ||||
|        argument: [test '='] test [gen_for]       # Really [keyword '='] test */ | ||||
|     /* testlist_comp: test ( comp_for | (',' test)* [','] )
 | ||||
|        argument: [test '='] test [comp_for]       # Really [keyword '='] test */ | ||||
|     expr_ty elt; | ||||
|     asdl_seq *genexps; | ||||
|     asdl_seq *comps; | ||||
|     int i, n_fors; | ||||
|     node *ch; | ||||
|      | ||||
|     assert(TYPE(n) == (testlist_gexp) || TYPE(n) == (argument)); | ||||
|     assert(NCH(n) > 1); | ||||
|      | ||||
|     elt = ast_for_expr(c, CHILD(n, 0)); | ||||
|     if (!elt) | ||||
|         return NULL; | ||||
|      | ||||
|     n_fors = count_gen_fors(n); | ||||
|     n_fors = count_comp_fors(n); | ||||
|     if (n_fors == -1) | ||||
|         return NULL; | ||||
| 
 | ||||
|     genexps = asdl_seq_new(n_fors, c->c_arena); | ||||
|     if (!genexps) | ||||
|     comps = asdl_seq_new(n_fors, c->c_arena); | ||||
|     if (!comps) | ||||
|         return NULL; | ||||
| 
 | ||||
|     ch = CHILD(n, 1); | ||||
|     for (i = 0; i < n_fors; i++) { | ||||
|         comprehension_ty ge; | ||||
|         comprehension_ty comp; | ||||
|         asdl_seq *t; | ||||
|         expr_ty expression; | ||||
|         node *for_ch; | ||||
|          | ||||
|         REQ(ch, gen_for); | ||||
|         REQ(ch, comp_for); | ||||
|          | ||||
|         for_ch = CHILD(ch, 1); | ||||
|         t = ast_for_exprlist(c, for_ch, Store); | ||||
|  | @ -1331,14 +1172,14 @@ ast_for_genexp(struct compiling *c, const node *n) | |||
|         /* Check the # of children rather than the length of t, since
 | ||||
|            (x for x, in ...) has 1 element in t, but still requires a Tuple. */ | ||||
|         if (NCH(for_ch) == 1) | ||||
|             ge = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, | ||||
|                                NULL, c->c_arena); | ||||
|             comp = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, | ||||
|                                  NULL, c->c_arena); | ||||
|         else | ||||
|             ge = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, | ||||
|                                      c->c_arena), | ||||
|                                expression, NULL, c->c_arena); | ||||
|             comp = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, | ||||
|                                        c->c_arena), | ||||
|                                  expression, NULL, c->c_arena); | ||||
| 
 | ||||
|         if (!ge) | ||||
|         if (!comp) | ||||
|             return NULL; | ||||
| 
 | ||||
|         if (NCH(ch) == 5) { | ||||
|  | @ -1346,7 +1187,7 @@ ast_for_genexp(struct compiling *c, const node *n) | |||
|             asdl_seq *ifs; | ||||
|              | ||||
|             ch = CHILD(ch, 4); | ||||
|             n_ifs = count_gen_ifs(ch); | ||||
|             n_ifs = count_comp_ifs(ch); | ||||
|             if (n_ifs == -1) | ||||
|                 return NULL; | ||||
| 
 | ||||
|  | @ -1355,9 +1196,9 @@ ast_for_genexp(struct compiling *c, const node *n) | |||
|                 return NULL; | ||||
| 
 | ||||
|             for (j = 0; j < n_ifs; j++) { | ||||
|                 REQ(ch, gen_iter); | ||||
|                 REQ(ch, comp_iter); | ||||
|                 ch = CHILD(ch, 0); | ||||
|                 REQ(ch, gen_if); | ||||
|                 REQ(ch, comp_if); | ||||
|                  | ||||
|                 expression = ast_for_expr(c, CHILD(ch, 1)); | ||||
|                 if (!expression) | ||||
|  | @ -1366,22 +1207,52 @@ ast_for_genexp(struct compiling *c, const node *n) | |||
|                 if (NCH(ch) == 3) | ||||
|                     ch = CHILD(ch, 2); | ||||
|             } | ||||
|             /* on exit, must guarantee that ch is a gen_for */ | ||||
|             if (TYPE(ch) == gen_iter) | ||||
|             /* on exit, must guarantee that ch is a comp_for */ | ||||
|             if (TYPE(ch) == comp_iter) | ||||
|                 ch = CHILD(ch, 0); | ||||
|             ge->ifs = ifs; | ||||
|             comp->ifs = ifs; | ||||
|         } | ||||
|         asdl_seq_SET(genexps, i, ge); | ||||
|         asdl_seq_SET(comps, i, comp); | ||||
|     } | ||||
|      | ||||
|     return GeneratorExp(elt, genexps, LINENO(n), n->n_col_offset, c->c_arena); | ||||
| 
 | ||||
|     if (type == COMP_GENEXP) | ||||
|         return GeneratorExp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena); | ||||
|     else if (type == COMP_LISTCOMP) | ||||
|         return ListComp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena); | ||||
|     else if (type == COMP_SETCOMP) | ||||
|         return SetComp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena); | ||||
|     else | ||||
|         /* Should never happen */ | ||||
|         return NULL; | ||||
| } | ||||
| 
 | ||||
| static expr_ty | ||||
| ast_for_genexp(struct compiling *c, const node *n) | ||||
| { | ||||
|     assert(TYPE(n) == (testlist_comp) || TYPE(n) == (argument)); | ||||
|     return ast_for_comprehension(c, n, COMP_GENEXP); | ||||
| } | ||||
| 
 | ||||
| static expr_ty | ||||
| ast_for_listcomp(struct compiling *c, const node *n) | ||||
| { | ||||
|     assert(TYPE(n) == (testlist_comp)); | ||||
|     return ast_for_comprehension(c, n, COMP_LISTCOMP); | ||||
| } | ||||
| 
 | ||||
| static expr_ty | ||||
| ast_for_setcomp(struct compiling *c, const node *n) | ||||
| { | ||||
|     assert(TYPE(n) == (dictorsetmaker)); | ||||
|     return ast_for_comprehension(c, n, COMP_SETCOMP); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static expr_ty | ||||
| ast_for_atom(struct compiling *c, const node *n) | ||||
| { | ||||
|     /* atom: '(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']'
 | ||||
|        | '{' [dictsetmaker] '}' | NAME | NUMBER | STRING+ | ||||
|     /* atom: '(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']'
 | ||||
|        | '{' [dictmaker|testlist_comp] '}' | NAME | NUMBER | STRING+ | ||||
|     */ | ||||
|     node *ch = CHILD(n, 0); | ||||
|     int bytesmode = 0; | ||||
|  | @ -1420,18 +1291,19 @@ ast_for_atom(struct compiling *c, const node *n) | |||
|          | ||||
|         if (TYPE(ch) == yield_expr) | ||||
|             return ast_for_expr(c, ch); | ||||
|          | ||||
|         if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for)) | ||||
| 
 | ||||
|         /* testlist_comp: test ( comp_for | (',' test)* [','] ) */  | ||||
|         if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == comp_for)) | ||||
|             return ast_for_genexp(c, ch); | ||||
|          | ||||
|         return ast_for_testlist_gexp(c, ch); | ||||
|         return ast_for_testlist(c, ch); | ||||
|     case LSQB: /* list (or list comprehension) */ | ||||
|         ch = CHILD(n, 1); | ||||
|          | ||||
|         if (TYPE(ch) == RSQB) | ||||
|             return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena); | ||||
|          | ||||
|         REQ(ch, listmaker); | ||||
|         REQ(ch, testlist_comp); | ||||
|         if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) { | ||||
|             asdl_seq *elts = seq_for_testlist(c, ch); | ||||
|             if (!elts) | ||||
|  | @ -1442,27 +1314,32 @@ ast_for_atom(struct compiling *c, const node *n) | |||
|         else | ||||
|             return ast_for_listcomp(c, ch); | ||||
|     case LBRACE: { | ||||
|         /* dictsetmaker: test ':' test (',' test ':' test)* [','] |
 | ||||
|          *               test (',' test)* [',']  */ | ||||
|         /* dictorsetmaker: test ':' test (',' test ':' test)* [','] |
 | ||||
|          *                 test (gen_for | (',' test)* [','])  */ | ||||
|         int i, size; | ||||
|         asdl_seq *keys, *values; | ||||
| 
 | ||||
|         ch = CHILD(n, 1); | ||||
|         if (NCH(ch) == 1 || (NCH(ch) > 0 && STR(CHILD(ch, 1))[0] == ',')) { | ||||
|             /* it's a set */ | ||||
|         if (TYPE(ch) == RBRACE) { | ||||
|             /* it's an empty dict */ | ||||
|             return Dict(NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena); | ||||
|         } else if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) { | ||||
|             /* it's a simple set */ | ||||
|             size = (NCH(ch) + 1) / 2; /* +1 in case no trailing comma */ | ||||
|             keys = asdl_seq_new(size, c->c_arena); | ||||
|             if (!keys) | ||||
|             asdl_seq *elts = asdl_seq_new(size, c->c_arena); | ||||
|             if (!elts) | ||||
|                 return NULL; | ||||
| 
 | ||||
|             for (i = 0; i < NCH(ch); i += 2) { | ||||
|                 expr_ty expression; | ||||
|                 expression = ast_for_expr(c, CHILD(ch, i)); | ||||
|                 if (!expression) | ||||
|                     return NULL; | ||||
|                 asdl_seq_SET(keys, i / 2, expression); | ||||
|                 asdl_seq_SET(elts, i / 2, expression); | ||||
|             } | ||||
|             return Set(keys, LINENO(n), n->n_col_offset, c->c_arena); | ||||
|             return Set(elts, LINENO(n), n->n_col_offset, c->c_arena); | ||||
|         } else if (TYPE(CHILD(ch, 1)) == comp_for) { | ||||
|             /* it's a set comprehension */ | ||||
|             return ast_for_setcomp(c, ch); | ||||
|         } else { | ||||
|             /* it's a dict */ | ||||
|             size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */ | ||||
|  | @ -1790,6 +1667,7 @@ ast_for_expr(struct compiling *c, const node *n) | |||
| { | ||||
|     /* handle the full range of simple expressions
 | ||||
|        test: or_test ['if' or_test 'else' test] | lambdef | ||||
|        test_nocond: or_test | lambdef_nocond | ||||
|        or_test: and_test ('or' and_test)*  | ||||
|        and_test: not_test ('and' not_test)* | ||||
|        not_test: 'not' not_test | comparison | ||||
|  | @ -1802,15 +1680,6 @@ ast_for_expr(struct compiling *c, const node *n) | |||
|        term: factor (('*'|'/'|'%'|'//') factor)*
 | ||||
|        factor: ('+'|'-'|'~') factor | power | ||||
|        power: atom trailer* ('**' factor)* | ||||
| 
 | ||||
|        As well as modified versions that exist for backward compatibility, | ||||
|        to explicitly allow: | ||||
|        [ x for x in lambda: 0, lambda: 1 ] | ||||
|        (which would be ambiguous without these extra rules) | ||||
|         | ||||
|        old_test: or_test | old_lambdef | ||||
|        old_lambdef: 'lambda' [vararglist] ':' old_test | ||||
| 
 | ||||
|     */ | ||||
| 
 | ||||
|     asdl_seq *seq; | ||||
|  | @ -1819,9 +1688,9 @@ ast_for_expr(struct compiling *c, const node *n) | |||
|  loop: | ||||
|     switch (TYPE(n)) { | ||||
|         case test: | ||||
|         case old_test: | ||||
|         case test_nocond: | ||||
|             if (TYPE(CHILD(n, 0)) == lambdef || | ||||
|                 TYPE(CHILD(n, 0)) == old_lambdef) | ||||
|                 TYPE(CHILD(n, 0)) == lambdef_nocond) | ||||
|                 return ast_for_lambdef(c, CHILD(n, 0)); | ||||
|             else if (NCH(n) > 1) | ||||
|                 return ast_for_ifexpr(c, n); | ||||
|  | @ -1947,7 +1816,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) | |||
|     /*
 | ||||
|       arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | ||||
|                | '**' test) | ||||
|       argument: [test '='] test [gen_for]        # Really [keyword '='] test | ||||
|       argument: [test '='] test [comp_for]        # Really [keyword '='] test | ||||
|     */ | ||||
| 
 | ||||
|     int i, nargs, nkeywords, ngens; | ||||
|  | @ -1965,7 +1834,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) | |||
|         if (TYPE(ch) == argument) { | ||||
|             if (NCH(ch) == 1) | ||||
|                 nargs++; | ||||
|             else if (TYPE(CHILD(ch, 1)) == gen_for) | ||||
|             else if (TYPE(CHILD(ch, 1)) == comp_for) | ||||
|                 ngens++; | ||||
|             else | ||||
|                 nkeywords++; | ||||
|  | @ -2005,7 +1874,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) | |||
|                     return NULL; | ||||
|                 asdl_seq_SET(args, nargs++, e); | ||||
|             }   | ||||
|             else if (TYPE(CHILD(ch, 1)) == gen_for) { | ||||
|             else if (TYPE(CHILD(ch, 1)) == comp_for) { | ||||
|                 e = ast_for_genexp(c, ch); | ||||
|                 if (!e) | ||||
|                     return NULL; | ||||
|  | @ -2057,18 +1926,16 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) | |||
| static expr_ty | ||||
| ast_for_testlist(struct compiling *c, const node* n) | ||||
| { | ||||
|     /* testlist_gexp: test (',' test)* [','] */ | ||||
|     /* testlist_comp: test (comp_for | (',' test)* [',']) */ | ||||
|     /* testlist: test (',' test)* [','] */ | ||||
|     /* testlist_safe: test (',' test)+ [','] */ | ||||
|     /* testlist1: test (',' test)* */ | ||||
|     assert(NCH(n) > 0); | ||||
|     if (TYPE(n) == testlist_gexp) { | ||||
|     if (TYPE(n) == testlist_comp) { | ||||
|         if (NCH(n) > 1) | ||||
|             assert(TYPE(CHILD(n, 1)) != gen_for); | ||||
|             assert(TYPE(CHILD(n, 1)) != comp_for); | ||||
|     } | ||||
|     else { | ||||
|         assert(TYPE(n) == testlist || | ||||
|                TYPE(n) == testlist_safe || | ||||
|                TYPE(n) == testlist1); | ||||
|     } | ||||
|     if (NCH(n) == 1) | ||||
|  | @ -2081,17 +1948,6 @@ ast_for_testlist(struct compiling *c, const node* n) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
|     return ast_for_testlist(c, n); | ||||
| } | ||||
| 
 | ||||
| static stmt_ty | ||||
| ast_for_expr_stmt(struct compiling *c, const node *n) | ||||
| { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Nick Coghlan
						Nick Coghlan