cinap_lenrekadd hg and python4bb9e2215 years agoHistory
1425 lines · 36.9 KB · C
RawDownload
			      "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 intupdate_symbols(PyObject *symbols, PyObject *scope,                PyObject *bound, PyObject *free, int classflag){	PyObject *name, *v, *u, *w, *free_value = NULL;	Py_ssize_t pos = 0; 	while (PyDict_Next(symbols, &pos, &name, &v)) {		long i, flags;		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 (!u)			return 0;		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  (classflag && 			     PyInt_AS_LONG(o) & (DEF_BOUND | DEF_GLOBAL)) {				long 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;				}				Py_DECREF(o);			}			/* 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 intanalyze_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, success = 0;	Py_ssize_t pos = 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)) {		long 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);		PySTEntryObject* entry;		assert(c && PySTEntry_Check(c));		entry = (PySTEntryObject*)c;		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 intsymtable_analyze(struct symtable *st){	PyObject *free, *global;	int r; 	free = PyDict_New();	if (!free)	    return 0;	global = PyDict_New();	if (!global) {	    Py_DECREF(free);	    return 0;	}	r = analyze_block(st->st_top, NULL, free, global);	Py_DECREF(free);	Py_DECREF(global);	return r;}  static intsymtable_warn(struct symtable *st, char *msg, int lineno){	if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, st->st_filename,			       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 intsymtable_exit_block(struct symtable *st, void *ast){	Py_ssize_t end; 	Py_CLEAR(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);		if (st->st_cur == NULL)			return 0;		Py_INCREF(st->st_cur);		if (PySequence_DelItem(st->st_stack, end) < 0)			return 0;	}	return 1;} static intsymtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, 		     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 (st->st_cur == NULL)		return 0;	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 longsymtable_lookup(struct symtable *st, PyObject *name){	PyObject *o;	PyObject *mangled = _Py_Mangle(st->st_private, name);	if (!mangled)		return 0;	o = PyDict_GetItem(st->st_cur->ste_symbols, mangled);	Py_DECREF(mangled);	if (!o)		return 0;	return PyInt_AsLong(o);} static intsymtable_add_def(struct symtable *st, PyObject *name, int flag) {	PyObject *o;	PyObject *dict;	long val;	PyObject *mangled = _Py_Mangle(st->st_private, name); 	if (!mangled)		return 0;	dict = st->st_cur->ste_symbols;	if ((o = PyDict_GetItem(dict, mangled))) {	    val = PyInt_AS_LONG(o);	    if ((flag & DEF_PARAM) && (val & DEF_PARAM)) {		    /* Is it better to use 'mangled' or 'name' here? */		    PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT,				 PyString_AsString(name));		    PyErr_SyntaxLocation(st->st_filename,				       st->st_cur->ste_lineno);		    goto error;	    }	    val |= flag;	} else	    val = flag;	o = PyInt_FromLong(val);        if (o == NULL)	    goto error;	if (PyDict_SetItem(dict, mangled, o) < 0) {		Py_DECREF(o);		goto error;	}	Py_DECREF(o); 	if (flag & DEF_PARAM) {		if (PyList_Append(st->st_cur->ste_varnames, mangled) < 0)			goto error;	} else	if (flag & DEF_GLOBAL) {		/* XXX need to update DEF_GLOBAL for other flags too;		   perhaps only DEF_FREE_GLOBAL */		val = flag;		if ((o = PyDict_GetItem(st->st_global, mangled))) {			val |= PyInt_AS_LONG(o);		}		o = PyInt_FromLong(val);		if (o == NULL)			goto error;		if (PyDict_SetItem(st->st_global, mangled, o) < 0) {			Py_DECREF(o);			goto error;		}		Py_DECREF(o);	}	Py_DECREF(mangled);	return 1; error:	Py_DECREF(mangled);	return 0;} /* 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;  #define VISIT_IN_BLOCK(ST, TYPE, V, S) \	if (!symtable_visit_ ## TYPE((ST), (V))) { \		symtable_exit_block((ST), (S)); \		return 0; \	} #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 = (TYPE ## _ty)asdl_seq_GET(seq, i); \		if (!symtable_visit_ ## TYPE((ST), elt)) \			return 0; \	} \} #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 = (TYPE ## _ty)asdl_seq_GET(seq, i); \		if (!symtable_visit_ ## TYPE((ST), elt)) { \			symtable_exit_block((ST), (S)); \			return 0; \		} \	} \} #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 = (TYPE ## _ty)asdl_seq_GET(seq, i); \		if (!symtable_visit_ ## TYPE((ST), elt)) \			return 0; \	} \} #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 = (TYPE ## _ty)asdl_seq_GET(seq, i); \		if (!symtable_visit_ ## TYPE((ST), elt)) { \			symtable_exit_block((ST), (S)); \			return 0; \		} \	} \} static intsymtable_new_tmpname(struct symtable *st){	char tmpname[256];	identifier tmp; 	PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]",		      ++st->st_cur->ste_tmpname);	tmp = PyString_InternFromString(tmpname);	if (!tmp)		return 0;	if (!symtable_add_def(st, tmp, DEF_LOCAL))		return 0;	Py_DECREF(tmp);	return 1;} static intsymtable_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;		VISIT_IN_BLOCK(st, arguments, s->v.FunctionDef.args, s);		VISIT_SEQ_IN_BLOCK(st, stmt, s->v.FunctionDef.body, s);		if (!symtable_exit_block(st, s))			return 0;		break;        case ClassDef_kind: {		PyObject *tmp;		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;		tmp = st->st_private;		st->st_private = s->v.ClassDef.name;		VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s);		st->st_private = tmp;		if (!symtable_exit_block(st, s))			return 0;		break;	}        case Return_kind:		if (s->v.Return.value) {			VISIT(st, expr, s->v.Return.value);			st->st_cur->ste_returns_value = 1;			if (st->st_cur->ste_generator) {				PyErr_SetString(PyExc_SyntaxError,					RETURN_VAL_IN_GENERATOR);			        PyErr_SyntaxLocation(st->st_filename,				             s->lineno);				return 0;			}		}		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)

Lines 501–1000 of 1425. Previous lines