PageRenderTime 26ms CodeModel.GetById 18ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/Python/future.c

http://unladen-swallow.googlecode.com/
C | 140 lines | 111 code | 17 blank | 12 comment | 51 complexity | 4ed7ea2db19ee5debe15db6951ba4c7c MD5 | raw file
  1#include "Python.h"
  2#include "Python-ast.h"
  3#include "node.h"
  4#include "token.h"
  5#include "graminit.h"
  6#include "code.h"
  7#include "compile.h"
  8#include "symtable.h"
  9
 10#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
 11
 12static int
 13future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
 14{
 15	int i;
 16	asdl_seq *names;
 17
 18	assert(s->kind == ImportFrom_kind);
 19
 20	names = s->v.ImportFrom.names;
 21	for (i = 0; i < asdl_seq_LEN(names); i++) {
 22                alias_ty name = (alias_ty)asdl_seq_GET(names, i);
 23		const char *feature = PyString_AsString(name->name);
 24		if (!feature)
 25			return 0;
 26		if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
 27			continue;
 28		} else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
 29			continue;
 30		} else if (strcmp(feature, FUTURE_DIVISION) == 0) {
 31			ff->ff_features |= CO_FUTURE_DIVISION;
 32		} else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
 33			ff->ff_features |= CO_FUTURE_ABSOLUTE_IMPORT;
 34		} else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
 35			ff->ff_features |= CO_FUTURE_WITH_STATEMENT;
 36		} else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
 37			ff->ff_features |= CO_FUTURE_PRINT_FUNCTION;
 38		} else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
 39			ff->ff_features |= CO_FUTURE_UNICODE_LITERALS;
 40		} else if (strcmp(feature, "braces") == 0) {
 41			PyErr_SetString(PyExc_SyntaxError,
 42					"not a chance");
 43			PyErr_SyntaxLocation(filename, s->lineno);
 44			return 0;
 45		} else {
 46			PyErr_Format(PyExc_SyntaxError,
 47				     UNDEFINED_FUTURE_FEATURE, feature);
 48			PyErr_SyntaxLocation(filename, s->lineno);
 49			return 0;
 50		}
 51	}
 52	return 1;
 53}
 54
 55static int
 56future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
 57{
 58	int i, found_docstring = 0, done = 0, prev_line = 0;
 59
 60	static PyObject *future;
 61	if (!future) {
 62		future = PyString_InternFromString("__future__");
 63		if (!future)
 64			return 0;
 65	}
 66
 67	if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
 68		return 1;
 69
 70	/* A subsequent pass will detect future imports that don't
 71	   appear at the beginning of the file.  There's one case,
 72	   however, that is easier to handle here: A series of imports
 73	   joined by semi-colons, where the first import is a future
 74	   statement but some subsequent import has the future form
 75	   but is preceded by a regular import.
 76	*/
 77	   
 78
 79	for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
 80		stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
 81
 82		if (done && s->lineno > prev_line)
 83			return 1;
 84		prev_line = s->lineno;
 85
 86		/* The tests below will return from this function unless it is
 87		   still possible to find a future statement.  The only things
 88		   that can precede a future statement are another future
 89		   statement and a doc string.
 90		*/
 91
 92		if (s->kind == ImportFrom_kind) {
 93			if (s->v.ImportFrom.module == future) {
 94				if (done) {
 95					PyErr_SetString(PyExc_SyntaxError,
 96							ERR_LATE_FUTURE);
 97					PyErr_SyntaxLocation(filename, 
 98							     s->lineno);
 99					return 0;
100				}
101				if (!future_check_features(ff, s, filename))
102					return 0;
103				ff->ff_lineno = s->lineno;
104			}
105			else
106				done = 1;
107		}
108		else if (s->kind == Expr_kind && !found_docstring) {
109			expr_ty e = s->v.Expr.value;
110			if (e->kind != Str_kind)
111				done = 1;
112			else
113				found_docstring = 1;
114		}
115		else
116			done = 1;
117	}
118	return 1;
119}
120
121
122PyFutureFeatures *
123PyFuture_FromAST(mod_ty mod, const char *filename)
124{
125	PyFutureFeatures *ff;
126
127	ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
128	if (ff == NULL) {
129		PyErr_NoMemory();
130		return NULL;
131	}
132	ff->ff_features = 0;
133	ff->ff_lineno = -1;
134
135	if (!future_parse(ff, mod, filename)) {
136		PyObject_Free(ff);
137		return NULL;
138	}
139	return ff;
140}