mirror of
https://github.com/python/cpython.git
synced 2025-07-23 19:25:40 +00:00
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:
parent
2cb94aba12
commit
3e0055f8c6
54 changed files with 13675 additions and 6810 deletions
2281
Python/Python-ast.c
Normal file
2281
Python/Python-ast.c
Normal file
File diff suppressed because it is too large
Load diff
92
Python/asdl.c
Normal file
92
Python/asdl.c
Normal 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
3114
Python/ast.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,9 @@
|
|||
|
||||
/* Built-in functions */
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
#include "node.h"
|
||||
#include "code.h"
|
||||
#include "compile.h"
|
||||
#include "eval.h"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
9391
Python/compile.c
9391
Python/compile.c
File diff suppressed because it is too large
Load diff
282
Python/future.c
282
Python/future.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "Python.h"
|
||||
#include "longintrepr.h"
|
||||
#include "code.h"
|
||||
#include "compile.h"
|
||||
#include "marshal.h"
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
1241
Python/symtable.c
1241
Python/symtable.c
File diff suppressed because it is too large
Load diff
|
@ -15,7 +15,7 @@ Data members:
|
|||
*/
|
||||
|
||||
#include "Python.h"
|
||||
#include "compile.h"
|
||||
#include "code.h"
|
||||
#include "frameobject.h"
|
||||
#include "eval.h"
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "Python.h"
|
||||
|
||||
#include "compile.h"
|
||||
#include "code.h"
|
||||
#include "frameobject.h"
|
||||
#include "structmember.h"
|
||||
#include "osdefs.h"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue