mirror of
				https://github.com/python/cpython.git
				synced 2025-11-01 06:01:29 +00:00 
			
		
		
		
	PEP 3107 - Function Annotations thanks to Tony Lownds
This commit is contained in:
		
							parent
							
								
									f6657e67b3
								
							
						
					
					
						commit
						c150536b5e
					
				
					 32 changed files with 2855 additions and 1897 deletions
				
			
		|  | @ -34,6 +34,7 @@ static char *FunctionDef_fields[]={ | |||
|         "args", | ||||
|         "body", | ||||
|         "decorators", | ||||
|         "returns", | ||||
| }; | ||||
| static PyTypeObject *ClassDef_type; | ||||
| static char *ClassDef_fields[]={ | ||||
|  | @ -333,11 +334,24 @@ static PyObject* ast2obj_arguments(void*); | |||
| static char *arguments_fields[]={ | ||||
|         "args", | ||||
|         "vararg", | ||||
|         "varargannotation", | ||||
|         "kwonlyargs", | ||||
|         "kwarg", | ||||
|         "kwargannotation", | ||||
|         "defaults", | ||||
|         "kw_defaults", | ||||
| }; | ||||
| static PyTypeObject *arg_type; | ||||
| static PyObject* ast2obj_arg(void*); | ||||
| static PyTypeObject *SimpleArg_type; | ||||
| static char *SimpleArg_fields[]={ | ||||
|         "arg", | ||||
|         "annotation", | ||||
| }; | ||||
| static PyTypeObject *NestedArgs_type; | ||||
| static char *NestedArgs_fields[]={ | ||||
|         "args", | ||||
| }; | ||||
| static PyTypeObject *keyword_type; | ||||
| static PyObject* ast2obj_keyword(void*); | ||||
| static char *keyword_fields[]={ | ||||
|  | @ -454,7 +468,7 @@ static int init_types(void) | |||
|         if (!stmt_type) return 0; | ||||
|         if (!add_attributes(stmt_type, stmt_attributes, 2)) return 0; | ||||
|         FunctionDef_type = make_type("FunctionDef", stmt_type, | ||||
|                                      FunctionDef_fields, 4); | ||||
|                                      FunctionDef_fields, 5); | ||||
|         if (!FunctionDef_type) return 0; | ||||
|         ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 3); | ||||
|         if (!ClassDef_type) return 0; | ||||
|  | @ -710,8 +724,16 @@ static int init_types(void) | |||
|         excepthandler_type = make_type("excepthandler", AST_type, | ||||
|                                        excepthandler_fields, 5); | ||||
|         if (!excepthandler_type) return 0; | ||||
|         arguments_type = make_type("arguments", AST_type, arguments_fields, 6); | ||||
|         arguments_type = make_type("arguments", AST_type, arguments_fields, 8); | ||||
|         if (!arguments_type) return 0; | ||||
|         arg_type = make_type("arg", AST_type, NULL, 0); | ||||
|         if (!arg_type) return 0; | ||||
|         if (!add_attributes(arg_type, NULL, 0)) return 0; | ||||
|         SimpleArg_type = make_type("SimpleArg", arg_type, SimpleArg_fields, 2); | ||||
|         if (!SimpleArg_type) return 0; | ||||
|         NestedArgs_type = make_type("NestedArgs", arg_type, NestedArgs_fields, | ||||
|                                     1); | ||||
|         if (!NestedArgs_type) return 0; | ||||
|         keyword_type = make_type("keyword", AST_type, keyword_fields, 2); | ||||
|         if (!keyword_type) return 0; | ||||
|         alias_type = make_type("alias", AST_type, alias_fields, 2); | ||||
|  | @ -783,7 +805,8 @@ Suite(asdl_seq * body, PyArena *arena) | |||
| 
 | ||||
| stmt_ty | ||||
| FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * | ||||
|             decorators, int lineno, int col_offset, PyArena *arena) | ||||
|             decorators, expr_ty returns, int lineno, int col_offset, PyArena | ||||
|             *arena) | ||||
| { | ||||
|         stmt_ty p; | ||||
|         if (!name) { | ||||
|  | @ -806,6 +829,7 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * | |||
|         p->v.FunctionDef.args = args; | ||||
|         p->v.FunctionDef.body = body; | ||||
|         p->v.FunctionDef.decorators = decorators; | ||||
|         p->v.FunctionDef.returns = returns; | ||||
|         p->lineno = lineno; | ||||
|         p->col_offset = col_offset; | ||||
|         return p; | ||||
|  | @ -1830,8 +1854,9 @@ excepthandler(expr_ty type, expr_ty name, asdl_seq * body, int lineno, int | |||
| } | ||||
| 
 | ||||
| arguments_ty | ||||
| arguments(asdl_seq * args, identifier vararg, asdl_seq * kwonlyargs, identifier | ||||
|           kwarg, asdl_seq * defaults, asdl_seq * kw_defaults, PyArena *arena) | ||||
| arguments(asdl_seq * args, identifier vararg, expr_ty varargannotation, | ||||
|           asdl_seq * kwonlyargs, identifier kwarg, expr_ty kwargannotation, | ||||
|           asdl_seq * defaults, asdl_seq * kw_defaults, PyArena *arena) | ||||
| { | ||||
|         arguments_ty p; | ||||
|         p = (arguments_ty)PyArena_Malloc(arena, sizeof(*p)); | ||||
|  | @ -1841,13 +1866,49 @@ arguments(asdl_seq * args, identifier vararg, asdl_seq * kwonlyargs, identifier | |||
|         } | ||||
|         p->args = args; | ||||
|         p->vararg = vararg; | ||||
|         p->varargannotation = varargannotation; | ||||
|         p->kwonlyargs = kwonlyargs; | ||||
|         p->kwarg = kwarg; | ||||
|         p->kwargannotation = kwargannotation; | ||||
|         p->defaults = defaults; | ||||
|         p->kw_defaults = kw_defaults; | ||||
|         return p; | ||||
| } | ||||
| 
 | ||||
| arg_ty | ||||
| SimpleArg(identifier arg, expr_ty annotation, PyArena *arena) | ||||
| { | ||||
|         arg_ty p; | ||||
|         if (!arg) { | ||||
|                 PyErr_SetString(PyExc_ValueError, | ||||
|                                 "field arg is required for SimpleArg"); | ||||
|                 return NULL; | ||||
|         } | ||||
|         p = (arg_ty)PyArena_Malloc(arena, sizeof(*p)); | ||||
|         if (!p) { | ||||
|                 PyErr_NoMemory(); | ||||
|                 return NULL; | ||||
|         } | ||||
|         p->kind = SimpleArg_kind; | ||||
|         p->v.SimpleArg.arg = arg; | ||||
|         p->v.SimpleArg.annotation = annotation; | ||||
|         return p; | ||||
| } | ||||
| 
 | ||||
| arg_ty | ||||
| NestedArgs(asdl_seq * args, PyArena *arena) | ||||
| { | ||||
|         arg_ty p; | ||||
|         p = (arg_ty)PyArena_Malloc(arena, sizeof(*p)); | ||||
|         if (!p) { | ||||
|                 PyErr_NoMemory(); | ||||
|                 return NULL; | ||||
|         } | ||||
|         p->kind = NestedArgs_kind; | ||||
|         p->v.NestedArgs.args = args; | ||||
|         return p; | ||||
| } | ||||
| 
 | ||||
| keyword_ty | ||||
| keyword(identifier arg, expr_ty value, PyArena *arena) | ||||
| { | ||||
|  | @ -1981,6 +2042,11 @@ ast2obj_stmt(void* _o) | |||
|                 if (PyObject_SetAttrString(result, "decorators", value) == -1) | ||||
|                         goto failed; | ||||
|                 Py_DECREF(value); | ||||
|                 value = ast2obj_expr(o->v.FunctionDef.returns); | ||||
|                 if (!value) goto failed; | ||||
|                 if (PyObject_SetAttrString(result, "returns", value) == -1) | ||||
|                         goto failed; | ||||
|                 Py_DECREF(value); | ||||
|                 break; | ||||
|         case ClassDef_kind: | ||||
|                 result = PyType_GenericNew(ClassDef_type, NULL, NULL); | ||||
|  | @ -2901,7 +2967,7 @@ ast2obj_arguments(void* _o) | |||
| 
 | ||||
|         result = PyType_GenericNew(arguments_type, NULL, NULL); | ||||
|         if (!result) return NULL; | ||||
|         value = ast2obj_list(o->args, ast2obj_expr); | ||||
|         value = ast2obj_list(o->args, ast2obj_arg); | ||||
|         if (!value) goto failed; | ||||
|         if (PyObject_SetAttrString(result, "args", value) == -1) | ||||
|                 goto failed; | ||||
|  | @ -2911,7 +2977,12 @@ ast2obj_arguments(void* _o) | |||
|         if (PyObject_SetAttrString(result, "vararg", value) == -1) | ||||
|                 goto failed; | ||||
|         Py_DECREF(value); | ||||
|         value = ast2obj_list(o->kwonlyargs, ast2obj_expr); | ||||
|         value = ast2obj_expr(o->varargannotation); | ||||
|         if (!value) goto failed; | ||||
|         if (PyObject_SetAttrString(result, "varargannotation", value) == -1) | ||||
|                 goto failed; | ||||
|         Py_DECREF(value); | ||||
|         value = ast2obj_list(o->kwonlyargs, ast2obj_arg); | ||||
|         if (!value) goto failed; | ||||
|         if (PyObject_SetAttrString(result, "kwonlyargs", value) == -1) | ||||
|                 goto failed; | ||||
|  | @ -2921,6 +2992,11 @@ ast2obj_arguments(void* _o) | |||
|         if (PyObject_SetAttrString(result, "kwarg", value) == -1) | ||||
|                 goto failed; | ||||
|         Py_DECREF(value); | ||||
|         value = ast2obj_expr(o->kwargannotation); | ||||
|         if (!value) goto failed; | ||||
|         if (PyObject_SetAttrString(result, "kwargannotation", value) == -1) | ||||
|                 goto failed; | ||||
|         Py_DECREF(value); | ||||
|         value = ast2obj_list(o->defaults, ast2obj_expr); | ||||
|         if (!value) goto failed; | ||||
|         if (PyObject_SetAttrString(result, "defaults", value) == -1) | ||||
|  | @ -2938,6 +3014,48 @@ failed: | |||
|         return NULL; | ||||
| } | ||||
| 
 | ||||
| PyObject* | ||||
| ast2obj_arg(void* _o) | ||||
| { | ||||
|         arg_ty o = (arg_ty)_o; | ||||
|         PyObject *result = NULL, *value = NULL; | ||||
|         if (!o) { | ||||
|                 Py_INCREF(Py_None); | ||||
|                 return Py_None; | ||||
|         } | ||||
| 
 | ||||
|         switch (o->kind) { | ||||
|         case SimpleArg_kind: | ||||
|                 result = PyType_GenericNew(SimpleArg_type, NULL, NULL); | ||||
|                 if (!result) goto failed; | ||||
|                 value = ast2obj_identifier(o->v.SimpleArg.arg); | ||||
|                 if (!value) goto failed; | ||||
|                 if (PyObject_SetAttrString(result, "arg", value) == -1) | ||||
|                         goto failed; | ||||
|                 Py_DECREF(value); | ||||
|                 value = ast2obj_expr(o->v.SimpleArg.annotation); | ||||
|                 if (!value) goto failed; | ||||
|                 if (PyObject_SetAttrString(result, "annotation", value) == -1) | ||||
|                         goto failed; | ||||
|                 Py_DECREF(value); | ||||
|                 break; | ||||
|         case NestedArgs_kind: | ||||
|                 result = PyType_GenericNew(NestedArgs_type, NULL, NULL); | ||||
|                 if (!result) goto failed; | ||||
|                 value = ast2obj_list(o->v.NestedArgs.args, ast2obj_arg); | ||||
|                 if (!value) goto failed; | ||||
|                 if (PyObject_SetAttrString(result, "args", value) == -1) | ||||
|                         goto failed; | ||||
|                 Py_DECREF(value); | ||||
|                 break; | ||||
|         } | ||||
|         return result; | ||||
| failed: | ||||
|         Py_XDECREF(value); | ||||
|         Py_XDECREF(result); | ||||
|         return NULL; | ||||
| } | ||||
| 
 | ||||
| PyObject* | ||||
| ast2obj_keyword(void* _o) | ||||
| { | ||||
|  | @ -3008,7 +3126,7 @@ init_ast(void) | |||
|         if (PyDict_SetItemString(d, "AST", (PyObject*)AST_type) < 0) return; | ||||
|         if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) | ||||
|                 return; | ||||
|         if (PyModule_AddStringConstant(m, "__version__", "51773") < 0) | ||||
|         if (PyModule_AddStringConstant(m, "__version__", "52491") < 0) | ||||
|                 return; | ||||
|         if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return; | ||||
|         if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0) | ||||
|  | @ -3146,6 +3264,11 @@ init_ast(void) | |||
|             (PyObject*)excepthandler_type) < 0) return; | ||||
|         if (PyDict_SetItemString(d, "arguments", (PyObject*)arguments_type) < | ||||
|             0) return; | ||||
|         if (PyDict_SetItemString(d, "arg", (PyObject*)arg_type) < 0) return; | ||||
|         if (PyDict_SetItemString(d, "SimpleArg", (PyObject*)SimpleArg_type) < | ||||
|             0) return; | ||||
|         if (PyDict_SetItemString(d, "NestedArgs", (PyObject*)NestedArgs_type) < | ||||
|             0) return; | ||||
|         if (PyDict_SetItemString(d, "keyword", (PyObject*)keyword_type) < 0) | ||||
|             return; | ||||
|         if (PyDict_SetItemString(d, "alias", (PyObject*)alias_type) < 0) return; | ||||
|  |  | |||
							
								
								
									
										303
									
								
								Python/ast.c
									
										
									
									
									
								
							
							
						
						
									
										303
									
								
								Python/ast.c
									
										
									
									
									
								
							|  | @ -388,14 +388,14 @@ set_context(expr_ty e, expr_context_ty ctx, const node *n) | |||
|             expr_name = "list comprehension"; | ||||
|             break; | ||||
|         case Dict_kind: | ||||
| 	case Set_kind: | ||||
|         case Set_kind: | ||||
|         case Num_kind: | ||||
|         case Str_kind: | ||||
|             expr_name = "literal"; | ||||
|             break; | ||||
| 	case Ellipsis_kind: | ||||
| 	    expr_name = "Ellipsis"; | ||||
| 	    break; | ||||
|         case Ellipsis_kind: | ||||
|             expr_name = "Ellipsis"; | ||||
|             break; | ||||
|         case Compare_kind: | ||||
|             expr_name = "comparison"; | ||||
|             break; | ||||
|  | @ -553,59 +553,74 @@ seq_for_testlist(struct compiling *c, const node *n) | |||
|     return seq; | ||||
| } | ||||
| 
 | ||||
| static expr_ty | ||||
| static arg_ty | ||||
| compiler_simple_arg(struct compiling *c, const node *n) | ||||
| { | ||||
|     identifier name; | ||||
|     expr_ty annotation = NULL; | ||||
|     node *ch; | ||||
| 
 | ||||
|     assert(TYPE(n) == tname || TYPE(n) == vname); | ||||
|     ch = CHILD(n, 0); | ||||
|     if (!strcmp(STR(ch), "None")) { | ||||
|         ast_error(ch, "assignment to None"); | ||||
|         return NULL; | ||||
|     } | ||||
|     name = NEW_IDENTIFIER(ch); | ||||
|     if (!name) | ||||
|         return NULL; | ||||
| 
 | ||||
|     if (NCH(n) == 3 && TYPE(CHILD(n, 1)) == COLON) { | ||||
|         annotation = ast_for_expr(c, CHILD(n, 2)); | ||||
|         if (!annotation) | ||||
|             return NULL; | ||||
|     } | ||||
| 
 | ||||
|     return SimpleArg(name, annotation, c->c_arena); | ||||
| } | ||||
| 
 | ||||
| static arg_ty | ||||
| compiler_complex_args(struct compiling *c, const node *n) | ||||
| { | ||||
|     int i, len = (NCH(n) + 1) / 2; | ||||
|     expr_ty result; | ||||
|     arg_ty arg; | ||||
|     asdl_seq *args = asdl_seq_new(len, c->c_arena); | ||||
|     if (!args) | ||||
|         return NULL; | ||||
| 
 | ||||
|     /* fpdef: NAME | '(' fplist ')'
 | ||||
|        fplist: fpdef (',' fpdef)* [','] | ||||
|     */ | ||||
|     REQ(n, fplist); | ||||
|     assert(TYPE(n) == tfplist || TYPE(n) == vfplist); | ||||
|     for (i = 0; i < len; i++) { | ||||
|         const node *fpdef_node = CHILD(n, 2*i); | ||||
|         const node *child; | ||||
|         expr_ty arg; | ||||
| set_name: | ||||
|         /* fpdef_node is either a NAME or an fplist */ | ||||
|         child = CHILD(fpdef_node, 0); | ||||
|         if (TYPE(child) == NAME) { | ||||
|                 if (!strcmp(STR(child), "None")) { | ||||
|                         ast_error(child, "assignment to None"); | ||||
|                         return NULL; | ||||
|                     }    | ||||
|             arg = Name(NEW_IDENTIFIER(child), Store, LINENO(child), | ||||
|                        child->n_col_offset, c->c_arena); | ||||
|             } | ||||
|         else { | ||||
|             assert(TYPE(fpdef_node) == fpdef); | ||||
|             /* fpdef_node[0] is not a name, so it must be a '(', get CHILD[1] */ | ||||
|             child = CHILD(fpdef_node, 1); | ||||
|             assert(TYPE(child) == fplist); | ||||
|             /* NCH == 1 means we have (x), we need to elide the extra parens */ | ||||
|             if (NCH(child) == 1) { | ||||
|                 fpdef_node = CHILD(child, 0); | ||||
|                 assert(TYPE(fpdef_node) == fpdef); | ||||
|                 goto set_name; | ||||
|             } | ||||
|             arg = compiler_complex_args(c, child); | ||||
|         const node *child = CHILD(n, 2*i); | ||||
|         /* def foo(((x), y)): -- x is not nested complex, special case. */ | ||||
|         while (NCH(child) == 3 && NCH(CHILD(child, 1)) == 1) | ||||
|             child = CHILD(CHILD(child, 1), 0); | ||||
| 
 | ||||
|         /* child either holds a tname or '(', a tfplist, ')' */ | ||||
|         switch (TYPE(CHILD(child, 0))) { | ||||
|         case tname: | ||||
|         case vname: | ||||
|             arg = compiler_simple_arg(c, CHILD(child, 0)); | ||||
|             break; | ||||
|         case LPAR: | ||||
|             arg = compiler_complex_args(c, CHILD(child, 1)); | ||||
|             break; | ||||
|         default: | ||||
|             PyErr_Format(PyExc_SystemError, | ||||
|                              "unexpected node in args: %d @ %d", | ||||
|                              TYPE(CHILD(child, 0)), i); | ||||
|             arg = NULL; | ||||
|         } | ||||
|         if (!arg) | ||||
|             return NULL; | ||||
|         asdl_seq_SET(args, i, arg); | ||||
|     } | ||||
| 
 | ||||
|     result = Tuple(args, Store, LINENO(n), n->n_col_offset, c->c_arena); | ||||
|     if (!set_context(result, Store, n)) | ||||
|         return NULL; | ||||
|     return result; | ||||
|     return NestedArgs(args, c->c_arena); | ||||
| } | ||||
| 
 | ||||
| /* returns -1 if failed to handle keyword only arguments
 | ||||
|    returns new position to keep processing if successful | ||||
|                (',' NAME ['=' test])*  | ||||
|                (',' tname ['=' test])* | ||||
|                      ^^^ | ||||
|    start pointing here | ||||
|  */ | ||||
|  | @ -614,7 +629,8 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start, | |||
|                         asdl_seq *kwonlyargs, asdl_seq *kwdefaults) | ||||
| { | ||||
|     node *ch; | ||||
|     expr_ty name; | ||||
|     expr_ty expression, annotation; | ||||
|     arg_ty arg; | ||||
|     int i = start; | ||||
|     int j = 0; /* index for kwdefaults and kwonlyargs */ | ||||
|     assert(kwonlyargs != NULL); | ||||
|  | @ -622,9 +638,10 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start, | |||
|     while (i < NCH(n)) { | ||||
|         ch = CHILD(n, i); | ||||
|         switch (TYPE(ch)) { | ||||
|             case NAME: | ||||
|             case vname: | ||||
|             case tname: | ||||
|                 if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) { | ||||
|                     expr_ty expression = ast_for_expr(c, CHILD(n, i + 2)); | ||||
|                     expression = ast_for_expr(c, CHILD(n, i + 2)); | ||||
|                     if (!expression) { | ||||
|                         ast_error(ch, "assignment to None"); | ||||
|                         goto error; | ||||
|  | @ -635,18 +652,28 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start, | |||
|                 else { /* setting NULL if no default value exists */ | ||||
|                     asdl_seq_SET(kwdefaults, j, NULL); | ||||
|                 } | ||||
|                 if (NCH(ch) == 3) { | ||||
|                     /* ch is NAME ':' test */ | ||||
|                     annotation = ast_for_expr(c, CHILD(ch, 2)); | ||||
|                     if (!annotation) { | ||||
|                         ast_error(ch, "expected expression"); | ||||
|                         goto error; | ||||
|                     } | ||||
|                 } | ||||
|                 else { | ||||
|                     annotation = NULL; | ||||
|                 } | ||||
|                 ch = CHILD(ch, 0); | ||||
|                 if (!strcmp(STR(ch), "None")) { | ||||
|                     ast_error(ch, "assignment to None"); | ||||
|                     goto error; | ||||
|                 } | ||||
|                 name = Name(NEW_IDENTIFIER(ch), | ||||
|                             Param, LINENO(ch), ch->n_col_offset, | ||||
|                             c->c_arena); | ||||
|                 if (!name) { | ||||
|                 arg = SimpleArg(NEW_IDENTIFIER(ch), annotation, c->c_arena); | ||||
|                 if (!arg) { | ||||
|                     ast_error(ch, "expecting name"); | ||||
|                     goto error; | ||||
|                 } | ||||
|                 asdl_seq_SET(kwonlyargs, j++, name); | ||||
|                 asdl_seq_SET(kwonlyargs, j++, arg); | ||||
|                 i += 2; /* the name and the comma */ | ||||
|                 break; | ||||
|             case DOUBLESTAR: | ||||
|  | @ -666,29 +693,41 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start, | |||
| static arguments_ty | ||||
| ast_for_arguments(struct compiling *c, const node *n) | ||||
| { | ||||
|     /* parameters: '(' [varargslist] ')'
 | ||||
|        varargslist: (fpdef ['=' test] ',')*  | ||||
|              ('*' [NAME] (',' fpdef ['=' test])* [',' '**' NAME] | '**' NAME) | ||||
|              | fpdef ['=' test] (',' fpdef ['=' test])* [','] | ||||
|     /* This function handles both typedargslist (function definition)
 | ||||
|        and varargslist (lambda definition). | ||||
| 
 | ||||
|        parameters: '(' [typedargslist] ')' | ||||
|        typedargslist: ((tfpdef ['=' test] ',')* | ||||
|            ('*' [tname] (',' tname ['=' test])* [',' '**' tname] | ||||
|            | '**' tname) | ||||
|            | tfpdef ['=' test] (',' tfpdef ['=' test])* [',']) | ||||
|        varargslist: ((vfpdef ['=' test] ',')* | ||||
|            ('*' [vname] (',' vname ['=' test])*  [',' '**' vname] | ||||
|            | '**' vname) | ||||
|            | vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) | ||||
|     */ | ||||
|     int i, j, k, nposargs = 0, nkwonlyargs = 0; | ||||
|     int nposdefaults = 0, found_default = 0; | ||||
|     asdl_seq *posargs, *posdefaults, *kwonlyargs, *kwdefaults; | ||||
|     identifier vararg = NULL, kwarg = NULL; | ||||
|     arg_ty arg; | ||||
|     expr_ty varargannotation = NULL, kwargannotation = NULL; | ||||
|     node *ch; | ||||
| 
 | ||||
|     if (TYPE(n) == parameters) { | ||||
|         if (NCH(n) == 2) /* () as argument list */ | ||||
|             return arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena); | ||||
|             return arguments(NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||||
|                              NULL, c->c_arena); | ||||
|         n = CHILD(n, 1); | ||||
|     } | ||||
|     REQ(n, varargslist); | ||||
|     assert(TYPE(n) == typedargslist || TYPE(n) == varargslist); | ||||
| 
 | ||||
|     /* first count the number of positional args & defaults */ | ||||
|     for (i = 0; i < NCH(n); i++) { | ||||
|         ch = CHILD(n, i); | ||||
|         if (TYPE(ch) == STAR) { | ||||
|             if (TYPE(CHILD(n, i+1)) == NAME) { | ||||
|             if (TYPE(CHILD(n, i+1)) == tname | ||||
|                 || TYPE(CHILD(n, i+1)) == vname) { | ||||
|             /* skip NAME of vararg */ | ||||
|             /* so that following can count only keyword only args */ | ||||
|                 i += 2; | ||||
|  | @ -698,7 +737,7 @@ ast_for_arguments(struct compiling *c, const node *n) | |||
|             } | ||||
|             break;  | ||||
|         } | ||||
|         if (TYPE(ch) == fpdef) nposargs++; | ||||
|         if (TYPE(ch) == vfpdef || TYPE(ch) == tfpdef) nposargs++; | ||||
|         if (TYPE(ch) == EQUAL) nposdefaults++; | ||||
|     } | ||||
|     /* count the number of keyword only args & 
 | ||||
|  | @ -706,35 +745,39 @@ ast_for_arguments(struct compiling *c, const node *n) | |||
|     for ( ; i < NCH(n); ++i) { | ||||
|         ch = CHILD(n, i); | ||||
|         if (TYPE(ch) == DOUBLESTAR) break; | ||||
|         if (TYPE(ch) == NAME) nkwonlyargs++; | ||||
|         if (TYPE(ch) == tname || TYPE(ch) == vname) nkwonlyargs++; | ||||
|     } | ||||
| 
 | ||||
|     posargs = (nposargs ? asdl_seq_new(nposargs, c->c_arena) : NULL); | ||||
|     if (!posargs && nposargs) | ||||
|             return NULL; /* Don't need to goto error; no objects allocated */ | ||||
|         goto error; | ||||
|     kwonlyargs = (nkwonlyargs ? | ||||
|                    asdl_seq_new(nkwonlyargs, c->c_arena) : NULL); | ||||
|     if (!kwonlyargs && nkwonlyargs) | ||||
|             return NULL; /* Don't need to goto error; no objects allocated */ | ||||
|         goto error; | ||||
|     posdefaults = (nposdefaults ?  | ||||
|                     asdl_seq_new(nposdefaults, c->c_arena) : NULL); | ||||
|     if (!posdefaults && nposdefaults) | ||||
|             return NULL; /* Don't need to goto error; no objects allocated */ | ||||
|         goto error; | ||||
|     /* The length of kwonlyargs and kwdefaults are same 
 | ||||
|        since we set NULL as default for keyword only argument w/o default | ||||
|        - we have sequence data structure, but no dictionary */ | ||||
|     kwdefaults = (nkwonlyargs ?  | ||||
|     kwdefaults = (nkwonlyargs ? | ||||
|                    asdl_seq_new(nkwonlyargs, c->c_arena) : NULL); | ||||
|     if (!kwdefaults && nkwonlyargs) | ||||
|             return NULL; /* Don't need to goto error; no objects allocated */ | ||||
|         goto error; | ||||
| 
 | ||||
|     if (nposargs + nkwonlyargs > 255) { | ||||
| 		ast_error(n, "more than 255 arguments"); | ||||
| 		return NULL; | ||||
|         ast_error(n, "more than 255 arguments"); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     /* fpdef: NAME | '(' fplist ')'
 | ||||
|        fplist: fpdef (',' fpdef)* [','] | ||||
|     /* tname: NAME [':' test]
 | ||||
|        tfpdef: tname | '(' tfplist ')' | ||||
|        tfplist: tfpdef (',' tfpdef)* [','] | ||||
|        vname: NAME | ||||
|        vfpdef: NAME | '(' vfplist ')' | ||||
|        vfplist: vfpdef (',' vfpdef)* [','] | ||||
|     */ | ||||
|     i = 0; | ||||
|     j = 0;  /* index for defaults */ | ||||
|  | @ -742,8 +785,8 @@ ast_for_arguments(struct compiling *c, const node *n) | |||
|     while (i < NCH(n)) { | ||||
|         ch = CHILD(n, i); | ||||
|         switch (TYPE(ch)) { | ||||
|             case fpdef: | ||||
|             handle_fpdef: | ||||
|             case tfpdef: | ||||
|             case vfpdef: | ||||
|                 /* XXX Need to worry about checking if TYPE(CHILD(n, i+1)) is
 | ||||
|                    anything other than EQUAL or a comma? */ | ||||
|                 /* XXX Should NCH(n) check be made a separate check? */ | ||||
|  | @ -753,7 +796,6 @@ ast_for_arguments(struct compiling *c, const node *n) | |||
|                         goto error; | ||||
|                     assert(posdefaults != NULL); | ||||
|                     asdl_seq_SET(posdefaults, j++, expression); | ||||
| 
 | ||||
|                     i += 2; | ||||
|                     found_default = 1; | ||||
|                 } | ||||
|  | @ -762,59 +804,47 @@ ast_for_arguments(struct compiling *c, const node *n) | |||
|                              "non-default argument follows default argument"); | ||||
|                     goto error; | ||||
|                 } | ||||
|                 if (NCH(ch) == 3) { | ||||
|                     ch = CHILD(ch, 1); | ||||
|                     /* def foo((x)): is not complex, special case. */ | ||||
|                     if (NCH(ch) != 1) { | ||||
|                         /* We have complex arguments, setup for unpacking. */ | ||||
|                         asdl_seq_SET(posargs, k++, | ||||
|                                      compiler_complex_args(c, ch)); | ||||
|                     } else { | ||||
|                         /* def foo((x)): setup for checking NAME below. */ | ||||
|                         /* Loop because there can be many parens and tuple
 | ||||
|                            unpacking mixed in. */ | ||||
|                         ch = CHILD(ch, 0); | ||||
|                         assert(TYPE(ch) == fpdef); | ||||
|                         goto handle_fpdef; | ||||
|                     } | ||||
|                 } | ||||
|                 if (TYPE(CHILD(ch, 0)) == NAME) { | ||||
|                     expr_ty name; | ||||
|                     if (!strcmp(STR(CHILD(ch, 0)), "None")) { | ||||
|                             ast_error(CHILD(ch, 0), "assignment to None"); | ||||
|                             goto error; | ||||
|                     } | ||||
|                     name = Name(NEW_IDENTIFIER(CHILD(ch, 0)), | ||||
|                                 Param, LINENO(ch), ch->n_col_offset, | ||||
|                                 c->c_arena); | ||||
|                     if (!name) | ||||
|                         goto error; | ||||
|                     asdl_seq_SET(posargs, k++, name); | ||||
|                 /* def foo((x)): is not complex, special case. */ | ||||
|                 while (NCH(ch) == 3 && NCH(CHILD(ch, 1)) == 1) | ||||
|                     ch = CHILD(CHILD(ch, 1), 0); | ||||
| 
 | ||||
|                 if (NCH(ch) != 1) | ||||
|                     arg = compiler_complex_args(c, CHILD(ch, 1)); | ||||
|                 else | ||||
|                     arg = compiler_simple_arg(c, CHILD(ch, 0)); | ||||
|                 if (!arg) | ||||
|                     goto error; | ||||
|                 asdl_seq_SET(posargs, k++, arg); | ||||
| 
 | ||||
|                 } | ||||
|                 i += 2; /* the name and the comma */ | ||||
|                 break; | ||||
|             case STAR: | ||||
|                 if (i+1 >= NCH(n)) { | ||||
|                     ast_error(CHILD(n, i), "no name for vararg"); | ||||
| 		    goto error; | ||||
|                     goto error; | ||||
|                 } | ||||
|                 if (!strcmp(STR(CHILD(n, i+1)), "None")) { | ||||
|                         ast_error(CHILD(n, i+1), "assignment to None"); | ||||
|                         goto error; | ||||
|                 } | ||||
|                 if (TYPE(CHILD(n, i+1)) == COMMA) { | ||||
|                     int res = 0;     | ||||
|                 ch = CHILD(n, i+1);  /* tname or COMMA */ | ||||
|                 if (TYPE(ch) == COMMA) { | ||||
|                     int res = 0; | ||||
|                     i += 2; /* now follows keyword only arguments */ | ||||
|                     res = handle_keywordonly_args(c, n, i, | ||||
|                                                   kwonlyargs, kwdefaults); | ||||
|                     if (res == -1) goto error; | ||||
|                     i = res; /* res has new position to process */ | ||||
|                 } | ||||
|                 else if (!strcmp(STR(CHILD(ch, 0)), "None")) { | ||||
|                     ast_error(CHILD(ch, 0), "assignment to None"); | ||||
|                     goto error; | ||||
|                 } | ||||
|                 else { | ||||
|                     vararg = NEW_IDENTIFIER(CHILD(n, i+1)); | ||||
|                     vararg = NEW_IDENTIFIER(CHILD(ch, 0)); | ||||
|                     if (NCH(ch) > 1) { | ||||
|                             /* there is an annotation on the vararg */ | ||||
|                             varargannotation = ast_for_expr(c, CHILD(ch, 2)); | ||||
|                     } | ||||
|                     i += 3; | ||||
|                     if (i < NCH(n) && TYPE(CHILD(n, i)) == NAME) { | ||||
|                     if (i < NCH(n) && (TYPE(CHILD(n, i)) == tname | ||||
|                                     || TYPE(CHILD(n, i)) == vname)) { | ||||
|                         int res = 0; | ||||
|                         res = handle_keywordonly_args(c, n, i, | ||||
|                                                       kwonlyargs, kwdefaults); | ||||
|  | @ -824,11 +854,17 @@ ast_for_arguments(struct compiling *c, const node *n) | |||
|                 } | ||||
|                 break; | ||||
|             case DOUBLESTAR: | ||||
|                 if (!strcmp(STR(CHILD(n, i+1)), "None")) { | ||||
|                         ast_error(CHILD(n, i+1), "assignment to None"); | ||||
|                 ch = CHILD(n, i+1);  /* tname */ | ||||
|                 assert(TYPE(ch) == tname || TYPE(ch) == vname); | ||||
|                 if (!strcmp(STR(CHILD(ch, 0)), "None")) { | ||||
|                         ast_error(CHILD(ch, 0), "assignment to None"); | ||||
|                         goto error; | ||||
|                 } | ||||
|                 kwarg = NEW_IDENTIFIER(CHILD(n, i+1)); | ||||
|                 kwarg = NEW_IDENTIFIER(CHILD(ch, 0)); | ||||
|                 if (NCH(ch) > 1) { | ||||
|                     /* there is an annotation on the kwarg */ | ||||
|                     kwargannotation = ast_for_expr(c, CHILD(ch, 2)); | ||||
|                 } | ||||
|                 i += 3; | ||||
|                 break; | ||||
|             default: | ||||
|  | @ -838,8 +874,8 @@ ast_for_arguments(struct compiling *c, const node *n) | |||
|                 goto error; | ||||
|         } | ||||
|     } | ||||
|     return arguments(posargs, vararg, kwonlyargs, kwarg,  | ||||
|                      posdefaults, kwdefaults, c->c_arena); | ||||
|     return arguments(posargs, vararg, varargannotation, kwonlyargs, kwarg, | ||||
|                     kwargannotation, posdefaults, kwdefaults, c->c_arena); | ||||
|  error: | ||||
|     Py_XDECREF(vararg); | ||||
|     Py_XDECREF(kwarg); | ||||
|  | @ -938,11 +974,12 @@ ast_for_decorators(struct compiling *c, const node *n) | |||
| static stmt_ty | ||||
| ast_for_funcdef(struct compiling *c, const node *n) | ||||
| { | ||||
|     /* funcdef: 'def' [decorators] NAME parameters ':' suite */ | ||||
|     /* funcdef: 'def' [decorators] NAME parameters ['->' test] ':' suite */ | ||||
|     identifier name; | ||||
|     arguments_ty args; | ||||
|     asdl_seq *body; | ||||
|     asdl_seq *decorator_seq = NULL; | ||||
|     expr_ty returns = NULL; | ||||
|     int name_i; | ||||
| 
 | ||||
|     REQ(n, funcdef); | ||||
|  | @ -967,11 +1004,17 @@ ast_for_funcdef(struct compiling *c, const node *n) | |||
|     args = ast_for_arguments(c, CHILD(n, name_i + 1)); | ||||
|     if (!args) | ||||
|         return NULL; | ||||
|     if (TYPE(CHILD(n, name_i+2)) == RARROW) { | ||||
|         returns = ast_for_expr(c, CHILD(n, name_i + 3)); | ||||
|         if (!returns) | ||||
|                 return NULL; | ||||
|         name_i += 2; | ||||
|     } | ||||
|     body = ast_for_suite(c, CHILD(n, name_i + 3)); | ||||
|     if (!body) | ||||
|         return NULL; | ||||
| 
 | ||||
|     return FunctionDef(name, args, body, decorator_seq, LINENO(n), | ||||
|     return FunctionDef(name, args, body, decorator_seq, returns, LINENO(n), | ||||
|                        n->n_col_offset, c->c_arena); | ||||
| } | ||||
| 
 | ||||
|  | @ -983,7 +1026,8 @@ ast_for_lambdef(struct compiling *c, const node *n) | |||
|     expr_ty expression; | ||||
| 
 | ||||
|     if (NCH(n) == 3) { | ||||
|         args = arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena); | ||||
|         args = arguments(NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||||
|                          NULL, c->c_arena); | ||||
|         if (!args) | ||||
|             return NULL; | ||||
|         expression = ast_for_expr(c, CHILD(n, 2)); | ||||
|  | @ -1361,9 +1405,8 @@ ast_for_atom(struct compiling *c, const node *n) | |||
|         PyArena_AddPyObject(c->c_arena, pynum); | ||||
|         return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena); | ||||
|     } | ||||
|     case DOT: | ||||
|     	/* Ellipsis */ | ||||
| 	return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena); | ||||
|     case DOT: /* Ellipsis */ | ||||
|         return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena); | ||||
|     case LPAR: /* some parenthesized expressions */ | ||||
|         ch = CHILD(n, 1); | ||||
|          | ||||
|  | @ -1394,13 +1437,13 @@ 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)* [',']  */ | ||||
| 	int i, size; | ||||
| 	asdl_seq *keys, *values; | ||||
| 	 | ||||
| 	ch = CHILD(n, 1); | ||||
| 	if (NCH(ch) == 1 || (NCH(ch) > 0 && STR(CHILD(ch, 1))[0] == ',')) { | ||||
|         /* dictsetmaker: test ':' test (',' test ':' test)* [','] |
 | ||||
|          *               test (',' 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 */ | ||||
|             size = (NCH(ch) + 1) / 2; /* +1 in case no trailing comma */ | ||||
|             keys = asdl_seq_new(size, c->c_arena); | ||||
|  | @ -3046,10 +3089,10 @@ ast_for_stmt(struct compiling *c, const node *n) | |||
|         n = CHILD(n, 0); | ||||
|     } | ||||
|     if (TYPE(n) == small_stmt) { | ||||
| 	REQ(n, small_stmt); | ||||
| 	n = CHILD(n, 0); | ||||
| 	/* small_stmt: expr_stmt | print_stmt  | del_stmt | pass_stmt
 | ||||
| 	             | flow_stmt | import_stmt | global_stmt | assert_stmt | ||||
|         REQ(n, small_stmt); | ||||
|         n = CHILD(n, 0); | ||||
|         /* small_stmt: expr_stmt | print_stmt  | del_stmt | pass_stmt
 | ||||
|                      | flow_stmt | import_stmt | global_stmt | assert_stmt | ||||
|         */ | ||||
|         switch (TYPE(n)) { | ||||
|             case expr_stmt: | ||||
|  |  | |||
|  | @ -2293,10 +2293,37 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) | |||
| 		{ | ||||
| 		    int posdefaults = oparg & 0xff; | ||||
| 		    int kwdefaults = (oparg>>8) & 0xff; | ||||
| 		    int num_annotations = (oparg >> 16) & 0x7fff; | ||||
| 
 | ||||
| 			v = POP(); /* code object */ | ||||
| 			x = PyFunction_New(v, f->f_globals); | ||||
| 			Py_DECREF(v); | ||||
| 
 | ||||
| 			if (x != NULL && num_annotations > 0) { | ||||
| 				Py_ssize_t name_ix; | ||||
| 				u = POP(); /* names of args with annotations */ | ||||
| 				v = PyDict_New(); | ||||
| 				if (v == NULL) { | ||||
| 					Py_DECREF(x); | ||||
| 					x = NULL; | ||||
| 					break; | ||||
| 				} | ||||
| 				name_ix = PyTuple_Size(u); | ||||
| 				assert(num_annotations == name_ix+1); | ||||
| 				while (name_ix > 0) { | ||||
| 					--name_ix; | ||||
| 					t = PyTuple_GET_ITEM(u, name_ix); | ||||
| 					w = POP(); | ||||
| 					/* XXX(nnorwitz): check for errors */ | ||||
| 					PyDict_SetItem(v, t, w); | ||||
| 					Py_DECREF(w); | ||||
| 				} | ||||
| 
 | ||||
| 				err = PyFunction_SetAnnotations(x, v); | ||||
| 				Py_DECREF(v); | ||||
| 				Py_DECREF(u); | ||||
| 			} | ||||
| 
 | ||||
| 			/* XXX Maybe this should be a separate opcode? */ | ||||
| 			if (x != NULL && posdefaults > 0) { | ||||
| 				v = PyTuple_New(posdefaults); | ||||
|  | @ -2322,6 +2349,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) | |||
| 				while (--kwdefaults >= 0) { | ||||
| 					w = POP(); /* default value */ | ||||
| 					u = POP(); /* kw only arg name */ | ||||
| 					/* XXX(nnorwitz): check for errors */ | ||||
| 					PyDict_SetItem(v, u, w); | ||||
| 				} | ||||
| 				err = PyFunction_SetKwDefaults(x, v); | ||||
|  |  | |||
							
								
								
									
										141
									
								
								Python/compile.c
									
										
									
									
									
								
							
							
						
						
									
										141
									
								
								Python/compile.c
									
										
									
									
									
								
							|  | @ -832,7 +832,7 @@ opcode_stack_effect(int opcode, int oparg) | |||
| 
 | ||||
| 		case RAISE_VARARGS: | ||||
| 			return -oparg; | ||||
| #define NARGS(o) (((o) % 256) + 2*((o) / 256)) | ||||
| #define NARGS(o) (((o) % 256) + 2*(((o) / 256) % 256)) | ||||
| 		case CALL_FUNCTION: | ||||
| 			return -NARGS(oparg); | ||||
| 		case CALL_FUNCTION_VAR: | ||||
|  | @ -841,7 +841,7 @@ opcode_stack_effect(int opcode, int oparg) | |||
| 		case CALL_FUNCTION_VAR_KW: | ||||
| 			return -NARGS(oparg)-2; | ||||
| 		case MAKE_FUNCTION: | ||||
| 			return -NARGS(oparg); | ||||
| 			return -NARGS(oparg) - ((oparg >> 16) & 0xffff); | ||||
| #undef NARGS | ||||
| 		case BUILD_SLICE: | ||||
| 			if (oparg == 3) | ||||
|  | @ -1266,15 +1266,38 @@ compiler_decorators(struct compiler *c, asdl_seq* decos) | |||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| compiler_unpack_nested(struct compiler *c, asdl_seq *args) { | ||||
| 	int i, len; | ||||
| 	len = asdl_seq_LEN(args); | ||||
| 	ADDOP_I(c, UNPACK_SEQUENCE, len); | ||||
| 	for (i = 0; i < len; i++) { | ||||
| 		arg_ty elt = (arg_ty)asdl_seq_GET(args, i); | ||||
| 		switch (elt->kind) { | ||||
| 		case SimpleArg_kind: | ||||
| 			if (!compiler_nameop(c, elt->v.SimpleArg.arg, Store)) | ||||
| 				return 0; | ||||
| 			break; | ||||
| 		case NestedArgs_kind: | ||||
| 			if (!compiler_unpack_nested(c, elt->v.NestedArgs.args)) | ||||
| 				return 0; | ||||
| 			break; | ||||
| 		default: | ||||
| 			return 0; | ||||
| 		} | ||||
|     } | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| compiler_arguments(struct compiler *c, arguments_ty args) | ||||
| { | ||||
| 	int i; | ||||
| 	int n = asdl_seq_LEN(args->args); | ||||
| 	/* Correctly handle nested argument lists */ | ||||
| 
 | ||||
| 	for (i = 0; i < n; i++) { | ||||
| 		expr_ty arg = (expr_ty)asdl_seq_GET(args->args, i); | ||||
| 		if (arg->kind == Tuple_kind) { | ||||
| 		arg_ty arg = (arg_ty)asdl_seq_GET(args->args, i); | ||||
| 		if (arg->kind == NestedArgs_kind) { | ||||
| 			PyObject *id = PyString_FromFormat(".%d", i); | ||||
| 			if (id == NULL) { | ||||
| 				return 0; | ||||
|  | @ -1284,7 +1307,8 @@ compiler_arguments(struct compiler *c, arguments_ty args) | |||
| 				return 0; | ||||
| 			} | ||||
| 			Py_DECREF(id); | ||||
| 			VISIT(c, expr, arg); | ||||
| 			if (!compiler_unpack_nested(c, arg->v.NestedArgs.args)) | ||||
| 				return 0; | ||||
| 		} | ||||
| 	} | ||||
| 	return 1; | ||||
|  | @ -1296,10 +1320,10 @@ compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs, | |||
| { | ||||
| 	int i, default_count = 0; | ||||
| 	for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) { | ||||
| 		expr_ty arg = asdl_seq_GET(kwonlyargs, i); | ||||
| 		arg_ty arg = asdl_seq_GET(kwonlyargs, i); | ||||
| 		expr_ty default_ = asdl_seq_GET(kw_defaults, i); | ||||
| 		if (default_) { | ||||
| 			ADDOP_O(c, LOAD_CONST, arg->v.Name.id, consts); | ||||
| 			ADDOP_O(c, LOAD_CONST, arg->v.SimpleArg.arg, consts); | ||||
| 			if (!compiler_visit_expr(c, default_)) { | ||||
| 			    return -1; | ||||
| 			} | ||||
|  | @ -1309,15 +1333,113 @@ compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs, | |||
| 	return default_count; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| compiler_visit_argannotation(struct compiler *c, identifier id, | ||||
|     expr_ty annotation, PyObject *names) | ||||
| { | ||||
| 	if (annotation) { | ||||
| 		VISIT(c, expr, annotation); | ||||
| 		if (PyList_Append(names, id)) | ||||
| 			return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| compiler_visit_argannotations(struct compiler *c, asdl_seq* args, | ||||
|                               PyObject *names) | ||||
| { | ||||
| 	int i, error; | ||||
| 	for (i = 0; i < asdl_seq_LEN(args); i++) { | ||||
| 		arg_ty arg = (arg_ty)asdl_seq_GET(args, i); | ||||
| 		if (arg->kind == NestedArgs_kind) | ||||
| 			error = compiler_visit_argannotations( | ||||
| 			           c, | ||||
| 			           arg->v.NestedArgs.args, | ||||
| 			           names); | ||||
| 		else | ||||
| 			error = compiler_visit_argannotation( | ||||
| 			           c, | ||||
| 			           arg->v.SimpleArg.arg, | ||||
| 			           arg->v.SimpleArg.annotation, | ||||
| 			           names); | ||||
| 		if (error) | ||||
| 			return error; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| compiler_visit_annotations(struct compiler *c, arguments_ty args, | ||||
|                            expr_ty returns) | ||||
| { | ||||
| 	/* push arg annotations and a list of the argument names. return the #
 | ||||
| 	   of items pushed. this is out-of-order wrt the source code. */ | ||||
| 	static identifier return_str; | ||||
| 	PyObject *names; | ||||
| 	int len; | ||||
| 	names = PyList_New(0); | ||||
| 	if (!names) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	if (compiler_visit_argannotations(c, args->args, names)) | ||||
| 		goto error; | ||||
| 	if (args->varargannotation && | ||||
| 	    compiler_visit_argannotation(c, args->vararg, | ||||
| 	                                 args->varargannotation, names)) | ||||
| 		goto error; | ||||
| 	if (compiler_visit_argannotations(c, args->kwonlyargs, names)) | ||||
| 		goto error; | ||||
| 	if (args->kwargannotation && | ||||
| 	    compiler_visit_argannotation(c, args->kwarg, | ||||
| 	                                 args->kwargannotation, names)) | ||||
| 		goto error; | ||||
| 
 | ||||
| 	if (!return_str) { | ||||
| 		return_str = PyString_InternFromString("return"); | ||||
| 		if (!return_str) | ||||
| 			goto error; | ||||
| 	} | ||||
| 	if (compiler_visit_argannotation(c, return_str, returns, names)) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 
 | ||||
| 	len = PyList_GET_SIZE(names); | ||||
| 	if (len) { | ||||
| 		/* convert names to a tuple and place on stack */ | ||||
| 		PyObject *elt; | ||||
| 		int i; | ||||
| 		PyObject *s = PyTuple_New(len); | ||||
| 		if (!s) | ||||
| 			goto error; | ||||
| 		for (i = 0; i < len; i++) { | ||||
| 			elt = PyList_GET_ITEM(names, i); | ||||
| 			Py_INCREF(elt); | ||||
| 			PyTuple_SET_ITEM(s, i, elt); | ||||
| 		} | ||||
| 		ADDOP_O(c, LOAD_CONST, s, consts); | ||||
| 		Py_DECREF(s); | ||||
| 		len++; /* include the just-pushed tuple */ | ||||
| 	} | ||||
| 	Py_DECREF(names); | ||||
| 	return len; | ||||
| 
 | ||||
| error: | ||||
| 	Py_DECREF(names); | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| compiler_function(struct compiler *c, stmt_ty s) | ||||
| { | ||||
| 	PyCodeObject *co; | ||||
| 	PyObject *first_const = Py_None; | ||||
| 	arguments_ty args = s->v.FunctionDef.args; | ||||
| 	expr_ty returns = s->v.FunctionDef.returns; | ||||
| 	asdl_seq* decos = s->v.FunctionDef.decorators; | ||||
| 	stmt_ty st; | ||||
| 	int i, n, docstring, kw_default_count = 0, arglength; | ||||
| 	int num_annotations; | ||||
| 
 | ||||
| 	assert(s->kind == FunctionDef_kind); | ||||
| 
 | ||||
|  | @ -1332,6 +1454,7 @@ compiler_function(struct compiler *c, stmt_ty s) | |||
| 	} | ||||
| 	if (args->defaults) | ||||
| 		VISIT_SEQ(c, expr, args->defaults); | ||||
| 	num_annotations = compiler_visit_annotations(c, args, returns); | ||||
| 
 | ||||
| 	if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s, | ||||
| 				  s->lineno)) | ||||
|  | @ -1364,9 +1487,11 @@ compiler_function(struct compiler *c, stmt_ty s) | |||
| 
 | ||||
| 	arglength = asdl_seq_LEN(args->defaults); | ||||
| 	arglength |= kw_default_count << 8; | ||||
| 	arglength |= num_annotations << 16; | ||||
| 	compiler_make_closure(c, co, arglength); | ||||
| 	Py_DECREF(co); | ||||
| 
 | ||||
|         /* decorators */ | ||||
| 	for (i = 0; i < asdl_seq_LEN(decos); i++) { | ||||
| 		ADDOP_I(c, CALL_FUNCTION, 1); | ||||
| 	} | ||||
|  |  | |||
							
								
								
									
										2969
									
								
								Python/graminit.c
									
										
									
									
									
								
							
							
						
						
									
										2969
									
								
								Python/graminit.c
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -172,9 +172,12 @@ static int symtable_visit_alias(struct symtable *st, alias_ty); | |||
| static int symtable_visit_comprehension(struct symtable *st, comprehension_ty); | ||||
| static int symtable_visit_keyword(struct symtable *st, keyword_ty); | ||||
| static int symtable_visit_slice(struct symtable *st, slice_ty); | ||||
| static int symtable_visit_params(struct symtable *st, asdl_seq *args, int top); | ||||
| static int symtable_visit_params_nested(struct symtable *st, asdl_seq *args); | ||||
| static int symtable_visit_params(struct symtable *st, asdl_seq *args, int top, | ||||
|                                  int annotations); | ||||
| static int symtable_visit_params_nested(struct symtable *st, asdl_seq *args, | ||||
|                                         int annotations); | ||||
| static int symtable_implicit_arg(struct symtable *st, int pos); | ||||
| static int symtable_visit_annotations(struct symtable *st, stmt_ty s); | ||||
| 
 | ||||
| 
 | ||||
| static identifier top = NULL, lambda = NULL, genexpr = NULL; | ||||
|  | @ -935,6 +938,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) | |||
| 		if (s->v.FunctionDef.args->kw_defaults) | ||||
| 			VISIT_KWONLYDEFAULTS(st,  | ||||
| 					   s->v.FunctionDef.args->kw_defaults); | ||||
| 		if (!symtable_visit_annotations(st, s)) | ||||
| 			return 0; | ||||
| 		if (s->v.FunctionDef.decorators) | ||||
| 			VISIT_SEQ(st, expr, s->v.FunctionDef.decorators); | ||||
| 		if (!symtable_enter_block(st, s->v.FunctionDef.name,  | ||||
|  | @ -1219,22 +1224,29 @@ symtable_implicit_arg(struct symtable *st, int pos) | |||
| } | ||||
| 
 | ||||
| static int  | ||||
| symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel) | ||||
| symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel, | ||||
|                       int annotations) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (!args) | ||||
| 		return -1; | ||||
| 	 | ||||
|         /* go through all the toplevel arguments first */ | ||||
| 	for (i = 0; i < asdl_seq_LEN(args); i++) { | ||||
| 		expr_ty arg = (expr_ty)asdl_seq_GET(args, i); | ||||
| 		if (arg->kind == Name_kind) { | ||||
| 			assert(arg->v.Name.ctx == Param || | ||||
|                                (arg->v.Name.ctx == Store && !toplevel)); | ||||
| 			if (!symtable_add_def(st, arg->v.Name.id, DEF_PARAM)) | ||||
| 				return 0; | ||||
| 		arg_ty arg = (arg_ty)asdl_seq_GET(args, i); | ||||
| 		if (arg->kind == SimpleArg_kind) { | ||||
| 			if (!annotations) { | ||||
| 				if (!symtable_add_def(st, | ||||
| 				                      arg->v.SimpleArg.arg, | ||||
| 				                      DEF_PARAM)) | ||||
| 					return 0; | ||||
| 			} | ||||
| 			else if (arg->v.SimpleArg.annotation) | ||||
| 				VISIT(st, expr, arg->v.SimpleArg.annotation); | ||||
| 		} | ||||
| 		else if (arg->kind == Tuple_kind) { | ||||
| 			assert(arg->v.Tuple.ctx == Store); | ||||
| 			if (toplevel) { | ||||
| 		else if (arg->kind == NestedArgs_kind) { | ||||
| 			if (toplevel && !annotations) { | ||||
| 				if (!symtable_implicit_arg(st, i)) | ||||
| 					return 0; | ||||
| 			} | ||||
|  | @ -1249,7 +1261,7 @@ symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel) | |||
| 	} | ||||
| 
 | ||||
| 	if (!toplevel) { | ||||
| 		if (!symtable_visit_params_nested(st, args)) | ||||
| 		if (!symtable_visit_params_nested(st, args, annotations)) | ||||
| 			return 0; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1257,16 +1269,37 @@ symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel) | |||
| } | ||||
| 
 | ||||
| static int | ||||
| symtable_visit_params_nested(struct symtable *st, asdl_seq *args) | ||||
| symtable_visit_params_nested(struct symtable *st, asdl_seq *args, | ||||
|                              int annotations) | ||||
| { | ||||
| 	int i; | ||||
| 	for (i = 0; i < asdl_seq_LEN(args); i++) { | ||||
| 		expr_ty arg = (expr_ty)asdl_seq_GET(args, i); | ||||
| 		if (arg->kind == Tuple_kind && | ||||
| 		    !symtable_visit_params(st, arg->v.Tuple.elts, 0)) | ||||
| 		arg_ty arg = (arg_ty)asdl_seq_GET(args, i); | ||||
| 		if (arg->kind == NestedArgs_kind && | ||||
| 		    !symtable_visit_params(st, arg->v.NestedArgs.args, 0, | ||||
| 		                           annotations)) | ||||
| 			return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| symtable_visit_annotations(struct symtable *st, stmt_ty s) | ||||
| { | ||||
| 	arguments_ty a = s->v.FunctionDef.args; | ||||
| 	 | ||||
| 	if (a->args && !symtable_visit_params(st, a->args, 1, 1)) | ||||
| 		return 0; | ||||
| 	if (a->varargannotation) | ||||
| 		VISIT(st, expr, a->varargannotation); | ||||
| 	if (a->kwargannotation) | ||||
| 		VISIT(st, expr, a->kwargannotation); | ||||
| 	if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs, 1, 1)) | ||||
| 		return 0; | ||||
| 	if (s->v.FunctionDef.returns) | ||||
| 		VISIT(st, expr, s->v.FunctionDef.returns); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
|  | @ -1276,9 +1309,9 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a) | |||
| 	/* skip default arguments inside function block
 | ||||
| 	   XXX should ast be different? | ||||
| 	*/ | ||||
| 	if (a->args && !symtable_visit_params(st, a->args, 1)) | ||||
| 	if (a->args && !symtable_visit_params(st, a->args, 1, 0)) | ||||
| 		return 0; | ||||
| 	if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs, 1)) | ||||
| 	if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs, 1, 0)) | ||||
| 		return 0; | ||||
| 	if (a->vararg) { | ||||
| 		if (!symtable_add_def(st, a->vararg, DEF_PARAM)) | ||||
|  | @ -1290,7 +1323,7 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a) | |||
| 			return 0; | ||||
| 		st->st_cur->ste_varkeywords = 1; | ||||
| 	} | ||||
| 	if (a->args && !symtable_visit_params_nested(st, a->args)) | ||||
| 	if (a->args && !symtable_visit_params_nested(st, a->args, 0)) | ||||
| 		return 0; | ||||
| 	return 1; | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Neal Norwitz
						Neal Norwitz