[Python-checkins] python/dist/src/Python future.c,2.12.2.2,2.12.2.3

jhylton@users.sourceforge.net jhylton@users.sourceforge.net
Fri, 16 Aug 2002 13:19:55 -0700


Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv13783

Modified Files:
      Tag: ast-branch
	future.c 
Log Message:
Rewrite future to use the AST.


Index: future.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/future.c,v
retrieving revision 2.12.2.2
retrieving revision 2.12.2.3
diff -C2 -d -r2.12.2.2 -r2.12.2.3
*** future.c	9 Jul 2002 13:22:01 -0000	2.12.2.2
--- future.c	16 Aug 2002 20:19:53 -0000	2.12.2.3
***************
*** 11,38 ****
  #define FUTURE_IMPORT_STAR "future statement does not support import *"
  
- /* FUTURE_POSSIBLE() is provided to accomodate doc strings, which is
-    the only statement that can occur before a future statement.
- */
- #define FUTURE_POSSIBLE(FF) ((FF)->ff_last_lineno == -1)
- 
  static int
! future_check_features(PyFutureFeatures *ff, node *n, char *filename)
  {
  	int i;
! 	char *feature;
! 	node *ch;
  
! 	REQ(n, import_stmt); /* must by from __future__ import ... */
  
! 	for (i = 3; i < NCH(n); i += 2) {
! 		ch = CHILD(n, i);
! 		if (TYPE(ch) == STAR) {
! 			PyErr_SetString(PyExc_SyntaxError,
! 					FUTURE_IMPORT_STAR);
! 			PyErr_SyntaxLocation(filename, ch->n_lineno);
! 			return -1;
! 		}
! 		REQ(ch, import_as_name);
! 		feature = STR(CHILD(ch, 0));
  		if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
  			continue;
--- 11,28 ----
  #define FUTURE_IMPORT_STAR "future statement does not support import *"
  
  static int
! future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
  {
  	int i;
! 	const char *feature;
! 	asdl_seq *names;
  
! 	assert(s->kind == ImportFrom_kind);
  
! 	names = s->v.ImportFrom.names;
! 	for (i = 0; i < asdl_seq_LEN(names); i++) {
! 		feature = PyString_AsString(asdl_seq_get(names, i));
! 		if (!feature)
! 			return 0;
  		if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
  			continue;
***************
*** 44,247 ****
  			PyErr_SetString(PyExc_SyntaxError,
  					"not a chance");
! 			PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
! 			return -1;
  		} else {
  			PyErr_Format(PyExc_SyntaxError,
  				     UNDEFINED_FUTURE_FEATURE, feature);
! 			PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
! 			return -1;
  		}
  	}
! 	return 0;
! }
! 
! static void
! future_error(node *n, char *filename)
! {
! 	PyErr_SetString(PyExc_SyntaxError,
! 			"from __future__ imports must occur at the "
! 			"beginning of the file");
! 	PyErr_SyntaxLocation(filename, n->n_lineno);
  }
  
! /* Relevant portions of the grammar:
! 
! single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
! file_input: (NEWLINE | stmt)* ENDMARKER
! stmt: simple_stmt | compound_stmt
! simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
! small_stmt: expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt 
!     | import_stmt | global_stmt | exec_stmt | assert_stmt
! import_stmt: 'import' dotted_as_name (',' dotted_as_name)* 
!     | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*)
! import_as_name: NAME [NAME NAME]
! dotted_as_name: dotted_name [NAME NAME]
! dotted_name: NAME ('.' NAME)*
! */
! 
! /* future_parse() finds future statements at the beginnning of a
!    module.  The function calls itself recursively, rather than
!    factoring out logic for different kinds of statements into
!    different routines.
! 
!    Return values:
!    -1 indicates an error occurred, e.g. unknown feature name
!    0 indicates no feature was found
!    1 indicates a feature was found
! */
! 
! static int
! future_parse(PyFutureFeatures *ff, node *n, char *filename)
  {
! 	int i, r;
!  loop:
  
! 	switch (TYPE(n)) {
  
! 	case single_input:
! 		if (TYPE(CHILD(n, 0)) == simple_stmt) {
! 			n = CHILD(n, 0);
! 			goto loop;
! 		}
! 		return 0;
  
! 	case file_input:
! 		/* Check each statement in the file, starting with the
! 		   first, and continuing until the first statement
! 		   that isn't a future statement.
  		*/
- 		for (i = 0; i < NCH(n); i++) {
- 			node *ch = CHILD(n, i);
- 			if (TYPE(ch) == stmt) {
- 				r = future_parse(ff, ch, filename);
- 				/* Need to check both conditions below
- 				   to accomodate doc strings, which
- 				   causes r < 0.
- 				*/
- 				if (r < 1 && !FUTURE_POSSIBLE(ff))
- 					return r;
- 			}
- 		}
- 		return 0;
  
! 	case simple_stmt:
! 		if (NCH(n) == 2) {
! 			REQ(CHILD(n, 0), small_stmt);
! 			n = CHILD(n, 0);
! 			goto loop;
! 		} else {
! 			/* Deal with the special case of a series of
! 			   small statements on a single line.  If a
! 			   future statement follows some other
! 			   statement, the SyntaxError is raised here.
! 			   In all other cases, the symtable pass
! 			   raises the exception.
! 			*/
! 			int found = 0, end_of_future = 0;
! 
! 			for (i = 0; i < NCH(n); i += 2) {
! 				if (TYPE(CHILD(n, i)) == small_stmt) {
! 					r = future_parse(ff, CHILD(n, i), 
! 							 filename);
! 					if (r < 1)
! 						end_of_future = 1;
! 					else {
! 						found = 1;
! 						if (end_of_future) {
! 							future_error(n, 
! 								     filename);
! 							return -1;
! 						}
! 					}
! 				}
  			}
- 
- 			/* If we found one and only one, then the
- 			   current lineno is legal. 
- 			*/
- 			if (found)
- 				ff->ff_last_lineno = n->n_lineno + 1;
  			else
- 				ff->ff_last_lineno = n->n_lineno;
- 
- 			if (end_of_future && found)
  				return 1;
- 			else 
- 				return 0;
- 		}
- 	
- 	case stmt:
- 		if (TYPE(CHILD(n, 0)) == simple_stmt) {
- 			n = CHILD(n, 0);
- 			goto loop;
- 		} else if (TYPE(CHILD(n, 0)) == expr_stmt) {
- 			n = CHILD(n, 0);
- 			goto loop;
- 		} else {
- 			REQ(CHILD(n, 0), compound_stmt);
- 			ff->ff_last_lineno = n->n_lineno;
- 			return 0;
  		}
! 
! 	case small_stmt:
! 		n = CHILD(n, 0);
! 		goto loop;
! 
! 	case import_stmt: {
! 		node *name;
! 
! 		if (STR(CHILD(n, 0))[0] != 'f') { /* from */
! 			ff->ff_last_lineno = n->n_lineno;
! 			return 0;
! 		}
! 		name = CHILD(n, 1);
! 		if (strcmp(STR(CHILD(name, 0)), "__future__") != 0)
! 			return 0;
! 		if (future_check_features(ff, n, filename) < 0)
! 			return -1;
! 		ff->ff_last_lineno = n->n_lineno + 1;
! 		return 1;
! 	}
! 
! 	/* The cases below -- all of them! -- are necessary to find
! 	   and skip doc strings. */
! 	case expr_stmt:
! 	case testlist:
! 	case test:
! 	case and_test:
! 	case not_test:
! 	case comparison:
! 	case expr:
! 	case xor_expr:
! 	case and_expr:
! 	case shift_expr:
! 	case arith_expr:
! 	case term:
! 	case factor:
! 	case power:
! 		if (NCH(n) == 1) {
! 			n = CHILD(n, 0);
! 			goto loop;
! 		}
! 		break;
! 
! 	case atom:
! 		if (TYPE(CHILD(n, 0)) == STRING 
! 		    && ff->ff_found_docstring == 0) {
! 			ff->ff_found_docstring = 1;
! 			return 0;
  		}
! 		ff->ff_last_lineno = n->n_lineno;
! 		return 0;
! 
! 	default:
! 		ff->ff_last_lineno = n->n_lineno;
! 		return 0;
  	}
! 	return 0;
  }
  
  PyFutureFeatures *
! PyNode_Future(node *n, char *filename)
  {
  	PyFutureFeatures *ff;
--- 34,94 ----
  			PyErr_SetString(PyExc_SyntaxError,
  					"not a chance");
! 			PyErr_SyntaxLocation(filename, s->lineno);
! 			return 0;
  		} else {
  			PyErr_Format(PyExc_SyntaxError,
  				     UNDEFINED_FUTURE_FEATURE, feature);
! 			PyErr_SyntaxLocation(filename, s->lineno);
! 			return 0;
  		}
  	}
! 	return 1;
  }
  
! int
! future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
  {
! 	int i;
  
! 	static PyObject *future;
! 	if (!future) {
! 		future = PyString_InternFromString("__future__");
! 		if (!future)
! 			return 0;
! 	}
  
! 	if (mod->kind != Module_kind) /* XXX */
! 		return 1;
! 	for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
! 		stmt_ty s = asdl_seq_get(mod->v.Module.body, i);
  
! 		/* The tests below will return from this function unless it is
! 		   still possible to find a future statement.  The only things
! 		   that can precede a future statement are another future
! 		   statement and a doc string.
  		*/
  
! 		if (s->kind == ImportFrom_kind) {
! 			if (s->v.ImportFrom.module == future) {
! 				if (!future_check_features(ff, s, filename))
! 					return 0;
  			}
  			else
  				return 1;
  		}
! 		else if (s->kind == Expr_kind) {
! 			expr_ty e = s->v.Expr.value;
! 			if (e->kind != Str_kind)
! 				return 1;
  		}
! 		else
! 			return 1;
  	}
! 	return 1;
  }
  
+ 
  PyFutureFeatures *
! PyFuture_FromAST(mod_ty mod, const char *filename)
  {
  	PyFutureFeatures *ff;
***************
*** 254,258 ****
  	ff->ff_features = 0;
  
! 	if (future_parse(ff, n, filename) < 0) {
  		PyMem_Free((void *)ff);
  		return NULL;
--- 101,105 ----
  	ff->ff_features = 0;
  
! 	if (!future_parse(ff, mod, filename)) {
  		PyMem_Free((void *)ff);
  		return NULL;