Merge ast-branch to head

This change implements a new bytecode compiler, based on a
transformation of the parse tree to an abstract syntax defined in
Parser/Python.asdl.

The compiler implementation is not complete, but it is in stable
enough shape to run the entire test suite excepting two disabled
tests.
This commit is contained in:
Jeremy Hylton 2005-10-20 19:59:25 +00:00
parent 2cb94aba12
commit 3e0055f8c6
54 changed files with 13675 additions and 6810 deletions

2281
Python/Python-ast.c Normal file

File diff suppressed because it is too large Load diff

92
Python/asdl.c Normal file
View file

@ -0,0 +1,92 @@
#include "Python.h"
#include "asdl.h"
asdl_seq *
asdl_seq_new(int size)
{
asdl_seq *seq = NULL;
size_t n = sizeof(asdl_seq) +
(size ? (sizeof(void *) * (size - 1)) : 0);
seq = (asdl_seq *)PyObject_Malloc(n);
if (!seq) {
PyErr_SetString(PyExc_MemoryError, "no memory");
return NULL;
}
memset(seq, 0, n);
seq->size = size;
return seq;
}
void
asdl_seq_free(asdl_seq *seq)
{
PyObject_Free(seq);
}
#define CHECKSIZE(BUF, OFF, MIN) { \
int need = *(OFF) + MIN; \
if (need >= PyString_GET_SIZE(*(BUF))) { \
int newsize = PyString_GET_SIZE(*(BUF)) * 2; \
if (newsize < need) \
newsize = need; \
if (_PyString_Resize((BUF), newsize) < 0) \
return 0; \
} \
}
int
marshal_write_int(PyObject **buf, int *offset, int x)
{
char *s;
CHECKSIZE(buf, offset, 4)
s = PyString_AS_STRING(*buf) + (*offset);
s[0] = (x & 0xff);
s[1] = (x >> 8) & 0xff;
s[2] = (x >> 16) & 0xff;
s[3] = (x >> 24) & 0xff;
*offset += 4;
return 1;
}
int
marshal_write_bool(PyObject **buf, int *offset, bool b)
{
if (b)
marshal_write_int(buf, offset, 1);
else
marshal_write_int(buf, offset, 0);
return 1;
}
int
marshal_write_identifier(PyObject **buf, int *offset, identifier id)
{
int l = PyString_GET_SIZE(id);
marshal_write_int(buf, offset, l);
CHECKSIZE(buf, offset, l);
memcpy(PyString_AS_STRING(*buf) + *offset,
PyString_AS_STRING(id), l);
*offset += l;
return 1;
}
int
marshal_write_string(PyObject **buf, int *offset, string s)
{
int len = PyString_GET_SIZE(s);
marshal_write_int(buf, offset, len);
CHECKSIZE(buf, offset, len);
memcpy(PyString_AS_STRING(*buf) + *offset,
PyString_AS_STRING(s), len);
*offset += len;
return 1;
}
int
marshal_write_object(PyObject **buf, int *offset, object s)
{
/* XXX */
return 0;
}

3114
Python/ast.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,9 @@
/* Built-in functions */
#include "Python.h"
#include "node.h"
#include "code.h"
#include "compile.h"
#include "eval.h"

View file

@ -8,7 +8,7 @@
#include "Python.h"
#include "compile.h"
#include "code.h"
#include "frameobject.h"
#include "eval.h"
#include "opcode.h"
@ -543,7 +543,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throw)
#ifdef LLTRACE
int lltrace;
#endif
#if defined(Py_DEBUG) || defined(LLTRACE)
#if defined(Py_DEBUG)
/* Make it easier to find out where we are with a debugger */
char *filename;
#endif
@ -743,9 +743,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throw)
f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */
#ifdef LLTRACE
lltrace = PyDict_GetItemString(f->f_globals,"__lltrace__") != NULL;
lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL;
#endif
#if defined(Py_DEBUG) || defined(LLTRACE)
#if defined(Py_DEBUG)
filename = PyString_AsString(co->co_filename);
#endif
@ -2257,23 +2257,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throw)
case MAKE_CLOSURE:
{
int nfree;
v = POP(); /* code object */
x = PyFunction_New(v, f->f_globals);
nfree = PyCode_GetNumFree((PyCodeObject *)v);
Py_DECREF(v);
/* XXX Maybe this should be a separate opcode? */
if (x != NULL && nfree > 0) {
v = PyTuple_New(nfree);
if (v == NULL) {
Py_DECREF(x);
x = NULL;
break;
}
while (--nfree >= 0) {
w = POP();
PyTuple_SET_ITEM(v, nfree, w);
}
if (x != NULL) {
v = POP();
err = PyFunction_SetClosure(x, v);
Py_DECREF(v);
}
@ -2695,12 +2683,18 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
if (co->co_flags & CO_VARKEYWORDS)
nargs++;
/* Check for cells that shadow args */
for (i = 0; i < f->f_ncells && j < nargs; ++i) {
/* Initialize each cell var, taking into account
cell vars that are initialized from arguments.
Should arrange for the compiler to put cellvars
that are arguments at the beginning of the cellvars
list so that we can march over it more efficiently?
*/
for (i = 0; i < f->f_ncells; ++i) {
cellname = PyString_AS_STRING(
PyTuple_GET_ITEM(co->co_cellvars, i));
found = 0;
while (j < nargs) {
for (j = 0; j < nargs; j++) {
argname = PyString_AS_STRING(
PyTuple_GET_ITEM(co->co_varnames, j));
if (strcmp(cellname, argname) == 0) {
@ -2711,7 +2705,6 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
found = 1;
break;
}
j++;
}
if (found == 0) {
c = PyCell_New(NULL);
@ -2720,14 +2713,6 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
SETLOCAL(f->f_nlocals + i, c);
}
}
/* Initialize any that are left */
while (i < f->f_ncells) {
c = PyCell_New(NULL);
if (c == NULL)
goto fail;
SETLOCAL(f->f_nlocals + i, c);
i++;
}
}
if (f->f_nfreevars) {
int i;

File diff suppressed because it is too large Load diff

View file

@ -1,37 +1,30 @@
#include "Python.h"
#include "Python-ast.h"
#include "node.h"
#include "token.h"
#include "graminit.h"
#include "code.h"
#include "compile.h"
#include "symtable.h"
#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
#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, const char *filename)
future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
{
int i;
char *feature;
node *ch, *nn;
const char *feature;
asdl_seq *names;
REQ(n, import_from);
nn = CHILD(n, 3 + (TYPE(CHILD(n, 3)) == LPAR));
if (TYPE(nn) == STAR) {
PyErr_SetString(PyExc_SyntaxError, FUTURE_IMPORT_STAR);
PyErr_SyntaxLocation(filename, nn->n_lineno);
return -1;
}
REQ(nn, import_as_names);
for (i = 0; i < NCH(nn); i += 2) {
ch = CHILD(nn, i);
REQ(ch, import_as_name);
feature = STR(CHILD(ch, 0));
assert(s->kind == ImportFrom_kind);
names = s->v.ImportFrom.names;
for (i = 0; i < asdl_seq_LEN(names); i++) {
alias_ty name = asdl_seq_GET(names, i);
feature = PyString_AsString(name->name);
if (!feature)
return 0;
if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
continue;
} else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
@ -41,218 +34,97 @@ future_check_features(PyFutureFeatures *ff, node *n, const char *filename)
} else if (strcmp(feature, "braces") == 0) {
PyErr_SetString(PyExc_SyntaxError,
"not a chance");
PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
return -1;
PyErr_SyntaxLocation(filename, s->lineno);
return 0;
} else {
PyErr_Format(PyExc_SyntaxError,
UNDEFINED_FUTURE_FEATURE, feature);
PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
return -1;
PyErr_SyntaxLocation(filename, s->lineno);
return 0;
}
}
return 0;
return 1;
}
static void
future_error(node *n, const char *filename)
int
future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
{
PyErr_SetString(PyExc_SyntaxError,
"from __future__ imports must occur at the "
"beginning of the file");
PyErr_SyntaxLocation(filename, n->n_lineno);
}
int i, found_docstring = 0, done = 0, prev_line = 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() 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, const 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;
static PyObject *future;
if (!future) {
future = PyString_InternFromString("__future__");
if (!future)
return 0;
}
}
case small_stmt:
n = CHILD(n, 0);
goto loop;
case import_stmt: {
node *name;
n = CHILD(n, 0);
if (TYPE(n) != import_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;
if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
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;
/* A subsequent pass will detect future imports that don't
appear at the beginning of the file. There's one case,
however, that is easier to handl here: A series of imports
joined by semi-colons, where the first import is a future
statement but some subsequent import has the future form
but is preceded by a regular import.
*/
for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
stmt_ty s = asdl_seq_GET(mod->v.Module.body, i);
if (done && s->lineno > prev_line)
return 1;
prev_line = s->lineno;
/* 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 (done) {
PyErr_SetString(PyExc_SyntaxError,
ERR_LATE_FUTURE);
PyErr_SyntaxLocation(filename,
s->lineno);
return 0;
}
if (!future_check_features(ff, s, filename))
return 0;
ff->ff_lineno = s->lineno;
}
else
done = 1;
}
ff->ff_last_lineno = n->n_lineno;
break;
case atom:
if (TYPE(CHILD(n, 0)) == STRING
&& ff->ff_found_docstring == 0) {
ff->ff_found_docstring = 1;
return 0;
else if (s->kind == Expr_kind && !found_docstring) {
expr_ty e = s->v.Expr.value;
if (e->kind != Str_kind)
done = 1;
else
found_docstring = 1;
}
ff->ff_last_lineno = n->n_lineno;
return 0;
default:
ff->ff_last_lineno = n->n_lineno;
return 0;
else
done = 1;
}
return 0;
return 1;
}
PyFutureFeatures *
PyNode_Future(node *n, const char *filename)
PyFuture_FromAST(mod_ty mod, const char *filename)
{
PyFutureFeatures *ff;
ff = (PyFutureFeatures *)PyMem_Malloc(sizeof(PyFutureFeatures));
if (ff == NULL)
return NULL;
ff->ff_found_docstring = 0;
ff->ff_last_lineno = -1;
ff->ff_features = 0;
ff->ff_lineno = -1;
if (future_parse(ff, n, filename) < 0) {
if (!future_parse(ff, mod, filename)) {
PyMem_Free((void *)ff);
return NULL;
}

View file

@ -3,10 +3,11 @@
#include "Python.h"
#include "node.h"
#include "token.h"
#include "Python-ast.h"
#include "pythonrun.h"
#include "errcode.h"
#include "marshal.h"
#include "code.h"
#include "compile.h"
#include "eval.h"
#include "osdefs.h"
@ -766,17 +767,17 @@ load_compiled_module(char *name, char *cpathname, FILE *fp)
/* Parse a source file and return the corresponding code object */
static PyCodeObject *
parse_source_module(char *pathname, FILE *fp)
parse_source_module(const char *pathname, FILE *fp)
{
PyCodeObject *co;
node *n;
n = PyParser_SimpleParseFile(fp, pathname, Py_file_input);
if (n == NULL)
return NULL;
co = PyNode_Compile(n, pathname);
PyNode_Free(n);
PyCodeObject *co = NULL;
mod_ty mod;
mod = PyParser_ASTFromFile(fp, pathname, Py_file_input, 0, 0, 0,
NULL);
if (mod) {
co = PyAST_Compile(mod, pathname, NULL);
free_mod(mod);
}
return co;
}

View file

@ -6,6 +6,7 @@
#include "Python.h"
#include "longintrepr.h"
#include "code.h"
#include "compile.h"
#include "marshal.h"

View file

@ -3,13 +3,16 @@
#include "Python.h"
#include "Python-ast.h"
#include "grammar.h"
#include "node.h"
#include "token.h"
#include "parsetok.h"
#include "errcode.h"
#include "code.h"
#include "compile.h"
#include "symtable.h"
#include "ast.h"
#include "eval.h"
#include "marshal.h"
@ -32,9 +35,9 @@ extern grammar _PyParser_Grammar; /* From graminit.c */
/* Forward */
static void initmain(void);
static void initsite(void);
static PyObject *run_err_node(node *, const char *, PyObject *, PyObject *,
static PyObject *run_err_mod(mod_ty, const char *, PyObject *, PyObject *,
PyCompilerFlags *);
static PyObject *run_node(node *, const char *, PyObject *, PyObject *,
static PyObject *run_mod(mod_ty, const char *, PyObject *, PyObject *,
PyCompilerFlags *);
static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
PyCompilerFlags *);
@ -634,25 +637,7 @@ initsite(void)
/* Parse input from a file and execute it */
int
PyRun_AnyFile(FILE *fp, const char *filename)
{
return PyRun_AnyFileExFlags(fp, filename, 0, NULL);
}
int
PyRun_AnyFileFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
{
return PyRun_AnyFileExFlags(fp, filename, 0, flags);
}
int
PyRun_AnyFileEx(FILE *fp, const char *filename, int closeit)
{
return PyRun_AnyFileExFlags(fp, filename, closeit, NULL);
}
int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
PyRun_AnyFileExFlags(FILE *fp, char *filename, int closeit,
PyCompilerFlags *flags)
{
if (filename == NULL)
@ -667,12 +652,6 @@ PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
return PyRun_SimpleFileExFlags(fp, filename, closeit, flags);
}
int
PyRun_InteractiveLoop(FILE *fp, const char *filename)
{
return PyRun_InteractiveLoopFlags(fp, filename, NULL);
}
int
PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
{
@ -708,12 +687,6 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flag
}
}
int
PyRun_InteractiveOne(FILE *fp, const char *filename)
{
return PyRun_InteractiveOneFlags(fp, filename, NULL);
}
/* compute parser flags based on compiler flags */
#define PARSER_FLAGS(flags) \
(((flags) && (flags)->cf_flags & PyCF_DONT_IMPLY_DEDENT) ? \
@ -723,9 +696,9 @@ int
PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
{
PyObject *m, *d, *v, *w;
node *n;
perrdetail err;
mod_ty mod;
char *ps1 = "", *ps2 = "";
int errcode = 0;
v = PySys_GetObject("ps1");
if (v != NULL) {
@ -743,26 +716,25 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags
else if (PyString_Check(w))
ps2 = PyString_AsString(w);
}
n = PyParser_ParseFileFlags(fp, filename, &_PyParser_Grammar,
Py_single_input, ps1, ps2, &err,
PARSER_FLAGS(flags));
mod = PyParser_ASTFromFile(fp, filename,
Py_single_input, ps1, ps2,
flags, &errcode);
Py_XDECREF(v);
Py_XDECREF(w);
if (n == NULL) {
if (err.error == E_EOF) {
if (err.text)
PyMem_DEL(err.text);
if (mod == NULL) {
if (errcode == E_EOF) {
PyErr_Clear();
return E_EOF;
}
err_input(&err);
PyErr_Print();
return err.error;
return -1;
}
m = PyImport_AddModule("__main__");
if (m == NULL)
return -1;
d = PyModule_GetDict(m);
v = run_node(n, filename, d, d, flags);
v = run_mod(mod, filename, d, d, flags);
free_mod(mod);
if (v == NULL) {
PyErr_Print();
return -1;
@ -773,12 +745,6 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags
return 0;
}
int
PyRun_SimpleFile(FILE *fp, const char *filename)
{
return PyRun_SimpleFileEx(fp, filename, 0);
}
/* Check whether a file maybe a pyc file: Look at the extension,
the file type, and, if we may close it, at the first few bytes. */
@ -819,12 +785,6 @@ maybe_pyc_file(FILE *fp, const char* filename, const char* ext, int closeit)
return 0;
}
int
PyRun_SimpleFileEx(FILE *fp, const char *filename, int closeit)
{
return PyRun_SimpleFileExFlags(fp, filename, closeit, NULL);
}
int
PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
PyCompilerFlags *flags)
@ -873,12 +833,6 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
return 0;
}
int
PyRun_SimpleString(const char *command)
{
return PyRun_SimpleStringFlags(command, NULL);
}
int
PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags)
{
@ -1054,6 +1008,8 @@ PyErr_PrintEx(int set_sys_last_vars)
handle_system_exit();
}
PyErr_Fetch(&exception, &v, &tb);
if (exception == NULL)
return;
PyErr_NormalizeException(&exception, &v, &tb);
if (exception == NULL)
return;
@ -1195,74 +1151,48 @@ void PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
}
PyObject *
PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)
PyRun_StringFlags(const char *str, int start, PyObject *globals,
PyObject *locals, PyCompilerFlags *flags)
{
return run_err_node(PyParser_SimpleParseString(str, start),
"<string>", globals, locals, NULL);
}
PyObject *
PyRun_File(FILE *fp, const char *filename, int start, PyObject *globals,
PyObject *locals)
{
return PyRun_FileEx(fp, filename, start, globals, locals, 0);
}
PyObject *
PyRun_FileEx(FILE *fp, const char *filename, int start, PyObject *globals,
PyObject *locals, int closeit)
{
node *n = PyParser_SimpleParseFile(fp, filename, start);
if (closeit)
fclose(fp);
return run_err_node(n, filename, globals, locals, NULL);
}
PyObject *
PyRun_StringFlags(const char *str, int start, PyObject *globals, PyObject *locals,
PyCompilerFlags *flags)
{
return run_err_node(PyParser_SimpleParseStringFlags(
str, start, PARSER_FLAGS(flags)),
"<string>", globals, locals, flags);
}
PyObject *
PyRun_FileFlags(FILE *fp, const char *filename, int start, PyObject *globals,
PyObject *locals, PyCompilerFlags *flags)
{
return PyRun_FileExFlags(fp, filename, start, globals, locals, 0,
flags);
PyObject *ret;
mod_ty mod = PyParser_ASTFromString(str, "<string>", start, flags);
ret = run_err_mod(mod, "<string>", globals, locals, flags);
free_mod(mod);
return ret;
}
PyObject *
PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals,
PyObject *locals, int closeit, PyCompilerFlags *flags)
{
node *n = PyParser_SimpleParseFileFlags(fp, filename, start,
PARSER_FLAGS(flags));
PyObject *ret;
mod_ty mod = PyParser_ASTFromFile(fp, filename, start, 0, 0,
flags, NULL);
if (mod == NULL)
return NULL;
if (closeit)
fclose(fp);
return run_err_node(n, filename, globals, locals, flags);
ret = run_err_mod(mod, filename, globals, locals, flags);
free_mod(mod);
return ret;
}
static PyObject *
run_err_node(node *n, const char *filename, PyObject *globals, PyObject *locals,
PyCompilerFlags *flags)
run_err_mod(mod_ty mod, const char *filename, PyObject *globals,
PyObject *locals, PyCompilerFlags *flags)
{
if (n == NULL)
if (mod == NULL)
return NULL;
return run_node(n, filename, globals, locals, flags);
return run_mod(mod, filename, globals, locals, flags);
}
static PyObject *
run_node(node *n, const char *filename, PyObject *globals, PyObject *locals,
run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals,
PyCompilerFlags *flags)
{
PyCodeObject *co;
PyObject *v;
co = PyNode_CompileFlags(n, filename, flags);
PyNode_Free(n);
co = PyAST_Compile(mod, filename, flags);
if (co == NULL)
return NULL;
v = PyEval_EvalCode(co, globals, locals);
@ -1271,8 +1201,8 @@ run_node(node *n, const char *filename, PyObject *globals, PyObject *locals,
}
static PyObject *
run_pyc_file(FILE *fp, const char *filename, PyObject *globals, PyObject *locals,
PyCompilerFlags *flags)
run_pyc_file(FILE *fp, const char *filename, PyObject *globals,
PyObject *locals, PyCompilerFlags *flags)
{
PyCodeObject *co;
PyObject *v;
@ -1302,42 +1232,78 @@ run_pyc_file(FILE *fp, const char *filename, PyObject *globals, PyObject *locals
return v;
}
PyObject *
Py_CompileString(const char *str, const char *filename, int start)
{
return Py_CompileStringFlags(str, filename, start, NULL);
}
PyObject *
Py_CompileStringFlags(const char *str, const char *filename, int start,
PyCompilerFlags *flags)
{
node *n;
mod_ty mod;
PyCodeObject *co;
n = PyParser_SimpleParseStringFlagsFilename(str, filename, start,
PARSER_FLAGS(flags));
if (n == NULL)
mod = PyParser_ASTFromString(str, filename, start, flags);
if (mod == NULL)
return NULL;
co = PyNode_CompileFlags(n, filename, flags);
PyNode_Free(n);
co = PyAST_Compile(mod, filename, flags);
free_mod(mod);
return (PyObject *)co;
}
struct symtable *
Py_SymtableString(const char *str, const char *filename, int start)
{
node *n;
mod_ty mod;
struct symtable *st;
n = PyParser_SimpleParseStringFlagsFilename(str, filename,
start, 0);
if (n == NULL)
mod = PyParser_ASTFromString(str, filename, start, NULL);
if (mod == NULL)
return NULL;
st = PyNode_CompileSymtable(n, filename);
PyNode_Free(n);
st = PySymtable_Build(mod, filename, 0);
free_mod(mod);
return st;
}
/* Preferred access to parser is through AST. */
mod_ty
PyParser_ASTFromString(const char *s, const char *filename, int start,
PyCompilerFlags *flags)
{
node *n;
mod_ty mod;
perrdetail err;
n = PyParser_ParseStringFlagsFilename(s, filename, &_PyParser_Grammar,
start, &err,
PARSER_FLAGS(flags));
if (n) {
mod = PyAST_FromNode(n, flags, filename);
PyNode_Free(n);
return mod;
}
else {
err_input(&err);
return NULL;
}
}
mod_ty
PyParser_ASTFromFile(FILE *fp, const char *filename, int start, char *ps1,
char *ps2, PyCompilerFlags *flags, int *errcode)
{
node *n;
mod_ty mod;
perrdetail err;
n = PyParser_ParseFileFlags(fp, filename, &_PyParser_Grammar, start,
ps1, ps2, &err, PARSER_FLAGS(flags));
if (n) {
mod = PyAST_FromNode(n, flags, filename);
PyNode_Free(n);
return mod;
}
else {
err_input(&err);
if (errcode)
*errcode = err.error;
return NULL;
}
}
/* Simplified interface to parsefile -- return node or set exception */
node *
@ -1349,15 +1315,10 @@ PyParser_SimpleParseFileFlags(FILE *fp, const char *filename, int start, int fla
(char *)0, (char *)0, &err, flags);
if (n == NULL)
err_input(&err);
return n;
}
node *
PyParser_SimpleParseFile(FILE *fp, const char *filename, int start)
{
return PyParser_SimpleParseFileFlags(fp, filename, start, 0);
}
/* Simplified interface to parsestring -- return node or set exception */
node *
@ -1372,12 +1333,6 @@ PyParser_SimpleParseStringFlags(const char *str, int start, int flags)
return n;
}
node *
PyParser_SimpleParseString(const char *str, int start)
{
return PyParser_SimpleParseStringFlags(str, start, 0);
}
node *
PyParser_SimpleParseStringFlagsFilename(const char *str, const char *filename,
int start, int flags)
@ -1418,12 +1373,6 @@ err_input(perrdetail *err)
PyObject* u = NULL;
char *msg = NULL;
errtype = PyExc_SyntaxError;
v = Py_BuildValue("(ziiz)", err->filename,
err->lineno, err->offset, err->text);
if (err->text != NULL) {
PyMem_DEL(err->text);
err->text = NULL;
}
switch (err->error) {
case E_SYNTAX:
errtype = PyExc_IndentationError;
@ -1450,11 +1399,9 @@ err_input(perrdetail *err)
case E_INTR:
if (!PyErr_Occurred())
PyErr_SetNone(PyExc_KeyboardInterrupt);
Py_XDECREF(v);
return;
case E_NOMEM:
PyErr_NoMemory();
Py_XDECREF(v);
return;
case E_EOF:
msg = "unexpected EOF while parsing";
@ -1498,7 +1445,15 @@ err_input(perrdetail *err)
msg = "unknown parsing error";
break;
}
w = Py_BuildValue("(sO)", msg, v);
v = Py_BuildValue("(ziiz)", err->filename,
err->lineno, err->offset, err->text);
if (err->text != NULL) {
PyMem_DEL(err->text);
err->text = NULL;
}
w = NULL;
if (v != NULL)
w = Py_BuildValue("(sO)", msg, v);
Py_XDECREF(u);
Py_XDECREF(v);
PyErr_SetObject(errtype, w);
@ -1687,3 +1642,20 @@ PyOS_setsig(int sig, PyOS_sighandler_t handler)
return oldhandler;
#endif
}
/* Deprecated C API functions still provided for binary compatiblity */
#undef PyParser_SimpleParseFile
#undef PyParser_SimpleParseString
node *
PyParser_SimpleParseFile(FILE *fp, const char *filename, int start)
{
return PyParser_SimpleParseFileFlags(fp, filename, start, 0);
}
node *
PyParser_SimpleParseString(const char *str, int start)
{
return PyParser_SimpleParseStringFlags(str, start, 0);
}

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,7 @@ Data members:
*/
#include "Python.h"
#include "compile.h"
#include "code.h"
#include "frameobject.h"
#include "eval.h"

View file

@ -3,7 +3,7 @@
#include "Python.h"
#include "compile.h"
#include "code.h"
#include "frameobject.h"
#include "structmember.h"
#include "osdefs.h"