Merge from ast-arena. This reduces the code in Python/ast.c by ~300 lines,

simplifies a lot of error handling code, and fixes many memory leaks.
This commit is contained in:
Neal Norwitz 2005-12-17 20:54:49 +00:00
parent 23a6958910
commit adb69fcdff
16 changed files with 704 additions and 1242 deletions

View file

@ -328,81 +328,79 @@ struct _alias {
};
mod_ty Module(asdl_seq * body);
mod_ty Interactive(asdl_seq * body);
mod_ty Expression(expr_ty body);
mod_ty Suite(asdl_seq * body);
mod_ty Module(asdl_seq * body, PyArena *arena);
mod_ty Interactive(asdl_seq * body, PyArena *arena);
mod_ty Expression(expr_ty body, PyArena *arena);
mod_ty Suite(asdl_seq * body, PyArena *arena);
stmt_ty FunctionDef(identifier name, arguments_ty args, asdl_seq * body,
asdl_seq * decorators, int lineno);
asdl_seq * decorators, int lineno, PyArena *arena);
stmt_ty ClassDef(identifier name, asdl_seq * bases, asdl_seq * body, int
lineno);
stmt_ty Return(expr_ty value, int lineno);
stmt_ty Delete(asdl_seq * targets, int lineno);
stmt_ty Assign(asdl_seq * targets, expr_ty value, int lineno);
stmt_ty AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno);
stmt_ty Print(expr_ty dest, asdl_seq * values, bool nl, int lineno);
lineno, PyArena *arena);
stmt_ty Return(expr_ty value, int lineno, PyArena *arena);
stmt_ty Delete(asdl_seq * targets, int lineno, PyArena *arena);
stmt_ty Assign(asdl_seq * targets, expr_ty value, int lineno, PyArena *arena);
stmt_ty AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno,
PyArena *arena);
stmt_ty Print(expr_ty dest, asdl_seq * values, bool nl, int lineno, PyArena
*arena);
stmt_ty For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse,
int lineno);
stmt_ty While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno);
stmt_ty If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno);
stmt_ty Raise(expr_ty type, expr_ty inst, expr_ty tback, int lineno);
int lineno, PyArena *arena);
stmt_ty While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno,
PyArena *arena);
stmt_ty If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno,
PyArena *arena);
stmt_ty Raise(expr_ty type, expr_ty inst, expr_ty tback, int lineno, PyArena
*arena);
stmt_ty TryExcept(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, int
lineno);
stmt_ty TryFinally(asdl_seq * body, asdl_seq * finalbody, int lineno);
stmt_ty Assert(expr_ty test, expr_ty msg, int lineno);
stmt_ty Import(asdl_seq * names, int lineno);
stmt_ty ImportFrom(identifier module, asdl_seq * names, int lineno);
stmt_ty Exec(expr_ty body, expr_ty globals, expr_ty locals, int lineno);
stmt_ty Global(asdl_seq * names, int lineno);
stmt_ty Expr(expr_ty value, int lineno);
stmt_ty Pass(int lineno);
stmt_ty Break(int lineno);
stmt_ty Continue(int lineno);
expr_ty BoolOp(boolop_ty op, asdl_seq * values, int lineno);
expr_ty BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno);
expr_ty UnaryOp(unaryop_ty op, expr_ty operand, int lineno);
expr_ty Lambda(arguments_ty args, expr_ty body, int lineno);
expr_ty Dict(asdl_seq * keys, asdl_seq * values, int lineno);
expr_ty ListComp(expr_ty elt, asdl_seq * generators, int lineno);
expr_ty GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno);
expr_ty Yield(expr_ty value, int lineno);
lineno, PyArena *arena);
stmt_ty TryFinally(asdl_seq * body, asdl_seq * finalbody, int lineno, PyArena
*arena);
stmt_ty Assert(expr_ty test, expr_ty msg, int lineno, PyArena *arena);
stmt_ty Import(asdl_seq * names, int lineno, PyArena *arena);
stmt_ty ImportFrom(identifier module, asdl_seq * names, int lineno, PyArena
*arena);
stmt_ty Exec(expr_ty body, expr_ty globals, expr_ty locals, int lineno, PyArena
*arena);
stmt_ty Global(asdl_seq * names, int lineno, PyArena *arena);
stmt_ty Expr(expr_ty value, int lineno, PyArena *arena);
stmt_ty Pass(int lineno, PyArena *arena);
stmt_ty Break(int lineno, PyArena *arena);
stmt_ty Continue(int lineno, PyArena *arena);
expr_ty BoolOp(boolop_ty op, asdl_seq * values, int lineno, PyArena *arena);
expr_ty BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno, PyArena
*arena);
expr_ty UnaryOp(unaryop_ty op, expr_ty operand, int lineno, PyArena *arena);
expr_ty Lambda(arguments_ty args, expr_ty body, int lineno, PyArena *arena);
expr_ty Dict(asdl_seq * keys, asdl_seq * values, int lineno, PyArena *arena);
expr_ty ListComp(expr_ty elt, asdl_seq * generators, int lineno, PyArena
*arena);
expr_ty GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, PyArena
*arena);
expr_ty Yield(expr_ty value, int lineno, PyArena *arena);
expr_ty Compare(expr_ty left, asdl_seq * ops, asdl_seq * comparators, int
lineno);
lineno, PyArena *arena);
expr_ty Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, expr_ty
starargs, expr_ty kwargs, int lineno);
expr_ty Repr(expr_ty value, int lineno);
expr_ty Num(object n, int lineno);
expr_ty Str(string s, int lineno);
starargs, expr_ty kwargs, int lineno, PyArena *arena);
expr_ty Repr(expr_ty value, int lineno, PyArena *arena);
expr_ty Num(object n, int lineno, PyArena *arena);
expr_ty Str(string s, int lineno, PyArena *arena);
expr_ty Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int
lineno);
lineno, PyArena *arena);
expr_ty Subscript(expr_ty value, slice_ty slice, expr_context_ty ctx, int
lineno);
expr_ty Name(identifier id, expr_context_ty ctx, int lineno);
expr_ty List(asdl_seq * elts, expr_context_ty ctx, int lineno);
expr_ty Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno);
slice_ty Ellipsis(void);
slice_ty Slice(expr_ty lower, expr_ty upper, expr_ty step);
slice_ty ExtSlice(asdl_seq * dims);
slice_ty Index(expr_ty value);
comprehension_ty comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs);
excepthandler_ty excepthandler(expr_ty type, expr_ty name, asdl_seq * body);
lineno, PyArena *arena);
expr_ty Name(identifier id, expr_context_ty ctx, int lineno, PyArena *arena);
expr_ty List(asdl_seq * elts, expr_context_ty ctx, int lineno, PyArena *arena);
expr_ty Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno, PyArena *arena);
slice_ty Ellipsis(PyArena *arena);
slice_ty Slice(expr_ty lower, expr_ty upper, expr_ty step, PyArena *arena);
slice_ty ExtSlice(asdl_seq * dims, PyArena *arena);
slice_ty Index(expr_ty value, PyArena *arena);
comprehension_ty comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs,
PyArena *arena);
excepthandler_ty excepthandler(expr_ty type, expr_ty name, asdl_seq * body,
PyArena *arena);
arguments_ty arguments(asdl_seq * args, identifier vararg, identifier kwarg,
asdl_seq * defaults);
keyword_ty keyword(identifier arg, expr_ty value);
alias_ty alias(identifier name, identifier asname);
void free_mod(mod_ty);
void free_stmt(stmt_ty);
void free_expr(expr_ty);
void free_expr_context(expr_context_ty);
void free_slice(slice_ty);
void free_boolop(boolop_ty);
void free_operator(operator_ty);
void free_unaryop(unaryop_ty);
void free_cmpop(cmpop_ty);
void free_comprehension(comprehension_ty);
void free_excepthandler(excepthandler_ty);
void free_arguments(arguments_ty);
void free_keyword(keyword_ty);
void free_alias(alias_ty);
asdl_seq * defaults, PyArena *arena);
keyword_ty keyword(identifier arg, expr_ty value, PyArena *arena);
alias_ty alias(identifier name, identifier asname, PyArena *arena);

View file

@ -113,6 +113,7 @@
#include "pystate.h"
#include "pyarena.h"
#include "modsupport.h"
#include "pythonrun.h"
#include "ceval.h"

View file

@ -23,7 +23,7 @@ typedef struct {
void *elements[1];
} asdl_seq;
asdl_seq *asdl_seq_new(int size);
asdl_seq *asdl_seq_new(int size, PyArena *arena);
void asdl_seq_free(asdl_seq *);
#ifdef Py_DEBUG

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
PyAPI_FUNC(mod_ty) PyAST_FromNode(const node *, PyCompilerFlags *flags,
const char *);
const char *, PyArena *);
#ifdef __cplusplus
}

View file

@ -25,7 +25,7 @@ typedef struct {
struct _mod; /* Declare the existence of this type */
PyAPI_FUNC(PyCodeObject *) PyAST_Compile(struct _mod *, const char *,
PyCompilerFlags *);
PyCompilerFlags *, PyArena *);
PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST(struct _mod *, const char *);
#define ERR_LATE_FUTURE \

42
Include/pyarena.h Normal file
View file

@ -0,0 +1,42 @@
/* An arena-like memory interface for the compiler.
*/
#ifndef Py_PYARENA_H
#define Py_PYARENA_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _arena PyArena;
/* PyArena_New() and PyArena_Free() create a new arena and free it,
respectively. Once an arena has been created, it can be used
to allocate memory. Once it is freed, all the memory it allocated
is freed and none of its pointers are valid.
PyArena_New() returns an arena pointer. On error, it
returns a negative number and sets an exception.
*/
PyAPI_FUNC(PyArena *) PyArena_New(void);
PyAPI_FUNC(void) PyArena_Free(PyArena *);
PyAPI_FUNC(void *) PyArena_Malloc(PyArena *, size_t);
/* The next two routines aren't proper arena allocation routines.
They exist to experiment with the arena API without making wholesale
changes to the implementation.
The two functions register pointers with the arena id. These
are externally allocated pointers that will be freed when the
arena is freed. One takes a pointer allocated with malloc. The
other takes a PyObject that is DECREFed when the arena is freed.
*/
PyAPI_FUNC(int) PyArena_AddMallocPointer(PyArena *, void *);
PyAPI_FUNC(int) PyArena_AddPyObject(PyArena *, PyObject *);
#ifdef __cplusplus
}
#endif
#endif /* !Py_PYARENA_H */

View file

@ -37,10 +37,12 @@ PyAPI_FUNC(int) PyRun_InteractiveOneFlags(FILE *, const char *, PyCompilerFlags
PyAPI_FUNC(int) PyRun_InteractiveLoopFlags(FILE *, const char *, PyCompilerFlags *);
PyAPI_FUNC(struct _mod *) PyParser_ASTFromString(const char *, const char *,
int, PyCompilerFlags *flags);
int, PyCompilerFlags *flags,
PyArena *);
PyAPI_FUNC(struct _mod *) PyParser_ASTFromFile(FILE *, const char *, int,
char *, char *,
PyCompilerFlags *, int *);
PyCompilerFlags *, int *,
PyArena *);
#define PyParser_SimpleParseString(S, B) \
PyParser_SimpleParseStringFlags(S, B, 0)
#define PyParser_SimpleParseFile(FP, S, B) \

View file

@ -254,6 +254,7 @@ PYTHON_OBJS= \
Python/modsupport.o \
Python/mystrtoul.o \
Python/mysnprintf.o \
Python/pyarena.o \
Python/pyfpe.o \
Python/pystate.o \
Python/pythonrun.o \
@ -520,6 +521,7 @@ PYTHON_HEADERS= \
Include/object.h \
Include/objimpl.h \
Include/patchlevel.h \
Include/pyarena.h \
Include/pydebug.h \
Include/pyerrors.h \
Include/pyfpe.h \

View file

@ -249,8 +249,9 @@ def emit_function(self, name, ctype, args, attrs, union=1):
if args:
argstr = ", ".join(["%s %s" % (atype, aname)
for atype, aname, opt in args])
argstr += ", PyArena *arena"
else:
argstr = "void"
argstr = "PyArena *arena"
self.emit("%s %s(%s);" % (ctype, name, argstr), 0)
def visitProduct(self, prod, name):
@ -265,6 +266,10 @@ def emit(s, depth=0, reflow=1):
self.emit(s, depth, reflow)
argstr = ", ".join(["%s %s" % (atype, aname)
for atype, aname, opt in args + attrs])
if argstr:
argstr += ", PyArena *arena"
else:
argstr = "PyArena *arena"
self.emit("%s" % ctype, 0)
emit("%s(%s)" % (name, argstr))
emit("{")
@ -280,7 +285,7 @@ def emit(s, depth=0, reflow=1):
emit('return NULL;', 2)
emit('}', 1)
emit("p = (%s)malloc(sizeof(*p));" % ctype, 1)
emit("p = (%s)PyArena_Malloc(arena, sizeof(*p));" % ctype, 1);
emit("if (!p) {", 1)
emit("PyErr_NoMemory();", 2)
emit("return NULL;", 2)
@ -655,7 +660,7 @@ def main(srcfile):
c = ChainOfVisitors(TypeDefVisitor(f),
StructVisitor(f),
PrototypeVisitor(f),
FreePrototypeVisitor(f),
## FreePrototypeVisitor(f),
)
c.visit(mod)
f.close()
@ -671,8 +676,8 @@ def main(srcfile):
print >> f
v = ChainOfVisitors(MarshalPrototypeVisitor(f),
FunctionVisitor(f),
FreeUtilVisitor(f),
FreeVisitor(f),
## FreeUtilVisitor(f),
## FreeVisitor(f),
MarshalUtilVisitor(f),
MarshalFunctionVisitor(f),
)

File diff suppressed because it is too large Load diff

View file

@ -2,17 +2,18 @@
#include "asdl.h"
asdl_seq *
asdl_seq_new(int size)
asdl_seq_new(int size, PyArena *arena)
{
asdl_seq *seq = NULL;
size_t n = sizeof(asdl_seq) +
(size ? (sizeof(void *) * (size - 1)) : 0);
seq = (asdl_seq *)PyObject_Malloc(n);
seq = (asdl_seq *)malloc(n);
if (!seq) {
PyErr_NoMemory();
return NULL;
}
PyArena_AddMallocPointer(arena, (void *)seq);
memset(seq, 0, n);
seq->size = size;
return seq;
@ -21,6 +22,4 @@ asdl_seq_new(int size)
void
asdl_seq_free(asdl_seq *seq)
{
PyObject_Free(seq);
}

File diff suppressed because it is too large Load diff

View file

@ -23,6 +23,7 @@
#include "Python-ast.h"
#include "node.h"
#include "pyarena.h"
#include "ast.h"
#include "code.h"
#include "compile.h"
@ -148,6 +149,7 @@ struct compiler {
struct compiler_unit *u; /* compiler state for current block */
PyObject *c_stack; /* Python list holding compiler_unit ptrs */
char *c_encoding; /* source encoding (a borrowed reference) */
PyArena *c_arena; /* pointer to memory allocation arena */
};
struct assembler {
@ -243,7 +245,8 @@ compiler_init(struct compiler *c)
}
PyCodeObject *
PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags)
PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags,
PyArena *arena)
{
struct compiler c;
PyCodeObject *co = NULL;
@ -259,6 +262,7 @@ PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags)
if (!compiler_init(&c))
goto error;
c.c_filename = filename;
c.c_arena = arena;
c.c_future = PyFuture_FromAST(mod, filename);
if (c.c_future == NULL)
goto error;
@ -292,12 +296,13 @@ PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags)
PyCodeObject *
PyNode_Compile(struct _node *n, const char *filename)
{
PyCodeObject *co;
mod_ty mod = PyAST_FromNode(n, NULL, filename);
if (!mod)
return NULL;
co = PyAST_Compile(mod, filename, NULL);
free_mod(mod);
PyCodeObject *co = NULL;
PyArena *arena;
arena = PyArena_New();
mod_ty mod = PyAST_FromNode(n, NULL, filename, arena);
if (mod)
co = PyAST_Compile(mod, filename, NULL, arena);
PyArena_Free(arena);
return co;
}
@ -3404,7 +3409,7 @@ compiler_augassign(struct compiler *c, stmt_ty s)
switch (e->kind) {
case Attribute_kind:
auge = Attribute(e->v.Attribute.value, e->v.Attribute.attr,
AugLoad, e->lineno);
AugLoad, e->lineno, c->c_arena);
if (auge == NULL)
return 0;
VISIT(c, expr, auge);
@ -3412,11 +3417,10 @@ compiler_augassign(struct compiler *c, stmt_ty s)
ADDOP(c, inplace_binop(c, s->v.AugAssign.op));
auge->v.Attribute.ctx = AugStore;
VISIT(c, expr, auge);
free(auge);
break;
case Subscript_kind:
auge = Subscript(e->v.Subscript.value, e->v.Subscript.slice,
AugLoad, e->lineno);
AugLoad, e->lineno, c->c_arena);
if (auge == NULL)
return 0;
VISIT(c, expr, auge);
@ -3424,7 +3428,6 @@ compiler_augassign(struct compiler *c, stmt_ty s)
ADDOP(c, inplace_binop(c, s->v.AugAssign.op));
auge->v.Subscript.ctx = AugStore;
VISIT(c, expr, auge);
free(auge);
break;
case Name_kind:
VISIT(c, expr, s->v.AugAssign.target);

View file

@ -4,6 +4,7 @@
#include "Python.h"
#include "Python-ast.h"
#include "pyarena.h"
#include "pythonrun.h"
#include "errcode.h"
#include "marshal.h"
@ -773,13 +774,14 @@ parse_source_module(const char *pathname, FILE *fp)
{
PyCodeObject *co = NULL;
mod_ty mod;
PyArena *arena = PyArena_New();
mod = PyParser_ASTFromFile(fp, pathname, Py_file_input, 0, 0, 0,
NULL);
NULL, arena);
if (mod) {
co = PyAST_Compile(mod, pathname, NULL);
free_mod(mod);
co = PyAST_Compile(mod, pathname, NULL, arena);
}
PyArena_Free(arena);
return co;
}

133
Python/pyarena.c Normal file
View file

@ -0,0 +1,133 @@
#include "Python.h"
#include "pyarena.h"
/* An arena list is a linked list that can store either pointers or
PyObjects. The type is clear from context.
*/
typedef struct _arena_list {
struct _arena_list *al_next;
void *al_pointer;
} PyArenaList;
/* There are two linked lists in an arena, one for malloc pointers and
one for PyObject. For each list, there is a pointer to the head
and to the tail. The head is used to free the list. The tail is
used to add a new element to the list.
The list always keeps one un-used node at the end of the list.
*/
struct _arena {
PyArenaList *a_malloc_head;
PyArenaList *a_malloc_tail;
PyArenaList *a_object_head;
PyArenaList *a_object_tail;
};
static PyArenaList*
PyArenaList_New(void)
{
PyArenaList *alist = (PyArenaList *)malloc(sizeof(PyArenaList));
if (!alist)
return NULL;
alist->al_next = NULL;
alist->al_pointer = NULL;
return alist;
}
static void
PyArenaList_FreeObject(PyArenaList *alist)
{
if (!alist)
return;
while (alist) {
PyArenaList *prev;
Py_XDECREF((PyObject *)alist->al_pointer);
alist->al_pointer = NULL;
prev = alist;
alist = alist->al_next;
free(prev);
}
}
static void
PyArenaList_FreeMalloc(PyArenaList *alist)
{
if (!alist)
return;
while (alist) {
PyArenaList *prev;
if (alist->al_pointer) {
free(alist->al_pointer);
}
alist->al_pointer = NULL;
prev = alist;
alist = alist->al_next;
free(prev);
}
}
PyArena *
PyArena_New()
{
PyArena* arena = (PyArena *)malloc(sizeof(PyArena));
if (!arena)
return NULL;
arena->a_object_head = PyArenaList_New();
arena->a_object_tail = arena->a_object_head;
arena->a_malloc_head = PyArenaList_New();
arena->a_malloc_tail = arena->a_malloc_head;
return arena;
}
void
PyArena_Free(PyArena *arena)
{
assert(arena);
PyArenaList_FreeObject(arena->a_object_head);
PyArenaList_FreeMalloc(arena->a_malloc_head);
free(arena);
}
void *
PyArena_Malloc(PyArena *arena, size_t size)
{
/* A better implementation might actually use an arena. The current
approach is just a trivial implementation of the API that allows
it to be tested.
*/
void *p;
assert(size != 0);
p = malloc(size);
PyArena_AddMallocPointer(arena, p);
return p;
}
int
PyArena_AddMallocPointer(PyArena *arena, void *pointer)
{
assert(pointer);
PyArenaList *tail = arena->a_malloc_tail;
assert(tail->al_pointer != pointer);
tail->al_next = PyArenaList_New();
tail->al_pointer = pointer;
arena->a_malloc_tail = tail->al_next;
return 1;
}
int
PyArena_AddPyObject(PyArena *arena, PyObject *pointer)
{
assert(pointer);
PyArenaList *tail = arena->a_object_tail;
tail->al_next = PyArenaList_New();
tail->al_pointer = pointer;
arena->a_object_tail = tail->al_next;
return 1;
}

View file

@ -12,6 +12,7 @@
#include "code.h"
#include "compile.h"
#include "symtable.h"
#include "pyarena.h"
#include "ast.h"
#include "eval.h"
#include "marshal.h"
@ -36,9 +37,9 @@ extern grammar _PyParser_Grammar; /* From graminit.c */
static void initmain(void);
static void initsite(void);
static PyObject *run_err_mod(mod_ty, const char *, PyObject *, PyObject *,
PyCompilerFlags *);
PyCompilerFlags *, PyArena *arena);
static PyObject *run_mod(mod_ty, const char *, PyObject *, PyObject *,
PyCompilerFlags *);
PyCompilerFlags *, PyArena *);
static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
PyCompilerFlags *);
static void err_input(perrdetail *);
@ -697,6 +698,7 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags
{
PyObject *m, *d, *v, *w;
mod_ty mod;
PyArena *arena;
char *ps1 = "", *ps2 = "";
int errcode = 0;
@ -716,12 +718,14 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags
else if (PyString_Check(w))
ps2 = PyString_AsString(w);
}
arena = PyArena_New();
mod = PyParser_ASTFromFile(fp, filename,
Py_single_input, ps1, ps2,
flags, &errcode);
flags, &errcode, arena);
Py_XDECREF(v);
Py_XDECREF(w);
if (mod == NULL) {
PyArena_Free(arena);
if (errcode == E_EOF) {
PyErr_Clear();
return E_EOF;
@ -730,11 +734,13 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags
return -1;
}
m = PyImport_AddModule("__main__");
if (m == NULL)
if (m == NULL) {
PyArena_Free(arena);
return -1;
}
d = PyModule_GetDict(m);
v = run_mod(mod, filename, d, d, flags);
free_mod(mod);
v = run_mod(mod, filename, d, d, flags, arena);
PyArena_Free(arena);
if (v == NULL) {
PyErr_Print();
return -1;
@ -1155,9 +1161,11 @@ PyRun_StringFlags(const char *str, int start, PyObject *globals,
PyObject *locals, PyCompilerFlags *flags)
{
PyObject *ret;
mod_ty mod = PyParser_ASTFromString(str, "<string>", start, flags);
ret = run_err_mod(mod, "<string>", globals, locals, flags);
free_mod(mod);
PyArena *arena = PyArena_New();
mod_ty mod = PyParser_ASTFromString(str, "<string>", start, flags,
arena);
ret = run_err_mod(mod, "<string>", globals, locals, flags, arena);
PyArena_Free(arena);
return ret;
}
@ -1166,33 +1174,36 @@ PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals,
PyObject *locals, int closeit, PyCompilerFlags *flags)
{
PyObject *ret;
PyArena *arena = PyArena_New();
mod_ty mod = PyParser_ASTFromFile(fp, filename, start, 0, 0,
flags, NULL);
if (mod == NULL)
flags, NULL, arena);
if (mod == NULL) {
PyArena_Free(arena);
return NULL;
}
if (closeit)
fclose(fp);
ret = run_err_mod(mod, filename, globals, locals, flags);
free_mod(mod);
ret = run_err_mod(mod, filename, globals, locals, flags, arena);
PyArena_Free(arena);
return ret;
}
static PyObject *
run_err_mod(mod_ty mod, const char *filename, PyObject *globals,
PyObject *locals, PyCompilerFlags *flags)
PyObject *locals, PyCompilerFlags *flags, PyArena *arena)
{
if (mod == NULL)
return NULL;
return run_mod(mod, filename, globals, locals, flags);
return run_mod(mod, filename, globals, locals, flags, arena);
}
static PyObject *
run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals,
PyCompilerFlags *flags)
PyCompilerFlags *flags, PyArena *arena)
{
PyCodeObject *co;
PyObject *v;
co = PyAST_Compile(mod, filename, flags);
co = PyAST_Compile(mod, filename, flags, arena);
if (co == NULL)
return NULL;
v = PyEval_EvalCode(co, globals, locals);
@ -1236,43 +1247,45 @@ PyObject *
Py_CompileStringFlags(const char *str, const char *filename, int start,
PyCompilerFlags *flags)
{
mod_ty mod;
PyCodeObject *co;
mod = PyParser_ASTFromString(str, filename, start, flags);
if (mod == NULL)
PyArena *arena = PyArena_New();
mod_ty mod = PyParser_ASTFromString(str, filename, start, flags, arena);
if (mod == NULL) {
PyArena_Free(arena);
return NULL;
co = PyAST_Compile(mod, filename, flags);
free_mod(mod);
}
co = PyAST_Compile(mod, filename, flags, arena);
PyArena_Free(arena);
return (PyObject *)co;
}
struct symtable *
Py_SymtableString(const char *str, const char *filename, int start)
{
mod_ty mod;
struct symtable *st;
mod = PyParser_ASTFromString(str, filename, start, NULL);
if (mod == NULL)
PyArena *arena = PyArena_New();
mod_ty mod = PyParser_ASTFromString(str, filename, start, NULL, arena);
if (mod == NULL) {
PyArena_Free(arena);
return NULL;
}
st = PySymtable_Build(mod, filename, 0);
free_mod(mod);
PyArena_Free(arena);
return st;
}
/* Preferred access to parser is through AST. */
mod_ty
PyParser_ASTFromString(const char *s, const char *filename, int start,
PyCompilerFlags *flags)
PyCompilerFlags *flags, PyArena *arena)
{
node *n;
mod_ty mod;
perrdetail err;
n = PyParser_ParseStringFlagsFilename(s, filename, &_PyParser_Grammar,
start, &err,
PARSER_FLAGS(flags));
node *n = PyParser_ParseStringFlagsFilename(s, filename,
&_PyParser_Grammar, start, &err,
PARSER_FLAGS(flags));
if (n) {
mod = PyAST_FromNode(n, flags, filename);
mod = PyAST_FromNode(n, flags, filename, arena);
PyNode_Free(n);
return mod;
}
@ -1284,15 +1297,15 @@ PyParser_ASTFromString(const char *s, const char *filename, int start,
mod_ty
PyParser_ASTFromFile(FILE *fp, const char *filename, int start, char *ps1,
char *ps2, PyCompilerFlags *flags, int *errcode)
char *ps2, PyCompilerFlags *flags, int *errcode,
PyArena *arena)
{
node *n;
mod_ty mod;
perrdetail err;
n = PyParser_ParseFileFlags(fp, filename, &_PyParser_Grammar, start,
ps1, ps2, &err, PARSER_FLAGS(flags));
node *n = PyParser_ParseFileFlags(fp, filename, &_PyParser_Grammar,
start, ps1, ps2, &err, PARSER_FLAGS(flags));
if (n) {
mod = PyAST_FromNode(n, flags, filename);
mod = PyAST_FromNode(n, flags, filename, arena);
PyNode_Free(n);
return mod;
}
@ -1309,10 +1322,9 @@ PyParser_ASTFromFile(FILE *fp, const char *filename, int start, char *ps1,
node *
PyParser_SimpleParseFileFlags(FILE *fp, const char *filename, int start, int flags)
{
node *n;
perrdetail err;
n = PyParser_ParseFileFlags(fp, filename, &_PyParser_Grammar, start,
(char *)0, (char *)0, &err, flags);
node *n = PyParser_ParseFileFlags(fp, filename, &_PyParser_Grammar,
start, NULL, NULL, &err, flags);
if (n == NULL)
err_input(&err);
@ -1324,10 +1336,9 @@ PyParser_SimpleParseFileFlags(FILE *fp, const char *filename, int start, int fla
node *
PyParser_SimpleParseStringFlags(const char *str, int start, int flags)
{
node *n;
perrdetail err;
n = PyParser_ParseStringFlags(str, &_PyParser_Grammar, start, &err,
flags);
node *n = PyParser_ParseStringFlags(str, &_PyParser_Grammar,
start, &err, flags);
if (n == NULL)
err_input(&err);
return n;
@ -1337,12 +1348,9 @@ node *
PyParser_SimpleParseStringFlagsFilename(const char *str, const char *filename,
int start, int flags)
{
node *n;
perrdetail err;
n = PyParser_ParseStringFlagsFilename(str, filename,
&_PyParser_Grammar,
start, &err, flags);
node *n = PyParser_ParseStringFlagsFilename(str, filename,
&_PyParser_Grammar, start, &err, flags);
if (n == NULL)
err_input(&err);
return n;
@ -1351,8 +1359,7 @@ PyParser_SimpleParseStringFlagsFilename(const char *str, const char *filename,
node *
PyParser_SimpleParseStringFilename(const char *str, const char *filename, int start)
{
return PyParser_SimpleParseStringFlagsFilename(str, filename,
start, 0);
return PyParser_SimpleParseStringFlagsFilename(str, filename, start, 0);
}
/* May want to move a more generalized form of this to parsetok.c or