[Python-checkins] CVS: python/dist/src/Python future.c,NONE,2.1 compile.c,2.173,2.174 symtable.c,2.3,2.4

Jeremy Hylton jhylton@users.sourceforge.net
Tue, 27 Feb 2001 11:07:04 -0800


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

Modified Files:
	compile.c symtable.c 
Added Files:
	future.c 
Log Message:
Improved __future__ parser; still more to do

Makefile.pre.in: add target future.o

Include/compile.h: define PyFutureFeaters and PyNode_Future()
                   add c_future slot to struct compiling

Include/symtable.h: add st_future slot to struct symtable

Python/future.c: implementation of PyNode_Future()

Python/compile.c: use PyNode_Future() for nested_scopes support

Python/symtable.c: include compile.h to pick up PyFutureFeatures decl



--- NEW FILE: future.c ---
#include "Python.h"
#include "node.h"
#include "token.h"
#include "graminit.h"
#include "compile.h"
#include "symtable.h"

#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"

static int
future_check_features(PyFutureFeatures *ff, node *n)
{
	int i;
	char *feature;

	REQ(n, import_stmt); /* must by from __future__ import ... */

	for (i = 3; i < NCH(n); ++i) {
		feature = STR(CHILD(CHILD(n, i), 0));
		if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
			ff->ff_nested_scopes = 1;
		} else {
			PyErr_Format(PyExc_SyntaxError,
				     UNDEFINED_FUTURE_FEATURE, feature);
			return -1;
		}
	}
	return 0;
}

/* 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() 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)
{
	int i, r, found;
 loop:

/*	fprintf(stderr, "future_parse(%d, %d, %s)\n",
		TYPE(n), NCH(n), (n == NULL) ? "NULL" : STR(n));
*/
	switch (TYPE(n)) {

	case file_input:
		for (i = 0; i < NCH(n); i++) {
			node *ch = CHILD(n, i);
			if (TYPE(ch) == stmt) {
				n = ch;
				goto loop;
			}
		}
		return 0;

	case simple_stmt:
		if (NCH(n) == 1) {
			REQ(CHILD(n, 0), small_stmt);
			n = CHILD(n, 0);
			goto loop;
		}
		found = 0;
		for (i = 0; i < NCH(n); ++i)
			if (TYPE(CHILD(n, i)) == small_stmt) {
				r = future_parse(ff, CHILD(n, i));
				if (r < 1) {
					ff->ff_last_lineno = n->n_lineno;
					ff->ff_n_simple_stmt = i;
					return r;
				} else
					found++;
			}
		if (found)
			return 1;
		else
			return 0;
	
	case stmt:
		if (TYPE(CHILD(n, 0)) == simple_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) < 0)
			return -1;
		return 1;
	}

	default:
		ff->ff_last_lineno = n->n_lineno;
		return 0;
	}
}

PyFutureFeatures *
PyNode_Future(node *n, char *filename)
{
	PyFutureFeatures *ff;

	ff = (PyFutureFeatures *)PyMem_Malloc(sizeof(PyFutureFeatures));
	if (ff == NULL)
		return NULL;
	ff->ff_last_lineno = 0;
	ff->ff_n_simple_stmt = -1;
	ff->ff_nested_scopes = 0;

	if (future_parse(ff, n) < 0) {
		PyMem_Free((void *)ff);
		return NULL;
	}
	return ff;
}


Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.173
retrieving revision 2.174
diff -C2 -r2.173 -r2.174
*** compile.c	2001/02/27 05:15:57	2.173
--- compile.c	2001/02/27 19:07:02	2.174
***************
*** 56,62 ****
  "%.100s: exec or 'import *' makes names ambiguous in nested scope"
  
- #define UNDEFINED_FUTURE_FEATURE \
- "future feature %.100s is not defined"
- 
  #define GLOBAL_AFTER_ASSIGN \
  "name '%.400s' is assigned to before global declaration"
--- 56,59 ----
***************
*** 369,372 ****
--- 366,370 ----
  	int c_closure;		/* Is nested w/freevars? */
  	struct symtable *c_symtable; /* pointer to module symbol table */
+         PyFutureFeatures *c_future; /* pointer to module's __future__ */
  };
  
***************
*** 3865,3869 ****
  	} else {
  		sc.c_private = NULL;
! 		if (symtable_build(&sc, n) < 0) {
  			com_free(&sc);
  			return NULL;
--- 3863,3868 ----
  	} else {
  		sc.c_private = NULL;
! 		sc.c_future = PyNode_Future(n, filename);
! 		if (sc.c_future == NULL || symtable_build(&sc, n) < 0) {
  			com_free(&sc);
  			return NULL;
***************
*** 3997,4000 ****
--- 3996,4001 ----
  	if ((c->c_symtable = symtable_init()) == NULL)
  		return -1;
+ 	if (c->c_future->ff_nested_scopes)
+ 		c->c_symtable->st_nested_scopes = 1;
  	c->c_symtable->st_filename = c->c_filename;
  	symtable_enter_scope(c->c_symtable, TOP, TYPE(n), n->n_lineno);
***************
*** 4281,4322 ****
  }
  
- /* XXX this code is a placeholder for correct code.
-    from __future__ import name set language options */
- 
- static int
- symtable_check_future(struct symtable *st, node *n)
- {
- 	int i;
- 	node *name = CHILD(n, 1);
- 
- 	if (strcmp(STR(CHILD(name, 0)), "__future__") != 0)
- 		return 0;
- 	/* It is only legal to define __future__ features at the top
- 	   of a module.  If the current scope is not the module level
- 	   or if there are any symbols defined, it is too late. */
- 	if (st->st_cur->ste_symbols != st->st_global
- 	    || PyDict_Size(st->st_cur->ste_symbols) != 0) {
- 		PyErr_SetString(PyExc_SyntaxError, 
- 	"imports from __future__ are only legal at the beginning of a module");
- 		return -1;
- 	}
- 	for (i = 3; i < NCH(n); ++i) {
- 		char *feature = STR(CHILD(CHILD(n, i), 0));
- 		/* Do a linear search through the defined features,
- 		   assuming there aren't very many of them. */ 
- 		if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
- 			st->st_nested_scopes = 1;
- 		} else {
- 			PyErr_Format(PyExc_SyntaxError,
- 				     UNDEFINED_FUTURE_FEATURE, feature);
- 			set_error_location(st->st_filename,
- 					   st->st_cur->ste_lineno);
- 			st->st_errors++;
- 			return -1;
- 		}
- 	}
- 	return 1;
- }
- 
  /* When the compiler exits a scope, it must should update the scope's
     free variable information with the list of free variables in its
--- 4282,4285 ----
***************
*** 4911,4915 ****
  	*/
  	if (STR(CHILD(n, 0))[0] == 'f') {  /* from */
- 		symtable_check_future(st, n);
  		if (TYPE(CHILD(n, 3)) == STAR) {
  			st->st_cur->ste_optimized |= OPT_IMPORT_STAR;
--- 4874,4877 ----

Index: symtable.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/symtable.c,v
retrieving revision 2.3
retrieving revision 2.4
diff -C2 -r2.3 -r2.4
*** symtable.c	2001/02/27 04:23:34	2.3
--- symtable.c	2001/02/27 19:07:02	2.4
***************
*** 1,3 ****
--- 1,4 ----
  #include "Python.h"
+ #include "compile.h"
  #include "symtable.h"
  #include "graminit.h"