| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | #include "Python-ast.h"
 | 
					
						
							|  |  |  | #include "code.h"
 | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | #include "symtable.h"
 | 
					
						
							|  |  |  | #include "structmember.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | /* two error strings used for warnings */ | 
					
						
							|  |  |  | #define GLOBAL_AFTER_ASSIGN \
 | 
					
						
							|  |  |  | "name '%.400s' is assigned to before global declaration" | 
					
						
							| 
									
										
										
										
											2001-12-10 00:53:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | #define GLOBAL_AFTER_USE \
 | 
					
						
							|  |  |  | "name '%.400s' is used prior to global declaration" | 
					
						
							| 
									
										
										
										
											2001-12-10 00:53:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | PySTEntryObject * | 
					
						
							| 
									
										
										
										
											2005-10-24 00:30:44 +00:00
										 |  |  | PySTEntry_New(struct symtable *st, identifier name, _Py_block_ty block, | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	      void *key, int lineno) | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	PySTEntryObject *ste = NULL; | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	PyObject *k; | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	k = PyLong_FromVoidPtr(key); | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	if (k == NULL) | 
					
						
							|  |  |  | 		goto fail; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	ste = (PySTEntryObject *)PyObject_New(PySTEntryObject, | 
					
						
							|  |  |  | 					      &PySTEntry_Type); | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	ste->ste_table = st; | 
					
						
							|  |  |  | 	ste->ste_id = k; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	ste->ste_tmpname = 0; | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	ste->ste_name = name; | 
					
						
							|  |  |  | 	Py_INCREF(name); | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ste->ste_symbols = NULL; | 
					
						
							|  |  |  | 	ste->ste_varnames = NULL; | 
					
						
							|  |  |  | 	ste->ste_children = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ste->ste_symbols = PyDict_New(); | 
					
						
							|  |  |  | 	if (ste->ste_symbols == NULL) | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	    goto fail; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	ste->ste_varnames = PyList_New(0); | 
					
						
							|  |  |  | 	if (ste->ste_varnames == NULL) | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	    goto fail; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	ste->ste_children = PyList_New(0); | 
					
						
							|  |  |  | 	if (ste->ste_children == NULL) | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	    goto fail; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	ste->ste_type = block; | 
					
						
							|  |  |  | 	ste->ste_unoptimized = 0; | 
					
						
							|  |  |  | 	ste->ste_nested = 0; | 
					
						
							|  |  |  | 	ste->ste_free = 0; | 
					
						
							|  |  |  | 	ste->ste_varargs = 0; | 
					
						
							|  |  |  | 	ste->ste_varkeywords = 0; | 
					
						
							| 
									
										
										
										
											2001-12-04 02:41:46 +00:00
										 |  |  | 	ste->ste_opt_lineno = 0; | 
					
						
							| 
									
										
										
										
											2003-05-21 17:34:50 +00:00
										 |  |  | 	ste->ste_tmpname = 0; | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	ste->ste_lineno = lineno; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	if (st->st_cur != NULL && | 
					
						
							|  |  |  | 	    (st->st_cur->ste_nested || | 
					
						
							|  |  |  | 	     st->st_cur->ste_type == FunctionBlock)) | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 		ste->ste_nested = 1; | 
					
						
							|  |  |  | 	ste->ste_child_free = 0; | 
					
						
							| 
									
										
										
										
											2001-06-18 22:08:13 +00:00
										 |  |  | 	ste->ste_generator = 0; | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0) | 
					
						
							|  |  |  | 	    goto fail; | 
					
						
							| 
									
										
										
										
											2001-02-23 17:55:27 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	return ste; | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  |  fail: | 
					
						
							|  |  |  | 	Py_XDECREF(ste); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | ste_repr(PySTEntryObject *ste) | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	char buf[256]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-28 21:36:28 +00:00
										 |  |  | 	PyOS_snprintf(buf, sizeof(buf), | 
					
						
							|  |  |  | 		      "<symtable entry %.100s(%ld), line %d>", | 
					
						
							|  |  |  | 		      PyString_AS_STRING(ste->ste_name), | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		      PyInt_AS_LONG(ste->ste_id), ste->ste_lineno); | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	return PyString_FromString(buf); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | ste_dealloc(PySTEntryObject *ste) | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	ste->ste_table = NULL; | 
					
						
							|  |  |  | 	Py_XDECREF(ste->ste_id); | 
					
						
							|  |  |  | 	Py_XDECREF(ste->ste_name); | 
					
						
							|  |  |  | 	Py_XDECREF(ste->ste_symbols); | 
					
						
							|  |  |  | 	Py_XDECREF(ste->ste_varnames); | 
					
						
							|  |  |  | 	Py_XDECREF(ste->ste_children); | 
					
						
							|  |  |  | 	PyObject_Del(ste); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | #define OFF(x) offsetof(PySTEntryObject, x)
 | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | static PyMemberDef ste_memberlist[] = { | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	{"id",       T_OBJECT, OFF(ste_id), READONLY}, | 
					
						
							|  |  |  | 	{"name",     T_OBJECT, OFF(ste_name), READONLY}, | 
					
						
							|  |  |  | 	{"symbols",  T_OBJECT, OFF(ste_symbols), READONLY}, | 
					
						
							|  |  |  | 	{"varnames", T_OBJECT, OFF(ste_varnames), READONLY}, | 
					
						
							|  |  |  | 	{"children", T_OBJECT, OFF(ste_children), READONLY}, | 
					
						
							|  |  |  | 	{"type",     T_INT,    OFF(ste_type), READONLY}, | 
					
						
							|  |  |  | 	{"lineno",   T_INT,    OFF(ste_lineno), READONLY}, | 
					
						
							|  |  |  | 	{NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | PyTypeObject PySTEntry_Type = { | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	PyObject_HEAD_INIT(&PyType_Type) | 
					
						
							|  |  |  | 	0, | 
					
						
							|  |  |  | 	"symtable entry", | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	sizeof(PySTEntryObject), | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	0, | 
					
						
							|  |  |  | 	(destructor)ste_dealloc,                /* tp_dealloc */ | 
					
						
							|  |  |  | 	0,                                      /* tp_print */ | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 	0,			               /* tp_getattr */ | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	0,					/* tp_setattr */ | 
					
						
							|  |  |  | 	0,			                /* tp_compare */ | 
					
						
							|  |  |  | 	(reprfunc)ste_repr,			/* tp_repr */ | 
					
						
							|  |  |  | 	0,					/* tp_as_number */ | 
					
						
							|  |  |  | 	0,			                /* tp_as_sequence */ | 
					
						
							|  |  |  | 	0,					/* tp_as_mapping */ | 
					
						
							|  |  |  | 	0,					/* tp_hash */ | 
					
						
							|  |  |  | 	0,					/* tp_call */ | 
					
						
							|  |  |  | 	0,					/* tp_str */ | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 	PyObject_GenericGetAttr,		/* tp_getattro */ | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | 	0,					/* tp_setattro */ | 
					
						
							|  |  |  | 	0,					/* tp_as_buffer */ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT,	                /* tp_flags */ | 
					
						
							|  |  |  |  	0,					/* tp_doc */ | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 	0,					/* tp_traverse */ | 
					
						
							|  |  |  | 	0,					/* tp_clear */ | 
					
						
							|  |  |  | 	0,					/* tp_richcompare */ | 
					
						
							|  |  |  | 	0,					/* tp_weaklistoffset */ | 
					
						
							|  |  |  | 	0,					/* tp_iter */ | 
					
						
							|  |  |  | 	0,					/* tp_iternext */ | 
					
						
							|  |  |  | 	0,					/* tp_methods */ | 
					
						
							|  |  |  | 	ste_memberlist,				/* tp_members */ | 
					
						
							|  |  |  | 	0,					/* tp_getset */ | 
					
						
							|  |  |  | 	0,					/* tp_base */ | 
					
						
							|  |  |  | 	0,					/* tp_dict */ | 
					
						
							|  |  |  | 	0,					/* tp_descr_get */ | 
					
						
							|  |  |  | 	0,					/* tp_descr_set */ | 
					
						
							|  |  |  | 	0,					/* tp_dictoffset */ | 
					
						
							|  |  |  | 	0,					/* tp_init */ | 
					
						
							|  |  |  | 	0,					/* tp_alloc */ | 
					
						
							|  |  |  | 	0,					/* tp_new */ | 
					
						
							| 
									
										
										
										
											2001-02-09 22:22:18 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int symtable_analyze(struct symtable *st); | 
					
						
							|  |  |  | static int symtable_warn(struct symtable *st, char *msg); | 
					
						
							|  |  |  | static int symtable_enter_block(struct symtable *st, identifier name,  | 
					
						
							| 
									
										
										
										
											2005-10-24 00:30:44 +00:00
										 |  |  | 				_Py_block_ty block, void *ast, int lineno); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | static int symtable_exit_block(struct symtable *st, void *ast); | 
					
						
							|  |  |  | static int symtable_visit_stmt(struct symtable *st, stmt_ty s); | 
					
						
							|  |  |  | static int symtable_visit_expr(struct symtable *st, expr_ty s); | 
					
						
							|  |  |  | static int symtable_visit_genexp(struct symtable *st, expr_ty s); | 
					
						
							|  |  |  | static int symtable_visit_arguments(struct symtable *st, arguments_ty); | 
					
						
							|  |  |  | static int symtable_visit_excepthandler(struct symtable *st, excepthandler_ty); | 
					
						
							|  |  |  | 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_implicit_arg(struct symtable *st, int pos); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-16 12:45:24 +00:00
										 |  |  | static identifier top = NULL, lambda = NULL, genexpr = NULL; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define GET_IDENTIFIER(VAR) \
 | 
					
						
							|  |  |  | 	((VAR) ? (VAR) : ((VAR) = PyString_InternFromString(# VAR))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define DUPLICATE_ARGUMENT \
 | 
					
						
							|  |  |  | "duplicate argument '%s' in function definition" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct symtable * | 
					
						
							|  |  |  | symtable_new(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct symtable *st; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	st = (struct symtable *)PyMem_Malloc(sizeof(struct symtable)); | 
					
						
							|  |  |  | 	if (st == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	st->st_filename = NULL; | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	st->st_symbols = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	if ((st->st_stack = PyList_New(0)) == NULL) | 
					
						
							|  |  |  | 		goto fail; | 
					
						
							|  |  |  | 	if ((st->st_symbols = PyDict_New()) == NULL) | 
					
						
							|  |  |  | 		goto fail;  | 
					
						
							|  |  |  | 	st->st_cur = NULL; | 
					
						
							|  |  |  | 	st->st_tmpname = 0; | 
					
						
							|  |  |  | 	st->st_private = NULL; | 
					
						
							|  |  |  | 	return st; | 
					
						
							|  |  |  |  fail: | 
					
						
							|  |  |  | 	PySymtable_Free(st); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct symtable * | 
					
						
							|  |  |  | PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct symtable *st = symtable_new(); | 
					
						
							|  |  |  | 	asdl_seq *seq; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (st == NULL) | 
					
						
							|  |  |  | 		return st; | 
					
						
							|  |  |  | 	st->st_filename = filename; | 
					
						
							|  |  |  | 	st->st_future = future; | 
					
						
							|  |  |  | 	symtable_enter_block(st, GET_IDENTIFIER(top), ModuleBlock,  | 
					
						
							|  |  |  | 			     (void *)mod, 0); | 
					
						
							|  |  |  | 	st->st_top = st->st_cur; | 
					
						
							|  |  |  | 	st->st_cur->ste_unoptimized = OPT_TOPLEVEL; | 
					
						
							|  |  |  | 	/* Any other top-level initialization? */ | 
					
						
							|  |  |  | 	switch (mod->kind) { | 
					
						
							|  |  |  | 	case Module_kind: | 
					
						
							|  |  |  | 		seq = mod->v.Module.body; | 
					
						
							|  |  |  | 		for (i = 0; i < asdl_seq_LEN(seq); i++) | 
					
						
							|  |  |  | 			if (!symtable_visit_stmt(st, asdl_seq_GET(seq, i))) | 
					
						
							|  |  |  | 				goto error; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Expression_kind: | 
					
						
							|  |  |  | 		if (!symtable_visit_expr(st, mod->v.Expression.body)) | 
					
						
							|  |  |  | 			goto error; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Interactive_kind: | 
					
						
							|  |  |  | 		seq = mod->v.Interactive.body; | 
					
						
							|  |  |  | 		for (i = 0; i < asdl_seq_LEN(seq); i++) | 
					
						
							|  |  |  | 			if (!symtable_visit_stmt(st, asdl_seq_GET(seq, i))) | 
					
						
							|  |  |  | 				goto error; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Suite_kind: | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"this compiler does not handle Suites"); | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 		goto error; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	if (!symtable_exit_block(st, (void *)mod)) { | 
					
						
							|  |  |  | 		PySymtable_Free(st); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	if (symtable_analyze(st)) | 
					
						
							|  |  |  | 		return st; | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	PySymtable_Free(st); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  |  error: | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	(void) symtable_exit_block(st, (void *)mod); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	PySymtable_Free(st); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | PySymtable_Free(struct symtable *st) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Py_XDECREF(st->st_symbols); | 
					
						
							|  |  |  | 	Py_XDECREF(st->st_stack); | 
					
						
							|  |  |  | 	PyMem_Free((void *)st); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PySTEntryObject * | 
					
						
							|  |  |  | PySymtable_Lookup(struct symtable *st, void *key) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *k, *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	k = PyLong_FromVoidPtr(key); | 
					
						
							|  |  |  | 	if (k == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	v = PyDict_GetItem(st->st_symbols, k); | 
					
						
							|  |  |  | 	if (v) { | 
					
						
							|  |  |  | 		assert(PySTEntry_Check(v)); | 
					
						
							|  |  |  | 		Py_INCREF(v); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_KeyError, | 
					
						
							|  |  |  | 				"unknown symbol table entry"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Py_DECREF(k); | 
					
						
							|  |  |  | 	return (PySTEntryObject *)v; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int  | 
					
						
							|  |  |  | PyST_GetScope(PySTEntryObject *ste, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *v = PyDict_GetItem(ste->ste_symbols, name); | 
					
						
							|  |  |  | 	if (!v) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	assert(PyInt_Check(v)); | 
					
						
							|  |  |  | 	return (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Analyze raw symbol information to determine scope of each name.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The next several functions are helpers for PySymtable_Analyze(), | 
					
						
							|  |  |  |    which determines whether a name is local, global, or free.  In addition,  | 
					
						
							|  |  |  |    it determines which local variables are cell variables; they provide | 
					
						
							|  |  |  |    bindings that are used for free variables in enclosed blocks.   | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    There are also two kinds of free variables, implicit and explicit.  An  | 
					
						
							|  |  |  |    explicit global is declared with the global statement.  An implicit | 
					
						
							|  |  |  |    global is a free variable for which the compiler has found no binding | 
					
						
							|  |  |  |    in an enclosing function scope.  The implicit global is either a global | 
					
						
							|  |  |  |    or a builtin.  Python's module and class blocks use the xxx_NAME opcodes | 
					
						
							|  |  |  |    to handle these names to implement slightly odd semantics.  In such a | 
					
						
							|  |  |  |    block, the name is treated as global until it is assigned to; then it | 
					
						
							|  |  |  |    is treated as a local. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The symbol table requires two passes to determine the scope of each name. | 
					
						
							|  |  |  |    The first pass collects raw facts from the AST: the name is a parameter  | 
					
						
							|  |  |  |    here, the name is used by not defined here, etc.  The second pass analyzes | 
					
						
							|  |  |  |    these facts during a pass over the PySTEntryObjects created during pass 1. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    When a function is entered during the second pass, the parent passes | 
					
						
							|  |  |  |    the set of all name bindings visible to its children.  These bindings  | 
					
						
							|  |  |  |    are used to determine if the variable is free or an implicit global. | 
					
						
							|  |  |  |    After doing the local analysis, it analyzes each of its child blocks | 
					
						
							|  |  |  |    using an updated set of name bindings.   | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The children update the free variable set.  If a local variable is free  | 
					
						
							|  |  |  |    in a child, the variable is marked as a cell.  The current function must  | 
					
						
							|  |  |  |    provide runtime storage for the variable that may outlive the function's  | 
					
						
							|  |  |  |    frame.  Cell variables are removed from the free set before the analyze | 
					
						
							|  |  |  |    function returns to its parent. | 
					
						
							|  |  |  |     | 
					
						
							|  |  |  |    The sets of bound and free variables are implemented as dictionaries | 
					
						
							|  |  |  |    mapping strings to None. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SET_SCOPE(DICT, NAME, I) { \
 | 
					
						
							|  |  |  | 	PyObject *o = PyInt_FromLong(I); \ | 
					
						
							|  |  |  | 	if (!o) \ | 
					
						
							|  |  |  | 		return 0; \ | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	if (PyDict_SetItem((DICT), (NAME), o) < 0) { \ | 
					
						
							|  |  |  | 		Py_DECREF(o); \ | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		return 0; \ | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	} \ | 
					
						
							|  |  |  | 	Py_DECREF(o); \ | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Decide on scope of name, given flags.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The dicts passed in as arguments are modified as necessary. | 
					
						
							|  |  |  |    ste is passed so that flags can be updated. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int  | 
					
						
							|  |  |  | analyze_name(PySTEntryObject *ste, PyObject *dict, PyObject *name, int flags, | 
					
						
							|  |  |  | 	     PyObject *bound, PyObject *local, PyObject *free,  | 
					
						
							|  |  |  | 	     PyObject *global) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (flags & DEF_GLOBAL) { | 
					
						
							|  |  |  | 		if (flags & DEF_PARAM) { | 
					
						
							|  |  |  | 			PyErr_Format(PyExc_SyntaxError, | 
					
						
							|  |  |  | 				     "name '%s' is local and global", | 
					
						
							|  |  |  | 				     PyString_AS_STRING(name)); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		SET_SCOPE(dict, name, GLOBAL_EXPLICIT); | 
					
						
							|  |  |  | 		if (PyDict_SetItem(global, name, Py_None) < 0) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		if (bound && PyDict_GetItem(bound, name)) { | 
					
						
							|  |  |  | 			if (PyDict_DelItem(bound, name) < 0) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (flags & DEF_BOUND) { | 
					
						
							|  |  |  | 		SET_SCOPE(dict, name, LOCAL); | 
					
						
							|  |  |  | 		if (PyDict_SetItem(local, name, Py_None) < 0) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		if (PyDict_GetItem(global, name)) { | 
					
						
							|  |  |  | 			if (PyDict_DelItem(global, name) < 0) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* If an enclosing block has a binding for this name, it
 | 
					
						
							|  |  |  | 	   is a free variable rather than a global variable. | 
					
						
							|  |  |  | 	   Note that having a non-NULL bound implies that the block | 
					
						
							|  |  |  | 	   is nested. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	if (bound && PyDict_GetItem(bound, name)) { | 
					
						
							|  |  |  | 		SET_SCOPE(dict, name, FREE); | 
					
						
							|  |  |  | 		ste->ste_free = 1; | 
					
						
							|  |  |  | 		if (PyDict_SetItem(free, name, Py_None) < 0) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* If a parent has a global statement, then call it global
 | 
					
						
							|  |  |  | 	   explicit?  It could also be global implicit. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	else if (global && PyDict_GetItem(global, name)) { | 
					
						
							|  |  |  | 		SET_SCOPE(dict, name, GLOBAL_EXPLICIT); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		if (ste->ste_nested) | 
					
						
							|  |  |  | 			ste->ste_free = 1; | 
					
						
							|  |  |  | 		SET_SCOPE(dict, name, GLOBAL_IMPLICIT); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; /* Can't get here */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef SET_SCOPE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* If a name is defined in free and also in locals, then this block
 | 
					
						
							|  |  |  |    provides the binding for the free variable.  The name should be | 
					
						
							|  |  |  |    marked CELL in this block and removed from the free list. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Note that the current block's free variables are included in free. | 
					
						
							|  |  |  |    That's safe because no name can be free and local in the same scope. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | analyze_cells(PyObject *scope, PyObject *free) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |         PyObject *name, *v, *w; | 
					
						
							|  |  |  | 	int flags, pos = 0, success = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	w = PyInt_FromLong(CELL); | 
					
						
							|  |  |  | 	if (!w) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	while (PyDict_Next(scope, &pos, &name, &v)) { | 
					
						
							|  |  |  | 		assert(PyInt_Check(v)); | 
					
						
							|  |  |  | 		flags = PyInt_AS_LONG(v); | 
					
						
							|  |  |  | 		if (flags != LOCAL) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		if (!PyDict_GetItem(free, name)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		/* Replace LOCAL with CELL for this name, and remove
 | 
					
						
							|  |  |  | 		   from free. It is safe to replace the value of name  | 
					
						
							|  |  |  | 		   in the dict, because it will not cause a resize. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		if (PyDict_SetItem(scope, name, w) < 0) | 
					
						
							|  |  |  | 			goto error; | 
					
						
							|  |  |  | 		if (!PyDict_DelItem(free, name) < 0) | 
					
						
							|  |  |  | 			goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	success = 1; | 
					
						
							|  |  |  |  error: | 
					
						
							|  |  |  | 	Py_DECREF(w); | 
					
						
							|  |  |  | 	return success; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Check for illegal statements in unoptimized namespaces */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | check_unoptimized(const PySTEntryObject* ste) { | 
					
						
							|  |  |  | 	char buf[300]; | 
					
						
							| 
									
										
										
										
											2005-10-21 12:57:31 +00:00
										 |  |  | 	const char* trailer; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-23 18:50:36 +00:00
										 |  |  | 	if (ste->ste_type != FunctionBlock || !ste->ste_unoptimized | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	    || !(ste->ste_free || ste->ste_child_free)) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-21 12:57:31 +00:00
										 |  |  | 	trailer = (ste->ste_child_free ?  | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		       "contains a nested function with free variables" : | 
					
						
							|  |  |  | 			       "is a nested function"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (ste->ste_unoptimized) { | 
					
						
							|  |  |  | 	case OPT_TOPLEVEL: /* exec / import * at top-level is fine */ | 
					
						
							|  |  |  | 	case OPT_EXEC: /* qualified exec is fine */ | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	case OPT_IMPORT_STAR: | 
					
						
							|  |  |  | 		PyOS_snprintf(buf, sizeof(buf),  | 
					
						
							|  |  |  | 			      "import * is not allowed in function '%.100s' " | 
					
						
							|  |  |  | 			      "because it is %s", | 
					
						
							|  |  |  | 			      PyString_AS_STRING(ste->ste_name), trailer); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case OPT_BARE_EXEC: | 
					
						
							|  |  |  | 		PyOS_snprintf(buf, sizeof(buf), | 
					
						
							|  |  |  | 			      "unqualified exec is not allowed in function " | 
					
						
							|  |  |  | 			      "'%.100s' it %s", | 
					
						
							|  |  |  | 			      PyString_AS_STRING(ste->ste_name), trailer); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		PyOS_snprintf(buf, sizeof(buf),  | 
					
						
							|  |  |  | 			      "function '%.100s' uses import * and bare exec, " | 
					
						
							|  |  |  | 			      "which are illegal because it %s", | 
					
						
							|  |  |  | 			      PyString_AS_STRING(ste->ste_name), trailer); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyErr_SetString(PyExc_SyntaxError, buf); | 
					
						
							|  |  |  | 	PyErr_SyntaxLocation(ste->ste_table->st_filename,  | 
					
						
							|  |  |  | 			     ste->ste_opt_lineno); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Enter the final scope information into the st_symbols dict. 
 | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * All arguments are dicts.  Modifies symbols, others are read-only. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | update_symbols(PyObject *symbols, PyObject *scope,  | 
					
						
							|  |  |  |                PyObject *bound, PyObject *free, int class) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *name, *v, *u, *w, *free_value = NULL; | 
					
						
							|  |  |  | 	int i, flags, pos = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (PyDict_Next(symbols, &pos, &name, &v)) { | 
					
						
							|  |  |  | 		assert(PyInt_Check(v)); | 
					
						
							|  |  |  | 		flags = PyInt_AS_LONG(v); | 
					
						
							|  |  |  | 		w = PyDict_GetItem(scope, name); | 
					
						
							|  |  |  | 		assert(w && PyInt_Check(w)); | 
					
						
							|  |  |  | 		i = PyInt_AS_LONG(w); | 
					
						
							|  |  |  | 		flags |= (i << SCOPE_OFF); | 
					
						
							|  |  |  | 		u = PyInt_FromLong(flags); | 
					
						
							|  |  |  | 		if (PyDict_SetItem(symbols, name, u) < 0) { | 
					
						
							|  |  |  | 			Py_DECREF(u); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF(u); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         free_value = PyInt_FromLong(FREE << SCOPE_OFF); | 
					
						
							|  |  |  |         if (!free_value) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* add a free variable when it's only use is for creating a closure */ | 
					
						
							|  |  |  |         pos = 0; | 
					
						
							|  |  |  | 	while (PyDict_Next(free, &pos, &name, &v)) { | 
					
						
							|  |  |  | 		PyObject *o = PyDict_GetItem(symbols, name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (o) { | 
					
						
							|  |  |  | 			/* It could be a free variable in a method of
 | 
					
						
							|  |  |  | 			   the class that has the same name as a local | 
					
						
							|  |  |  | 			   or global in the class scope. | 
					
						
							|  |  |  | 			*/ | 
					
						
							|  |  |  | 			if  (class &&  | 
					
						
							|  |  |  | 			     PyInt_AS_LONG(o) & (DEF_BOUND | DEF_GLOBAL)) { | 
					
						
							|  |  |  | 				int i = PyInt_AS_LONG(o) | DEF_FREE_CLASS; | 
					
						
							|  |  |  | 				o = PyInt_FromLong(i); | 
					
						
							|  |  |  | 				if (!o) { | 
					
						
							|  |  |  | 					Py_DECREF(free_value); | 
					
						
							|  |  |  | 					return 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (PyDict_SetItem(symbols, name, o) < 0) { | 
					
						
							|  |  |  | 					Py_DECREF(o); | 
					
						
							|  |  |  | 					Py_DECREF(free_value); | 
					
						
							|  |  |  | 					return 0; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 				Py_DECREF(o); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			/* else it's not free, probably a cell */ | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!PyDict_GetItem(bound, name)) | 
					
						
							|  |  |  | 			continue;       /* it's a global */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (PyDict_SetItem(symbols, name, free_value) < 0) { | 
					
						
							|  |  |  | 			Py_DECREF(free_value); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_DECREF(free_value); | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | }    | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Make final symbol table decisions for block of ste.
 | 
					
						
							|  |  |  |    Arguments: | 
					
						
							|  |  |  |    ste -- current symtable entry (input/output) | 
					
						
							|  |  |  |    bound -- set of variables bound in enclosing scopes (input) | 
					
						
							|  |  |  |    free -- set of free variables in enclosed scopes (output) | 
					
						
							|  |  |  |    globals -- set of declared global variables in enclosing scopes (input) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,  | 
					
						
							|  |  |  | 	      PyObject *global) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *name, *v, *local = NULL, *scope = NULL, *newbound = NULL; | 
					
						
							|  |  |  | 	PyObject *newglobal = NULL, *newfree = NULL; | 
					
						
							|  |  |  | 	int i, flags, pos = 0, success = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	local = PyDict_New(); | 
					
						
							|  |  |  | 	if (!local) | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	scope = PyDict_New(); | 
					
						
							|  |  |  | 	if (!scope) | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	newglobal = PyDict_New(); | 
					
						
							|  |  |  | 	if (!newglobal) | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	newfree = PyDict_New(); | 
					
						
							|  |  |  | 	if (!newfree) | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	newbound = PyDict_New(); | 
					
						
							|  |  |  | 	if (!newbound) | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ste->ste_type == ClassBlock) { | 
					
						
							|  |  |  | 		/* make a copy of globals before calling analyze_name(),
 | 
					
						
							|  |  |  | 		   because global statements in the class have no effect | 
					
						
							|  |  |  | 		   on nested functions. | 
					
						
							|  |  |  | 		*/ | 
					
						
							|  |  |  | 		if (PyDict_Update(newglobal, global) < 0) | 
					
						
							|  |  |  | 			goto error; | 
					
						
							|  |  |  | 		if (bound) | 
					
						
							|  |  |  | 			if (PyDict_Update(newbound, bound) < 0) | 
					
						
							|  |  |  | 				goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(PySTEntry_Check(ste)); | 
					
						
							|  |  |  | 	assert(PyDict_Check(ste->ste_symbols)); | 
					
						
							|  |  |  | 	while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) { | 
					
						
							|  |  |  | 		flags = PyInt_AS_LONG(v); | 
					
						
							|  |  |  | 		if (!analyze_name(ste, scope, name, flags, bound, local, free, | 
					
						
							|  |  |  | 				  global)) | 
					
						
							|  |  |  | 			goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ste->ste_type != ClassBlock) { | 
					
						
							|  |  |  | 		if (ste->ste_type == FunctionBlock) { | 
					
						
							|  |  |  | 			if (PyDict_Update(newbound, local) < 0) | 
					
						
							|  |  |  | 				goto error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (bound) { | 
					
						
							|  |  |  | 			if (PyDict_Update(newbound, bound) < 0) | 
					
						
							|  |  |  | 				goto error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (PyDict_Update(newglobal, global) < 0) | 
					
						
							|  |  |  | 			goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Recursively call analyze_block() on each child block */ | 
					
						
							|  |  |  | 	for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) { | 
					
						
							|  |  |  | 		PyObject *c = PyList_GET_ITEM(ste->ste_children, i); | 
					
						
							| 
									
										
										
										
											2005-10-21 12:57:31 +00:00
										 |  |  | 		PySTEntryObject* entry; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		assert(c && PySTEntry_Check(c)); | 
					
						
							| 
									
										
										
										
											2005-10-21 12:57:31 +00:00
										 |  |  | 		entry = (PySTEntryObject*)c; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		if (!analyze_block(entry, newbound, newfree, newglobal)) | 
					
						
							|  |  |  | 			goto error; | 
					
						
							|  |  |  | 		if (entry->ste_free || entry->ste_child_free) | 
					
						
							|  |  |  | 			ste->ste_child_free = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ste->ste_type == FunctionBlock && !analyze_cells(scope, newfree)) | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	if (!update_symbols(ste->ste_symbols, scope, bound, newfree, | 
					
						
							|  |  |  | 			    ste->ste_type == ClassBlock)) | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	if (!check_unoptimized(ste)) | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (PyDict_Update(free, newfree) < 0) | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	success = 1; | 
					
						
							|  |  |  |  error: | 
					
						
							|  |  |  | 	Py_XDECREF(local); | 
					
						
							|  |  |  | 	Py_XDECREF(scope); | 
					
						
							|  |  |  | 	Py_XDECREF(newbound); | 
					
						
							|  |  |  | 	Py_XDECREF(newglobal); | 
					
						
							|  |  |  | 	Py_XDECREF(newfree); | 
					
						
							|  |  |  | 	if (!success) | 
					
						
							|  |  |  | 		assert(PyErr_Occurred()); | 
					
						
							|  |  |  | 	return success; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | symtable_analyze(struct symtable *st) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *free, *global; | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	free = PyDict_New(); | 
					
						
							|  |  |  | 	if (!free) | 
					
						
							|  |  |  | 	    return 0; | 
					
						
							|  |  |  | 	global = PyDict_New(); | 
					
						
							|  |  |  | 	if (!global) { | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	    Py_DECREF(free); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	    return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	r = analyze_block(st->st_top, NULL, free, global); | 
					
						
							|  |  |  | 	Py_DECREF(free); | 
					
						
							|  |  |  | 	Py_DECREF(global); | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | symtable_warn(struct symtable *st, char *msg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, st->st_filename, | 
					
						
							|  |  |  | 			       st->st_cur->ste_lineno, NULL, NULL) < 0)	{ | 
					
						
							|  |  |  | 		if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) { | 
					
						
							|  |  |  | 			PyErr_SetString(PyExc_SyntaxError, msg); | 
					
						
							|  |  |  | 			PyErr_SyntaxLocation(st->st_filename,  | 
					
						
							|  |  |  | 					     st->st_cur->ste_lineno); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* symtable_enter_block() gets a reference via PySTEntry_New().
 | 
					
						
							|  |  |  |    This reference is released when the block is exited, via the DECREF | 
					
						
							|  |  |  |    in symtable_exit_block(). | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | symtable_exit_block(struct symtable *st, void *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_DECREF(st->st_cur); | 
					
						
							|  |  |  | 	end = PyList_GET_SIZE(st->st_stack) - 1; | 
					
						
							|  |  |  | 	if (end >= 0) { | 
					
						
							|  |  |  | 		st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack,  | 
					
						
							|  |  |  | 								end); | 
					
						
							|  |  |  | 		Py_INCREF(st->st_cur); | 
					
						
							|  |  |  | 		if (PySequence_DelItem(st->st_stack, end) < 0) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2005-10-24 00:30:44 +00:00
										 |  |  | symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,  | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		     void *ast, int lineno) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PySTEntryObject *prev = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (st->st_cur) { | 
					
						
							|  |  |  | 		prev = st->st_cur; | 
					
						
							|  |  |  | 		if (PyList_Append(st->st_stack, (PyObject *)st->st_cur) < 0) { | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF(st->st_cur); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	st->st_cur = PySTEntry_New(st, name, block, ast, lineno); | 
					
						
							|  |  |  | 	if (name == GET_IDENTIFIER(top)) | 
					
						
							|  |  |  | 		st->st_global = st->st_cur->ste_symbols; | 
					
						
							|  |  |  | 	if (prev) { | 
					
						
							|  |  |  | 		if (PyList_Append(prev->ste_children,  | 
					
						
							|  |  |  | 				  (PyObject *)st->st_cur) < 0) { | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | symtable_lookup(struct symtable *st, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *o; | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 	PyObject *mangled = _Py_Mangle(st->st_private, name); | 
					
						
							|  |  |  | 	if (!mangled) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	o = PyDict_GetItem(st->st_cur->ste_symbols, mangled); | 
					
						
							|  |  |  | 	Py_DECREF(mangled); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	if (!o) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	return PyInt_AsLong(o); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | symtable_add_def(struct symtable *st, PyObject *name, int flag)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *o; | 
					
						
							|  |  |  | 	PyObject *dict; | 
					
						
							|  |  |  | 	int val; | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 	PyObject *mangled = _Py_Mangle(st->st_private, name); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 	if (!mangled) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	dict = st->st_cur->ste_symbols; | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 	if ((o = PyDict_GetItem(dict, mangled))) { | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	    val = PyInt_AS_LONG(o); | 
					
						
							|  |  |  | 	    if ((flag & DEF_PARAM) && (val & DEF_PARAM)) { | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 		    /* Is it better to use 'mangled' or 'name' here? */ | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		    PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, | 
					
						
							|  |  |  | 				 PyString_AsString(name)); | 
					
						
							|  |  |  | 		    PyErr_SyntaxLocation(st->st_filename, | 
					
						
							|  |  |  | 				       st->st_cur->ste_lineno); | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 		    goto error; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	    } | 
					
						
							|  |  |  | 	    val |= flag; | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 	    val = flag; | 
					
						
							|  |  |  | 	o = PyInt_FromLong(val); | 
					
						
							|  |  |  |         if (o == NULL) | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 	    goto error; | 
					
						
							|  |  |  | 	if (PyDict_SetItem(dict, mangled, o) < 0) { | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		Py_DECREF(o); | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 		goto error; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	Py_DECREF(o); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (flag & DEF_PARAM) { | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 		if (PyList_Append(st->st_cur->ste_varnames, mangled) < 0) | 
					
						
							|  |  |  | 			goto error; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	} else	if (flag & DEF_GLOBAL) { | 
					
						
							|  |  |  | 		/* XXX need to update DEF_GLOBAL for other flags too;
 | 
					
						
							|  |  |  | 		   perhaps only DEF_FREE_GLOBAL */ | 
					
						
							|  |  |  | 		val = flag; | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 		if ((o = PyDict_GetItem(st->st_global, mangled))) { | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 			val |= PyInt_AS_LONG(o); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		o = PyInt_FromLong(val); | 
					
						
							|  |  |  | 		if (o == NULL) | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 			goto error; | 
					
						
							|  |  |  | 		if (PyDict_SetItem(st->st_global, mangled, o) < 0) { | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 			Py_DECREF(o); | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 			goto error; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF(o); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-19 23:58:29 +00:00
										 |  |  | 	Py_DECREF(mangled); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  | 	Py_DECREF(mangled); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument.
 | 
					
						
							|  |  |  |    They use the ASDL name to synthesize the name of the C type and the visit | 
					
						
							|  |  |  |    function.  | 
					
						
							|  |  |  |     | 
					
						
							|  |  |  |    VISIT_SEQ_TAIL permits the start of an ASDL sequence to be skipped, which is | 
					
						
							|  |  |  |    useful if the first node in the sequence requires special treatment. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define VISIT(ST, TYPE, V) \
 | 
					
						
							|  |  |  | 	if (!symtable_visit_ ## TYPE((ST), (V))) \ | 
					
						
							|  |  |  | 		return 0;  | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define VISIT_IN_BLOCK(ST, TYPE, V, S) \
 | 
					
						
							|  |  |  | 	if (!symtable_visit_ ## TYPE((ST), (V))) { \ | 
					
						
							|  |  |  | 		symtable_exit_block((ST), (S)); \ | 
					
						
							|  |  |  | 		return 0; \ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | #define VISIT_SEQ(ST, TYPE, SEQ) { \
 | 
					
						
							|  |  |  | 	int i; \ | 
					
						
							|  |  |  | 	asdl_seq *seq = (SEQ); /* avoid variable capture */ \ | 
					
						
							|  |  |  | 	for (i = 0; i < asdl_seq_LEN(seq); i++) { \ | 
					
						
							|  |  |  | 		TYPE ## _ty elt = asdl_seq_GET(seq, i); \ | 
					
						
							|  |  |  | 		if (!symtable_visit_ ## TYPE((ST), elt)) \ | 
					
						
							|  |  |  | 			return 0; \ | 
					
						
							|  |  |  | 	} \ | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define VISIT_SEQ_IN_BLOCK(ST, TYPE, SEQ, S) { \
 | 
					
						
							|  |  |  | 	int i; \ | 
					
						
							|  |  |  | 	asdl_seq *seq = (SEQ); /* avoid variable capture */ \ | 
					
						
							|  |  |  | 	for (i = 0; i < asdl_seq_LEN(seq); i++) { \ | 
					
						
							|  |  |  | 		TYPE ## _ty elt = asdl_seq_GET(seq, i); \ | 
					
						
							|  |  |  | 		if (!symtable_visit_ ## TYPE((ST), elt)) { \ | 
					
						
							|  |  |  | 			symtable_exit_block((ST), (S)); \ | 
					
						
							|  |  |  | 			return 0; \ | 
					
						
							|  |  |  | 		} \ | 
					
						
							|  |  |  | 	} \ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | #define VISIT_SEQ_TAIL(ST, TYPE, SEQ, START) { \
 | 
					
						
							|  |  |  | 	int i; \ | 
					
						
							|  |  |  | 	asdl_seq *seq = (SEQ); /* avoid variable capture */ \ | 
					
						
							|  |  |  | 	for (i = (START); i < asdl_seq_LEN(seq); i++) { \ | 
					
						
							|  |  |  | 		TYPE ## _ty elt = asdl_seq_GET(seq, i); \ | 
					
						
							|  |  |  | 		if (!symtable_visit_ ## TYPE((ST), elt)) \ | 
					
						
							|  |  |  | 			return 0; \ | 
					
						
							|  |  |  | 	} \ | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define VISIT_SEQ_TAIL_IN_BLOCK(ST, TYPE, SEQ, START, S) { \
 | 
					
						
							|  |  |  | 	int i; \ | 
					
						
							|  |  |  | 	asdl_seq *seq = (SEQ); /* avoid variable capture */ \ | 
					
						
							|  |  |  | 	for (i = (START); i < asdl_seq_LEN(seq); i++) { \ | 
					
						
							|  |  |  | 		TYPE ## _ty elt = asdl_seq_GET(seq, i); \ | 
					
						
							|  |  |  | 		if (!symtable_visit_ ## TYPE((ST), elt)) { \ | 
					
						
							|  |  |  | 			symtable_exit_block((ST), (S)); \ | 
					
						
							|  |  |  | 			return 0; \ | 
					
						
							|  |  |  | 		} \ | 
					
						
							|  |  |  | 	} \ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | symtable_visit_stmt(struct symtable *st, stmt_ty s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	switch (s->kind) { | 
					
						
							|  |  |  |         case FunctionDef_kind: | 
					
						
							|  |  |  | 		if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		if (s->v.FunctionDef.args->defaults) | 
					
						
							|  |  |  | 			VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); | 
					
						
							|  |  |  | 		if (s->v.FunctionDef.decorators) | 
					
						
							|  |  |  | 			VISIT_SEQ(st, expr, s->v.FunctionDef.decorators); | 
					
						
							|  |  |  | 		if (!symtable_enter_block(st, s->v.FunctionDef.name,  | 
					
						
							|  |  |  | 					  FunctionBlock, (void *)s, s->lineno)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 		VISIT_IN_BLOCK(st, arguments, s->v.FunctionDef.args, s); | 
					
						
							|  |  |  | 		VISIT_SEQ_IN_BLOCK(st, stmt, s->v.FunctionDef.body, s); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		if (!symtable_exit_block(st, s)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  |         case ClassDef_kind: { | 
					
						
							|  |  |  | 		PyObject *tmp; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		VISIT_SEQ(st, expr, s->v.ClassDef.bases); | 
					
						
							|  |  |  | 		if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,  | 
					
						
							|  |  |  | 					  (void *)s, s->lineno)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 		tmp = st->st_private; | 
					
						
							|  |  |  | 		st->st_private = s->v.ClassDef.name; | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 		VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s); | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 		st->st_private = tmp; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		if (!symtable_exit_block(st, s)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-10-23 18:37:42 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  |         case Return_kind: | 
					
						
							|  |  |  | 		if (s->v.Return.value) | 
					
						
							|  |  |  | 			VISIT(st, expr, s->v.Return.value); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Delete_kind: | 
					
						
							|  |  |  | 		VISIT_SEQ(st, expr, s->v.Delete.targets); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Assign_kind: | 
					
						
							|  |  |  | 		VISIT_SEQ(st, expr, s->v.Assign.targets); | 
					
						
							|  |  |  | 		VISIT(st, expr, s->v.Assign.value); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case AugAssign_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, s->v.AugAssign.target); | 
					
						
							|  |  |  | 		VISIT(st, expr, s->v.AugAssign.value); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Print_kind: | 
					
						
							|  |  |  | 		if (s->v.Print.dest) | 
					
						
							|  |  |  | 			VISIT(st, expr, s->v.Print.dest); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, expr, s->v.Print.values); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case For_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, s->v.For.target); | 
					
						
							|  |  |  | 		VISIT(st, expr, s->v.For.iter); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, stmt, s->v.For.body); | 
					
						
							|  |  |  | 		if (s->v.For.orelse) | 
					
						
							|  |  |  | 			VISIT_SEQ(st, stmt, s->v.For.orelse); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case While_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, s->v.While.test); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, stmt, s->v.While.body); | 
					
						
							|  |  |  | 		if (s->v.While.orelse) | 
					
						
							|  |  |  | 			VISIT_SEQ(st, stmt, s->v.While.orelse); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case If_kind: | 
					
						
							|  |  |  | 		/* XXX if 0: and lookup_yield() hacks */ | 
					
						
							|  |  |  | 		VISIT(st, expr, s->v.If.test); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, stmt, s->v.If.body); | 
					
						
							|  |  |  | 		if (s->v.If.orelse) | 
					
						
							|  |  |  | 			VISIT_SEQ(st, stmt, s->v.If.orelse); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Raise_kind: | 
					
						
							|  |  |  | 		if (s->v.Raise.type) { | 
					
						
							|  |  |  | 			VISIT(st, expr, s->v.Raise.type); | 
					
						
							|  |  |  | 			if (s->v.Raise.inst) { | 
					
						
							|  |  |  | 				VISIT(st, expr, s->v.Raise.inst); | 
					
						
							|  |  |  | 				if (s->v.Raise.tback) | 
					
						
							|  |  |  | 					VISIT(st, expr, s->v.Raise.tback); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case TryExcept_kind: | 
					
						
							|  |  |  | 		VISIT_SEQ(st, stmt, s->v.TryExcept.body); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, stmt, s->v.TryExcept.orelse); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, excepthandler, s->v.TryExcept.handlers); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case TryFinally_kind: | 
					
						
							|  |  |  | 		VISIT_SEQ(st, stmt, s->v.TryFinally.body); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, stmt, s->v.TryFinally.finalbody); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Assert_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, s->v.Assert.test); | 
					
						
							|  |  |  | 		if (s->v.Assert.msg) | 
					
						
							|  |  |  | 			VISIT(st, expr, s->v.Assert.msg); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Import_kind: | 
					
						
							|  |  |  | 		VISIT_SEQ(st, alias, s->v.Import.names); | 
					
						
							|  |  |  | 		/* XXX Don't have the lineno available inside
 | 
					
						
							|  |  |  | 		   visit_alias */ | 
					
						
							|  |  |  | 		if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno) | 
					
						
							|  |  |  | 			st->st_cur->ste_opt_lineno = s->lineno; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case ImportFrom_kind: | 
					
						
							|  |  |  | 		VISIT_SEQ(st, alias, s->v.ImportFrom.names); | 
					
						
							|  |  |  | 		/* XXX Don't have the lineno available inside
 | 
					
						
							|  |  |  | 		   visit_alias */ | 
					
						
							|  |  |  | 		if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno) | 
					
						
							|  |  |  | 			st->st_cur->ste_opt_lineno = s->lineno; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Exec_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, s->v.Exec.body); | 
					
						
							|  |  |  | 		if (!st->st_cur->ste_opt_lineno) | 
					
						
							|  |  |  | 			st->st_cur->ste_opt_lineno = s->lineno; | 
					
						
							|  |  |  | 		if (s->v.Exec.globals) { | 
					
						
							|  |  |  | 			st->st_cur->ste_unoptimized |= OPT_EXEC; | 
					
						
							|  |  |  | 			VISIT(st, expr, s->v.Exec.globals); | 
					
						
							|  |  |  | 			if (s->v.Exec.locals)  | 
					
						
							|  |  |  | 				VISIT(st, expr, s->v.Exec.locals); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			st->st_cur->ste_unoptimized |= OPT_BARE_EXEC; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Global_kind: { | 
					
						
							|  |  |  | 		int i; | 
					
						
							|  |  |  | 		asdl_seq *seq = s->v.Global.names; | 
					
						
							|  |  |  | 		for (i = 0; i < asdl_seq_LEN(seq); i++) { | 
					
						
							|  |  |  | 			identifier name = asdl_seq_GET(seq, i); | 
					
						
							|  |  |  | 			char *c_name = PyString_AS_STRING(name); | 
					
						
							|  |  |  | 			int cur = symtable_lookup(st, name); | 
					
						
							|  |  |  | 			if (cur < 0) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			if (cur & (DEF_LOCAL | USE)) { | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 				char buf[256]; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 				if (cur & DEF_LOCAL)  | 
					
						
							|  |  |  | 					PyOS_snprintf(buf, sizeof(buf), | 
					
						
							|  |  |  | 						      GLOBAL_AFTER_ASSIGN, | 
					
						
							|  |  |  | 						      c_name); | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					PyOS_snprintf(buf, sizeof(buf), | 
					
						
							|  |  |  | 						      GLOBAL_AFTER_USE, | 
					
						
							|  |  |  | 						      c_name); | 
					
						
							|  |  |  | 				if (!symtable_warn(st, buf)) | 
					
						
							|  |  |  |                                     return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (!symtable_add_def(st, name, DEF_GLOBAL)) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |         case Expr_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, s->v.Expr.value); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Pass_kind: | 
					
						
							|  |  |  |         case Break_kind: | 
					
						
							|  |  |  |         case Continue_kind: | 
					
						
							|  |  |  | 		/* nothing to do here */ | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int  | 
					
						
							|  |  |  | symtable_visit_expr(struct symtable *st, expr_ty e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	switch (e->kind) { | 
					
						
							|  |  |  |         case BoolOp_kind: | 
					
						
							|  |  |  | 		VISIT_SEQ(st, expr, e->v.BoolOp.values); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case BinOp_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, e->v.BinOp.left); | 
					
						
							|  |  |  | 		VISIT(st, expr, e->v.BinOp.right); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case UnaryOp_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, e->v.UnaryOp.operand); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Lambda_kind: { | 
					
						
							|  |  |  | 		if (!symtable_add_def(st, GET_IDENTIFIER(lambda), DEF_LOCAL)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		if (e->v.Lambda.args->defaults) | 
					
						
							|  |  |  | 			VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); | 
					
						
							|  |  |  | 		/* XXX how to get line numbers for expressions */ | 
					
						
							|  |  |  | 		if (!symtable_enter_block(st, GET_IDENTIFIER(lambda), | 
					
						
							|  |  |  |                                           FunctionBlock, (void *)e, 0)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 		VISIT_IN_BLOCK(st, arguments, e->v.Lambda.args, (void*)e); | 
					
						
							|  |  |  | 		VISIT_IN_BLOCK(st, expr, e->v.Lambda.body, (void*)e); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		if (!symtable_exit_block(st, (void *)e)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |         case Dict_kind: | 
					
						
							|  |  |  | 		VISIT_SEQ(st, expr, e->v.Dict.keys); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, expr, e->v.Dict.values); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case ListComp_kind: { | 
					
						
							|  |  |  | 		char tmpname[256]; | 
					
						
							|  |  |  | 		identifier tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", | 
					
						
							|  |  |  | 			      ++st->st_cur->ste_tmpname); | 
					
						
							| 
									
										
										
										
											2005-11-19 23:58:29 +00:00
										 |  |  | 		tmp = PyString_InternFromString(tmpname); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		if (!symtable_add_def(st, tmp, DEF_LOCAL)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2005-11-19 23:58:29 +00:00
										 |  |  | 		Py_DECREF(tmp); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		VISIT(st, expr, e->v.ListComp.elt); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, comprehension, e->v.ListComp.generators); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |         case GeneratorExp_kind: { | 
					
						
							|  |  |  | 		if (!symtable_visit_genexp(st, e)) { | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |         case Yield_kind: | 
					
						
							|  |  |  | 		if (e->v.Yield.value) | 
					
						
							|  |  |  | 			VISIT(st, expr, e->v.Yield.value); | 
					
						
							|  |  |  |                 st->st_cur->ste_generator = 1; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Compare_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, e->v.Compare.left); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, expr, e->v.Compare.comparators); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Call_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, e->v.Call.func); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, expr, e->v.Call.args); | 
					
						
							|  |  |  | 		VISIT_SEQ(st, keyword, e->v.Call.keywords); | 
					
						
							|  |  |  | 		if (e->v.Call.starargs) | 
					
						
							|  |  |  | 			VISIT(st, expr, e->v.Call.starargs); | 
					
						
							|  |  |  | 		if (e->v.Call.kwargs) | 
					
						
							|  |  |  | 			VISIT(st, expr, e->v.Call.kwargs); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Repr_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, e->v.Repr.value); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Num_kind: | 
					
						
							|  |  |  |         case Str_kind: | 
					
						
							|  |  |  | 		/* Nothing to do here. */ | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	/* The following exprs can be assignment targets. */ | 
					
						
							|  |  |  |         case Attribute_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, e->v.Attribute.value); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Subscript_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, e->v.Subscript.value); | 
					
						
							|  |  |  | 		VISIT(st, slice, e->v.Subscript.slice); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Name_kind: | 
					
						
							|  |  |  | 		if (!symtable_add_def(st, e->v.Name.id,  | 
					
						
							|  |  |  | 				      e->v.Name.ctx == Load ? USE : DEF_LOCAL)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	/* child nodes of List and Tuple will have expr_context set */ | 
					
						
							|  |  |  |         case List_kind: | 
					
						
							|  |  |  | 		VISIT_SEQ(st, expr, e->v.List.elts); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |         case Tuple_kind: | 
					
						
							|  |  |  | 		VISIT_SEQ(st, expr, e->v.Tuple.elts); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | symtable_implicit_arg(struct symtable *st, int pos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *id = PyString_FromFormat(".%d", pos); | 
					
						
							|  |  |  | 	if (id == NULL) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	if (!symtable_add_def(st, id, DEF_PARAM)) { | 
					
						
							|  |  |  | 		Py_DECREF(id); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Py_DECREF(id); | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int  | 
					
						
							|  |  |  | symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, complex = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  |         /* go through all the toplevel arguments first */ | 
					
						
							|  |  |  | 	for (i = 0; i < asdl_seq_LEN(args); i++) { | 
					
						
							|  |  |  | 		expr_ty arg = 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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (arg->kind == Tuple_kind) { | 
					
						
							|  |  |  | 			assert(arg->v.Tuple.ctx == Store); | 
					
						
							|  |  |  |                         complex = 1; | 
					
						
							|  |  |  | 			if (toplevel) { | 
					
						
							|  |  |  | 				if (!symtable_implicit_arg(st, i)) | 
					
						
							|  |  |  | 					return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2005-11-19 23:58:29 +00:00
										 |  |  | 		        PyErr_SetString(PyExc_SyntaxError, | 
					
						
							|  |  |  | 					"invalid expression in parameter list"); | 
					
						
							|  |  |  | 		        PyErr_SyntaxLocation(st->st_filename, | 
					
						
							|  |  |  | 				             st->st_cur->ste_lineno); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!toplevel) { | 
					
						
							|  |  |  | 		if (!symtable_visit_params_nested(st, args)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | symtable_visit_params_nested(struct symtable *st, asdl_seq *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	for (i = 0; i < asdl_seq_LEN(args); i++) { | 
					
						
							|  |  |  | 		expr_ty arg = asdl_seq_GET(args, i); | 
					
						
							|  |  |  | 		if (arg->kind == Tuple_kind && | 
					
						
							|  |  |  | 		    !symtable_visit_params(st, arg->v.Tuple.elts, 0)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int  | 
					
						
							|  |  |  | 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)) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	if (a->vararg) { | 
					
						
							|  |  |  | 		if (!symtable_add_def(st, a->vararg, DEF_PARAM)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		st->st_cur->ste_varargs = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (a->kwarg) { | 
					
						
							|  |  |  | 		if (!symtable_add_def(st, a->kwarg, DEF_PARAM)) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		st->st_cur->ste_varkeywords = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (a->args && !symtable_visit_params_nested(st, a->args)) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int  | 
					
						
							|  |  |  | symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (eh->type) | 
					
						
							|  |  |  | 		VISIT(st, expr, eh->type); | 
					
						
							|  |  |  | 	if (eh->name) | 
					
						
							|  |  |  | 		VISIT(st, expr, eh->name); | 
					
						
							|  |  |  | 	VISIT_SEQ(st, stmt, eh->body); | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int  | 
					
						
							|  |  |  | symtable_visit_alias(struct symtable *st, alias_ty a) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Compute store_name, the name actually bound by the import
 | 
					
						
							|  |  |  | 	   operation.  It is diferent than a->name when a->name is a | 
					
						
							|  |  |  | 	   dotted package name (e.g. spam.eggs)  | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	PyObject *store_name; | 
					
						
							|  |  |  | 	PyObject *name = (a->asname == NULL) ? a->name : a->asname; | 
					
						
							|  |  |  | 	const char *base = PyString_AS_STRING(name); | 
					
						
							|  |  |  | 	char *dot = strchr(base, '.'); | 
					
						
							|  |  |  | 	if (dot) | 
					
						
							|  |  |  | 		store_name = PyString_FromStringAndSize(base, dot - base); | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		store_name = name; | 
					
						
							|  |  |  | 		Py_INCREF(store_name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (strcmp(PyString_AS_STRING(name), "*")) { | 
					
						
							|  |  |  | 		int r = symtable_add_def(st, store_name, DEF_IMPORT);  | 
					
						
							|  |  |  | 		Py_DECREF(store_name); | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  |             if (st->st_cur->ste_type != ModuleBlock) { | 
					
						
							|  |  |  |                 if (!symtable_warn(st, | 
					
						
							| 
									
										
										
										
											2005-11-24 22:09:18 +00:00
										 |  |  |                                    "import * only allowed at module level")) { | 
					
						
							|  |  |  |                     Py_DECREF(store_name); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  |                     return 0; | 
					
						
							| 
									
										
										
										
											2005-11-24 22:09:18 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  |             } | 
					
						
							|  |  |  | 	    st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR; | 
					
						
							| 
									
										
										
										
											2005-11-19 23:58:29 +00:00
										 |  |  | 	    Py_DECREF(store_name); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	    return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int  | 
					
						
							|  |  |  | symtable_visit_comprehension(struct symtable *st, comprehension_ty lc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	VISIT(st, expr, lc->target); | 
					
						
							|  |  |  | 	VISIT(st, expr, lc->iter); | 
					
						
							|  |  |  | 	VISIT_SEQ(st, expr, lc->ifs); | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int  | 
					
						
							|  |  |  | symtable_visit_keyword(struct symtable *st, keyword_ty k) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	VISIT(st, expr, k->value); | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int  | 
					
						
							|  |  |  | symtable_visit_slice(struct symtable *st, slice_ty s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	switch (s->kind) { | 
					
						
							|  |  |  | 	case Slice_kind: | 
					
						
							|  |  |  | 		if (s->v.Slice.lower) | 
					
						
							|  |  |  | 			VISIT(st, expr, s->v.Slice.lower) | 
					
						
							|  |  |  | 		if (s->v.Slice.upper) | 
					
						
							|  |  |  | 			VISIT(st, expr, s->v.Slice.upper) | 
					
						
							|  |  |  | 		if (s->v.Slice.step) | 
					
						
							|  |  |  | 			VISIT(st, expr, s->v.Slice.step) | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case ExtSlice_kind: | 
					
						
							|  |  |  | 		VISIT_SEQ(st, slice, s->v.ExtSlice.dims) | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Index_kind: | 
					
						
							|  |  |  | 		VISIT(st, expr, s->v.Index.value) | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case Ellipsis_kind: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int  | 
					
						
							|  |  |  | symtable_visit_genexp(struct symtable *st, expr_ty e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	comprehension_ty outermost = ((comprehension_ty) | 
					
						
							|  |  |  | 			 (asdl_seq_GET(e->v.GeneratorExp.generators, 0))); | 
					
						
							|  |  |  | 	/* Outermost iterator is evaluated in current scope */ | 
					
						
							|  |  |  | 	VISIT(st, expr, outermost->iter); | 
					
						
							|  |  |  | 	/* Create generator scope for the rest */ | 
					
						
							| 
									
										
										
										
											2005-11-16 12:45:24 +00:00
										 |  |  | 	if (!symtable_enter_block(st, GET_IDENTIFIER(genexpr), | 
					
						
							|  |  |  | 				  FunctionBlock, (void *)e, 0)) { | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	st->st_cur->ste_generator = 1; | 
					
						
							|  |  |  | 	/* Outermost iter is received as an argument */ | 
					
						
							|  |  |  | 	if (!symtable_implicit_arg(st, 0)) { | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 		symtable_exit_block(st, (void *)e); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-11-13 18:50:34 +00:00
										 |  |  | 	VISIT_IN_BLOCK(st, expr, outermost->target, (void*)e); | 
					
						
							|  |  |  | 	VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e); | 
					
						
							|  |  |  | 	VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension, | 
					
						
							|  |  |  | 				e->v.GeneratorExp.generators, 1, (void*)e); | 
					
						
							|  |  |  | 	VISIT_IN_BLOCK(st, expr, e->v.GeneratorExp.elt, (void*)e); | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 	if (!symtable_exit_block(st, (void *)e)) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } |