[Python-checkins] python/dist/src/Python newcompile.c,NONE,1.1.2.1
jhylton@users.sourceforge.net
jhylton@users.sourceforge.net
Tue, 09 Jul 2002 06:24:47 -0700
Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv10776/Python
Added Files:
Tag: ast-branch
newcompile.c
Log Message:
Temporarily commit newcompile.c which will replace compile.c.
--- NEW FILE: newcompile.c ---
#include "Python.h"
#include "Python-ast.h"
#include "code.h"
#include "compile.h"
#include "symtable.h"
#include "opcode.h"
struct compiler {
const char *c_filename;
struct symtable *c_st;
PyFutureFeatures *c_future; /* pointer to module's __future__ */
PyCompilerFlags *c_flags;
int c_interactive;
/* info that changes for each code block */
PySymtableEntryObject *c_symbols;
int c_nblocks;
int c_curblock;
struct basicblock c_entry;
struct basicblock c_exit;
struct basicblock **c_blocks;
};
static void
compiler_free(struct compiler *c)
{
int i;
if (c->c_st)
PySymtable_Free(c->c_st);
if (c->c_future)
PyMem_Free((void *)c->c_future);
for (i = 0; i < c->c_nblocks; i++)
free((void *)c->c_blocks[i]);
if (c->c_blocks)
free((void *)c->c_blocks);
}
PyCodeObject *
PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags)
{
struct compiler c;
PyCodeObject *co;
c.c_filename = filename;
c.c_future = PyFuture_FromAST(mod, filename);
if (c.c_future == NULL)
goto error;
if (flags) {
int merged = c.c_future->ff_features | flags->cf_flags;
c.c_future->ff_features = merged;
flags->cf_flags = merged;
}
c.c_st = PySymtable_Build(mod, filename, flags);
if (c.c_st == NULL)
goto error;
return NULL;
compiler_mod(&c, mod);
error:
compiler_free(&c);
return NULL;
}
static int
compiler_enter_scope(struct compiler *c, identifier name, void *key)
{
/* XXX need stack of info */
PyObject *k, *v;
k = PyLong_FromVoidPtr(key);
if (k == NULL)
return 0;
v = PyDict_GetItem(c->c_st->st_symbols, k);
if (!v) {
/* XXX */
PyErr_SetObject(PyExc_KeyError, name);
return 0;
}
assert(PySymtableEntry_Check(v));
c->c_symbols = v;
c->c_nblocks = 0;
c->c_blocks = (struct basicblock **)malloc(sizeof(struct basicblock *)
* DEFAULT_BLOCKS);
if (!c->c_blocks)
return 0;
return 1;
}
static int
compiler_exit_scope(struct compiler *c, identifier name, void *key)
{
/* pop current scope off stack & reinit */
return 1;
}
static PyCodeObject *
compiler_get_code(struct compiler *c)
{
/* get the code object for the current block.
XXX may want to return a thunk insttead
to allow later passes
*/
return NULL;
}
static int
compiler_new_block(struct compiler *c)
{
int i;
struct basicblock *b;
if (c->c_nblocks && c->c_nblocks % DEFAULT_BLOCKS == 0) {
/* XXX should double */
int newsize = c->c_nblocks + DEFAULT_BLOCKS;
c->c_blocks = (struct basicblock **)realloc(c->c_blocks,
newsize);
if (c->c_blocks == NULL)
return 0;
}
i = c->c_nblocks++;
b = (struct basicblock *)malloc(sizeof(struct basicblock));
if (b == NULL)
return 0;
memset((void *)b, 0, sizeof(struct basicblock));
b->b_ialloc = DEFAULT_BLOCK_SIZE;
c->c_blocks[i] = b;
return i;
}
/* Note: returns -1 on failure */
static int
compiler_next_instr(struct compiler *c, int block)
{
struct basicblock *b;
assert(block < c->c_nblocks);
b = c->c_blocks[block];
if (b->b_ioffset == b->b_ialloc) {
void *ptr;
int newsize;
b->b_ialloc *= 2;
/* XXX newsize is wrong */
ptr = realloc((void *)b, newsize);
if (ptr == NULL)
return -1;
if (ptr != (void *)b)
c->c_blocks[block] = (struct basicblock *)ptr;
}
return b->b_ioffset++;
}
static int
compiler_addop(struct compiler *c, int opcode)
{
int off;
off = compiler_next_instr(c, c->c_curblock);
if (off < 0)
return 0;
c->c_blocks[c->c_curblock]->b_instr[off].i_opcode = opcode;
return 1;
}
static int
compiler_addop_o(struct compiler *c, int opcode, PyObject *o)
{
struct instr *i;
int off;
off = compiler_next_instr(c, c->c_curblock);
if (off < 0)
return 0;
i = c->c_blocks[c->c_curblock];
i->i_opcode = i->i_opcode;
i->i_arg = o;
return 1;
}
static int
compiler_addop_i(struct compiler *c, int opcode, int oparg)
{
struct instr *i;
int off;
off = compiler_next_instr(c, c->c_curblock);
if (off < 0)
return 0;
i = c->c_blocks[c->c_curblock];
i->i_opcode = i->i_opcode;
i->i_oparg = oparg;
return 1;
}
/* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use
the ASDL name to synthesize the name of the C type and the visit function.
*/
#define ADDOP(C, OP) { \
if (!compiler_addop((C), (OP))) \
return 0; \
}
#define ADDOP_O(C, OP, O) { \
if (!compiler_addop_o((C), (OP), (O))) \
return 0; \
}
#define ADDOP_I(C, OP, O) { \
if (!compiler_addop_i((C), (OP), (O))) \
return 0; \
}
#define VISIT(C, TYPE, V) {\
if (!compiler_visit_ ## TYPE((C), (V))) \
return 0; \
}
#define VISIT_SEQ(C, TYPE, SEQ) { \
int i; \
asdl_seq *seq = (SEQ); /* avoid variable capture */ \
for (i = 0; i < asdl_seq_LEN(seq); i++) { \
TYPE ## _ty elt = asdl_seq_get(seq, i); \
if (!compiler_visit_ ## TYPE((C), elt)) \
return 0; \
} \
}
static int
compiler_mod(struct compiler *c, mod_ty mod)
{
switch (mod->kind) {
case Module_kind:
break;
case Interactive_kind:
break;
case Expression_kind:
break;
case Suite_kind:
break;
}
return 1;
}
static int
compiler_function(struct compiler *c, stmt_ty s)
{
PyCodeObject *co;
assert(s->kind == Function_kind);
if (s->v.FunctionDef.args->defaults)
VISIT_SEQ(c, expr, s->v.FunctionDef.args->defaults);
if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s))
return 0;
VISIT(c, arguments, s->v.FunctionDef.args);
VISIT_SEQ(c, stmt, s->v.FunctionDef.body);
co = compiler_get_code(c);
if (co == NULL)
return 0;
return 1;
}
static int
compiler_print(struct compiler *c, stmt_ty s)
{
int i, n;
bool dest;
assert(s->kind == Print_kind);
n = asdl_seq_LEN(s->v.Print.values);
dest = false;
if (s->v.Print.dest) {
VISIT(C, EXPR, s->v.Print.dest);
dest = true;
}
for (i = 0; i < n; i++) {
if (dest) {
ADDOP(c, DUP_TOP);
VISIT(c, expr, asdl_get_seq(s->v.Print.values, i));
ADDOP(c, ROT_TWO);
ADDOP(c, PRINT_ITEM_TO);
}
else {
VISIT(c, expr, asdl_get_seq(s->v.Print.values, i));
ADDOP(c, PRINT_ITEM);
}
}
if (s->v.Print.nl) {
if (dest)
ADDOP(c, PRINT_NEWLINE_TO);
else
ADDOP(c, PRINT_NEWLINE);
}
else if (dest)
ADDOP(c, POP_TOP);
return 1;
}
static int
compiler_function(struct compiler *c, stmt_ty s)
{
int i, n;
assert(s->kind == If_kind);
}
static int
compiler_stmt(struct compiler *c, stmt_ty s)
{
int i, n;
switch (s->kind) {
case FunctionDef_kind:
return compiler_function(c, s);
break;
case ClassDef_kind:
break;
case Return_kind:
if (s->v.Return.value)
VISIT(c, expr, s->v.Return.value)
else
ADDOP_O(c, LOAD_CONST, Py_None);
ADDOP(c, RETURN_VALUE);
break;
case Yield_kind:
VISIT(c, expr, s->v.Yield.value);
ADDOP(c, YIELD_VALUE);
break;
case Delete_kind:
VISIT_SEQ(c, expr, s->v.Delete.targets)
break;
case Assign_kind:
n = asdl_seq_LEN(s->v.Assign.targets);
VISIT(c, expr, s->v.Assign.value);
for (i = 0; i < n; i++) {
if (i < n - 1)
ADDOP(c, DUP_TOP);
VISIT(c, expr, asdl_get_seq(s->v.Assign.targets, i));
}
break;
case AugAssign_kind:
break;
case Print_kind:
return compiler_print(c, s);
break;
case For_kind:
break;
case While_kind:
break;
case If_kind:
return compiler_if(c, s);
break;
case Raise_kind:
if (s->v.Raise.type) {
VISIT(st, expr, s->v.Raise.type);
n++;
if (s->v.Raise.inst) {
VISIT(st, expr, s->v.Raise.inst);
n++;
if (s->v.Raise.tback) {
VISIT(st, expr, s->v.Raise.tback);
n++;
}
}
}
ADDOP_I(c, RAISE_VARARGS, n);
break;
case TryExcept_kind:
break;
case TryFinally_kind:
break;
case Assert_kind:
break;
case Import_kind:
break;
case ImportFrom_kind:
break;
case Exec_kind:
VISIT(st, expr, s->v.Exec.body);
if (s->v.Exec.globals) {
VISIT(st, expr, s->v.Exec.globals);
if (s->v.Exec.locals)
VISIT(st, expr, s->v.Exec.locals);
else
ADDOP(c, DUP_TOP);
} else {
ADDOP_O(c, LOAD_CONST, Py_None);
ADDOP(c, DUP_TOP);
}
ADDOP(c, EXEC_STMT);
break;
case Global_kind:
break;
case Expr_kind:
VISIT(c, expr, s->v.Expr.value);
if (c->c_interactive)
ADDOP(c, PRINT_EXPR);
else
ADDOP(c, DUP_TOP);
break;
case Pass_kind:
break;
case Break_kind:
break;
case Continue_kind:
break;
}
return 1;
}
static int
unaryop(unaryop_ty op)
{
switch (op) {
case Invert:
return UNARY_INVERT;
case Not:
return UNARY_NOT;
case UAdd:
return UNARY_POSITIVE;
case USub:
return UNARY_NEGATIVE;
}
}
static int
binop(operator_ty op)
{
switch (op) {
case Add:
return BINARY_ADD;
case Sub:
return BINARY_SUBTRACT;
case Mult:
return BINARY_MULTIPLY;
case Div:
if (c->c_flags & CO_FUTURE_DIVISION)
return BINARY_TRUE_DIVIDE;
else
return BINARY_DIVIDE;
case Mod:
return BINARY_MODULO;
case Pow:
return BINARY_POWER;
case LShift:
return BINARY_LSHIFT;
case RShift:
return BINARY_RSHIFT;
case BitOr:
return BINARY_OR;
case BitXor:
return BINARY_XOR;
case BitAnd:
return BINARY_AND;
case FloorDiv:
return BINARY_FLOOR_DIVIDE;
}
}
static int
compiler_visit_expr(struct compiler *c, expr_ty e)
{
int i, n;
switch (e->kind) {
case BoolOp_kind:
break;
case BinOp_kind:
VISIT(c, expr, e->v.BinOp.left);
VISIT(c, expr, e->v.BinOp.right);
ADDOP(c, binop(e->v.BinOp.op));
break;
case UnaryOp_kind:
VISIT(c, expr, e->v.UnaryOp.operand);
ADDOP(c, unaryop(e->v.UnaryOp.op));
break;
case Lambda_kind:
break;
case Dict_kind:
/* XXX get rid of arg? */
ADDOP_I(c, BUILD_MAP, 0);
n = asdl_seq_LEN(e->v.Dict.values);
/* We must arrange things just right for STORE_SUBSCR.
It wants the stack to look like (value) (dict) (key) */
for (i = 0; i < n; i++) {
ADDOP(c, DUP_TOP);
VISIT(c, expr, asdl_seq_get(e->v.Dict.values, i));
ADDOP(c, ROT_TWO);
VISIT(c, expr, asdl_seq_get(e->v.Dict.keys, i));
ADDOP(c, STORE_SUBSCR);
}
break;
case ListComp_kind:
break;
case Compare_kind:
break;
case Call_kind:
break;
case Repr_kind:
VISIT(c, expr, e->v.Repr.value);
ADDOP(c, UNARY_CONVERT);
break;
case Num_kind:
break;
case Str_kind:
break;
/* The following exprs can be assignment targets. */
case Attribute_kind:
VISIT(c, expr, e->v.Attribute.value);
switch (e->v.Attribute.ctx) {
case Load:
ADDOP_O(c, LOAD_ATTR, e->v.Attribute.attr);
break;
case Store:
ADDOP_O(c, STORE_ATTR, e->v.Attribute.attr);
break;
case Del:
ADDOP_O(c, DELETE_ATTR, e->v.Attribute.attr);
break;
case AugStore:
/* XXX */
break;
}
break;
case Subscript_kind:
VISIT(c, expr, e->v.Subscript.value);
VISIT(c, slice, e->v.Subscript.slice);
break;
case Name_kind:
compiler_add_def(c, e->v.Name.id,
e->v.Name.ctx == Load ? USE : DEF_LOCAL);
break;
/* child nodes of List and Tuple will have expr_context set */
case List_kind:
VISIT_SEQ(c, expr, e->v.List.elts);
break;
case Tuple_kind:
VISIT_SEQ(c, expr, e->v.Tuple.elts);
break;
}
return 1;
}