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.
diff --git a/Include/Python-ast.h b/Include/Python-ast.h
new file mode 100644
index 0000000..0859acf
--- /dev/null
+++ b/Include/Python-ast.h
@@ -0,0 +1,418 @@
+/* File automatically generated by ../Parser/asdl_c.py */
+
+#include "asdl.h"
+
+typedef struct _mod *mod_ty;
+
+typedef struct _stmt *stmt_ty;
+
+typedef struct _expr *expr_ty;
+
+typedef enum _expr_context { Load=1, Store=2, Del=3, AugLoad=4, AugStore=5,
+                             Param=6 } expr_context_ty;
+
+typedef struct _slice *slice_ty;
+
+typedef enum _boolop { And=1, Or=2 } boolop_ty;
+
+typedef enum _operator { Add=1, Sub=2, Mult=3, Div=4, Mod=5, Pow=6, LShift=7,
+                         RShift=8, BitOr=9, BitXor=10, BitAnd=11, FloorDiv=12 }
+                         operator_ty;
+
+typedef enum _unaryop { Invert=1, Not=2, UAdd=3, USub=4 } unaryop_ty;
+
+typedef enum _cmpop { Eq=1, NotEq=2, Lt=3, LtE=4, Gt=5, GtE=6, Is=7, IsNot=8,
+                      In=9, NotIn=10 } cmpop_ty;
+
+typedef struct _comprehension *comprehension_ty;
+
+typedef struct _excepthandler *excepthandler_ty;
+
+typedef struct _arguments *arguments_ty;
+
+typedef struct _keyword *keyword_ty;
+
+typedef struct _alias *alias_ty;
+
+struct _mod {
+        enum { Module_kind=1, Interactive_kind=2, Expression_kind=3,
+               Suite_kind=4 } kind;
+        union {
+                struct {
+                        asdl_seq *body;
+                } Module;
+                
+                struct {
+                        asdl_seq *body;
+                } Interactive;
+                
+                struct {
+                        expr_ty body;
+                } Expression;
+                
+                struct {
+                        asdl_seq *body;
+                } Suite;
+                
+        } v;
+};
+
+struct _stmt {
+        enum { FunctionDef_kind=1, ClassDef_kind=2, Return_kind=3,
+               Delete_kind=4, Assign_kind=5, AugAssign_kind=6, Print_kind=7,
+               For_kind=8, While_kind=9, If_kind=10, Raise_kind=11,
+               TryExcept_kind=12, TryFinally_kind=13, Assert_kind=14,
+               Import_kind=15, ImportFrom_kind=16, Exec_kind=17,
+               Global_kind=18, Expr_kind=19, Pass_kind=20, Break_kind=21,
+               Continue_kind=22 } kind;
+        union {
+                struct {
+                        identifier name;
+                        arguments_ty args;
+                        asdl_seq *body;
+                        asdl_seq *decorators;
+                } FunctionDef;
+                
+                struct {
+                        identifier name;
+                        asdl_seq *bases;
+                        asdl_seq *body;
+                } ClassDef;
+                
+                struct {
+                        expr_ty value;
+                } Return;
+                
+                struct {
+                        asdl_seq *targets;
+                } Delete;
+                
+                struct {
+                        asdl_seq *targets;
+                        expr_ty value;
+                } Assign;
+                
+                struct {
+                        expr_ty target;
+                        operator_ty op;
+                        expr_ty value;
+                } AugAssign;
+                
+                struct {
+                        expr_ty dest;
+                        asdl_seq *values;
+                        bool nl;
+                } Print;
+                
+                struct {
+                        expr_ty target;
+                        expr_ty iter;
+                        asdl_seq *body;
+                        asdl_seq *orelse;
+                } For;
+                
+                struct {
+                        expr_ty test;
+                        asdl_seq *body;
+                        asdl_seq *orelse;
+                } While;
+                
+                struct {
+                        expr_ty test;
+                        asdl_seq *body;
+                        asdl_seq *orelse;
+                } If;
+                
+                struct {
+                        expr_ty type;
+                        expr_ty inst;
+                        expr_ty tback;
+                } Raise;
+                
+                struct {
+                        asdl_seq *body;
+                        asdl_seq *handlers;
+                        asdl_seq *orelse;
+                } TryExcept;
+                
+                struct {
+                        asdl_seq *body;
+                        asdl_seq *finalbody;
+                } TryFinally;
+                
+                struct {
+                        expr_ty test;
+                        expr_ty msg;
+                } Assert;
+                
+                struct {
+                        asdl_seq *names;
+                } Import;
+                
+                struct {
+                        identifier module;
+                        asdl_seq *names;
+                } ImportFrom;
+                
+                struct {
+                        expr_ty body;
+                        expr_ty globals;
+                        expr_ty locals;
+                } Exec;
+                
+                struct {
+                        asdl_seq *names;
+                } Global;
+                
+                struct {
+                        expr_ty value;
+                } Expr;
+                
+        } v;
+        int lineno;
+};
+
+struct _expr {
+        enum { BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
+               Dict_kind=5, ListComp_kind=6, GeneratorExp_kind=7, Yield_kind=8,
+               Compare_kind=9, Call_kind=10, Repr_kind=11, Num_kind=12,
+               Str_kind=13, Attribute_kind=14, Subscript_kind=15, Name_kind=16,
+               List_kind=17, Tuple_kind=18 } kind;
+        union {
+                struct {
+                        boolop_ty op;
+                        asdl_seq *values;
+                } BoolOp;
+                
+                struct {
+                        expr_ty left;
+                        operator_ty op;
+                        expr_ty right;
+                } BinOp;
+                
+                struct {
+                        unaryop_ty op;
+                        expr_ty operand;
+                } UnaryOp;
+                
+                struct {
+                        arguments_ty args;
+                        expr_ty body;
+                } Lambda;
+                
+                struct {
+                        asdl_seq *keys;
+                        asdl_seq *values;
+                } Dict;
+                
+                struct {
+                        expr_ty elt;
+                        asdl_seq *generators;
+                } ListComp;
+                
+                struct {
+                        expr_ty elt;
+                        asdl_seq *generators;
+                } GeneratorExp;
+                
+                struct {
+                        expr_ty value;
+                } Yield;
+                
+                struct {
+                        expr_ty left;
+                        asdl_seq *ops;
+                        asdl_seq *comparators;
+                } Compare;
+                
+                struct {
+                        expr_ty func;
+                        asdl_seq *args;
+                        asdl_seq *keywords;
+                        expr_ty starargs;
+                        expr_ty kwargs;
+                } Call;
+                
+                struct {
+                        expr_ty value;
+                } Repr;
+                
+                struct {
+                        object n;
+                } Num;
+                
+                struct {
+                        string s;
+                } Str;
+                
+                struct {
+                        expr_ty value;
+                        identifier attr;
+                        expr_context_ty ctx;
+                } Attribute;
+                
+                struct {
+                        expr_ty value;
+                        slice_ty slice;
+                        expr_context_ty ctx;
+                } Subscript;
+                
+                struct {
+                        identifier id;
+                        expr_context_ty ctx;
+                } Name;
+                
+                struct {
+                        asdl_seq *elts;
+                        expr_context_ty ctx;
+                } List;
+                
+                struct {
+                        asdl_seq *elts;
+                        expr_context_ty ctx;
+                } Tuple;
+                
+        } v;
+        int lineno;
+};
+
+struct _slice {
+        enum { Ellipsis_kind=1, Slice_kind=2, ExtSlice_kind=3, Index_kind=4 }
+               kind;
+        union {
+                struct {
+                        expr_ty lower;
+                        expr_ty upper;
+                        expr_ty step;
+                } Slice;
+                
+                struct {
+                        asdl_seq *dims;
+                } ExtSlice;
+                
+                struct {
+                        expr_ty value;
+                } Index;
+                
+        } v;
+};
+
+struct _comprehension {
+        expr_ty target;
+        expr_ty iter;
+        asdl_seq *ifs;
+};
+
+struct _excepthandler {
+        expr_ty type;
+        expr_ty name;
+        asdl_seq *body;
+};
+
+struct _arguments {
+        asdl_seq *args;
+        identifier vararg;
+        identifier kwarg;
+        asdl_seq *defaults;
+};
+
+struct _keyword {
+        identifier arg;
+        expr_ty value;
+};
+
+struct _alias {
+        identifier name;
+        identifier asname;
+};
+
+mod_ty Module(asdl_seq * body);
+mod_ty Interactive(asdl_seq * body);
+mod_ty Expression(expr_ty body);
+mod_ty Suite(asdl_seq * body);
+stmt_ty FunctionDef(identifier name, arguments_ty args, asdl_seq * body,
+                    asdl_seq * decorators, int lineno);
+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);
+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);
+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);
+expr_ty Compare(expr_ty left, asdl_seq * ops, asdl_seq * comparators, int
+                lineno);
+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);
+expr_ty Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int
+                  lineno);
+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);
+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);
+int marshal_write_mod(PyObject **, int *, mod_ty);
+int marshal_write_stmt(PyObject **, int *, stmt_ty);
+int marshal_write_expr(PyObject **, int *, expr_ty);
+int marshal_write_expr_context(PyObject **, int *, expr_context_ty);
+int marshal_write_slice(PyObject **, int *, slice_ty);
+int marshal_write_boolop(PyObject **, int *, boolop_ty);
+int marshal_write_operator(PyObject **, int *, operator_ty);
+int marshal_write_unaryop(PyObject **, int *, unaryop_ty);
+int marshal_write_cmpop(PyObject **, int *, cmpop_ty);
+int marshal_write_comprehension(PyObject **, int *, comprehension_ty);
+int marshal_write_excepthandler(PyObject **, int *, excepthandler_ty);
+int marshal_write_arguments(PyObject **, int *, arguments_ty);
+int marshal_write_keyword(PyObject **, int *, keyword_ty);
+int marshal_write_alias(PyObject **, int *, alias_ty);
diff --git a/Include/Python.h b/Include/Python.h
index 2d48d2e..f941cba 100644
--- a/Include/Python.h
+++ b/Include/Python.h
@@ -128,8 +128,7 @@
 #include "pystrtod.h"
 
 /* _Py_Mangle is defined in compile.c */
-PyAPI_FUNC(int) _Py_Mangle(char *p, char *name, \
-				 char *buffer, size_t maxlen);
+PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name);
 
 /* PyArg_GetInt is deprecated and should not be used, use PyArg_Parse(). */
 #define PyArg_GetInt(v, a)	PyArg_Parse((v), "i", (a))
diff --git a/Include/asdl.h b/Include/asdl.h
new file mode 100644
index 0000000..8ad46fa
--- /dev/null
+++ b/Include/asdl.h
@@ -0,0 +1,54 @@
+#ifndef Py_ASDL_H
+#define Py_ASDL_H
+
+typedef PyObject * identifier;
+typedef PyObject * string;
+typedef PyObject * object;
+
+typedef enum {false, true} bool;
+
+/* It would be nice if the code generated by asdl_c.py was completely
+   independent of Python, but it is a goal the requires too much work
+   at this stage.  So, for example, I'll represent identifiers as
+   interned Python strings.
+*/
+
+/* XXX A sequence should be typed so that its use can be typechecked. */
+
+/* XXX We shouldn't pay for offset when we don't need APPEND. */
+
+typedef struct {
+    int size;
+    int offset;
+    void *elements[1];
+} asdl_seq;
+
+asdl_seq *asdl_seq_new(int size);
+void asdl_seq_free(asdl_seq *);
+
+#ifdef Py_DEBUG
+#define asdl_seq_GET(S, I) (S)->elements[(I)]
+#define asdl_seq_SET(S, I, V) { \
+        int _asdl_i = (I); \
+        assert((S) && _asdl_i < (S)->size); \
+        (S)->elements[_asdl_i] = (V); \
+}
+#define asdl_seq_APPEND(S, V) { \
+        assert((S) && (S)->offset < (S)->size); \
+        (S)->elements[(S)->offset++] = (V); \
+}
+#else
+#define asdl_seq_GET(S, I) (S)->elements[(I)]
+#define asdl_seq_SET(S, I, V) (S)->elements[I] = (V)
+#define asdl_seq_APPEND(S, V) (S)->elements[(S)->offset++] = (V)
+#endif
+#define asdl_seq_LEN(S) ((S) == NULL ? 0 : (S)->size)
+
+/* Routines to marshal the basic types. */
+int marshal_write_int(PyObject **, int *, int);
+int marshal_write_bool(PyObject **, int *, bool);
+int marshal_write_identifier(PyObject **, int *, identifier);
+int marshal_write_string(PyObject **, int *, string);
+int marshal_write_object(PyObject **, int *, object);
+
+#endif /* !Py_ASDL_H */
diff --git a/Include/ast.h b/Include/ast.h
new file mode 100644
index 0000000..8912f38
--- /dev/null
+++ b/Include/ast.h
@@ -0,0 +1,13 @@
+#ifndef Py_AST_H
+#define Py_AST_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern DL_IMPORT(mod_ty) PyAST_FromNode(const node *, PyCompilerFlags *flags,
+					const char *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_AST_H */
diff --git a/Include/code.h b/Include/code.h
new file mode 100644
index 0000000..e6478b0
--- /dev/null
+++ b/Include/code.h
@@ -0,0 +1,73 @@
+/* Definitions for bytecode */
+
+#ifndef Py_CODE_H
+#define Py_CODE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Bytecode object */
+typedef struct {
+    PyObject_HEAD
+    int co_argcount;		/* #arguments, except *args */
+    int co_nlocals;		/* #local variables */
+    int co_stacksize;		/* #entries needed for evaluation stack */
+    int co_flags;		/* CO_..., see below */
+    PyObject *co_code;		/* instruction opcodes */
+    PyObject *co_consts;	/* list (constants used) */
+    PyObject *co_names;		/* list of strings (names used) */
+    PyObject *co_varnames;	/* tuple of strings (local variable names) */
+    PyObject *co_freevars;	/* tuple of strings (free variable names) */
+    PyObject *co_cellvars;      /* tuple of strings (cell variable names) */
+    /* The rest doesn't count for hash/cmp */
+    PyObject *co_filename;	/* string (where it was loaded from) */
+    PyObject *co_name;		/* string (name, for reference) */
+    int co_firstlineno;		/* first source line number */
+    PyObject *co_lnotab;	/* string (encoding addr<->lineno mapping) */
+} PyCodeObject;
+
+/* Masks for co_flags above */
+#define CO_OPTIMIZED	0x0001
+#define CO_NEWLOCALS	0x0002
+#define CO_VARARGS	0x0004
+#define CO_VARKEYWORDS	0x0008
+#define CO_NESTED       0x0010
+#define CO_GENERATOR    0x0020
+/* The CO_NOFREE flag is set if there are no free or cell variables.
+   This information is redundant, but it allows a single flag test
+   to determine whether there is any extra work to be done when the
+   call frame it setup.
+*/
+#define CO_NOFREE       0x0040
+/* XXX Temporary hack.  Until generators are a permanent part of the
+   language, we need a way for a code object to record that generators
+   were *possible* when it was compiled.  This is so code dynamically
+   compiled *by* a code object knows whether to allow yield stmts.  In
+   effect, this passes on the "from __future__ import generators" state
+   in effect when the code block was compiled. */
+#define CO_GENERATOR_ALLOWED    0x1000 /* no longer used in an essential way */
+#define CO_FUTURE_DIVISION    	0x2000
+
+#define CO_MAXBLOCKS 20 /* Max static block nesting within a function */
+
+extern DL_IMPORT(PyTypeObject) PyCode_Type;
+
+#define PyCode_Check(op) ((op)->ob_type == &PyCode_Type)
+#define PyCode_GetNumFree(op) (PyTuple_GET_SIZE((op)->co_freevars))
+
+/* Public interface */
+DL_IMPORT(PyCodeObject *) PyCode_New(
+	int, int, int, int, PyObject *, PyObject *, PyObject *, PyObject *,
+	PyObject *, PyObject *, PyObject *, PyObject *, int, PyObject *); 
+        /* same as struct above */
+DL_IMPORT(int) PyCode_Addr2Line(PyCodeObject *, int);
+
+/* for internal use only */
+#define _PyCode_GETCODEPTR(co, pp) \
+	((*(co)->co_code->ob_type->tp_as_buffer->bf_getreadbuffer) \
+	 ((co)->co_code, 0, (void **)(pp)))
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_CODE_H */
diff --git a/Include/compile.h b/Include/compile.h
index 82bf708..27a3f76 100644
--- a/Include/compile.h
+++ b/Include/compile.h
@@ -1,5 +1,6 @@
-
-/* Definitions for bytecode */
+#ifndef Py_CODE_H
+#include "code.h"
+#endif
 
 #ifndef Py_COMPILE_H
 #define Py_COMPILE_H
@@ -7,55 +8,6 @@
 extern "C" {
 #endif
 
-/* Bytecode object */
-typedef struct {
-    PyObject_HEAD
-    int co_argcount;		/* #arguments, except *args */
-    int co_nlocals;		/* #local variables */
-    int co_stacksize;		/* #entries needed for evaluation stack */
-    int co_flags;		/* CO_..., see below */
-    PyObject *co_code;		/* instruction opcodes */
-    PyObject *co_consts;	/* list (constants used) */
-    PyObject *co_names;		/* list of strings (names used) */
-    PyObject *co_varnames;	/* tuple of strings (local variable names) */
-    PyObject *co_freevars;	/* tuple of strings (free variable names) */
-    PyObject *co_cellvars;      /* tuple of strings (cell variable names) */
-    /* The rest doesn't count for hash/cmp */
-    PyObject *co_filename;	/* string (where it was loaded from) */
-    PyObject *co_name;		/* string (name, for reference) */
-    int co_firstlineno;		/* first source line number */
-    PyObject *co_lnotab;	/* string (encoding addr<->lineno mapping) */
-} PyCodeObject;
-
-/* Masks for co_flags above */
-#define CO_OPTIMIZED	0x0001
-#define CO_NEWLOCALS	0x0002
-#define CO_VARARGS	0x0004
-#define CO_VARKEYWORDS	0x0008
-#define CO_NESTED       0x0010
-#define CO_GENERATOR    0x0020
-/* The CO_NOFREE flag is set if there are no free or cell variables.
-   This information is redundant, but it allows a single flag test
-   to determine whether there is any extra work to be done when the
-   call frame it setup.
-*/
-#define CO_NOFREE       0x0040
-/* XXX Temporary hack.  Until generators are a permanent part of the
-   language, we need a way for a code object to record that generators
-   were *possible* when it was compiled.  This is so code dynamically
-   compiled *by* a code object knows whether to allow yield stmts.  In
-   effect, this passes on the "from __future__ import generators" state
-   in effect when the code block was compiled. */
-#define CO_GENERATOR_ALLOWED    0x1000 /* no longer used in an essential way */
-#define CO_FUTURE_DIVISION    	0x2000
-
-PyAPI_DATA(PyTypeObject) PyCode_Type;
-
-#define PyCode_Check(op) ((op)->ob_type == &PyCode_Type)
-#define PyCode_GetNumFree(op) (PyTuple_GET_SIZE((op)->co_freevars))
-
-#define CO_MAXBLOCKS 20 /* Max static block nesting within a function */
-
 /* Public interface */
 struct _node; /* Declare the existence of this type */
 PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);
@@ -68,19 +20,22 @@
 /* Future feature support */
 
 typedef struct {
-    int ff_found_docstring;
-    int ff_last_lineno;
-    int ff_features;
+    int ff_features;      /* flags set by future statements */
+    int ff_lineno;        /* line number of last future statement */
 } PyFutureFeatures;
 
-PyAPI_FUNC(PyFutureFeatures *) PyNode_Future(struct _node *, const char *);
-PyAPI_FUNC(PyCodeObject *) PyNode_CompileFlags(struct _node *, const char *,
-					      PyCompilerFlags *);
-
 #define FUTURE_NESTED_SCOPES "nested_scopes"
 #define FUTURE_GENERATORS "generators"
 #define FUTURE_DIVISION "division"
 
+struct _mod; /* Declare the existence of this type */
+DL_IMPORT(PyCodeObject *) PyAST_Compile(struct _mod *, const char *,
+					PyCompilerFlags *);
+DL_IMPORT(PyFutureFeatures *) PyFuture_FromAST(struct _mod *, const char *);
+
+#define ERR_LATE_FUTURE \
+"from __future__ imports must occur at the beginning of the file"
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Include/pyport.h b/Include/pyport.h
index 2440c55..ea2091b 100644
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -583,6 +583,7 @@
 
 #ifndef INT_MAX
 #define INT_MAX 2147483647
+#define INT_MIN (-INT_MAX - 1)
 #endif
 
 #ifndef LONG_MAX
diff --git a/Include/pythonrun.h b/Include/pythonrun.h
index f461d13..490613e 100644
--- a/Include/pythonrun.h
+++ b/Include/pythonrun.h
@@ -29,46 +29,37 @@
 PyAPI_FUNC(PyThreadState *) Py_NewInterpreter(void);
 PyAPI_FUNC(void) Py_EndInterpreter(PyThreadState *);
 
-PyAPI_FUNC(int) PyRun_AnyFile(FILE *, const char *);
-PyAPI_FUNC(int) PyRun_AnyFileEx(FILE *, const char *, int);
-
-PyAPI_FUNC(int) PyRun_AnyFileFlags(FILE *, const char *, PyCompilerFlags *);
-PyAPI_FUNC(int) PyRun_AnyFileExFlags(FILE *, const char *, int, PyCompilerFlags *);
-
-PyAPI_FUNC(int) PyRun_SimpleString(const char *);
+PyAPI_FUNC(int) PyRun_AnyFileFlags(FILE *, char *, PyCompilerFlags *);
+PyAPI_FUNC(int) PyRun_AnyFileExFlags(FILE *, char *, int, PyCompilerFlags *);
 PyAPI_FUNC(int) PyRun_SimpleStringFlags(const char *, PyCompilerFlags *);
-PyAPI_FUNC(int) PyRun_SimpleFile(FILE *, const char *);
-PyAPI_FUNC(int) PyRun_SimpleFileEx(FILE *, const char *, int);
 PyAPI_FUNC(int) PyRun_SimpleFileExFlags(FILE *, const char *, int, PyCompilerFlags *);
-PyAPI_FUNC(int) PyRun_InteractiveOne(FILE *, const char *);
 PyAPI_FUNC(int) PyRun_InteractiveOneFlags(FILE *, const char *, PyCompilerFlags *);
-PyAPI_FUNC(int) PyRun_InteractiveLoop(FILE *, const char *);
 PyAPI_FUNC(int) PyRun_InteractiveLoopFlags(FILE *, const char *, PyCompilerFlags *);
 
-PyAPI_FUNC(struct _node *) PyParser_SimpleParseString(const char *, int);
-PyAPI_FUNC(struct _node *) PyParser_SimpleParseFile(FILE *, const char *, int);
-PyAPI_FUNC(struct _node *) PyParser_SimpleParseStringFlags(const char *, int, int);
-PyAPI_FUNC(struct _node *) PyParser_SimpleParseStringFlagsFilename(const char *,
-								  const char *,
-								  int,
-								  int);
+PyAPI_FUNC(struct _mod *) PyParser_ASTFromString(const char *, const char *, 
+						 int, PyCompilerFlags *flags);
+PyAPI_FUNC(struct _mod *) PyParser_ASTFromFile(FILE *, const char *, int, 
+					       char *, char *,
+                                               PyCompilerFlags *, int *);
+#define PyParser_SimpleParseString(S, B) \
+        PyParser_SimpleParseStringFlags(S, B, 0)
+#define PyParser_SimpleParseFile(FP, S, B) \
+        PyParser_SimpleParseFileFlags(FP, S, B, 0)
+PyAPI_FUNC(struct _node *) PyParser_SimpleParseStringFlags(const char *, int, 
+							  int);
 PyAPI_FUNC(struct _node *) PyParser_SimpleParseFileFlags(FILE *, const char *,
 							int, int);
 
-PyAPI_FUNC(PyObject *) PyRun_String(const char *, int, PyObject *, PyObject *);
-PyAPI_FUNC(PyObject *) PyRun_File(FILE *, const char *, int, PyObject *, PyObject *);
-PyAPI_FUNC(PyObject *) PyRun_FileEx(FILE *, const char *, int,
-				   PyObject *, PyObject *, int);
-PyAPI_FUNC(PyObject *) PyRun_StringFlags(const char *, int, PyObject *, PyObject *,
-					PyCompilerFlags *);
-PyAPI_FUNC(PyObject *) PyRun_FileFlags(FILE *, const char *, int, PyObject *, 
-				      PyObject *, PyCompilerFlags *);
-PyAPI_FUNC(PyObject *) PyRun_FileExFlags(FILE *, const char *, int, PyObject *, 
-					PyObject *, int, PyCompilerFlags *);
+PyAPI_FUNC(PyObject *) PyRun_StringFlags(const char *, int, PyObject *, 
+					 PyObject *, PyCompilerFlags *);
 
-PyAPI_FUNC(PyObject *) Py_CompileString(const char *, const char *, int);
+PyAPI_FUNC(PyObject *) PyRun_FileExFlags(FILE *, const char *, int, 
+					 PyObject *, PyObject *, int, 
+					 PyCompilerFlags *);
+
+#define Py_CompileString(str, p, s) Py_CompileStringFlags(str, p, s, NULL)
 PyAPI_FUNC(PyObject *) Py_CompileStringFlags(const char *, const char *, int,
-					    PyCompilerFlags *);
+					     PyCompilerFlags *);
 PyAPI_FUNC(struct symtable *) Py_SymtableString(const char *, const char *, int);
 
 PyAPI_FUNC(void) PyErr_Print(void);
@@ -84,6 +75,25 @@
 /* Bootstrap */
 PyAPI_FUNC(int) Py_Main(int argc, char **argv);
 
+/* Use macros for a bunch of old variants */
+#define PyRun_String(str, s, g, l) PyRun_StringFlags(str, s, g, l, NULL)
+#define PyRun_AnyFile(fp, name) PyRun_AnyFileExFlags(fp, name, 0, NULL)
+#define PyRun_AnyFileEx(fp, name, closeit) \
+	PyRun_AnyFileExFlags(fp, name, closeit, NULL)
+#define PyRun_AnyFileFlags(fp, name, flags) \
+	PyRun_AnyFileExFlags(fp, name, 0, flags)
+#define PyRun_SimpleString(s, f) PyRunSimpleStringFlags(s, f, NULL)
+#define PyRun_SimpleFile(f, p) PyRun_SimpleFileExFlags(f, p, 0, NULL)
+#define PyRun_SimpleFileEx(f, p, c) PyRun_SimpleFileExFlags(f, p, c, NULL)
+#define PyRun_InteractiveOne(f, p) PyRun_InteractiveOneFlags(f, p, NULL)
+#define PyRun_InteractiveLoop(f, p) PyRun_InteractiveLoopFlags(f, p, NULL)
+#define PyRun_File(fp, p, s, g, l) \
+        PyRun_FileExFlags(fp, p, s, g, l, 0, NULL)
+#define PyRun_FileEx(fp, p, s, g, l, c) \
+        PyRun_FileExFlags(fp, p, s, g, l, c, NULL)
+#define PyRun_FileFlags(fp, p, s, g, l, flags) \
+        PyRun_FileExFlags(fp, p, s, g, l, 0, flags)
+
 /* In getpath.c */
 PyAPI_FUNC(char *) Py_GetProgramFullPath(void);
 PyAPI_FUNC(char *) Py_GetPrefix(void);
diff --git a/Include/symtable.h b/Include/symtable.h
index 628c3e6..646602c 100644
--- a/Include/symtable.h
+++ b/Include/symtable.h
@@ -4,65 +4,60 @@
 extern "C" {
 #endif
 
-/* A symbol table is constructed each time PyNode_Compile() is
-   called.  The table walks the entire parse tree and identifies each
-   use or definition of a variable. 
-
-   The symbol table contains a dictionary for each code block in a
-   module: The symbol dictionary for the block.  They keys of these
-   dictionaries are the name of all variables used or defined in the
-   block; the integer values are used to store several flags,
-   e.g. DEF_PARAM indicates that a variable is a parameter to a
-   function. 
-*/
+typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock }
+    block_ty;
 
 struct _symtable_entry;
 
 struct symtable {
-	int st_pass;             /* pass == 1 or 2 */
 	const char *st_filename; /* name of file being compiled */
 	struct _symtable_entry *st_cur; /* current symbol table entry */
+	struct _symtable_entry *st_top; /* module entry */
 	PyObject *st_symbols;    /* dictionary of symbol table entries */
         PyObject *st_stack;      /* stack of namespace info */
 	PyObject *st_global;     /* borrowed ref to MODULE in st_symbols */
-	int st_nscopes;          /* number of scopes */
-	int st_errors;           /* number of errors */
+	int st_nblocks;          /* number of blocks */
 	char *st_private;        /* name of current class or NULL */
+        int st_tmpname;          /* temporary name counter */
 	PyFutureFeatures *st_future; /* module's future features */
 };
 
 typedef struct _symtable_entry {
 	PyObject_HEAD
-	PyObject *ste_id;        /* int: key in st_symbols) */
-	PyObject *ste_symbols;   /* dict: name to flags) */
-	PyObject *ste_name;      /* string: name of scope */
+	PyObject *ste_id;        /* int: key in st_symbols */
+	PyObject *ste_symbols;   /* dict: name to flags */
+	PyObject *ste_name;      /* string: name of block */
 	PyObject *ste_varnames;  /* list of variable names */
 	PyObject *ste_children;  /* list of child ids */
-	int ste_type;            /* module, class, or function */
-	int ste_lineno;          /* first line of scope */
-	int ste_optimized;       /* true if namespace can't be optimized */
-	int ste_nested;          /* true if scope is nested */
-	int ste_child_free;      /* true if a child scope has free variables,
+	block_ty ste_type;       /* module, class, or function */
+	int ste_unoptimized;     /* false if namespace is optimized */
+	int ste_nested : 1;      /* true if block is nested */
+	int ste_free : 1;        /* true if block has free variables */
+	int ste_child_free : 1;  /* true if a child block has free variables,
 				    including free refs to globals */
-	int ste_generator;       /* true if namespace is a generator */
+	int ste_generator : 1;   /* true if namespace is a generator */
+	int ste_varargs : 1;     /* true if block has varargs */
+	int ste_varkeywords : 1; /* true if block has varkeywords */
+	int ste_lineno;          /* first line of block */
 	int ste_opt_lineno;      /* lineno of last exec or import * */
-	int ste_tmpname;         /* temporary name counter */
+	int ste_tmpname;         /* counter for listcomp temp vars */
 	struct symtable *ste_table;
-} PySymtableEntryObject;
+} PySTEntryObject;
 
-PyAPI_DATA(PyTypeObject) PySymtableEntry_Type;
+PyAPI_DATA(PyTypeObject) PySTEntry_Type;
 
-#define PySymtableEntry_Check(op) ((op)->ob_type == &PySymtableEntry_Type)
+#define PySTEntry_Check(op) ((op)->ob_type == &PySTEntry_Type)
 
-PyAPI_FUNC(PyObject *) PySymtableEntry_New(struct symtable *,
-						 char *, int, int);
+PyAPI_FUNC(PySTEntryObject *) \
+	PySTEntry_New(struct symtable *, identifier, block_ty, void *, int);
+PyAPI_FUNC(int) PyST_GetScope(PySTEntryObject *, PyObject *);
 
-PyAPI_FUNC(struct symtable *) PyNode_CompileSymtable(struct _node *, const char *);
+PyAPI_FUNC(struct symtable *) PySymtable_Build(mod_ty, const char *, 
+					      PyFutureFeatures *);
+PyAPI_FUNC(PySTEntryObject *) PySymtable_Lookup(struct symtable *, void *);
+
 PyAPI_FUNC(void) PySymtable_Free(struct symtable *);
 
-
-#define TOP "global"
-
 /* Flags for def-use information */
 
 #define DEF_GLOBAL 1           /* global stmt */
@@ -72,16 +67,19 @@
 #define DEF_STAR 2<<3          /* parameter is star arg */
 #define DEF_DOUBLESTAR 2<<4    /* parameter is star-star arg */
 #define DEF_INTUPLE 2<<5       /* name defined in tuple in parameters */
-#define DEF_FREE 2<<6          /* name used but not defined in nested scope */
+#define DEF_FREE 2<<6          /* name used but not defined in nested block */
 #define DEF_FREE_GLOBAL 2<<7   /* free variable is actually implicit global */
 #define DEF_FREE_CLASS 2<<8    /* free variable from class's method */
 #define DEF_IMPORT 2<<9        /* assignment occurred via import */
 
 #define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT)
 
-#define TYPE_FUNCTION 1
-#define TYPE_CLASS 2
-#define TYPE_MODULE 3
+/* GLOBAL_EXPLICIT and GLOBAL_IMPLICIT are used internally by the symbol
+   table.  GLOBAL is returned from PyST_GetScope() for either of them. 
+   It is stored in ste_symbols at bits 12-14.
+*/
+#define SCOPE_OFF 11
+#define SCOPE_MASK 7
 
 #define LOCAL 1
 #define GLOBAL_EXPLICIT 2
@@ -89,9 +87,14 @@
 #define FREE 4
 #define CELL 5
 
+/* The following three names are used for the ste_unoptimized bit field */
 #define OPT_IMPORT_STAR 1
 #define OPT_EXEC 2
 #define OPT_BARE_EXEC 4
+#define OPT_TOPLEVEL 8  /* top-level names, including eval and exec */
+
+#define GENERATOR 1
+#define GENERATOR_EXPRESSION 2
 
 #define GENERATOR 1
 #define GENERATOR_EXPRESSION 2
diff --git a/Lib/cgitb.py b/Lib/cgitb.py
index 8d979b8..ae25cf1 100644
--- a/Lib/cgitb.py
+++ b/Lib/cgitb.py
@@ -22,6 +22,7 @@
 """
 
 __author__ = 'Ka-Ping Yee'
+
 __version__ = '$Revision$'
 
 import sys
diff --git a/Lib/compiler/pyassem.py b/Lib/compiler/pyassem.py
index 0547eeb..e1fb063 100644
--- a/Lib/compiler/pyassem.py
+++ b/Lib/compiler/pyassem.py
@@ -364,16 +364,15 @@
 
     def getCode(self):
         """Get a Python code object"""
-        if self.stage == RAW:
-            self.computeStackDepth()
-            self.flattenGraph()
-        if self.stage == FLAT:
-            self.convertArgs()
-        if self.stage == CONV:
-            self.makeByteCode()
-        if self.stage == DONE:
-            return self.newCodeObject()
-        raise RuntimeError, "inconsistent PyFlowGraph state"
+        assert self.stage == RAW
+        self.computeStackDepth()
+        self.flattenGraph()
+        assert self.stage == FLAT
+        self.convertArgs()
+        assert self.stage == CONV
+        self.makeByteCode()
+        assert self.stage == DONE
+        return self.newCodeObject()
 
     def dump(self, io=None):
         if io:
diff --git a/Lib/pydoc.py b/Lib/pydoc.py
index 4084b7e..5d16fa5 100755
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -36,6 +36,7 @@
 
 __author__ = "Ka-Ping Yee <ping@lfw.org>"
 __date__ = "26 February 2001"
+
 __version__ = "$Revision$"
 __credits__ = """Guido van Rossum, for an excellent programming language.
 Tommy Burnette, the original creator of manpy.
diff --git a/Lib/test/output/test_grammar b/Lib/test/output/test_grammar
index 6174e7a..fed4197 100644
--- a/Lib/test/output/test_grammar
+++ b/Lib/test/output/test_grammar
@@ -34,6 +34,7 @@
 continue + try/finally ok
 testing continue and break in try/except in loop
 return_stmt
+yield_stmt
 raise_stmt
 import_name
 import_from
diff --git a/Lib/test/output/test_profile b/Lib/test/output/test_profile
index b46bb6a..e745075 100644
--- a/Lib/test/output/test_profile
+++ b/Lib/test/output/test_profile
@@ -7,7 +7,7 @@
        12    0.000    0.000    0.012    0.001 :0(hasattr)
         8    0.000    0.000    0.000    0.000 :0(range)
         1    0.000    0.000    0.000    0.000 :0(setprofile)
-        1    0.000    0.000    1.000    1.000 <string>:1(?)
+        1    0.000    0.000    1.000    1.000 <string>:1(<module>)
         0    0.000             0.000          profile:0(profiler)
         1    0.000    0.000    1.000    1.000 profile:0(testfunc())
         1    0.400    0.400    1.000    1.000 test_profile.py:23(testfunc)
diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py
new file mode 100644
index 0000000..ff95c6a
--- /dev/null
+++ b/Lib/test/test_code.py
@@ -0,0 +1,85 @@
+"""This module includes tests of the code object representation.
+
+>>> def f(x):
+...     def g(y):
+...         return x + y
+...     return g
+...
+
+>>> dump(f.func_code)
+name: f
+argcount: 1
+names: ()
+varnames: ('x', 'g')
+cellvars: ('x',)
+freevars: ()
+nlocals: 2
+flags: 3
+consts: ('None', '<code object g>')
+
+>>> dump(f(4).func_code)
+name: g
+argcount: 1
+names: ()
+varnames: ('y',)
+cellvars: ()
+freevars: ('x',)
+nlocals: 1
+flags: 19
+consts: ('None',)
+
+>>> def h(x, y):
+...     a = x + y
+...     b = x - y
+...     c = a * b
+...     return c
+... 
+>>> dump(h.func_code)
+name: h
+argcount: 2
+names: ()
+varnames: ('x', 'y', 'a', 'b', 'c')
+cellvars: ()
+freevars: ()
+nlocals: 5
+flags: 67
+consts: ('None',)
+
+>>> def attrs(obj):
+...     print obj.attr1
+...     print obj.attr2
+...     print obj.attr3
+
+>>> dump(attrs.func_code)
+name: attrs
+argcount: 1
+names: ('attr1', 'attr2', 'attr3')
+varnames: ('obj',)
+cellvars: ()
+freevars: ()
+nlocals: 1
+flags: 67
+consts: ('None',)
+
+"""
+
+def consts(t):
+    """Yield a doctest-safe sequence of object reprs."""
+    for elt in t:
+        r = repr(elt)
+        if r.startswith("<code object"):
+            yield "<code object %s>" % elt.co_name
+        else:
+            yield r
+
+def dump(co):
+    """Print out a text representation of a code object."""
+    for attr in ["name", "argcount", "names", "varnames", "cellvars",
+                 "freevars", "nlocals", "flags"]:
+        print "%s: %s" % (attr, getattr(co, "co_" + attr))
+    print "consts:", tuple(consts(co.co_consts))
+
+def test_main(verbose=None):
+    from test.test_support import run_doctest
+    from test import test_code
+    run_doctest(test_code, verbose)
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py
index fc4841a..9c39ee8 100644
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -1559,11 +1559,11 @@
 
     >>> try: doctest.debug_src(s)
     ... finally: sys.stdin = real_stdin
-    > <string>(1)?()
+    > <string>(1)<module>()
     (Pdb) next
     12
     --Return--
-    > <string>(1)?()->None
+    > <string>(1)<module>()->None
     (Pdb) print x
     12
     (Pdb) continue
@@ -1601,7 +1601,7 @@
       >>> try: runner.run(test)
       ... finally: sys.stdin = real_stdin
       --Return--
-      > <doctest foo[1]>(1)?()->None
+      > <doctest foo[1]>(1)<module>()->None
       -> import pdb; pdb.set_trace()
       (Pdb) print x
       42
@@ -1637,7 +1637,7 @@
       (Pdb) print y
       2
       (Pdb) up
-      > <doctest foo[1]>(1)?()
+      > <doctest foo[1]>(1)<module>()
       -> calls_set_trace()
       (Pdb) print x
       1
@@ -1686,7 +1686,7 @@
       [EOF]
       (Pdb) next
       --Return--
-      > <doctest foo[2]>(1)?()->None
+      > <doctest foo[2]>(1)<module>()->None
       -> f(3)
       (Pdb) list
         1  -> f(3)
@@ -1779,7 +1779,7 @@
     (Pdb) print y
     1
     (Pdb) up
-    > <doctest foo[1]>(1)?()
+    > <doctest foo[1]>(1)<module>()
     -> calls_set_trace()
     (Pdb) print foo
     *** NameError: name 'foo' is not defined
diff --git a/Lib/test/test_eof.py b/Lib/test/test_eof.py
index 683649d..aae3518 100644
--- a/Lib/test/test_eof.py
+++ b/Lib/test/test_eof.py
@@ -7,21 +7,21 @@
 
 class EOFTestCase(unittest.TestCase):
     def test_EOFC(self):
+        expect = "EOL while scanning single-quoted string (<string>, line 1)"
         try:
             eval("""'this is a test\
             """)
         except SyntaxError, msg:
-            self.assertEqual(str(msg),
-                             "EOL while scanning single-quoted string (line 1)")
+            self.assertEqual(str(msg), expect)
         else:
             raise test_support.TestFailed
 
     def test_EOFS(self):
+        expect = "EOF while scanning triple-quoted string (<string>, line 1)"
         try:
             eval("""'''this is a test""")
         except SyntaxError, msg:
-            self.assertEqual(str(msg),
-                             "EOF while scanning triple-quoted string (line 1)")
+            self.assertEqual(str(msg), expect)
         else:
             raise test_support.TestFailed
 
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index d226043..cb7e992 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -774,7 +774,7 @@
 ...         try:
 ...             1//0
 ...         except ZeroDivisionError:
-...             yield 666  # bad because *outer* try has finally
+...             yield 666 
 ...         except:
 ...             pass
 ...     finally:
diff --git a/Lib/test/test_genexps.py b/Lib/test/test_genexps.py
index 7c6fe4a..894ce6a 100644
--- a/Lib/test/test_genexps.py
+++ b/Lib/test/test_genexps.py
@@ -125,13 +125,12 @@
     >>> (y for y in (1,2)) = 10
     Traceback (most recent call last):
        ...
-    SyntaxError: assign to generator expression not possible
+    SyntaxError: assignment to generator expression not possible (<doctest test.test_genexps.__test__.doctests[38]>, line 1)
 
     >>> (y for y in (1,2)) += 10
     Traceback (most recent call last):
        ...
-    SyntaxError: augmented assign to tuple literal, yield, or generator expression not possible
-
+    SyntaxError: augmented assignment to generator expression not possible (<doctest test.test_genexps.__test__.doctests[39]>, line 1)
 
 
 ########### Tests borrowed from or inspired by test_generators.py ############
diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py
index 1b4a506..820fab5 100644
--- a/Lib/test/test_grammar.py
+++ b/Lib/test/test_grammar.py
@@ -8,7 +8,7 @@
 # regression test, the filterwarnings() call has been added to
 # regrtest.py.
 
-from test.test_support import TestFailed, verify, check_syntax
+from test.test_support import TestFailed, verify, vereq, check_syntax
 import sys
 
 print '1. Parser'
@@ -157,28 +157,31 @@
 def f3(two, arguments): pass
 def f4(two, (compound, (argument, list))): pass
 def f5((compound, first), two): pass
-verify(f2.func_code.co_varnames == ('one_argument',))
-verify(f3.func_code.co_varnames == ('two', 'arguments'))
+vereq(f2.func_code.co_varnames, ('one_argument',))
+vereq(f3.func_code.co_varnames, ('two', 'arguments'))
 if sys.platform.startswith('java'):
-    verify(f4.func_code.co_varnames ==
+    vereq(f4.func_code.co_varnames,
            ('two', '(compound, (argument, list))', 'compound', 'argument',
                         'list',))
-    verify(f5.func_code.co_varnames ==
+    vereq(f5.func_code.co_varnames,
            ('(compound, first)', 'two', 'compound', 'first'))
 else:
-    verify(f4.func_code.co_varnames == ('two', '.2', 'compound',
-                                        'argument',  'list'))
-    verify(f5.func_code.co_varnames == ('.0', 'two', 'compound', 'first'))
+    vereq(f4.func_code.co_varnames,
+          ('two', '.1', 'compound', 'argument',  'list'))
+    vereq(f5.func_code.co_varnames,
+          ('.0', 'two', 'compound', 'first'))
 def a1(one_arg,): pass
 def a2(two, args,): pass
 def v0(*rest): pass
 def v1(a, *rest): pass
 def v2(a, b, *rest): pass
 def v3(a, (b, c), *rest): return a, b, c, rest
+# ceval unpacks the formal arguments into the first argcount names;
+# thus, the names nested inside tuples must appear after these names.
 if sys.platform.startswith('java'):
     verify(v3.func_code.co_varnames == ('a', '(b, c)', 'rest', 'b', 'c'))
 else:
-    verify(v3.func_code.co_varnames == ('a', '.2', 'rest', 'b', 'c'))
+    vereq(v3.func_code.co_varnames, ('a', '.1', 'rest', 'b', 'c'))
 verify(v3(1, (2, 3), 4) == (1, 2, 3, (4,)))
 def d01(a=1): pass
 d01()
@@ -410,6 +413,10 @@
 def g2(): return 1
 g1()
 x = g2()
+check_syntax("class foo:return 1")
+
+print 'yield_stmt'
+check_syntax("class foo:yield 1")
 
 print 'raise_stmt' # 'raise' test [',' test]
 try: raise RuntimeError, 'just testing'
diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py
index b89f09b..72f27fa 100644
--- a/Lib/test/test_import.py
+++ b/Lib/test/test_import.py
@@ -192,3 +192,16 @@
             del sys.modules[TESTFN]
 
 test_failing_reload()
+
+def test_import_name_binding():
+    # import x.y.z binds x in the current namespace
+    import test as x
+    import test.test_support
+    assert x is test, x.__name__
+    assert hasattr(test.test_support, "__file__")
+
+    # import x.y.z as w binds z as w
+    import test.test_support as y
+    assert y is test.test_support, y.__name__
+
+test_import_name_binding()
diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py
index d1ace67..771fe9d 100644
--- a/Lib/test/test_parser.py
+++ b/Lib/test/test_parser.py
@@ -411,10 +411,32 @@
                 (0, ''))
         self.check_bad_tree(tree, "malformed global ast")
 
+
+class CompileTestCase(unittest.TestCase):
+
+    # These tests are very minimal. :-(
+
+    def test_compile_expr(self):
+        st = parser.expr('2 + 3')
+        code = parser.compilest(st)
+        self.assertEquals(eval(code), 5)
+
+    def test_compile_suite(self):
+        st = parser.suite('x = 2; y = x + 3')
+        code = parser.compilest(st)
+        globs = {}
+        exec code in globs
+        self.assertEquals(globs['y'], 5)
+
+    def test_compile_error(self):
+        st = parser.suite('1 = 3 + 4')
+        self.assertRaises(SyntaxError, parser.compilest, st)
+
 def test_main():
     test_support.run_unittest(
         RoundtripLegalSyntaxTestCase,
-        IllegalSyntaxTestCase
+        IllegalSyntaxTestCase,
+        CompileTestCase,
     )
 
 
diff --git a/Lib/test/test_repr.py b/Lib/test/test_repr.py
index 4ded484..a139473 100644
--- a/Lib/test/test_repr.py
+++ b/Lib/test/test_repr.py
@@ -123,7 +123,7 @@
 
     def test_lambda(self):
         self.failUnless(repr(lambda x: x).startswith(
-            "<function <lambda"))
+            "<function lambda"))
         # XXX anonymous functions?  see func_repr
 
     def test_builtin_function(self):
diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py
index bf9a658..34801bd 100644
--- a/Lib/test/test_scope.py
+++ b/Lib/test/test_scope.py
@@ -1,4 +1,4 @@
-from test.test_support import verify, TestFailed, check_syntax
+from test.test_support import verify, TestFailed, check_syntax, vereq
 
 import warnings
 warnings.filterwarnings("ignore", r"import \*", SyntaxWarning, "<string>")
@@ -13,8 +13,8 @@
 inc = make_adder(1)
 plus10 = make_adder(10)
 
-verify(inc(1) == 2)
-verify(plus10(-2) == 8)
+vereq(inc(1), 2)
+vereq(plus10(-2), 8)
 
 print "2. extra nesting"
 
@@ -28,8 +28,8 @@
 inc = make_adder2(1)
 plus10 = make_adder2(10)
 
-verify(inc(1) == 2)
-verify(plus10(-2) == 8)
+vereq(inc(1), 2)
+vereq(plus10(-2), 8)
 
 print "3. simple nesting + rebinding"
 
@@ -42,8 +42,8 @@
 inc = make_adder3(0)
 plus10 = make_adder3(9)
 
-verify(inc(1) == 2)
-verify(plus10(-2) == 8)
+vereq(inc(1), 2)
+vereq(plus10(-2), 8)
 
 print "4. nesting with global but no free"
 
@@ -58,10 +58,10 @@
 
 global_x = 1
 adder = make_adder4()
-verify(adder(1) == 2)
+vereq(adder(1), 2)
 
 global_x = 10
-verify(adder(-2) == 8)
+vereq(adder(-2), 8)
 
 print "5. nesting through class"
 
@@ -74,8 +74,8 @@
 inc = make_adder5(1)
 plus10 = make_adder5(10)
 
-verify(inc(1) == 2)
-verify(plus10(-2) == 8)
+vereq(inc(1), 2)
+vereq(plus10(-2), 8)
 
 print "6. nesting plus free ref to global"
 
@@ -89,8 +89,8 @@
 inc = make_adder6(1)
 plus10 = make_adder6(10)
 
-verify(inc(1) == 11) # there's only one global
-verify(plus10(-2) == 8)
+vereq(inc(1), 11) # there's only one global
+vereq(plus10(-2), 8)
 
 print "7. nearest enclosing scope"
 
@@ -103,7 +103,7 @@
     return g(2)
 
 test_func = f(10)
-verify(test_func(5) == 47)
+vereq(test_func(5), 47)
 
 print "8. mixed freevars and cellvars"
 
@@ -123,7 +123,7 @@
 
 g = f(1, 2, 3)
 h = g(2, 4, 6)
-verify(h() == 39)
+vereq(h(), 39)
 
 print "9. free variable in method"
 
@@ -141,9 +141,9 @@
     return Test()
 
 t = test()
-verify(t.test() == "var")
-verify(t.method_and_var() == "method")
-verify(t.actual_global() == "global")
+vereq(t.test(), "var")
+vereq(t.method_and_var(), "method")
+vereq(t.actual_global(), "global")
 
 method_and_var = "var"
 class Test:
@@ -158,9 +158,9 @@
         return str(self)
 
 t = Test()
-verify(t.test() == "var")
-verify(t.method_and_var() == "method")
-verify(t.actual_global() == "global")
+vereq(t.test(), "var")
+vereq(t.method_and_var(), "method")
+vereq(t.actual_global(), "global")
 
 print "10. recursion"
 
@@ -175,7 +175,7 @@
     else:
         raise ValueError, "x must be >= 0"
 
-verify(f(6) == 720)
+vereq(f(6), 720)
 
 
 print "11. unoptimized namespaces"
@@ -252,24 +252,24 @@
 f1 = lambda x: lambda y: x + y
 inc = f1(1)
 plus10 = f1(10)
-verify(inc(1) == 2)
-verify(plus10(5) == 15)
+vereq(inc(1), 2)
+vereq(plus10(5), 15)
 
 f2 = lambda x: (lambda : lambda y: x + y)()
 inc = f2(1)
 plus10 = f2(10)
-verify(inc(1) == 2)
-verify(plus10(5) == 15)
+vereq(inc(1), 2)
+vereq(plus10(5), 15)
 
 f3 = lambda x: lambda y: global_x + y
 global_x = 1
 inc = f3(None)
-verify(inc(2) == 3)
+vereq(inc(2), 3)
 
 f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y)
 g = f8(1, 2, 3)
 h = g(2, 4, 6)
-verify(h() == 18)
+vereq(h(), 18)
 
 print "13. UnboundLocal"
 
@@ -306,21 +306,21 @@
         return lst
     return returner
 
-verify(makeReturner(1,2,3)() == (1,2,3))
+vereq(makeReturner(1,2,3)(), (1,2,3))
 
 def makeReturner2(**kwargs):
     def returner():
         return kwargs
     return returner
 
-verify(makeReturner2(a=11)()['a'] == 11)
+vereq(makeReturner2(a=11)()['a'], 11)
 
 def makeAddPair((a, b)):
     def addPair((c, d)):
         return (a + c, b + d)
     return addPair
 
-verify(makeAddPair((1, 2))((100, 200)) == (101,202))
+vereq(makeAddPair((1, 2))((100, 200)), (101,202))
 
 print "15. scope of global statements"
 # Examples posted by Samuele Pedroni to python-dev on 3/1/2001
@@ -337,8 +337,8 @@
             return h()
         return i()
     return g()
-verify(f() == 7)
-verify(x == 7)
+vereq(f(), 7)
+vereq(x, 7)
 
 # II
 x = 7
@@ -352,8 +352,8 @@
             return h()
         return i()
     return g()
-verify(f() == 2)
-verify(x == 7)
+vereq(f(), 2)
+vereq(x, 7)
 
 # III
 x = 7
@@ -368,8 +368,8 @@
             return h()
         return i()
     return g()
-verify(f() == 2)
-verify(x == 2)
+vereq(f(), 2)
+vereq(x, 2)
 
 # IV
 x = 7
@@ -384,8 +384,25 @@
             return h()
         return i()
     return g()
-verify(f() == 2)
-verify(x == 2)
+vereq(f(), 2)
+vereq(x, 2)
+
+# XXX what about global statements in class blocks?
+# do they affect methods?
+
+x = 12
+class Global:
+    global x
+    x = 13
+    def set(self, val):
+        x = val
+    def get(self):
+        return x
+
+g = Global()
+vereq(g.get(), 13)
+g.set(15)
+vereq(g.get(), 13)
 
 print "16. check leaks"
 
@@ -407,7 +424,7 @@
 for i in range(100):
     f1()
 
-verify(Foo.count == 0)
+vereq(Foo.count, 0)
 
 print "17. class and global"
 
@@ -419,9 +436,9 @@
     return Foo()
 
 x = 0
-verify(test(6)(2) == 8)
+vereq(test(6)(2), 8)
 x = -1
-verify(test(3)(2) == 5)
+vereq(test(3)(2), 5)
 
 print "18. verify that locals() works"
 
@@ -437,7 +454,7 @@
 d = f(2)(4)
 verify(d.has_key('h'))
 del d['h']
-verify(d == {'x': 2, 'y': 7, 'w': 6})
+vereq(d, {'x': 2, 'y': 7, 'w': 6})
 
 print "19. var is bound and free in class"
 
@@ -449,7 +466,7 @@
     return C
 
 inst = f(3)()
-verify(inst.a == inst.m())
+vereq(inst.a, inst.m())
 
 print "20. interaction with trace function"
 
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 66bc88a..7a69a6b 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -216,10 +216,22 @@
 
 PGENOBJS=	$(PGENMAIN) $(POBJS) $(PGOBJS)
 
+##########################################################################
+# AST
+AST_H=		$(srcdir)/Include/Python-ast.h
+AST_C=		$(srcdir)/Python/Python-ast.c
+AST_ASDL=	$(srcdir)/Parser/Python.asdl
+
+ASDLGEN_FILES=	$(srcdir)/Parser/asdl.py $(srcdir)/Parser/asdl_c.py
+# XXX Note that a build now requires Python exist before the build starts
+ASDLGEN=	$(srcdir)/Parser/asdl_c.py -h $(srcdir)/Include -c $(srcdir)/Python
 
 ##########################################################################
 # Python
 PYTHON_OBJS=	\
+		Python/Python-ast.o \
+		Python/asdl.o \
+		Python/ast.o \
 		Python/bltinmodule.o \
 		Python/exceptions.o \
 		Python/ceval.o \
@@ -265,6 +277,7 @@
 		Objects/cellobject.o \
 		Objects/classobject.o \
 		Objects/cobject.o \
+		Objects/codeobject.o \
 		Objects/complexobject.o \
 		Objects/descrobject.o \
 		Objects/enumobject.o \
@@ -457,8 +470,10 @@
 
 Parser/tokenizer_pgen.o:	$(srcdir)/Parser/tokenizer.c
 
+$(AST_H) $(AST_C): $(AST_ASDL) $(ASDLGEN_FILES)
+	$(ASDLGEN) $(AST_ASDL)
 
-Python/compile.o Python/symtable.o: $(GRAMMAR_H)
+Python/compile.o Python/symtable.o: $(GRAMMAR_H) $(AST_H)
 
 Python/getplatform.o: $(srcdir)/Python/getplatform.c
 		$(CC) -c $(PY_CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c
@@ -474,12 +489,15 @@
 
 PYTHON_HEADERS= \
 		Include/Python.h \
+		Include/Python-ast.h \
+		Include/asdl.h \
 		Include/abstract.h \
 		Include/boolobject.h \
 		Include/bufferobject.h \
 		Include/ceval.h \
 		Include/classobject.h \
 		Include/cobject.h \
+		Include/code.h \
 		Include/codecs.h \
 		Include/compile.h \
 		Include/complexobject.h \
diff --git a/Misc/ACKS b/Misc/ACKS
index 58a2c86..b95902a 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -165,6 +165,7 @@
 Maxim Dzumanenko
 Hans Eckardt
 Grant Edwards
+John Ehresman
 Andrew Eland
 Lance Ellinghaus
 David Ely
diff --git a/Modules/_hotshot.c b/Modules/_hotshot.c
index b75b1a3..0842728 100644
--- a/Modules/_hotshot.c
+++ b/Modules/_hotshot.c
@@ -3,6 +3,7 @@
  */
 
 #include "Python.h"
+#include "code.h"
 #include "compile.h"
 #include "eval.h"
 #include "frameobject.h"
diff --git a/Modules/symtablemodule.c b/Modules/symtablemodule.c
index 909a404..7a52aae 100644
--- a/Modules/symtablemodule.c
+++ b/Modules/symtablemodule.c
@@ -1,6 +1,8 @@
 #include "Python.h"
 
+#include "code.h"
 #include "compile.h"
+#include "Python-ast.h"
 #include "symtable.h"
 
 static PyObject *
@@ -64,9 +66,9 @@
 	PyModule_AddIntConstant(m, "DEF_IMPORT", DEF_IMPORT);
 	PyModule_AddIntConstant(m, "DEF_BOUND", DEF_BOUND);
 
-	PyModule_AddIntConstant(m, "TYPE_FUNCTION", TYPE_FUNCTION);
-	PyModule_AddIntConstant(m, "TYPE_CLASS", TYPE_CLASS);
-	PyModule_AddIntConstant(m, "TYPE_MODULE", TYPE_MODULE);
+	PyModule_AddIntConstant(m, "TYPE_FUNCTION", FunctionBlock);
+	PyModule_AddIntConstant(m, "TYPE_CLASS", ClassBlock);
+	PyModule_AddIntConstant(m, "TYPE_MODULE", ModuleBlock);
 
 	PyModule_AddIntConstant(m, "OPT_IMPORT_STAR", OPT_IMPORT_STAR);
 	PyModule_AddIntConstant(m, "OPT_EXEC", OPT_EXEC);
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
new file mode 100644
index 0000000..c5ddfd5
--- /dev/null
+++ b/Objects/codeobject.c
@@ -0,0 +1,453 @@
+#include "Python.h"
+#include "code.h"
+#include "structmember.h"
+
+#define NAME_CHARS \
+	"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
+
+/* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */
+
+static int
+all_name_chars(unsigned char *s)
+{
+	static char ok_name_char[256];
+	static unsigned char *name_chars = (unsigned char *)NAME_CHARS;
+
+	if (ok_name_char[*name_chars] == 0) {
+		unsigned char *p;
+		for (p = name_chars; *p; p++)
+			ok_name_char[*p] = 1;
+	}
+	while (*s) {
+		if (ok_name_char[*s++] == 0)
+			return 0;
+	}
+	return 1;
+}
+
+static void
+intern_strings(PyObject *tuple)
+{
+	int i;
+
+	for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
+		PyObject *v = PyTuple_GET_ITEM(tuple, i);
+		if (v == NULL || !PyString_CheckExact(v)) {
+			Py_FatalError("non-string found in code slot");
+		}
+		PyString_InternInPlace(&PyTuple_GET_ITEM(tuple, i));
+	}
+}
+
+
+PyCodeObject *
+PyCode_New(int argcount, int nlocals, int stacksize, int flags,
+	   PyObject *code, PyObject *consts, PyObject *names,
+	   PyObject *varnames, PyObject *freevars, PyObject *cellvars,
+	   PyObject *filename, PyObject *name, int firstlineno,
+	   PyObject *lnotab)
+{
+	PyCodeObject *co;
+	int i;
+	/* Check argument types */
+	if (argcount < 0 || nlocals < 0 ||
+	    code == NULL ||
+	    consts == NULL || !PyTuple_Check(consts) ||
+	    names == NULL || !PyTuple_Check(names) ||
+	    varnames == NULL || !PyTuple_Check(varnames) ||
+	    freevars == NULL || !PyTuple_Check(freevars) ||
+	    cellvars == NULL || !PyTuple_Check(cellvars) ||
+	    name == NULL || !PyString_Check(name) ||
+	    filename == NULL || !PyString_Check(filename) ||
+	    lnotab == NULL || !PyString_Check(lnotab) ||
+	    !PyObject_CheckReadBuffer(code)) {
+		PyErr_BadInternalCall();
+		return NULL;
+	}
+	intern_strings(names);
+	intern_strings(varnames);
+	intern_strings(freevars);
+	intern_strings(cellvars);
+	/* Intern selected string constants */
+	for (i = PyTuple_Size(consts); --i >= 0; ) {
+		PyObject *v = PyTuple_GetItem(consts, i);
+		if (!PyString_Check(v))
+			continue;
+		if (!all_name_chars((unsigned char *)PyString_AS_STRING(v)))
+			continue;
+		PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i));
+	}
+	co = PyObject_NEW(PyCodeObject, &PyCode_Type);
+	if (co != NULL) {
+		co->co_argcount = argcount;
+		co->co_nlocals = nlocals;
+		co->co_stacksize = stacksize;
+		co->co_flags = flags;
+		Py_INCREF(code);
+		co->co_code = code;
+		Py_INCREF(consts);
+		co->co_consts = consts;
+		Py_INCREF(names);
+		co->co_names = names;
+		Py_INCREF(varnames);
+		co->co_varnames = varnames;
+		Py_INCREF(freevars);
+		co->co_freevars = freevars;
+		Py_INCREF(cellvars);
+		co->co_cellvars = cellvars;
+		Py_INCREF(filename);
+		co->co_filename = filename;
+		Py_INCREF(name);
+		co->co_name = name;
+		co->co_firstlineno = firstlineno;
+		Py_INCREF(lnotab);
+		co->co_lnotab = lnotab;
+	}
+	return co;
+}
+
+
+#define OFF(x) offsetof(PyCodeObject, x)
+
+static PyMemberDef code_memberlist[] = {
+	{"co_argcount",	T_INT,		OFF(co_argcount),	READONLY},
+	{"co_nlocals",	T_INT,		OFF(co_nlocals),	READONLY},
+	{"co_stacksize",T_INT,		OFF(co_stacksize),	READONLY},
+	{"co_flags",	T_INT,		OFF(co_flags),		READONLY},
+	{"co_code",	T_OBJECT,	OFF(co_code),		READONLY},
+	{"co_consts",	T_OBJECT,	OFF(co_consts),		READONLY},
+	{"co_names",	T_OBJECT,	OFF(co_names),		READONLY},
+	{"co_varnames",	T_OBJECT,	OFF(co_varnames),	READONLY},
+	{"co_freevars",	T_OBJECT,	OFF(co_freevars),	READONLY},
+	{"co_cellvars",	T_OBJECT,	OFF(co_cellvars),	READONLY},
+	{"co_filename",	T_OBJECT,	OFF(co_filename),	READONLY},
+	{"co_name",	T_OBJECT,	OFF(co_name),		READONLY},
+	{"co_firstlineno", T_INT,	OFF(co_firstlineno),	READONLY},
+	{"co_lnotab",	T_OBJECT,	OFF(co_lnotab),		READONLY},
+	{NULL}	/* Sentinel */
+};
+
+/* Helper for code_new: return a shallow copy of a tuple that is
+   guaranteed to contain exact strings, by converting string subclasses
+   to exact strings and complaining if a non-string is found. */
+static PyObject*
+validate_and_copy_tuple(PyObject *tup)
+{
+	PyObject *newtuple;
+	PyObject *item;
+	int i, len;
+
+	len = PyTuple_GET_SIZE(tup);
+	newtuple = PyTuple_New(len);
+	if (newtuple == NULL)
+		return NULL;
+
+	for (i = 0; i < len; i++) {
+		item = PyTuple_GET_ITEM(tup, i);
+		if (PyString_CheckExact(item)) {
+			Py_INCREF(item);
+		}
+		else if (!PyString_Check(item)) {
+			PyErr_Format(
+				PyExc_TypeError,
+				"name tuples must contain only "
+				"strings, not '%.500s'",
+				item->ob_type->tp_name);
+			Py_DECREF(newtuple);
+			return NULL;
+		}
+		else {
+			item = PyString_FromStringAndSize(
+				PyString_AS_STRING(item),
+				PyString_GET_SIZE(item));
+			if (item == NULL) {
+				Py_DECREF(newtuple);
+				return NULL;
+			}
+		}
+		PyTuple_SET_ITEM(newtuple, i, item);
+	}
+
+	return newtuple;
+}
+
+PyDoc_STRVAR(code_doc,
+"code(argcount, nlocals, stacksize, flags, codestring, constants, names,\n\
+      varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])\n\
+\n\
+Create a code object.  Not for the faint of heart.");
+
+static PyObject *
+code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
+{
+	int argcount;
+	int nlocals;
+	int stacksize;
+	int flags;
+	PyObject *co = NULL;
+	PyObject *code;
+	PyObject *consts;
+	PyObject *names, *ournames = NULL;
+	PyObject *varnames, *ourvarnames = NULL;
+	PyObject *freevars = NULL, *ourfreevars = NULL;
+	PyObject *cellvars = NULL, *ourcellvars = NULL;
+	PyObject *filename;
+	PyObject *name;
+	int firstlineno;
+	PyObject *lnotab;
+
+	if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code",
+			      &argcount, &nlocals, &stacksize, &flags,
+			      &code,
+			      &PyTuple_Type, &consts,
+			      &PyTuple_Type, &names,
+			      &PyTuple_Type, &varnames,
+			      &filename, &name,
+			      &firstlineno, &lnotab,
+			      &PyTuple_Type, &freevars,
+			      &PyTuple_Type, &cellvars))
+		return NULL;
+
+	if (argcount < 0) {
+		PyErr_SetString(
+			PyExc_ValueError,
+			"code: argcount must not be negative");
+		goto cleanup;
+	}
+
+	if (nlocals < 0) {
+		PyErr_SetString(
+			PyExc_ValueError,
+			"code: nlocals must not be negative");
+		goto cleanup;
+	}
+
+	ournames = validate_and_copy_tuple(names);
+	if (ournames == NULL)
+		goto cleanup;
+	ourvarnames = validate_and_copy_tuple(varnames);
+	if (ourvarnames == NULL)
+		goto cleanup;
+	if (freevars)
+		ourfreevars = validate_and_copy_tuple(freevars);
+	else
+		ourfreevars = PyTuple_New(0);
+	if (ourfreevars == NULL)
+		goto cleanup;
+	if (cellvars)
+		ourcellvars = validate_and_copy_tuple(cellvars);
+	else
+		ourcellvars = PyTuple_New(0);
+	if (ourcellvars == NULL)
+		goto cleanup;
+
+	co = (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags,
+				    code, consts, ournames, ourvarnames,
+				    ourfreevars, ourcellvars, filename,
+				    name, firstlineno, lnotab);
+  cleanup:
+	Py_XDECREF(ournames);
+	Py_XDECREF(ourvarnames);
+	Py_XDECREF(ourfreevars);
+	Py_XDECREF(ourcellvars);
+	return co;
+}
+
+static void
+code_dealloc(PyCodeObject *co)
+{
+	Py_XDECREF(co->co_code);
+	Py_XDECREF(co->co_consts);
+	Py_XDECREF(co->co_names);
+	Py_XDECREF(co->co_varnames);
+	Py_XDECREF(co->co_freevars);
+	Py_XDECREF(co->co_cellvars);
+	Py_XDECREF(co->co_filename);
+	Py_XDECREF(co->co_name);
+	Py_XDECREF(co->co_lnotab);
+	PyObject_DEL(co);
+}
+
+static PyObject *
+code_repr(PyCodeObject *co)
+{
+	char buf[500];
+	int lineno = -1;
+	char *filename = "???";
+	char *name = "???";
+
+	if (co->co_firstlineno != 0)
+		lineno = co->co_firstlineno;
+	if (co->co_filename && PyString_Check(co->co_filename))
+		filename = PyString_AS_STRING(co->co_filename);
+	if (co->co_name && PyString_Check(co->co_name))
+		name = PyString_AS_STRING(co->co_name);
+	PyOS_snprintf(buf, sizeof(buf),
+		      "<code object %.100s at %p, file \"%.300s\", line %d>",
+		      name, co, filename, lineno);
+	return PyString_FromString(buf);
+}
+
+static int
+code_compare(PyCodeObject *co, PyCodeObject *cp)
+{
+	int cmp;
+	cmp = PyObject_Compare(co->co_name, cp->co_name);
+	if (cmp) return cmp;
+	cmp = co->co_argcount - cp->co_argcount;
+	if (cmp) goto normalize;
+	cmp = co->co_nlocals - cp->co_nlocals;
+	if (cmp) goto normalize;
+	cmp = co->co_flags - cp->co_flags;
+	if (cmp) goto normalize;
+	cmp = co->co_firstlineno - cp->co_firstlineno;
+	if (cmp) goto normalize;
+	cmp = PyObject_Compare(co->co_code, cp->co_code);
+	if (cmp) return cmp;
+	cmp = PyObject_Compare(co->co_consts, cp->co_consts);
+	if (cmp) return cmp;
+	cmp = PyObject_Compare(co->co_names, cp->co_names);
+	if (cmp) return cmp;
+	cmp = PyObject_Compare(co->co_varnames, cp->co_varnames);
+	if (cmp) return cmp;
+	cmp = PyObject_Compare(co->co_freevars, cp->co_freevars);
+	if (cmp) return cmp;
+	cmp = PyObject_Compare(co->co_cellvars, cp->co_cellvars);
+	return cmp;
+
+ normalize:
+	if (cmp > 0)
+		return 1;
+	else if (cmp < 0)
+		return -1;
+	else
+		return 0;
+}
+
+static long
+code_hash(PyCodeObject *co)
+{
+	long h, h0, h1, h2, h3, h4, h5, h6;
+	h0 = PyObject_Hash(co->co_name);
+	if (h0 == -1) return -1;
+	h1 = PyObject_Hash(co->co_code);
+	if (h1 == -1) return -1;
+	h2 = PyObject_Hash(co->co_consts);
+	if (h2 == -1) return -1;
+	h3 = PyObject_Hash(co->co_names);
+	if (h3 == -1) return -1;
+	h4 = PyObject_Hash(co->co_varnames);
+	if (h4 == -1) return -1;
+	h5 = PyObject_Hash(co->co_freevars);
+	if (h5 == -1) return -1;
+	h6 = PyObject_Hash(co->co_cellvars);
+	if (h6 == -1) return -1;
+	h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
+		co->co_argcount ^ co->co_nlocals ^ co->co_flags;
+	if (h == -1) h = -2;
+	return h;
+}
+
+/* XXX code objects need to participate in GC? */
+
+PyTypeObject PyCode_Type = {
+	PyObject_HEAD_INIT(&PyType_Type)
+	0,
+	"code",
+	sizeof(PyCodeObject),
+	0,
+	(destructor)code_dealloc, 	/* tp_dealloc */
+	0,				/* tp_print */
+	0, 				/* tp_getattr */
+	0,				/* tp_setattr */
+	(cmpfunc)code_compare, 		/* tp_compare */
+	(reprfunc)code_repr,		/* tp_repr */
+	0,				/* tp_as_number */
+	0,				/* tp_as_sequence */
+	0,				/* tp_as_mapping */
+	(hashfunc)code_hash, 		/* tp_hash */
+	0,				/* tp_call */
+	0,				/* tp_str */
+	PyObject_GenericGetAttr,	/* tp_getattro */
+	0,				/* tp_setattro */
+	0,				/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT,		/* tp_flags */
+	code_doc,			/* tp_doc */
+	0,				/* tp_traverse */
+	0,				/* tp_clear */
+	0,				/* tp_richcompare */
+	0,				/* tp_weaklistoffset */
+	0,				/* tp_iter */
+	0,				/* tp_iternext */
+	0,				/* tp_methods */
+	code_memberlist,		/* tp_members */
+	0,				/* tp_getset */
+	0,				/* tp_base */
+	0,				/* tp_dict */
+	0,				/* tp_descr_get */
+	0,				/* tp_descr_set */
+	0,				/* tp_dictoffset */
+	0,				/* tp_init */
+	0,				/* tp_alloc */
+	code_new,			/* tp_new */
+};
+
+/* All about c_lnotab.
+
+c_lnotab is an array of unsigned bytes disguised as a Python string.  In -O
+mode, SET_LINENO opcodes aren't generated, and bytecode offsets are mapped
+to source code line #s (when needed for tracebacks) via c_lnotab instead.
+The array is conceptually a list of
+    (bytecode offset increment, line number increment)
+pairs.  The details are important and delicate, best illustrated by example:
+
+    byte code offset    source code line number
+        0		    1
+        6		    2
+       50		    7
+      350                 307
+      361                 308
+
+The first trick is that these numbers aren't stored, only the increments
+from one row to the next (this doesn't really work, but it's a start):
+
+    0, 1,  6, 1,  44, 5,  300, 300,  11, 1
+
+The second trick is that an unsigned byte can't hold negative values, or
+values larger than 255, so (a) there's a deep assumption that byte code
+offsets and their corresponding line #s both increase monotonically, and (b)
+if at least one column jumps by more than 255 from one row to the next, more
+than one pair is written to the table. In case #b, there's no way to know
+from looking at the table later how many were written.  That's the delicate
+part.  A user of c_lnotab desiring to find the source line number
+corresponding to a bytecode address A should do something like this
+
+    lineno = addr = 0
+    for addr_incr, line_incr in c_lnotab:
+        addr += addr_incr
+        if addr > A:
+            return lineno
+        lineno += line_incr
+
+In order for this to work, when the addr field increments by more than 255,
+the line # increment in each pair generated must be 0 until the remaining addr
+increment is < 256.  So, in the example above, com_set_lineno should not (as
+was actually done until 2.2) expand 300, 300 to 255, 255,  45, 45, but to
+255, 0,  45, 255,  0, 45.
+*/
+
+int
+PyCode_Addr2Line(PyCodeObject *co, int addrq)
+{
+	int size = PyString_Size(co->co_lnotab) / 2;
+	unsigned char *p = (unsigned char*)PyString_AsString(co->co_lnotab);
+	int line = co->co_firstlineno;
+	int addr = 0;
+	while (--size >= 0) {
+		addr += *p++;
+		if (addr > addrq)
+			break;
+		line += *p++;
+	}
+	return line;
+}
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index bc8cae9..8ebf500 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -3,6 +3,7 @@
 
 #include "Python.h"
 
+#include "code.h"
 #include "compile.h"
 #include "frameobject.h"
 #include "opcode.h"
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index c0c91c9..85cef6f 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -2,7 +2,7 @@
 /* Function object implementation */
 
 #include "Python.h"
-#include "compile.h"
+#include "code.h"
 #include "eval.h"
 #include "structmember.h"
 
@@ -144,7 +144,9 @@
 		Py_XINCREF(closure);
 	}
 	else {
-		PyErr_SetString(PyExc_SystemError, "non-tuple closure");
+		PyErr_Format(PyExc_SystemError, 
+			     "expected tuple for closure, got '%.100s'",
+			     closure->ob_type->tp_name);
 		return -1;
 	}
 	Py_XDECREF(((PyFunctionObject *) op) -> func_closure);
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 88c4a15..591c62b 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1737,20 +1737,14 @@
 			goto bad_slots;
 		for (i = j = 0; i < nslots; i++) {
 			char *s;
-			char buffer[256];
 			tmp = PyTuple_GET_ITEM(slots, i);
 			s = PyString_AS_STRING(tmp);
 			if ((add_dict && strcmp(s, "__dict__") == 0) ||
 			    (add_weak && strcmp(s, "__weakref__") == 0))
 				continue;
-			if (_Py_Mangle(PyString_AS_STRING(name),
-				       PyString_AS_STRING(tmp),
-				       buffer, sizeof(buffer)))
-			{
-				tmp = PyString_FromString(buffer);
-			} else {
-				Py_INCREF(tmp);
-			}
+			tmp =_Py_Mangle(name, tmp);
+                        if (!tmp)
+                            goto bad_slots;
 			PyTuple_SET_ITEM(newslots, j, tmp);
 			j++;
 		}
diff --git a/PCbuild/pythoncore.vcproj b/PCbuild/pythoncore.vcproj
index 945fd5c..ff9e48b 100644
--- a/PCbuild/pythoncore.vcproj
+++ b/PCbuild/pythoncore.vcproj
@@ -3,6 +3,7 @@
 	ProjectType="Visual C++"
 	Version="7.10"
 	Name="pythoncore"
+	ProjectGUID="{7AFA1F0B-A8A1-455A-A832-BF263404BBEF}"
 	SccProjectName="pythoncore"
 	SccLocalPath="..">
 	<Platforms>
@@ -478,6 +479,12 @@
 			</FileConfiguration>
 		</File>
 		<File
+			RelativePath="..\Python\asdl.c">
+		</File>
+		<File
+			RelativePath="..\Python\ast.c">
+		</File>
+		<File
 			RelativePath="..\Modules\audioop.c">
 			<FileConfiguration
 				Name="Release|Win32">
@@ -802,34 +809,10 @@
 			</FileConfiguration>
 		</File>
 		<File
-			RelativePath="..\Modules\collectionsmodule.c">
+			RelativePath="..\Objects\codeobject.c">
 		</File>
 		<File
-			RelativePath="..\Python\compile.c">
-			<FileConfiguration
-				Name="Release|Win32">
-				<Tool
-					Name="VCCLCompilerTool"
-					Optimization="2"
-					AdditionalIncludeDirectories=""
-					PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;USE_DL_EXPORT;$(NoInherit)"/>
-			</FileConfiguration>
-			<FileConfiguration
-				Name="Debug|Win32">
-				<Tool
-					Name="VCCLCompilerTool"
-					Optimization="0"
-					AdditionalIncludeDirectories=""
-					PreprocessorDefinitions="_DEBUG;USE_DL_EXPORT;WIN32;_WINDOWS;$(NoInherit)"/>
-			</FileConfiguration>
-			<FileConfiguration
-				Name="ReleaseItanium|Win32">
-				<Tool
-					Name="VCCLCompilerTool"
-					Optimization="2"
-					AdditionalIncludeDirectories=""
-					PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;USE_DL_EXPORT;$(NoInherit)"/>
-			</FileConfiguration>
+			RelativePath="..\Modules\collectionsmodule.c">
 		</File>
 		<File
 			RelativePath="..\Objects\complexobject.c">
@@ -1186,6 +1169,9 @@
 			</FileConfiguration>
 		</File>
 		<File
+			RelativePath="..\Parser\firstsets.c">
+		</File>
+		<File
 			RelativePath="..\Objects\floatobject.c">
 			<FileConfiguration
 				Name="Release|Win32">
@@ -1321,6 +1307,33 @@
 			</FileConfiguration>
 		</File>
 		<File
+			RelativePath="..\Modules\functionalmodule.c">
+			<FileConfiguration
+				Name="Release|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;USE_DL_EXPORT;$(NoInherit)"/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="Debug|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="0"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions="_DEBUG;USE_DL_EXPORT;WIN32;_WINDOWS;$(NoInherit)"/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="ReleaseItanium|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;USE_DL_EXPORT;$(NoInherit)"/>
+			</FileConfiguration>
+		</File>
+		<File
 			RelativePath="..\Python\future.c">
 			<FileConfiguration
 				Name="Release|Win32">
@@ -1648,6 +1661,9 @@
 			</FileConfiguration>
 		</File>
 		<File
+			RelativePath="..\Parser\grammar.c">
+		</File>
+		<File
 			RelativePath="..\Parser\grammar1.c">
 			<FileConfiguration
 				Name="Release|Win32">
@@ -2302,6 +2318,9 @@
 			</FileConfiguration>
 		</File>
 		<File
+			RelativePath="..\Python\compile.c">
+		</File>
+		<File
 			RelativePath="..\Parser\node.c">
 			<FileConfiguration
 				Name="Release|Win32">
@@ -2437,9 +2456,6 @@
 			</FileConfiguration>
 		</File>
 		<File
-			RelativePath="..\Modules\parsermodule.c">
-		</File>
-		<File
 			RelativePath="..\Parser\parsetok.c">
 			<FileConfiguration
 				Name="Release|Win32">
@@ -2467,6 +2483,9 @@
 			</FileConfiguration>
 		</File>
 		<File
+			RelativePath="..\Parser\pgen.c">
+		</File>
+		<File
 			RelativePath="..\Modules\posixmodule.c">
 			<FileConfiguration
 				Name="Release|Win32">
@@ -2551,6 +2570,9 @@
 			RelativePath="..\Python\pystrtod.c">
 		</File>
 		<File
+			RelativePath="..\Python\Python-ast.c">
+		</File>
+		<File
 			RelativePath="..\PC\python_nt.rc">
 			<FileConfiguration
 				Name="Release|Win32">
@@ -2764,6 +2786,7 @@
 			</FileConfiguration>
 		</File>
 		<File
+<<<<<<< pythoncore.vcproj
                         RelativePath="..\Modules\sha256module.c">
 			<FileConfiguration
 				Name="Release|Win32">
@@ -2819,6 +2842,63 @@
 		</File>
 		<File
 			RelativePath="..\Modules\signalmodule.c">
+=======
+                        RelativePath="..\Modules\sha256module.c">
+>>>>>>> 1.26.2.3
+			<FileConfiguration
+				Name="Release|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;USE_DL_EXPORT;$(NoInherit)"/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="Debug|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="0"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions="_DEBUG;USE_DL_EXPORT;WIN32;_WINDOWS;$(NoInherit)"/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="ReleaseItanium|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;USE_DL_EXPORT;$(NoInherit)"/>
+			</FileConfiguration>
+		</File>
+		<File
+                        RelativePath="..\Modules\sha512module.c">
+			<FileConfiguration
+				Name="Release|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;USE_DL_EXPORT;$(NoInherit)"/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="Debug|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="0"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions="_DEBUG;USE_DL_EXPORT;WIN32;_WINDOWS;$(NoInherit)"/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="ReleaseItanium|Win32">
+				<Tool
+					Name="VCCLCompilerTool"
+					Optimization="2"
+					AdditionalIncludeDirectories=""
+					PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;USE_DL_EXPORT;$(NoInherit)"/>
+			</FileConfiguration>
+		</File>
+		<File
+			RelativePath="..\Modules\signalmodule.c">
 			<FileConfiguration
 				Name="Release|Win32">
 				<Tool
@@ -3145,31 +3225,7 @@
 			</FileConfiguration>
 		</File>
 		<File
-			RelativePath="..\Parser\tokenizer.c">
-			<FileConfiguration
-				Name="Release|Win32">
-				<Tool
-					Name="VCCLCompilerTool"
-					Optimization="2"
-					AdditionalIncludeDirectories=""
-					PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;USE_DL_EXPORT;$(NoInherit)"/>
-			</FileConfiguration>
-			<FileConfiguration
-				Name="Debug|Win32">
-				<Tool
-					Name="VCCLCompilerTool"
-					Optimization="0"
-					AdditionalIncludeDirectories=""
-					PreprocessorDefinitions="_DEBUG;USE_DL_EXPORT;WIN32;_WINDOWS;$(NoInherit)"/>
-			</FileConfiguration>
-			<FileConfiguration
-				Name="ReleaseItanium|Win32">
-				<Tool
-					Name="VCCLCompilerTool"
-					Optimization="2"
-					AdditionalIncludeDirectories=""
-					PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;USE_DL_EXPORT;$(NoInherit)"/>
-			</FileConfiguration>
+			RelativePath="..\Parser\tokenizer_pgen.c">
 		</File>
 		<File
 			RelativePath="..\Python\traceback.c">
diff --git a/Parser/.cvsignore b/Parser/.cvsignore
index a7dd8e6..f300915 100644
--- a/Parser/.cvsignore
+++ b/Parser/.cvsignore
@@ -1,3 +1,6 @@
 Makefile
 pgen
 add2lib
+asdl.pyc
+asdl_c.pyc
+spark.pyc
diff --git a/Parser/Python.asdl b/Parser/Python.asdl
new file mode 100644
index 0000000..0883d91
--- /dev/null
+++ b/Parser/Python.asdl
@@ -0,0 +1,107 @@
+-- ASDL's three builtin types are identifier, int, string
+
+module Python
+{
+	mod = Module(stmt* body)
+	    | Interactive(stmt* body)
+	    | Expression(expr body)
+
+	    -- not really an actual node but useful in Jython's typesystem.
+	    | Suite(stmt* body)
+
+	stmt = FunctionDef(identifier name, arguments args, 
+                           stmt* body, expr* decorators)
+	      | ClassDef(identifier name, expr* bases, stmt* body)
+	      | Return(expr? value)
+
+	      | Delete(expr* targets)
+	      | Assign(expr* targets, expr value)
+	      | AugAssign(expr target, operator op, expr value)
+
+	      -- not sure if bool is allowed, can always use int
+ 	      | Print(expr? dest, expr* values, bool nl)
+
+	      -- use 'orelse' because else is a keyword in target languages
+	      | For(expr target, expr iter, stmt* body, stmt* orelse)
+	      | While(expr test, stmt* body, stmt* orelse)
+	      | If(expr test, stmt* body, stmt* orelse)
+
+	      -- 'type' is a bad name
+	      | Raise(expr? type, expr? inst, expr? tback)
+	      | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)
+	      | TryFinally(stmt* body, stmt* finalbody)
+	      | Assert(expr test, expr? msg)
+
+	      | Import(alias* names)
+	      | ImportFrom(identifier module, alias* names)
+
+	      -- Doesn't capture requirement that locals must be
+	      -- defined if globals is
+	      -- still supports use as a function!
+	      | Exec(expr body, expr? globals, expr? locals)
+
+	      | Global(identifier* names)
+	      | Expr(expr value)
+	      | Pass | Break | Continue
+
+	      -- XXX Jython will be different
+	      attributes (int lineno)
+
+	      -- BoolOp() can use left & right?
+	expr = BoolOp(boolop op, expr* values)
+	     | BinOp(expr left, operator op, expr right)
+	     | UnaryOp(unaryop op, expr operand)
+	     | Lambda(arguments args, expr body)
+	     | Dict(expr* keys, expr* values)
+	     | ListComp(expr elt, comprehension* generators)
+	     | GeneratorExp(expr elt, comprehension* generators)
+	     | Yield(expr? value)
+	     -- need sequences for compare to distinguish between
+	     -- x < 4 < 3 and (x < 4) < 3
+	     | Compare(expr left, cmpop* ops, expr* comparators)
+	     | Call(expr func, expr* args, keyword* keywords,
+			 expr? starargs, expr? kwargs)
+	     | Repr(expr value)
+	     | Num(object n) -- a number as a PyObject.
+	     | Str(string s) -- need to specify raw, unicode, etc?
+	     -- other literals? bools?
+
+	     -- the following expression can appear in assignment context
+	     | Attribute(expr value, identifier attr, expr_context ctx)
+	     | Subscript(expr value, slice slice, expr_context ctx)
+	     | Name(identifier id, expr_context ctx)
+	     | List(expr* elts, expr_context ctx) 
+	     | Tuple(expr *elts, expr_context ctx)
+
+	      attributes (int lineno)
+
+	expr_context = Load | Store | Del | AugLoad | AugStore | Param
+
+	slice = Ellipsis | Slice(expr? lower, expr? upper, expr? step) 
+	      | ExtSlice(slice* dims) 
+	      | Index(expr value) 
+
+	boolop = And | Or 
+
+	operator = Add | Sub | Mult | Div | Mod | Pow | LShift 
+                 | RShift | BitOr | BitXor | BitAnd | FloorDiv
+
+	unaryop = Invert | Not | UAdd | USub
+
+	cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
+
+	comprehension = (expr target, expr iter, expr* ifs)
+
+	-- not sure what to call the first argument for raise and except
+
+	excepthandler = (expr? type, expr? name, stmt* body)
+
+	arguments = (expr* args, identifier? vararg, 
+		     identifier? kwarg, expr* defaults)
+
+        -- keyword arguments supplied to call
+        keyword = (identifier arg, expr value)
+
+        -- import name with optional 'as' alias.
+        alias = (identifier name, identifier? asname)
+}
diff --git a/Parser/asdl.py b/Parser/asdl.py
new file mode 100644
index 0000000..0db4e3b
--- /dev/null
+++ b/Parser/asdl.py
@@ -0,0 +1,393 @@
+"""An implementation of the Zephyr Abstract Syntax Definition Language.
+
+See http://asdl.sourceforge.net/ and
+http://www.cs.princeton.edu/~danwang/Papers/dsl97/dsl97-abstract.html.
+
+Only supports top level module decl, not view.  I'm guessing that view
+is intended to support the browser and I'm not interested in the
+browser.
+"""
+
+#__metaclass__ = type
+
+import os
+import traceback
+
+import spark
+
+class Token:
+    # spark seems to dispatch in the parser based on a token's
+    # type attribute
+    def __init__(self, type, lineno):
+        self.type = type
+        self.lineno = lineno
+
+    def __str__(self):
+        return self.type
+
+    def __repr__(self):
+        return str(self)
+
+class Id(Token):
+    def __init__(self, value, lineno):
+        self.type = 'Id'
+        self.value = value
+        self.lineno = lineno
+
+    def __str__(self):
+        return self.value
+
+class ASDLSyntaxError:
+
+    def __init__(self, lineno, token=None, msg=None):
+        self.lineno = lineno
+        self.token = token
+        self.msg = msg
+
+    def __str__(self):
+        if self.msg is None:
+            return "Error at '%s', line %d" % (self.token, self.lineno)
+        else:
+            return "%s, line %d" % (self.msg, self.lineno)
+
+class ASDLScanner(spark.GenericScanner, object):
+
+    def tokenize(self, input):
+        self.rv = []
+        self.lineno = 1
+        super(ASDLScanner, self).tokenize(input)
+        return self.rv
+
+    def t_id(self, s):
+        r"[\w\.]+"
+        # XXX doesn't distinguish upper vs. lower, which is
+        # significant for ASDL.
+        self.rv.append(Id(s, self.lineno))
+
+    def t_xxx(self, s): # not sure what this production means
+        r"<="
+        self.rv.append(Token(s, self.lineno))
+
+    def t_punctuation(self, s):
+        r"[\{\}\*\=\|\(\)\,\?\:]"
+        self.rv.append(Token(s, self.lineno))
+
+    def t_comment(self, s):
+        r"\-\-[^\n]*"
+        pass
+
+    def t_newline(self, s):
+        r"\n"
+        self.lineno += 1
+
+    def t_whitespace(self, s):
+        r"[ \t]+"
+        pass
+
+    def t_default(self, s):
+        r" . +"
+        raise ValueError, "unmatched input: %s" % `s`
+
+class ASDLParser(spark.GenericParser, object):
+    def __init__(self):
+        super(ASDLParser, self).__init__("module")
+
+    def typestring(self, tok):
+        return tok.type
+
+    def error(self, tok):
+        raise ASDLSyntaxError(tok.lineno, tok)
+
+    def p_module_0(self, (module, name, _0, _1)):
+        " module ::= Id Id { } "
+        if module.value != "module":
+            raise ASDLSyntaxError(module.lineno,
+                                  msg="expected 'module', found %s" % module)
+        return Module(name, None)
+
+    def p_module(self, (module, name, _0, definitions, _1)):
+        " module ::= Id Id { definitions } "
+        if module.value != "module":
+            raise ASDLSyntaxError(module.lineno,
+                                  msg="expected 'module', found %s" % module)
+        return Module(name, definitions)
+
+    def p_definition_0(self, (definition,)):
+        " definitions ::= definition "
+        return definition
+
+    def p_definition_1(self, (definitions, definition)):
+        " definitions ::= definition definitions "
+        return definitions + definition
+
+    def p_definition(self, (id, _, type)):
+        " definition ::= Id = type "
+        return [Type(id, type)]
+
+    def p_type_0(self, (product,)):
+        " type ::= product "
+        return product
+
+    def p_type_1(self, (sum,)):
+        " type ::= sum "
+        return Sum(sum)
+
+    def p_type_2(self, (sum, id, _0, attributes, _1)):
+        " type ::= sum Id ( fields ) "
+        if id.value != "attributes":
+            raise ASDLSyntaxError(id.lineno,
+                                  msg="expected attributes, found %s" % id)
+        return Sum(sum, attributes)
+
+    def p_product(self, (_0, fields, _1)):
+        " product ::= ( fields ) "
+        # XXX can't I just construct things in the right order?
+        fields.reverse() 
+        return Product(fields)
+
+    def p_sum_0(self, (constructor,)):
+        " sum ::= constructor """
+        return [constructor]
+
+    def p_sum_1(self, (constructor, _, sum)):
+        " sum ::= constructor | sum "
+        return [constructor] + sum
+
+    def p_sum_2(self, (constructor, _, sum)):
+        " sum ::= constructor | sum "
+        return [constructor] + sum
+
+    def p_constructor_0(self, (id,)):
+        " constructor ::= Id "
+        return Constructor(id)
+
+    def p_constructor_1(self, (id, _0, fields, _1)):
+        " constructor ::= Id ( fields ) "
+        # XXX can't I just construct things in the right order?
+        fields.reverse() 
+        return Constructor(id, fields)
+
+    def p_fields_0(self, (field,)):
+        " fields ::= field "
+        return [field]
+
+    def p_fields_1(self, (field, _, fields)):
+        " fields ::= field , fields "
+        return fields + [field]
+
+    def p_field_0(self, (type,)):
+        " field ::= Id "
+        return Field(type)
+
+    def p_field_1(self, (type, name)):
+        " field ::= Id Id "
+        return Field(type, name)
+
+    def p_field_2(self, (type, _, name)):
+        " field ::= Id * Id "
+        return Field(type, name, seq=1)
+
+    def p_field_3(self, (type, _, name)):
+        " field ::= Id ? Id "
+        return Field(type, name, opt=1)
+
+    def p_field_4(self, (type, _)):
+        " field ::= Id * "
+        return Field(type, seq=1)
+
+    def p_field_5(self, (type, _)):
+        " field ::= Id ? "
+        return Field(type, opt=1)
+
+builtin_types = ("identifier", "string", "int", "bool", "object")
+
+# below is a collection of classes to capture the AST of an AST :-)
+# not sure if any of the methods are useful yet, but I'm adding them
+# piecemeal as they seem helpful
+
+class AST:
+    pass # a marker class
+
+class Module(AST):
+    def __init__(self, name, dfns):
+        self.name = name
+        self.dfns = dfns
+        self.types = {} # maps type name to value (from dfns)
+        for type in dfns:
+            self.types[type.name.value] = type.value
+
+    def __repr__(self):
+        return "Module(%s, %s)" % (self.name, self.dfns)
+
+class Type(AST):
+    def __init__(self, name, value):
+        self.name = name
+        self.value = value
+
+    def __repr__(self):
+        return "Type(%s, %s)" % (self.name, self.value)
+
+class Constructor(AST):
+    def __init__(self, name, fields=None):
+        self.name = name
+        self.fields = fields or []
+
+    def __repr__(self):
+        return "Constructor(%s, %s)" % (self.name, self.fields)
+
+class Field(AST):
+    def __init__(self, type, name=None, seq=0, opt=0):
+        self.type = type
+        self.name = name
+        self.seq = seq
+        self.opt = opt
+
+    def __repr__(self):
+        if self.seq:
+            extra = ", seq=1"
+        elif self.opt:
+            extra = ", opt=1"
+        else:
+            extra = ""
+        if self.name is None:
+            return "Field(%s%s)" % (self.type, extra)
+        else:
+            return "Field(%s, %s%s)" % (self.type, self.name, extra)
+
+class Sum(AST):
+    def __init__(self, types, attributes=None):
+        self.types = types
+        self.attributes = attributes or []
+
+    def __repr__(self):
+        if self.attributes is None:
+            return "Sum(%s)" % self.types
+        else:
+            return "Sum(%s, %s)" % (self.types, self.attributes)
+
+class Product(AST):
+    def __init__(self, fields):
+        self.fields = fields
+
+    def __repr__(self):
+        return "Product(%s)" % self.fields
+
+class VisitorBase(object):
+
+    def __init__(self, skip=0):
+        self.cache = {}
+        self.skip = skip
+
+    def visit(self, object, *args):
+        meth = self._dispatch(object)
+        if meth is None:
+            return
+        try:
+            meth(object, *args)
+        except Exception, err:
+            print "Error visiting", repr(object)
+            print err
+            traceback.print_exc()
+            # XXX hack
+            if hasattr(self, 'file'):
+                self.file.flush()
+            os._exit(1)
+
+    def _dispatch(self, object):
+        assert isinstance(object, AST), repr(object)
+        klass = object.__class__
+        meth = self.cache.get(klass)
+        if meth is None:
+            methname = "visit" + klass.__name__
+            if self.skip:
+                meth = getattr(self, methname, None)
+            else:
+                meth = getattr(self, methname)
+            self.cache[klass] = meth
+        return meth
+
+class Check(VisitorBase):
+
+    def __init__(self):
+        super(Check, self).__init__(skip=1)
+        self.cons = {}
+        self.errors = 0
+        self.types = {}
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type):
+        self.visit(type.value, str(type.name))
+
+    def visitSum(self, sum, name):
+        for t in sum.types:
+            self.visit(t, name)
+
+    def visitConstructor(self, cons, name):
+        key = str(cons.name)
+        conflict = self.cons.get(key)
+        if conflict is None:
+            self.cons[key] = name
+        else:
+            print "Redefinition of constructor %s" % key
+            print "Defined in %s and %s" % (conflict, name)
+            self.errors += 1
+        for f in cons.fields:
+            self.visit(f, key)
+
+    def visitField(self, field, name):
+        key = str(field.type)
+        l = self.types.setdefault(key, [])
+        l.append(name)
+
+    def visitProduct(self, prod, name):
+        for f in prod.fields:
+            self.visit(f, name)
+
+def check(mod):
+    v = Check()
+    v.visit(mod)
+
+    for t in v.types:
+        if not mod.types.has_key(t) and not t in builtin_types:
+            v.errors += 1
+            uses = ", ".join(v.types[t])
+            print "Undefined type %s, used in %s" % (t, uses)
+    
+    return not v.errors
+
+def parse(file):
+    scanner = ASDLScanner()
+    parser = ASDLParser()
+
+    buf = open(file).read()
+    tokens = scanner.tokenize(buf)
+    try:
+        return parser.parse(tokens)
+    except ASDLSyntaxError, err:
+        print err
+        lines = buf.split("\n")
+        print lines[err.lineno - 1] # lines starts at 0, files at 1
+
+if __name__ == "__main__":
+    import glob
+    import sys
+
+    if len(sys.argv) > 1:
+        files = sys.argv[1:]
+    else:
+        testdir = "tests"
+        files = glob.glob(testdir + "/*.asdl")
+    
+    for file in files:
+        print file
+        mod = parse(file)
+        print "module", mod.name
+        print len(mod.dfns), "definitions"
+        if not check(mod):
+            print "Check failed"
+        else:
+            for dfn in mod.dfns:
+                print dfn.type
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py
new file mode 100755
index 0000000..7c6df4e
--- /dev/null
+++ b/Parser/asdl_c.py
@@ -0,0 +1,621 @@
+#! /usr/bin/env python
+"""Generate C code from an ASDL description."""
+
+# TO DO
+# handle fields that have a type but no name
+
+import os, sys, traceback
+
+import asdl
+
+TABSIZE = 8
+MAX_COL = 80
+
+def get_c_type(name):
+    """Return a string for the C name of the type.
+
+    This function special cases the default types provided by asdl:
+    identifier, string, int, bool.
+    """
+    # XXX ack!  need to figure out where Id is useful and where string
+    if isinstance(name, asdl.Id):
+        name = name.value
+    if name in asdl.builtin_types:
+        return name
+    else:
+        return "%s_ty" % name
+
+def reflow_lines(s, depth):
+    """Reflow the line s indented depth tabs.
+
+    Return a sequence of lines where no line extends beyond MAX_COL
+    when properly indented.  The first line is properly indented based
+    exclusively on depth * TABSIZE.  All following lines -- these are
+    the reflowed lines generated by this function -- start at the same
+    column as the first character beyond the opening { in the first
+    line.
+    """
+    size = MAX_COL - depth * TABSIZE
+    if len(s) < size:
+        return [s]
+
+    lines = []
+    cur = s
+    padding = ""
+    while len(cur) > size:
+        i = cur.rfind(' ', 0, size)
+        # XXX this should be fixed for real
+        if i == -1 and 'GeneratorExp' in cur:
+            i = size + 3
+        assert i != -1, "Impossible line %d to reflow: %s" % (size, `s`)
+        lines.append(padding + cur[:i])
+        if len(lines) == 1:
+            # find new size based on brace
+            j = cur.find('{', 0, i)
+            if j >= 0:
+                j += 2 # account for the brace and the space after it
+                size -= j
+                padding = " " * j
+            else:
+                j = cur.find('(', 0, i)
+                if j >= 0:
+                    j += 1 # account for the paren (no space after it)
+                    size -= j
+                    padding = " " * j
+        cur = cur[i+1:]
+    else:
+        lines.append(padding + cur)
+    return lines
+
+def is_simple(sum):
+    """Return True if a sum is a simple.
+
+    A sum is simple if its types have no fields, e.g.
+    unaryop = Invert | Not | UAdd | USub
+    """
+
+    for t in sum.types:
+        if t.fields:
+            return False
+    return True
+
+class EmitVisitor(asdl.VisitorBase):
+    """Visit that emits lines"""
+
+    def __init__(self, file):
+        self.file = file
+        super(EmitVisitor, self).__init__()
+
+    def emit(self, s, depth, reflow=1):
+        # XXX reflow long lines?
+        if reflow:
+            lines = reflow_lines(s, depth)
+        else:
+            lines = [s]
+        for line in lines:
+            line = (" " * TABSIZE * depth) + line + "\n"
+            self.file.write(line)
+
+class TypeDefVisitor(EmitVisitor):
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type, depth=0):
+        self.visit(type.value, type.name, depth)
+
+    def visitSum(self, sum, name, depth):
+        if is_simple(sum):
+            self.simple_sum(sum, name, depth)
+        else:
+            self.sum_with_constructors(sum, name, depth)
+
+    def simple_sum(self, sum, name, depth):
+        enum = []
+        for i in range(len(sum.types)):
+            type = sum.types[i]
+            enum.append("%s=%d" % (type.name, i + 1))
+        enums = ", ".join(enum)
+        ctype = get_c_type(name)
+        s = "typedef enum _%s { %s } %s;" % (name, enums, ctype)
+        self.emit(s, depth)
+        self.emit("", depth)
+
+    def sum_with_constructors(self, sum, name, depth):
+        ctype = get_c_type(name)
+        s = "typedef struct _%(name)s *%(ctype)s;" % locals()
+        self.emit(s, depth)
+        self.emit("", depth)
+
+    def visitProduct(self, product, name, depth):
+        ctype = get_c_type(name)
+        s = "typedef struct _%(name)s *%(ctype)s;" % locals()
+        self.emit(s, depth)
+        self.emit("", depth)
+
+class StructVisitor(EmitVisitor):
+    """Visitor to generate typdefs for AST."""
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type, depth=0):
+        self.visit(type.value, type.name, depth)
+
+    def visitSum(self, sum, name, depth):
+        if not is_simple(sum):
+            self.sum_with_constructors(sum, name, depth)
+
+    def sum_with_constructors(self, sum, name, depth):
+        def emit(s, depth=depth):
+            self.emit(s % sys._getframe(1).f_locals, depth)
+        enum = []
+        for i in range(len(sum.types)):
+            type = sum.types[i]
+            enum.append("%s_kind=%d" % (type.name, i + 1))
+
+        emit("struct _%(name)s {")
+        emit("enum { " + ", ".join(enum) + " } kind;", depth + 1)
+        emit("union {", depth + 1)
+        for t in sum.types:
+            self.visit(t, depth + 2)
+        emit("} v;", depth + 1)
+        for field in sum.attributes:
+            # rudimentary attribute handling
+            type = str(field.type)
+            assert type in asdl.builtin_types, type
+            emit("%s %s;" % (type, field.name), depth + 1);
+        emit("};")
+        emit("")
+
+    def visitConstructor(self, cons, depth):
+        if cons.fields:
+            self.emit("struct {", depth)
+            for f in cons.fields:
+                self.visit(f, depth + 1)
+            self.emit("} %s;" % cons.name, depth)
+            self.emit("", depth)
+        else:
+            # XXX not sure what I want here, nothing is probably fine
+            pass
+
+    def visitField(self, field, depth):
+        # XXX need to lookup field.type, because it might be something
+        # like a builtin...
+        ctype = get_c_type(field.type)
+        name = field.name
+        if field.seq:
+            self.emit("asdl_seq *%(name)s;" % locals(), depth)
+        else:
+            self.emit("%(ctype)s %(name)s;" % locals(), depth)
+
+    def visitProduct(self, product, name, depth):
+        self.emit("struct _%(name)s {" % locals(), depth)
+        for f in product.fields:
+            self.visit(f, depth + 1)
+        self.emit("};", depth)
+        self.emit("", depth)
+
+class PrototypeVisitor(EmitVisitor):
+    """Generate function prototypes for the .h file"""
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type):
+        self.visit(type.value, type.name)
+
+    def visitSum(self, sum, name):
+        if is_simple(sum):
+            pass # XXX
+        else:
+            for t in sum.types:
+                self.visit(t, name, sum.attributes)
+
+    def get_args(self, fields):
+        """Return list of C argument into, one for each field.
+
+        Argument info is 3-tuple of a C type, variable name, and flag
+        that is true if type can be NULL.
+        """
+        args = []
+        unnamed = {}
+        for f in fields:
+            if f.name is None:
+                name = f.type
+                c = unnamed[name] = unnamed.get(name, 0) + 1
+                if c > 1:
+                    name = "name%d" % (c - 1)
+            else:
+                name = f.name
+            # XXX should extend get_c_type() to handle this
+            if f.seq:
+                ctype = "asdl_seq *"
+            else:
+                ctype = get_c_type(f.type)
+            args.append((ctype, name, f.opt or f.seq))
+        return args
+
+    def visitConstructor(self, cons, type, attrs):
+        args = self.get_args(cons.fields)
+        attrs = self.get_args(attrs)
+        ctype = get_c_type(type)
+        self.emit_function(cons.name, ctype, args, attrs)
+
+    def emit_function(self, name, ctype, args, attrs, union=1):
+        args = args + attrs
+        if args:
+            argstr = ", ".join(["%s %s" % (atype, aname)
+                                for atype, aname, opt in args])
+        else:
+            argstr = "void"
+        self.emit("%s %s(%s);" % (ctype, name, argstr), 0)
+
+    def visitProduct(self, prod, name):
+        self.emit_function(name, get_c_type(name),
+                           self.get_args(prod.fields), [], union=0)
+
+class FunctionVisitor(PrototypeVisitor):
+    """Visitor to generate constructor functions for AST."""
+
+    def emit_function(self, name, ctype, args, attrs, union=1):
+        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])
+        self.emit("%s" % ctype, 0)
+        emit("%s(%s)" % (name, argstr))
+        emit("{")
+        emit("%s p;" % ctype, 1)
+        for argtype, argname, opt in args:
+            # XXX hack alert: false is allowed for a bool
+            if not opt and not argtype == "bool":
+                emit("if (!%s) {" % argname, 1)
+                emit("PyErr_SetString(PyExc_ValueError,", 2)
+                msg = "field %s is required for %s" % (argname, name)
+                emit('                "%s");' % msg,
+                     2, reflow=0)
+                emit('return NULL;', 2)
+                emit('}', 1)
+
+        emit("p = (%s)malloc(sizeof(*p));" % ctype, 1)
+        emit("if (!p) {", 1)
+        emit("PyErr_SetString(PyExc_MemoryError, \"no memory\");", 2)
+        emit("return NULL;", 2)
+        emit("}", 1)
+        if union:
+            self.emit_body_union(name, args, attrs)
+        else:
+            self.emit_body_struct(name, args, attrs)
+        emit("return p;", 1)
+        emit("}")
+        emit("")
+
+    def emit_body_union(self, name, args, attrs):
+        def emit(s, depth=0, reflow=1):
+            self.emit(s, depth, reflow)
+        emit("p->kind = %s_kind;" % name, 1)
+        for argtype, argname, opt in args:
+            emit("p->v.%s.%s = %s;" % (name, argname, argname), 1)
+        for argtype, argname, opt in attrs:
+            emit("p->%s = %s;" % (argname, argname), 1)
+
+    def emit_body_struct(self, name, args, attrs):
+        def emit(s, depth=0, reflow=1):
+            self.emit(s, depth, reflow)
+        for argtype, argname, opt in args:
+            emit("p->%s = %s;" % (argname, argname), 1)
+        assert not attrs
+
+class PickleVisitor(EmitVisitor):
+
+    def visitModule(self, mod):
+        for dfn in mod.dfns:
+            self.visit(dfn)
+
+    def visitType(self, type):
+        self.visit(type.value, type.name)
+
+    def visitSum(self, sum, name):
+        pass
+
+    def visitProduct(self, sum, name):
+        pass
+
+    def visitConstructor(self, cons, name):
+        pass
+
+    def visitField(self, sum):
+        pass
+
+class MarshalPrototypeVisitor(PickleVisitor):
+
+    def prototype(self, sum, name):
+        ctype = get_c_type(name)
+        self.emit("int marshal_write_%s(PyObject **, int *, %s);"
+                  % (name, ctype), 0)
+
+    visitProduct = visitSum = prototype
+
+class FreePrototypeVisitor(PickleVisitor):
+
+    def prototype(self, sum, name):
+        ctype = get_c_type(name)
+        self.emit("void free_%s(%s);" % (name, ctype), 0)
+
+    visitProduct = visitSum = prototype
+
+_SPECIALIZED_SEQUENCES = ('stmt', 'expr')
+
+def find_sequence(fields, doing_specialization):
+    """Return True if any field uses a sequence."""
+    for f in fields:
+        if f.seq:
+            if not doing_specialization:
+                return True
+            if str(f.type) not in _SPECIALIZED_SEQUENCES:
+                return True
+    return False
+
+def has_sequence(types, doing_specialization):
+    for t in types:
+        if find_sequence(t.fields, doing_specialization):
+            return True
+    return False
+
+
+class StaticVisitor(PickleVisitor):
+    '''Very simple, always emit this static code'''
+
+    CODE = '''static void
+free_seq_exprs(asdl_seq *seq)
+{
+        int i, n;
+        n = asdl_seq_LEN(seq);
+        for (i = 0; i < n; i++)
+                free_expr((expr_ty)asdl_seq_GET(seq, i));
+        asdl_seq_free(seq);
+}
+
+static void
+free_seq_stmts(asdl_seq *seq)
+{
+        int i, n;
+        n = asdl_seq_LEN(seq);
+        for (i = 0; i < n; i++)
+                free_stmt((stmt_ty)asdl_seq_GET(seq, i));
+        asdl_seq_free(seq);
+}
+'''
+
+    def visit(self, object):
+        self.emit(self.CODE, 0, reflow=False)
+
+
+class FreeVisitor(PickleVisitor):
+
+    def func_begin(self, name, has_seq):
+        ctype = get_c_type(name)
+        self.emit("void", 0)
+        self.emit("free_%s(%s o)" % (name, ctype), 0)
+        self.emit("{", 0)
+        if has_seq:
+            self.emit("int i, n;", 1)
+            self.emit("asdl_seq *seq;", 1)
+            self.emit('', 0)
+        self.emit('if (!o)', 1)
+        self.emit('return;', 2)
+        self.emit('', 0)
+
+    def func_end(self):
+        self.emit("}", 0)
+        self.emit("", 0)
+
+    def visitSum(self, sum, name):
+        has_seq = has_sequence(sum.types, True)
+        self.func_begin(name, has_seq)
+        if not is_simple(sum):
+            self.emit("switch (o->kind) {", 1)
+            for i in range(len(sum.types)):
+                t = sum.types[i]
+                self.visitConstructor(t, i + 1, name)
+            self.emit("}", 1)
+            self.emit("", 0)
+            self.emit("free(o);", 1)
+        self.func_end()
+
+    def visitProduct(self, prod, name):
+        self.func_begin(name, find_sequence(prod.fields, True))
+        for field in prod.fields:
+            self.visitField(field, name, 1, True)
+        self.emit("", 0)
+        self.emit("free(o);", 1)
+        self.func_end()
+        
+    def visitConstructor(self, cons, enum, name):
+        self.emit("case %s_kind:" % cons.name, 1)
+        for f in cons.fields:
+            self.visitField(f, cons.name, 2, False)
+        self.emit("break;", 2)
+
+    def visitField(self, field, name, depth, product):
+        def emit(s, d):
+            self.emit(s, depth + d)
+        if product:
+            value = "o->%s" % field.name
+        else:
+            value = "o->v.%s.%s" % (name, field.name)
+        if field.seq:
+            self.emitSeq(field, value, depth, emit)
+
+        # XXX need to know the simple types in advance, so that we
+        # don't call free_TYPE() for them.
+
+        elif field.opt:
+            emit("if (%s) {" % value, 0)
+            self.free(field, value, depth + 1)
+            emit("}", 0)
+        else:
+            self.free(field, value, depth)
+
+    def emitSeq(self, field, value, depth, emit):
+        # specialize for freeing sequences of statements and expressions
+        if str(field.type) in _SPECIALIZED_SEQUENCES:
+            c_code = "free_seq_%ss(%s);" % (field.type, value)
+            emit(c_code, 0)
+        else:
+            emit("seq = %s;" % value, 0)
+            emit("n = asdl_seq_LEN(seq);", 0)
+            emit("for (i = 0; i < n; i++)", 0)
+            self.free(field, "asdl_seq_GET(seq, i)", depth + 1)
+            emit("asdl_seq_free(seq);", 0)
+
+    def free(self, field, value, depth):
+        if str(field.type) in ("identifier", "string", "object"):
+            ctype = get_c_type(field.type)
+            self.emit("Py_DECREF((%s)%s);" % (ctype, value), depth)
+        elif str(field.type) == "bool":
+            return
+        else:
+            ctype = get_c_type(field.type)
+            self.emit("free_%s((%s)%s);" % (field.type, ctype, value), depth)
+        
+
+class MarshalFunctionVisitor(PickleVisitor):
+
+    def func_begin(self, name, has_seq):
+        ctype = get_c_type(name)
+        self.emit("int", 0)
+        self.emit("marshal_write_%s(PyObject **buf, int *off, %s o)" %
+                  (name, ctype), 0)
+        self.emit("{", 0)
+        # XXX: add declaration of "int i;" properly
+        if has_seq or True:
+            self.emit("int i;", 1) # XXX only need it for sequences
+
+    def func_end(self):
+        self.emit("return 1;", 1)
+        self.emit("}", 0)
+        self.emit("", 0)
+    
+    def visitSum(self, sum, name):
+        has_seq = has_sequence(sum.types, False)
+        self.func_begin(name, has_seq)
+        simple = is_simple(sum)
+        if simple:
+            self.emit("switch (o) {", 1)
+        else:
+            self.emit("switch (o->kind) {", 1)
+        for i in range(len(sum.types)):
+            t = sum.types[i]
+            self.visitConstructor(t, i + 1, name, simple)
+        self.emit("}", 1)
+        self.func_end()
+
+    def visitProduct(self, prod, name):
+        self.func_begin(name, find_sequence(prod.fields, True))
+        for field in prod.fields:
+            self.visitField(field, name, 1, 1)
+        self.func_end()
+            
+    def visitConstructor(self, cons, enum, name, simple):
+        if simple:
+            self.emit("case %s:" % cons.name, 1)
+            self.emit("marshal_write_int(buf, off, %d);" % enum, 2);
+            self.emit("break;", 2)
+        else:
+            self.emit("case %s_kind:" % cons.name, 1)
+            self.emit("marshal_write_int(buf, off, %d);" % enum, 2)
+            for f in cons.fields:
+                self.visitField(f, cons.name, 2, 0)
+            self.emit("break;", 2)
+
+    def visitField(self, field, name, depth, product):
+        def emit(s, d):
+            self.emit(s, depth + d)
+        if product:
+            value = "o->%s" % field.name
+        else:
+            value = "o->v.%s.%s" % (name, field.name)
+        if field.seq:
+            emit("marshal_write_int(buf, off, asdl_seq_LEN(%s));" % value, 0)
+            emit("for (i = 0; i < asdl_seq_LEN(%s); i++) {" % value, 0)
+            emit("void *elt = asdl_seq_GET(%s, i);" % value, 1);
+            ctype = get_c_type(field.type);
+            emit("marshal_write_%s(buf, off, (%s)elt);" % (field.type,
+                    ctype), 1)
+            emit("}", 0)
+        elif field.opt:
+            emit("if (%s) {" % value, 0)
+            emit("marshal_write_int(buf, off, 1);", 1)
+            emit("marshal_write_%s(buf, off, %s);" % (field.type, value), 1)
+            emit("}", 0)
+            emit("else {", 0)
+            emit("marshal_write_int(buf, off, 0);", 1)
+            emit("}", 0)
+        else:
+            emit("marshal_write_%s(buf, off, %s);" % (field.type, value), 0)
+
+class ChainOfVisitors:
+    def __init__(self, *visitors):
+        self.visitors = visitors
+
+    def visit(self, object):
+        for v in self.visitors:
+            v.visit(object)
+
+def main(srcfile):
+    auto_gen_msg = '/* File automatically generated by %s */\n' % sys.argv[0]
+    mod = asdl.parse(srcfile)
+    if not asdl.check(mod):
+        sys.exit(1)
+    if INC_DIR:
+        p = "%s/%s-ast.h" % (INC_DIR, mod.name)
+    else:
+        p = "%s-ast.h" % mod.name
+    f = open(p, "wb")
+    print >> f, auto_gen_msg
+    print >> f, '#include "asdl.h"\n'
+    c = ChainOfVisitors(TypeDefVisitor(f),
+                        StructVisitor(f),
+                        PrototypeVisitor(f),
+                        FreePrototypeVisitor(f),
+                        MarshalPrototypeVisitor(f),
+                        )
+    c.visit(mod)
+    f.close()
+
+    if SRC_DIR:
+        p = "%s/%s-ast.c" % (SRC_DIR, mod.name)
+    else:
+        p = "%s-ast.c" % mod.name
+    f = open(p, "wb")
+    print >> f, auto_gen_msg
+    print >> f, '#include "Python.h"'
+    print >> f, '#include "%s-ast.h"' % mod.name
+    print >> f
+    v = ChainOfVisitors(FunctionVisitor(f),
+                        StaticVisitor(f),
+                        FreeVisitor(f),
+                        MarshalFunctionVisitor(f),
+                        )
+    v.visit(mod)
+    f.close()
+
+if __name__ == "__main__":
+    import sys
+    import getopt
+
+    INC_DIR = ''
+    SRC_DIR = ''
+    opts, args = getopt.getopt(sys.argv[1:], "h:c:")
+    for o, v in opts:
+        if o == '-h':
+            INC_DIR = v
+        if o == '-c':
+            SRC_DIR = v
+    if len(args) != 1:
+        print "Must specify single input file"
+    main(args[0])
diff --git a/Parser/grammar.mak b/Parser/grammar.mak
index a6f1abe..55f028f 100644
--- a/Parser/grammar.mak
+++ b/Parser/grammar.mak
@@ -15,7 +15,7 @@
 # particular case --pragma in PC\pyconfig.h, which demands that
 # python23.lib get linked in).
 
-LIBS= ..\PCbuild\python23.lib
+LIBS= ..\PCbuild\python25.lib
 
 CFLAGS= /I ..\Include /I ..\PC /D MS_NO_COREDLL /D PGEN /MD
 
diff --git a/Parser/parsetok.c b/Parser/parsetok.c
index 1d25437..11d2232 100644
--- a/Parser/parsetok.c
+++ b/Parser/parsetok.c
@@ -21,7 +21,7 @@
 node *
 PyParser_ParseString(const char *s, grammar *g, int start, perrdetail *err_ret)
 {
-	return PyParser_ParseStringFlags(s, g, start, err_ret, 0);
+	return PyParser_ParseStringFlagsFilename(s, NULL, g, start, err_ret, 0);
 }
 
 node *
@@ -56,7 +56,6 @@
 	return parsetok(tok, g, start, err_ret, flags);
 }
 
-
 /* Parse input coming from a file.  Return error code, print some errors. */
 
 node *
@@ -210,7 +209,7 @@
 }
 
 static void
-initerr(perrdetail *err_ret, const char* filename)
+initerr(perrdetail *err_ret, const char *filename)
 {
 	err_ret->error = E_OK;
 	err_ret->filename = filename;
diff --git a/Parser/spark.py b/Parser/spark.py
new file mode 100644
index 0000000..00d9733
--- /dev/null
+++ b/Parser/spark.py
@@ -0,0 +1,840 @@
+#  Copyright (c) 1998-2002 John Aycock
+#  
+#  Permission is hereby granted, free of charge, to any person obtaining
+#  a copy of this software and associated documentation files (the
+#  "Software"), to deal in the Software without restriction, including
+#  without limitation the rights to use, copy, modify, merge, publish,
+#  distribute, sublicense, and/or sell copies of the Software, and to
+#  permit persons to whom the Software is furnished to do so, subject to
+#  the following conditions:
+#  
+#  The above copyright notice and this permission notice shall be
+#  included in all copies or substantial portions of the Software.
+#  
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+#  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+#  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+#  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+#  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+__version__ = 'SPARK-0.7 (pre-alpha-5)'
+
+import re
+import sys
+import string
+
+def _namelist(instance):
+	namelist, namedict, classlist = [], {}, [instance.__class__]
+	for c in classlist:
+		for b in c.__bases__:
+			classlist.append(b)
+		for name in c.__dict__.keys():
+			if not namedict.has_key(name):
+				namelist.append(name)
+				namedict[name] = 1
+	return namelist
+
+class GenericScanner:
+	def __init__(self, flags=0):
+		pattern = self.reflect()
+		self.re = re.compile(pattern, re.VERBOSE|flags)
+
+		self.index2func = {}
+		for name, number in self.re.groupindex.items():
+			self.index2func[number-1] = getattr(self, 't_' + name)
+
+	def makeRE(self, name):
+		doc = getattr(self, name).__doc__
+		rv = '(?P<%s>%s)' % (name[2:], doc)
+		return rv
+
+	def reflect(self):
+		rv = []
+		for name in _namelist(self):
+			if name[:2] == 't_' and name != 't_default':
+				rv.append(self.makeRE(name))
+
+		rv.append(self.makeRE('t_default'))
+		return string.join(rv, '|')
+
+	def error(self, s, pos):
+		print "Lexical error at position %s" % pos
+		raise SystemExit
+
+	def tokenize(self, s):
+		pos = 0
+		n = len(s)
+		while pos < n:
+			m = self.re.match(s, pos)
+			if m is None:
+				self.error(s, pos)
+
+			groups = m.groups()
+			for i in range(len(groups)):
+				if groups[i] and self.index2func.has_key(i):
+					self.index2func[i](groups[i])
+			pos = m.end()
+
+	def t_default(self, s):
+		r'( . | \n )+'
+		print "Specification error: unmatched input"
+		raise SystemExit
+
+#
+#  Extracted from GenericParser and made global so that [un]picking works.
+#
+class _State:
+	def __init__(self, stateno, items):
+		self.T, self.complete, self.items = [], [], items
+		self.stateno = stateno
+
+class GenericParser:
+	#
+	#  An Earley parser, as per J. Earley, "An Efficient Context-Free
+	#  Parsing Algorithm", CACM 13(2), pp. 94-102.  Also J. C. Earley,
+	#  "An Efficient Context-Free Parsing Algorithm", Ph.D. thesis,
+	#  Carnegie-Mellon University, August 1968.  New formulation of
+	#  the parser according to J. Aycock, "Practical Earley Parsing
+	#  and the SPARK Toolkit", Ph.D. thesis, University of Victoria,
+	#  2001, and J. Aycock and R. N. Horspool, "Practical Earley
+	#  Parsing", unpublished paper, 2001.
+	#
+
+	def __init__(self, start):
+		self.rules = {}
+		self.rule2func = {}
+		self.rule2name = {}
+		self.collectRules()
+		self.augment(start)
+		self.ruleschanged = 1
+
+	_NULLABLE = '\e_'
+	_START = 'START'
+	_BOF = '|-'
+
+	#
+	#  When pickling, take the time to generate the full state machine;
+	#  some information is then extraneous, too.  Unfortunately we
+	#  can't save the rule2func map.
+	#
+	def __getstate__(self):
+		if self.ruleschanged:
+			#
+			#  XXX - duplicated from parse()
+			#
+			self.computeNull()
+			self.newrules = {}
+			self.new2old = {}
+			self.makeNewRules()
+			self.ruleschanged = 0
+			self.edges, self.cores = {}, {}
+			self.states = { 0: self.makeState0() }
+			self.makeState(0, self._BOF)
+		#
+		#  XXX - should find a better way to do this..
+		#
+		changes = 1
+		while changes:
+			changes = 0
+			for k, v in self.edges.items():
+				if v is None:
+					state, sym = k
+					if self.states.has_key(state):
+						self.goto(state, sym)
+						changes = 1
+		rv = self.__dict__.copy()
+		for s in self.states.values():
+			del s.items
+		del rv['rule2func']
+		del rv['nullable']
+		del rv['cores']
+		return rv
+
+	def __setstate__(self, D):
+		self.rules = {}
+		self.rule2func = {}
+		self.rule2name = {}
+		self.collectRules()
+		start = D['rules'][self._START][0][1][1]	# Blech.
+		self.augment(start)
+		D['rule2func'] = self.rule2func
+		D['makeSet'] = self.makeSet_fast
+		self.__dict__ = D
+
+	#
+	#  A hook for GenericASTBuilder and GenericASTMatcher.  Mess
+	#  thee not with this; nor shall thee toucheth the _preprocess
+	#  argument to addRule.
+	#
+	def preprocess(self, rule, func):	return rule, func
+
+	def addRule(self, doc, func, _preprocess=1):
+		fn = func
+		rules = string.split(doc)
+
+		index = []
+		for i in range(len(rules)):
+			if rules[i] == '::=':
+				index.append(i-1)
+		index.append(len(rules))
+
+		for i in range(len(index)-1):
+			lhs = rules[index[i]]
+			rhs = rules[index[i]+2:index[i+1]]
+			rule = (lhs, tuple(rhs))
+
+			if _preprocess:
+				rule, fn = self.preprocess(rule, func)
+
+			if self.rules.has_key(lhs):
+				self.rules[lhs].append(rule)
+			else:
+				self.rules[lhs] = [ rule ]
+			self.rule2func[rule] = fn
+			self.rule2name[rule] = func.__name__[2:]
+		self.ruleschanged = 1
+
+	def collectRules(self):
+		for name in _namelist(self):
+			if name[:2] == 'p_':
+				func = getattr(self, name)
+				doc = func.__doc__
+				self.addRule(doc, func)
+
+	def augment(self, start):
+		rule = '%s ::= %s %s' % (self._START, self._BOF, start)
+		self.addRule(rule, lambda args: args[1], 0)
+
+	def computeNull(self):
+		self.nullable = {}
+		tbd = []
+
+		for rulelist in self.rules.values():
+			lhs = rulelist[0][0]
+			self.nullable[lhs] = 0
+			for rule in rulelist:
+				rhs = rule[1]
+				if len(rhs) == 0:
+					self.nullable[lhs] = 1
+					continue
+				#
+				#  We only need to consider rules which
+				#  consist entirely of nonterminal symbols.
+				#  This should be a savings on typical
+				#  grammars.
+				#
+				for sym in rhs:
+					if not self.rules.has_key(sym):
+						break
+				else:
+					tbd.append(rule)
+		changes = 1
+		while changes:
+			changes = 0
+			for lhs, rhs in tbd:
+				if self.nullable[lhs]:
+					continue
+				for sym in rhs:
+					if not self.nullable[sym]:
+						break
+				else:
+					self.nullable[lhs] = 1
+					changes = 1
+
+	def makeState0(self):
+		s0 = _State(0, [])
+		for rule in self.newrules[self._START]:
+			s0.items.append((rule, 0))
+		return s0
+
+	def finalState(self, tokens):
+		#
+		#  Yuck.
+		#
+		if len(self.newrules[self._START]) == 2 and len(tokens) == 0:
+			return 1
+		start = self.rules[self._START][0][1][1]
+		return self.goto(1, start)
+
+	def makeNewRules(self):
+		worklist = []
+		for rulelist in self.rules.values():
+			for rule in rulelist:
+				worklist.append((rule, 0, 1, rule))
+
+		for rule, i, candidate, oldrule in worklist:
+			lhs, rhs = rule
+			n = len(rhs)
+			while i < n:
+				sym = rhs[i]
+				if not self.rules.has_key(sym) or \
+				   not self.nullable[sym]:
+					candidate = 0
+					i = i + 1
+					continue
+
+				newrhs = list(rhs)
+				newrhs[i] = self._NULLABLE+sym
+				newrule = (lhs, tuple(newrhs))
+				worklist.append((newrule, i+1,
+						 candidate, oldrule))
+				candidate = 0
+				i = i + 1
+			else:
+				if candidate:
+					lhs = self._NULLABLE+lhs
+					rule = (lhs, rhs)
+				if self.newrules.has_key(lhs):
+					self.newrules[lhs].append(rule)
+				else:
+					self.newrules[lhs] = [ rule ]
+				self.new2old[rule] = oldrule
+	
+	def typestring(self, token):
+		return None
+
+	def error(self, token):
+		print "Syntax error at or near `%s' token" % token
+		raise SystemExit
+
+	def parse(self, tokens):
+		sets = [ [(1,0), (2,0)] ]
+		self.links = {}
+		
+		if self.ruleschanged:
+			self.computeNull()
+			self.newrules = {}
+			self.new2old = {}
+			self.makeNewRules()
+			self.ruleschanged = 0
+			self.edges, self.cores = {}, {}
+			self.states = { 0: self.makeState0() }
+			self.makeState(0, self._BOF)
+
+		for i in xrange(len(tokens)):
+			sets.append([])
+
+			if sets[i] == []:
+				break				
+			self.makeSet(tokens[i], sets, i)
+		else:
+			sets.append([])
+			self.makeSet(None, sets, len(tokens))
+
+		#_dump(tokens, sets, self.states)
+
+		finalitem = (self.finalState(tokens), 0)
+		if finalitem not in sets[-2]:
+			if len(tokens) > 0:
+				self.error(tokens[i-1])
+			else:
+				self.error(None)
+
+		return self.buildTree(self._START, finalitem,
+				      tokens, len(sets)-2)
+
+	def isnullable(self, sym):
+		#
+		#  For symbols in G_e only.  If we weren't supporting 1.5,
+		#  could just use sym.startswith().
+		#
+		return self._NULLABLE == sym[0:len(self._NULLABLE)]
+
+	def skip(self, (lhs, rhs), pos=0):
+		n = len(rhs)
+		while pos < n:
+			if not self.isnullable(rhs[pos]):
+				break
+			pos = pos + 1
+		return pos
+
+	def makeState(self, state, sym):
+		assert sym is not None
+		#
+		#  Compute \epsilon-kernel state's core and see if
+		#  it exists already.
+		#
+		kitems = []
+		for rule, pos in self.states[state].items:
+			lhs, rhs = rule
+			if rhs[pos:pos+1] == (sym,):
+				kitems.append((rule, self.skip(rule, pos+1)))
+		core = kitems
+
+		core.sort()
+		tcore = tuple(core)
+		if self.cores.has_key(tcore):
+			return self.cores[tcore]
+		#
+		#  Nope, doesn't exist.  Compute it and the associated
+		#  \epsilon-nonkernel state together; we'll need it right away.
+		#
+		k = self.cores[tcore] = len(self.states)
+		K, NK = _State(k, kitems), _State(k+1, [])
+		self.states[k] = K
+		predicted = {}
+
+		edges = self.edges
+		rules = self.newrules
+		for X in K, NK:
+			worklist = X.items
+			for item in worklist:
+				rule, pos = item
+				lhs, rhs = rule
+				if pos == len(rhs):
+					X.complete.append(rule)
+					continue
+
+				nextSym = rhs[pos]
+				key = (X.stateno, nextSym)
+				if not rules.has_key(nextSym):
+					if not edges.has_key(key):
+						edges[key] = None
+						X.T.append(nextSym)
+				else:
+					edges[key] = None
+					if not predicted.has_key(nextSym):
+						predicted[nextSym] = 1
+						for prule in rules[nextSym]:
+							ppos = self.skip(prule)
+							new = (prule, ppos)
+							NK.items.append(new)
+			#
+			#  Problem: we know K needs generating, but we
+			#  don't yet know about NK.  Can't commit anything
+			#  regarding NK to self.edges until we're sure.  Should
+			#  we delay committing on both K and NK to avoid this
+			#  hacky code?  This creates other problems..
+			#
+			if X is K:
+				edges = {}
+
+		if NK.items == []:
+			return k
+
+		#
+		#  Check for \epsilon-nonkernel's core.  Unfortunately we
+		#  need to know the entire set of predicted nonterminals
+		#  to do this without accidentally duplicating states.
+		#
+		core = predicted.keys()
+		core.sort()
+		tcore = tuple(core)
+		if self.cores.has_key(tcore):
+			self.edges[(k, None)] = self.cores[tcore]
+			return k
+
+		nk = self.cores[tcore] = self.edges[(k, None)] = NK.stateno
+		self.edges.update(edges)
+		self.states[nk] = NK
+		return k
+
+	def goto(self, state, sym):
+		key = (state, sym)
+		if not self.edges.has_key(key):
+			#
+			#  No transitions from state on sym.
+			#
+			return None
+
+		rv = self.edges[key]
+		if rv is None:
+			#
+			#  Target state isn't generated yet.  Remedy this.
+			#
+			rv = self.makeState(state, sym)
+			self.edges[key] = rv
+		return rv
+
+	def gotoT(self, state, t):
+		return [self.goto(state, t)]
+
+	def gotoST(self, state, st):
+		rv = []
+		for t in self.states[state].T:
+			if st == t:
+				rv.append(self.goto(state, t))
+		return rv
+
+	def add(self, set, item, i=None, predecessor=None, causal=None):
+		if predecessor is None:
+			if item not in set:
+				set.append(item)
+		else:
+			key = (item, i)
+			if item not in set:
+				self.links[key] = []
+				set.append(item)
+			self.links[key].append((predecessor, causal))
+
+	def makeSet(self, token, sets, i):
+		cur, next = sets[i], sets[i+1]
+
+		ttype = token is not None and self.typestring(token) or None
+		if ttype is not None:
+			fn, arg = self.gotoT, ttype
+		else:
+			fn, arg = self.gotoST, token
+
+		for item in cur:
+			ptr = (item, i)
+			state, parent = item
+			add = fn(state, arg)
+			for k in add:
+				if k is not None:
+					self.add(next, (k, parent), i+1, ptr)
+					nk = self.goto(k, None)
+					if nk is not None:
+						self.add(next, (nk, i+1))
+
+			if parent == i:
+				continue
+
+			for rule in self.states[state].complete:
+				lhs, rhs = rule
+				for pitem in sets[parent]:
+					pstate, pparent = pitem
+					k = self.goto(pstate, lhs)
+					if k is not None:
+						why = (item, i, rule)
+						pptr = (pitem, parent)
+						self.add(cur, (k, pparent),
+							 i, pptr, why)
+						nk = self.goto(k, None)
+						if nk is not None:
+							self.add(cur, (nk, i))
+
+	def makeSet_fast(self, token, sets, i):
+		#
+		#  Call *only* when the entire state machine has been built!
+		#  It relies on self.edges being filled in completely, and
+		#  then duplicates and inlines code to boost speed at the
+		#  cost of extreme ugliness.
+		#
+		cur, next = sets[i], sets[i+1]
+		ttype = token is not None and self.typestring(token) or None
+
+		for item in cur:
+			ptr = (item, i)
+			state, parent = item
+			if ttype is not None:
+				k = self.edges.get((state, ttype), None)
+				if k is not None:
+					#self.add(next, (k, parent), i+1, ptr)
+					#INLINED --v
+					new = (k, parent)
+					key = (new, i+1)
+					if new not in next:
+						self.links[key] = []
+						next.append(new)
+					self.links[key].append((ptr, None))
+					#INLINED --^
+					#nk = self.goto(k, None)
+					nk = self.edges.get((k, None), None)
+					if nk is not None:
+						#self.add(next, (nk, i+1))
+						#INLINED --v
+						new = (nk, i+1)
+						if new not in next:
+							next.append(new)
+						#INLINED --^
+			else:
+				add = self.gotoST(state, token)
+				for k in add:
+					if k is not None:
+						self.add(next, (k, parent), i+1, ptr)
+						#nk = self.goto(k, None)
+						nk = self.edges.get((k, None), None)
+						if nk is not None:
+							self.add(next, (nk, i+1))
+
+			if parent == i:
+				continue
+
+			for rule in self.states[state].complete:
+				lhs, rhs = rule
+				for pitem in sets[parent]:
+					pstate, pparent = pitem
+					#k = self.goto(pstate, lhs)
+					k = self.edges.get((pstate, lhs), None)
+					if k is not None:
+						why = (item, i, rule)
+						pptr = (pitem, parent)
+						#self.add(cur, (k, pparent),
+						#	 i, pptr, why)
+						#INLINED --v
+						new = (k, pparent)
+						key = (new, i)
+						if new not in cur:
+							self.links[key] = []
+							cur.append(new)
+						self.links[key].append((pptr, why))
+						#INLINED --^
+						#nk = self.goto(k, None)
+						nk = self.edges.get((k, None), None)
+						if nk is not None:
+							#self.add(cur, (nk, i))
+							#INLINED --v
+							new = (nk, i)
+							if new not in cur:
+								cur.append(new)
+							#INLINED --^
+
+	def predecessor(self, key, causal):
+		for p, c in self.links[key]:
+			if c == causal:
+				return p
+		assert 0
+
+	def causal(self, key):
+		links = self.links[key]
+		if len(links) == 1:
+			return links[0][1]
+		choices = []
+		rule2cause = {}
+		for p, c in links:
+			rule = c[2]
+			choices.append(rule)
+			rule2cause[rule] = c
+		return rule2cause[self.ambiguity(choices)]
+
+	def deriveEpsilon(self, nt):
+		if len(self.newrules[nt]) > 1:
+			rule = self.ambiguity(self.newrules[nt])
+		else:
+			rule = self.newrules[nt][0]
+		#print rule
+
+		rhs = rule[1]
+		attr = [None] * len(rhs)
+
+		for i in range(len(rhs)-1, -1, -1):
+			attr[i] = self.deriveEpsilon(rhs[i])
+		return self.rule2func[self.new2old[rule]](attr)
+
+	def buildTree(self, nt, item, tokens, k):
+		state, parent = item
+
+		choices = []
+		for rule in self.states[state].complete:
+			if rule[0] == nt:
+				choices.append(rule)
+		rule = choices[0]
+		if len(choices) > 1:
+			rule = self.ambiguity(choices)
+		#print rule
+
+		rhs = rule[1]
+		attr = [None] * len(rhs)
+
+		for i in range(len(rhs)-1, -1, -1):
+			sym = rhs[i]
+			if not self.newrules.has_key(sym):
+				if sym != self._BOF:
+					attr[i] = tokens[k-1]
+					key = (item, k)
+					item, k = self.predecessor(key, None)
+			#elif self.isnullable(sym):
+			elif self._NULLABLE == sym[0:len(self._NULLABLE)]:
+				attr[i] = self.deriveEpsilon(sym)
+			else:
+				key = (item, k)
+				why = self.causal(key)
+				attr[i] = self.buildTree(sym, why[0],
+							 tokens, why[1])
+				item, k = self.predecessor(key, why)
+		return self.rule2func[self.new2old[rule]](attr)
+
+	def ambiguity(self, rules):
+		#
+		#  XXX - problem here and in collectRules() if the same rule
+		#	 appears in >1 method.  Also undefined results if rules
+		#	 causing the ambiguity appear in the same method.
+		#
+		sortlist = []
+		name2index = {}
+		for i in range(len(rules)):
+			lhs, rhs = rule = rules[i]
+			name = self.rule2name[self.new2old[rule]]
+			sortlist.append((len(rhs), name))
+			name2index[name] = i
+		sortlist.sort()
+		list = map(lambda (a,b): b, sortlist)
+		return rules[name2index[self.resolve(list)]]
+
+	def resolve(self, list):
+		#
+		#  Resolve ambiguity in favor of the shortest RHS.
+		#  Since we walk the tree from the top down, this
+		#  should effectively resolve in favor of a "shift".
+		#
+		return list[0]
+
+#
+#  GenericASTBuilder automagically constructs a concrete/abstract syntax tree
+#  for a given input.  The extra argument is a class (not an instance!)
+#  which supports the "__setslice__" and "__len__" methods.
+#
+#  XXX - silently overrides any user code in methods.
+#
+
+class GenericASTBuilder(GenericParser):
+	def __init__(self, AST, start):
+		GenericParser.__init__(self, start)
+		self.AST = AST
+
+	def preprocess(self, rule, func):
+		rebind = lambda lhs, self=self: \
+				lambda args, lhs=lhs, self=self: \
+					self.buildASTNode(args, lhs)
+		lhs, rhs = rule
+		return rule, rebind(lhs)
+
+	def buildASTNode(self, args, lhs):
+		children = []
+		for arg in args:
+			if isinstance(arg, self.AST):
+				children.append(arg)
+			else:
+				children.append(self.terminal(arg))
+		return self.nonterminal(lhs, children)
+
+	def terminal(self, token):	return token
+
+	def nonterminal(self, type, args):
+		rv = self.AST(type)
+		rv[:len(args)] = args
+		return rv
+
+#
+#  GenericASTTraversal is a Visitor pattern according to Design Patterns.  For
+#  each node it attempts to invoke the method n_<node type>, falling
+#  back onto the default() method if the n_* can't be found.  The preorder
+#  traversal also looks for an exit hook named n_<node type>_exit (no default
+#  routine is called if it's not found).  To prematurely halt traversal
+#  of a subtree, call the prune() method -- this only makes sense for a
+#  preorder traversal.  Node type is determined via the typestring() method.
+#
+
+class GenericASTTraversalPruningException:
+	pass
+
+class GenericASTTraversal:
+	def __init__(self, ast):
+		self.ast = ast
+
+	def typestring(self, node):
+		return node.type
+
+	def prune(self):
+		raise GenericASTTraversalPruningException
+
+	def preorder(self, node=None):
+		if node is None:
+			node = self.ast
+
+		try:
+			name = 'n_' + self.typestring(node)
+			if hasattr(self, name):
+				func = getattr(self, name)
+				func(node)
+			else:
+				self.default(node)
+		except GenericASTTraversalPruningException:
+			return
+
+		for kid in node:
+			self.preorder(kid)
+
+		name = name + '_exit'
+		if hasattr(self, name):
+			func = getattr(self, name)
+			func(node)
+
+	def postorder(self, node=None):
+		if node is None:
+			node = self.ast
+
+		for kid in node:
+			self.postorder(kid)
+
+		name = 'n_' + self.typestring(node)
+		if hasattr(self, name):
+			func = getattr(self, name)
+			func(node)
+		else:
+			self.default(node)
+
+
+	def default(self, node):
+		pass
+
+#
+#  GenericASTMatcher.  AST nodes must have "__getitem__" and "__cmp__"
+#  implemented.
+#
+#  XXX - makes assumptions about how GenericParser walks the parse tree.
+#
+
+class GenericASTMatcher(GenericParser):
+	def __init__(self, start, ast):
+		GenericParser.__init__(self, start)
+		self.ast = ast
+
+	def preprocess(self, rule, func):
+		rebind = lambda func, self=self: \
+				lambda args, func=func, self=self: \
+					self.foundMatch(args, func)
+		lhs, rhs = rule
+		rhslist = list(rhs)
+		rhslist.reverse()
+
+		return (lhs, tuple(rhslist)), rebind(func)
+
+	def foundMatch(self, args, func):
+		func(args[-1])
+		return args[-1]
+
+	def match_r(self, node):
+		self.input.insert(0, node)
+		children = 0
+
+		for child in node:
+			if children == 0:
+				self.input.insert(0, '(')
+			children = children + 1
+			self.match_r(child)
+
+		if children > 0:
+			self.input.insert(0, ')')
+
+	def match(self, ast=None):
+		if ast is None:
+			ast = self.ast
+		self.input = []
+
+		self.match_r(ast)
+		self.parse(self.input)
+
+	def resolve(self, list):
+		#
+		#  Resolve ambiguity in favor of the longest RHS.
+		#
+		return list[-1]
+
+def _dump(tokens, sets, states):
+	for i in range(len(sets)):
+		print 'set', i
+		for item in sets[i]:
+			print '\t', item
+			for (lhs, rhs), pos in states[item[0]].items:
+				print '\t\t', lhs, '::=',
+				print string.join(rhs[:pos]),
+				print '.',
+				print string.join(rhs[pos:])
+		if i < len(tokens):
+			print
+			print 'token', str(tokens[i])
+			print
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
new file mode 100644
index 0000000..e82b61c
--- /dev/null
+++ b/Python/Python-ast.c
@@ -0,0 +1,2281 @@
+/* File automatically generated by ../Parser/asdl_c.py */
+
+#include "Python.h"
+#include "Python-ast.h"
+
+mod_ty
+Module(asdl_seq * body)
+{
+        mod_ty p;
+        p = (mod_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Module_kind;
+        p->v.Module.body = body;
+        return p;
+}
+
+mod_ty
+Interactive(asdl_seq * body)
+{
+        mod_ty p;
+        p = (mod_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Interactive_kind;
+        p->v.Interactive.body = body;
+        return p;
+}
+
+mod_ty
+Expression(expr_ty body)
+{
+        mod_ty p;
+        if (!body) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field body is required for Expression");
+                return NULL;
+        }
+        p = (mod_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Expression_kind;
+        p->v.Expression.body = body;
+        return p;
+}
+
+mod_ty
+Suite(asdl_seq * body)
+{
+        mod_ty p;
+        p = (mod_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Suite_kind;
+        p->v.Suite.body = body;
+        return p;
+}
+
+stmt_ty
+FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
+            decorators, int lineno)
+{
+        stmt_ty p;
+        if (!name) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field name is required for FunctionDef");
+                return NULL;
+        }
+        if (!args) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field args is required for FunctionDef");
+                return NULL;
+        }
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = FunctionDef_kind;
+        p->v.FunctionDef.name = name;
+        p->v.FunctionDef.args = args;
+        p->v.FunctionDef.body = body;
+        p->v.FunctionDef.decorators = decorators;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+ClassDef(identifier name, asdl_seq * bases, asdl_seq * body, int lineno)
+{
+        stmt_ty p;
+        if (!name) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field name is required for ClassDef");
+                return NULL;
+        }
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = ClassDef_kind;
+        p->v.ClassDef.name = name;
+        p->v.ClassDef.bases = bases;
+        p->v.ClassDef.body = body;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Return(expr_ty value, int lineno)
+{
+        stmt_ty p;
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Return_kind;
+        p->v.Return.value = value;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Delete(asdl_seq * targets, int lineno)
+{
+        stmt_ty p;
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Delete_kind;
+        p->v.Delete.targets = targets;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Assign(asdl_seq * targets, expr_ty value, int lineno)
+{
+        stmt_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Assign");
+                return NULL;
+        }
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Assign_kind;
+        p->v.Assign.targets = targets;
+        p->v.Assign.value = value;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno)
+{
+        stmt_ty p;
+        if (!target) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field target is required for AugAssign");
+                return NULL;
+        }
+        if (!op) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field op is required for AugAssign");
+                return NULL;
+        }
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for AugAssign");
+                return NULL;
+        }
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = AugAssign_kind;
+        p->v.AugAssign.target = target;
+        p->v.AugAssign.op = op;
+        p->v.AugAssign.value = value;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Print(expr_ty dest, asdl_seq * values, bool nl, int lineno)
+{
+        stmt_ty p;
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Print_kind;
+        p->v.Print.dest = dest;
+        p->v.Print.values = values;
+        p->v.Print.nl = nl;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int
+    lineno)
+{
+        stmt_ty p;
+        if (!target) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field target is required for For");
+                return NULL;
+        }
+        if (!iter) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field iter is required for For");
+                return NULL;
+        }
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = For_kind;
+        p->v.For.target = target;
+        p->v.For.iter = iter;
+        p->v.For.body = body;
+        p->v.For.orelse = orelse;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno)
+{
+        stmt_ty p;
+        if (!test) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field test is required for While");
+                return NULL;
+        }
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = While_kind;
+        p->v.While.test = test;
+        p->v.While.body = body;
+        p->v.While.orelse = orelse;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno)
+{
+        stmt_ty p;
+        if (!test) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field test is required for If");
+                return NULL;
+        }
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = If_kind;
+        p->v.If.test = test;
+        p->v.If.body = body;
+        p->v.If.orelse = orelse;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Raise(expr_ty type, expr_ty inst, expr_ty tback, int lineno)
+{
+        stmt_ty p;
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Raise_kind;
+        p->v.Raise.type = type;
+        p->v.Raise.inst = inst;
+        p->v.Raise.tback = tback;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+TryExcept(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, int lineno)
+{
+        stmt_ty p;
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = TryExcept_kind;
+        p->v.TryExcept.body = body;
+        p->v.TryExcept.handlers = handlers;
+        p->v.TryExcept.orelse = orelse;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+TryFinally(asdl_seq * body, asdl_seq * finalbody, int lineno)
+{
+        stmt_ty p;
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = TryFinally_kind;
+        p->v.TryFinally.body = body;
+        p->v.TryFinally.finalbody = finalbody;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Assert(expr_ty test, expr_ty msg, int lineno)
+{
+        stmt_ty p;
+        if (!test) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field test is required for Assert");
+                return NULL;
+        }
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Assert_kind;
+        p->v.Assert.test = test;
+        p->v.Assert.msg = msg;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Import(asdl_seq * names, int lineno)
+{
+        stmt_ty p;
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Import_kind;
+        p->v.Import.names = names;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+ImportFrom(identifier module, asdl_seq * names, int lineno)
+{
+        stmt_ty p;
+        if (!module) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field module is required for ImportFrom");
+                return NULL;
+        }
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = ImportFrom_kind;
+        p->v.ImportFrom.module = module;
+        p->v.ImportFrom.names = names;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Exec(expr_ty body, expr_ty globals, expr_ty locals, int lineno)
+{
+        stmt_ty p;
+        if (!body) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field body is required for Exec");
+                return NULL;
+        }
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Exec_kind;
+        p->v.Exec.body = body;
+        p->v.Exec.globals = globals;
+        p->v.Exec.locals = locals;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Global(asdl_seq * names, int lineno)
+{
+        stmt_ty p;
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Global_kind;
+        p->v.Global.names = names;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Expr(expr_ty value, int lineno)
+{
+        stmt_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Expr");
+                return NULL;
+        }
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Expr_kind;
+        p->v.Expr.value = value;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Pass(int lineno)
+{
+        stmt_ty p;
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Pass_kind;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Break(int lineno)
+{
+        stmt_ty p;
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Break_kind;
+        p->lineno = lineno;
+        return p;
+}
+
+stmt_ty
+Continue(int lineno)
+{
+        stmt_ty p;
+        p = (stmt_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Continue_kind;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+BoolOp(boolop_ty op, asdl_seq * values, int lineno)
+{
+        expr_ty p;
+        if (!op) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field op is required for BoolOp");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = BoolOp_kind;
+        p->v.BoolOp.op = op;
+        p->v.BoolOp.values = values;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno)
+{
+        expr_ty p;
+        if (!left) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field left is required for BinOp");
+                return NULL;
+        }
+        if (!op) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field op is required for BinOp");
+                return NULL;
+        }
+        if (!right) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field right is required for BinOp");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = BinOp_kind;
+        p->v.BinOp.left = left;
+        p->v.BinOp.op = op;
+        p->v.BinOp.right = right;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+UnaryOp(unaryop_ty op, expr_ty operand, int lineno)
+{
+        expr_ty p;
+        if (!op) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field op is required for UnaryOp");
+                return NULL;
+        }
+        if (!operand) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field operand is required for UnaryOp");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = UnaryOp_kind;
+        p->v.UnaryOp.op = op;
+        p->v.UnaryOp.operand = operand;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Lambda(arguments_ty args, expr_ty body, int lineno)
+{
+        expr_ty p;
+        if (!args) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field args is required for Lambda");
+                return NULL;
+        }
+        if (!body) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field body is required for Lambda");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Lambda_kind;
+        p->v.Lambda.args = args;
+        p->v.Lambda.body = body;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Dict(asdl_seq * keys, asdl_seq * values, int lineno)
+{
+        expr_ty p;
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Dict_kind;
+        p->v.Dict.keys = keys;
+        p->v.Dict.values = values;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+ListComp(expr_ty elt, asdl_seq * generators, int lineno)
+{
+        expr_ty p;
+        if (!elt) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field elt is required for ListComp");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = ListComp_kind;
+        p->v.ListComp.elt = elt;
+        p->v.ListComp.generators = generators;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno)
+{
+        expr_ty p;
+        if (!elt) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field elt is required for GeneratorExp");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = GeneratorExp_kind;
+        p->v.GeneratorExp.elt = elt;
+        p->v.GeneratorExp.generators = generators;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Yield(expr_ty value, int lineno)
+{
+        expr_ty p;
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Yield_kind;
+        p->v.Yield.value = value;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Compare(expr_ty left, asdl_seq * ops, asdl_seq * comparators, int lineno)
+{
+        expr_ty p;
+        if (!left) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field left is required for Compare");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Compare_kind;
+        p->v.Compare.left = left;
+        p->v.Compare.ops = ops;
+        p->v.Compare.comparators = comparators;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, expr_ty starargs,
+     expr_ty kwargs, int lineno)
+{
+        expr_ty p;
+        if (!func) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field func is required for Call");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Call_kind;
+        p->v.Call.func = func;
+        p->v.Call.args = args;
+        p->v.Call.keywords = keywords;
+        p->v.Call.starargs = starargs;
+        p->v.Call.kwargs = kwargs;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Repr(expr_ty value, int lineno)
+{
+        expr_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Repr");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Repr_kind;
+        p->v.Repr.value = value;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Num(object n, int lineno)
+{
+        expr_ty p;
+        if (!n) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field n is required for Num");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Num_kind;
+        p->v.Num.n = n;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Str(string s, int lineno)
+{
+        expr_ty p;
+        if (!s) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field s is required for Str");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Str_kind;
+        p->v.Str.s = s;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int lineno)
+{
+        expr_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Attribute");
+                return NULL;
+        }
+        if (!attr) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field attr is required for Attribute");
+                return NULL;
+        }
+        if (!ctx) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field ctx is required for Attribute");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Attribute_kind;
+        p->v.Attribute.value = value;
+        p->v.Attribute.attr = attr;
+        p->v.Attribute.ctx = ctx;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Subscript(expr_ty value, slice_ty slice, expr_context_ty ctx, int lineno)
+{
+        expr_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Subscript");
+                return NULL;
+        }
+        if (!slice) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field slice is required for Subscript");
+                return NULL;
+        }
+        if (!ctx) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field ctx is required for Subscript");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Subscript_kind;
+        p->v.Subscript.value = value;
+        p->v.Subscript.slice = slice;
+        p->v.Subscript.ctx = ctx;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Name(identifier id, expr_context_ty ctx, int lineno)
+{
+        expr_ty p;
+        if (!id) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field id is required for Name");
+                return NULL;
+        }
+        if (!ctx) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field ctx is required for Name");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Name_kind;
+        p->v.Name.id = id;
+        p->v.Name.ctx = ctx;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+List(asdl_seq * elts, expr_context_ty ctx, int lineno)
+{
+        expr_ty p;
+        if (!ctx) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field ctx is required for List");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = List_kind;
+        p->v.List.elts = elts;
+        p->v.List.ctx = ctx;
+        p->lineno = lineno;
+        return p;
+}
+
+expr_ty
+Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno)
+{
+        expr_ty p;
+        if (!ctx) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field ctx is required for Tuple");
+                return NULL;
+        }
+        p = (expr_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Tuple_kind;
+        p->v.Tuple.elts = elts;
+        p->v.Tuple.ctx = ctx;
+        p->lineno = lineno;
+        return p;
+}
+
+slice_ty
+Ellipsis()
+{
+        slice_ty p;
+        p = (slice_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Ellipsis_kind;
+        return p;
+}
+
+slice_ty
+Slice(expr_ty lower, expr_ty upper, expr_ty step)
+{
+        slice_ty p;
+        p = (slice_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Slice_kind;
+        p->v.Slice.lower = lower;
+        p->v.Slice.upper = upper;
+        p->v.Slice.step = step;
+        return p;
+}
+
+slice_ty
+ExtSlice(asdl_seq * dims)
+{
+        slice_ty p;
+        p = (slice_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = ExtSlice_kind;
+        p->v.ExtSlice.dims = dims;
+        return p;
+}
+
+slice_ty
+Index(expr_ty value)
+{
+        slice_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for Index");
+                return NULL;
+        }
+        p = (slice_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->kind = Index_kind;
+        p->v.Index.value = value;
+        return p;
+}
+
+comprehension_ty
+comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs)
+{
+        comprehension_ty p;
+        if (!target) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field target is required for comprehension");
+                return NULL;
+        }
+        if (!iter) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field iter is required for comprehension");
+                return NULL;
+        }
+        p = (comprehension_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->target = target;
+        p->iter = iter;
+        p->ifs = ifs;
+        return p;
+}
+
+excepthandler_ty
+excepthandler(expr_ty type, expr_ty name, asdl_seq * body)
+{
+        excepthandler_ty p;
+        p = (excepthandler_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->type = type;
+        p->name = name;
+        p->body = body;
+        return p;
+}
+
+arguments_ty
+arguments(asdl_seq * args, identifier vararg, identifier kwarg, asdl_seq *
+          defaults)
+{
+        arguments_ty p;
+        p = (arguments_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->args = args;
+        p->vararg = vararg;
+        p->kwarg = kwarg;
+        p->defaults = defaults;
+        return p;
+}
+
+keyword_ty
+keyword(identifier arg, expr_ty value)
+{
+        keyword_ty p;
+        if (!arg) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field arg is required for keyword");
+                return NULL;
+        }
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for keyword");
+                return NULL;
+        }
+        p = (keyword_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->arg = arg;
+        p->value = value;
+        return p;
+}
+
+alias_ty
+alias(identifier name, identifier asname)
+{
+        alias_ty p;
+        if (!name) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field name is required for alias");
+                return NULL;
+        }
+        p = (alias_ty)malloc(sizeof(*p));
+        if (!p) {
+                PyErr_SetString(PyExc_MemoryError, "no memory");
+                return NULL;
+        }
+        p->name = name;
+        p->asname = asname;
+        return p;
+}
+
+static void
+free_seq_exprs(asdl_seq *seq)
+{
+        int i, n;
+        n = asdl_seq_LEN(seq);
+        for (i = 0; i < n; i++)
+                free_expr((expr_ty)asdl_seq_GET(seq, i));
+        asdl_seq_free(seq);
+}
+
+static void
+free_seq_stmts(asdl_seq *seq)
+{
+        int i, n;
+        n = asdl_seq_LEN(seq);
+        for (i = 0; i < n; i++)
+                free_stmt((stmt_ty)asdl_seq_GET(seq, i));
+        asdl_seq_free(seq);
+}
+
+void
+free_mod(mod_ty o)
+{
+        if (!o)
+                return;
+
+        switch (o->kind) {
+        case Module_kind:
+                free_seq_stmts(o->v.Module.body);
+                break;
+        case Interactive_kind:
+                free_seq_stmts(o->v.Interactive.body);
+                break;
+        case Expression_kind:
+                free_expr((expr_ty)o->v.Expression.body);
+                break;
+        case Suite_kind:
+                free_seq_stmts(o->v.Suite.body);
+                break;
+        }
+
+        free(o);
+}
+
+void
+free_stmt(stmt_ty o)
+{
+        int i, n;
+        asdl_seq *seq;
+
+        if (!o)
+                return;
+
+        switch (o->kind) {
+        case FunctionDef_kind:
+                Py_DECREF((identifier)o->v.FunctionDef.name);
+                free_arguments((arguments_ty)o->v.FunctionDef.args);
+                free_seq_stmts(o->v.FunctionDef.body);
+                free_seq_exprs(o->v.FunctionDef.decorators);
+                break;
+        case ClassDef_kind:
+                Py_DECREF((identifier)o->v.ClassDef.name);
+                free_seq_exprs(o->v.ClassDef.bases);
+                free_seq_stmts(o->v.ClassDef.body);
+                break;
+        case Return_kind:
+                if (o->v.Return.value) {
+                        free_expr((expr_ty)o->v.Return.value);
+                }
+                break;
+        case Delete_kind:
+                free_seq_exprs(o->v.Delete.targets);
+                break;
+        case Assign_kind:
+                free_seq_exprs(o->v.Assign.targets);
+                free_expr((expr_ty)o->v.Assign.value);
+                break;
+        case AugAssign_kind:
+                free_expr((expr_ty)o->v.AugAssign.target);
+                free_operator((operator_ty)o->v.AugAssign.op);
+                free_expr((expr_ty)o->v.AugAssign.value);
+                break;
+        case Print_kind:
+                if (o->v.Print.dest) {
+                        free_expr((expr_ty)o->v.Print.dest);
+                }
+                free_seq_exprs(o->v.Print.values);
+                break;
+        case For_kind:
+                free_expr((expr_ty)o->v.For.target);
+                free_expr((expr_ty)o->v.For.iter);
+                free_seq_stmts(o->v.For.body);
+                free_seq_stmts(o->v.For.orelse);
+                break;
+        case While_kind:
+                free_expr((expr_ty)o->v.While.test);
+                free_seq_stmts(o->v.While.body);
+                free_seq_stmts(o->v.While.orelse);
+                break;
+        case If_kind:
+                free_expr((expr_ty)o->v.If.test);
+                free_seq_stmts(o->v.If.body);
+                free_seq_stmts(o->v.If.orelse);
+                break;
+        case Raise_kind:
+                if (o->v.Raise.type) {
+                        free_expr((expr_ty)o->v.Raise.type);
+                }
+                if (o->v.Raise.inst) {
+                        free_expr((expr_ty)o->v.Raise.inst);
+                }
+                if (o->v.Raise.tback) {
+                        free_expr((expr_ty)o->v.Raise.tback);
+                }
+                break;
+        case TryExcept_kind:
+                free_seq_stmts(o->v.TryExcept.body);
+                seq = o->v.TryExcept.handlers;
+                n = asdl_seq_LEN(seq);
+                for (i = 0; i < n; i++)
+                        free_excepthandler((excepthandler_ty)asdl_seq_GET(seq,
+                                           i));
+                asdl_seq_free(seq);
+                free_seq_stmts(o->v.TryExcept.orelse);
+                break;
+        case TryFinally_kind:
+                free_seq_stmts(o->v.TryFinally.body);
+                free_seq_stmts(o->v.TryFinally.finalbody);
+                break;
+        case Assert_kind:
+                free_expr((expr_ty)o->v.Assert.test);
+                if (o->v.Assert.msg) {
+                        free_expr((expr_ty)o->v.Assert.msg);
+                }
+                break;
+        case Import_kind:
+                seq = o->v.Import.names;
+                n = asdl_seq_LEN(seq);
+                for (i = 0; i < n; i++)
+                        free_alias((alias_ty)asdl_seq_GET(seq, i));
+                asdl_seq_free(seq);
+                break;
+        case ImportFrom_kind:
+                Py_DECREF((identifier)o->v.ImportFrom.module);
+                seq = o->v.ImportFrom.names;
+                n = asdl_seq_LEN(seq);
+                for (i = 0; i < n; i++)
+                        free_alias((alias_ty)asdl_seq_GET(seq, i));
+                asdl_seq_free(seq);
+                break;
+        case Exec_kind:
+                free_expr((expr_ty)o->v.Exec.body);
+                if (o->v.Exec.globals) {
+                        free_expr((expr_ty)o->v.Exec.globals);
+                }
+                if (o->v.Exec.locals) {
+                        free_expr((expr_ty)o->v.Exec.locals);
+                }
+                break;
+        case Global_kind:
+                seq = o->v.Global.names;
+                n = asdl_seq_LEN(seq);
+                for (i = 0; i < n; i++)
+                        Py_DECREF((identifier)asdl_seq_GET(seq, i));
+                asdl_seq_free(seq);
+                break;
+        case Expr_kind:
+                free_expr((expr_ty)o->v.Expr.value);
+                break;
+        case Pass_kind:
+                break;
+        case Break_kind:
+                break;
+        case Continue_kind:
+                break;
+        }
+
+        free(o);
+}
+
+void
+free_expr(expr_ty o)
+{
+        int i, n;
+        asdl_seq *seq;
+
+        if (!o)
+                return;
+
+        switch (o->kind) {
+        case BoolOp_kind:
+                free_boolop((boolop_ty)o->v.BoolOp.op);
+                free_seq_exprs(o->v.BoolOp.values);
+                break;
+        case BinOp_kind:
+                free_expr((expr_ty)o->v.BinOp.left);
+                free_operator((operator_ty)o->v.BinOp.op);
+                free_expr((expr_ty)o->v.BinOp.right);
+                break;
+        case UnaryOp_kind:
+                free_unaryop((unaryop_ty)o->v.UnaryOp.op);
+                free_expr((expr_ty)o->v.UnaryOp.operand);
+                break;
+        case Lambda_kind:
+                free_arguments((arguments_ty)o->v.Lambda.args);
+                free_expr((expr_ty)o->v.Lambda.body);
+                break;
+        case Dict_kind:
+                free_seq_exprs(o->v.Dict.keys);
+                free_seq_exprs(o->v.Dict.values);
+                break;
+        case ListComp_kind:
+                free_expr((expr_ty)o->v.ListComp.elt);
+                seq = o->v.ListComp.generators;
+                n = asdl_seq_LEN(seq);
+                for (i = 0; i < n; i++)
+                        free_comprehension((comprehension_ty)asdl_seq_GET(seq,
+                                           i));
+                asdl_seq_free(seq);
+                break;
+        case GeneratorExp_kind:
+                free_expr((expr_ty)o->v.GeneratorExp.elt);
+                seq = o->v.GeneratorExp.generators;
+                n = asdl_seq_LEN(seq);
+                for (i = 0; i < n; i++)
+                        free_comprehension((comprehension_ty)asdl_seq_GET(seq,
+                                           i));
+                asdl_seq_free(seq);
+                break;
+        case Yield_kind:
+                if (o->v.Yield.value) {
+                        free_expr((expr_ty)o->v.Yield.value);
+                }
+                break;
+        case Compare_kind:
+                free_expr((expr_ty)o->v.Compare.left);
+                seq = o->v.Compare.ops;
+                n = asdl_seq_LEN(seq);
+                for (i = 0; i < n; i++)
+                        free_cmpop((cmpop_ty)asdl_seq_GET(seq, i));
+                asdl_seq_free(seq);
+                free_seq_exprs(o->v.Compare.comparators);
+                break;
+        case Call_kind:
+                free_expr((expr_ty)o->v.Call.func);
+                free_seq_exprs(o->v.Call.args);
+                seq = o->v.Call.keywords;
+                n = asdl_seq_LEN(seq);
+                for (i = 0; i < n; i++)
+                        free_keyword((keyword_ty)asdl_seq_GET(seq, i));
+                asdl_seq_free(seq);
+                if (o->v.Call.starargs) {
+                        free_expr((expr_ty)o->v.Call.starargs);
+                }
+                if (o->v.Call.kwargs) {
+                        free_expr((expr_ty)o->v.Call.kwargs);
+                }
+                break;
+        case Repr_kind:
+                free_expr((expr_ty)o->v.Repr.value);
+                break;
+        case Num_kind:
+                Py_DECREF((object)o->v.Num.n);
+                break;
+        case Str_kind:
+                Py_DECREF((string)o->v.Str.s);
+                break;
+        case Attribute_kind:
+                free_expr((expr_ty)o->v.Attribute.value);
+                Py_DECREF((identifier)o->v.Attribute.attr);
+                free_expr_context((expr_context_ty)o->v.Attribute.ctx);
+                break;
+        case Subscript_kind:
+                free_expr((expr_ty)o->v.Subscript.value);
+                free_slice((slice_ty)o->v.Subscript.slice);
+                free_expr_context((expr_context_ty)o->v.Subscript.ctx);
+                break;
+        case Name_kind:
+                Py_DECREF((identifier)o->v.Name.id);
+                free_expr_context((expr_context_ty)o->v.Name.ctx);
+                break;
+        case List_kind:
+                free_seq_exprs(o->v.List.elts);
+                free_expr_context((expr_context_ty)o->v.List.ctx);
+                break;
+        case Tuple_kind:
+                free_seq_exprs(o->v.Tuple.elts);
+                free_expr_context((expr_context_ty)o->v.Tuple.ctx);
+                break;
+        }
+
+        free(o);
+}
+
+void
+free_expr_context(expr_context_ty o)
+{
+        if (!o)
+                return;
+
+}
+
+void
+free_slice(slice_ty o)
+{
+        int i, n;
+        asdl_seq *seq;
+
+        if (!o)
+                return;
+
+        switch (o->kind) {
+        case Ellipsis_kind:
+                break;
+        case Slice_kind:
+                if (o->v.Slice.lower) {
+                        free_expr((expr_ty)o->v.Slice.lower);
+                }
+                if (o->v.Slice.upper) {
+                        free_expr((expr_ty)o->v.Slice.upper);
+                }
+                if (o->v.Slice.step) {
+                        free_expr((expr_ty)o->v.Slice.step);
+                }
+                break;
+        case ExtSlice_kind:
+                seq = o->v.ExtSlice.dims;
+                n = asdl_seq_LEN(seq);
+                for (i = 0; i < n; i++)
+                        free_slice((slice_ty)asdl_seq_GET(seq, i));
+                asdl_seq_free(seq);
+                break;
+        case Index_kind:
+                free_expr((expr_ty)o->v.Index.value);
+                break;
+        }
+
+        free(o);
+}
+
+void
+free_boolop(boolop_ty o)
+{
+        if (!o)
+                return;
+
+}
+
+void
+free_operator(operator_ty o)
+{
+        if (!o)
+                return;
+
+}
+
+void
+free_unaryop(unaryop_ty o)
+{
+        if (!o)
+                return;
+
+}
+
+void
+free_cmpop(cmpop_ty o)
+{
+        if (!o)
+                return;
+
+}
+
+void
+free_comprehension(comprehension_ty o)
+{
+        if (!o)
+                return;
+
+        free_expr((expr_ty)o->target);
+        free_expr((expr_ty)o->iter);
+        free_seq_exprs(o->ifs);
+
+        free(o);
+}
+
+void
+free_excepthandler(excepthandler_ty o)
+{
+        if (!o)
+                return;
+
+        if (o->type) {
+                free_expr((expr_ty)o->type);
+        }
+        if (o->name) {
+                free_expr((expr_ty)o->name);
+        }
+        free_seq_stmts(o->body);
+
+        free(o);
+}
+
+void
+free_arguments(arguments_ty o)
+{
+        if (!o)
+                return;
+
+        free_seq_exprs(o->args);
+        if (o->vararg) {
+                Py_DECREF((identifier)o->vararg);
+        }
+        if (o->kwarg) {
+                Py_DECREF((identifier)o->kwarg);
+        }
+        free_seq_exprs(o->defaults);
+
+        free(o);
+}
+
+void
+free_keyword(keyword_ty o)
+{
+        if (!o)
+                return;
+
+        Py_DECREF((identifier)o->arg);
+        free_expr((expr_ty)o->value);
+
+        free(o);
+}
+
+void
+free_alias(alias_ty o)
+{
+        if (!o)
+                return;
+
+        Py_DECREF((identifier)o->name);
+        if (o->asname) {
+                Py_DECREF((identifier)o->asname);
+        }
+
+        free(o);
+}
+
+int
+marshal_write_mod(PyObject **buf, int *off, mod_ty o)
+{
+        int i;
+        switch (o->kind) {
+        case Module_kind:
+                marshal_write_int(buf, off, 1);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Module.body));
+                for (i = 0; i < asdl_seq_LEN(o->v.Module.body); i++) {
+                        void *elt = asdl_seq_GET(o->v.Module.body, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                break;
+        case Interactive_kind:
+                marshal_write_int(buf, off, 2);
+                marshal_write_int(buf, off,
+                                  asdl_seq_LEN(o->v.Interactive.body));
+                for (i = 0; i < asdl_seq_LEN(o->v.Interactive.body); i++) {
+                        void *elt = asdl_seq_GET(o->v.Interactive.body, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                break;
+        case Expression_kind:
+                marshal_write_int(buf, off, 3);
+                marshal_write_expr(buf, off, o->v.Expression.body);
+                break;
+        case Suite_kind:
+                marshal_write_int(buf, off, 4);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Suite.body));
+                for (i = 0; i < asdl_seq_LEN(o->v.Suite.body); i++) {
+                        void *elt = asdl_seq_GET(o->v.Suite.body, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                break;
+        }
+        return 1;
+}
+
+int
+marshal_write_stmt(PyObject **buf, int *off, stmt_ty o)
+{
+        int i;
+        switch (o->kind) {
+        case FunctionDef_kind:
+                marshal_write_int(buf, off, 1);
+                marshal_write_identifier(buf, off, o->v.FunctionDef.name);
+                marshal_write_arguments(buf, off, o->v.FunctionDef.args);
+                marshal_write_int(buf, off,
+                                  asdl_seq_LEN(o->v.FunctionDef.body));
+                for (i = 0; i < asdl_seq_LEN(o->v.FunctionDef.body); i++) {
+                        void *elt = asdl_seq_GET(o->v.FunctionDef.body, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                marshal_write_int(buf, off,
+                                  asdl_seq_LEN(o->v.FunctionDef.decorators));
+                for (i = 0; i < asdl_seq_LEN(o->v.FunctionDef.decorators); i++)
+                     {
+                        void *elt = asdl_seq_GET(o->v.FunctionDef.decorators,
+                                                 i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                break;
+        case ClassDef_kind:
+                marshal_write_int(buf, off, 2);
+                marshal_write_identifier(buf, off, o->v.ClassDef.name);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.ClassDef.bases));
+                for (i = 0; i < asdl_seq_LEN(o->v.ClassDef.bases); i++) {
+                        void *elt = asdl_seq_GET(o->v.ClassDef.bases, i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.ClassDef.body));
+                for (i = 0; i < asdl_seq_LEN(o->v.ClassDef.body); i++) {
+                        void *elt = asdl_seq_GET(o->v.ClassDef.body, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                break;
+        case Return_kind:
+                marshal_write_int(buf, off, 3);
+                if (o->v.Return.value) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Return.value);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                break;
+        case Delete_kind:
+                marshal_write_int(buf, off, 4);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Delete.targets));
+                for (i = 0; i < asdl_seq_LEN(o->v.Delete.targets); i++) {
+                        void *elt = asdl_seq_GET(o->v.Delete.targets, i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                break;
+        case Assign_kind:
+                marshal_write_int(buf, off, 5);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Assign.targets));
+                for (i = 0; i < asdl_seq_LEN(o->v.Assign.targets); i++) {
+                        void *elt = asdl_seq_GET(o->v.Assign.targets, i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                marshal_write_expr(buf, off, o->v.Assign.value);
+                break;
+        case AugAssign_kind:
+                marshal_write_int(buf, off, 6);
+                marshal_write_expr(buf, off, o->v.AugAssign.target);
+                marshal_write_operator(buf, off, o->v.AugAssign.op);
+                marshal_write_expr(buf, off, o->v.AugAssign.value);
+                break;
+        case Print_kind:
+                marshal_write_int(buf, off, 7);
+                if (o->v.Print.dest) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Print.dest);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Print.values));
+                for (i = 0; i < asdl_seq_LEN(o->v.Print.values); i++) {
+                        void *elt = asdl_seq_GET(o->v.Print.values, i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                marshal_write_bool(buf, off, o->v.Print.nl);
+                break;
+        case For_kind:
+                marshal_write_int(buf, off, 8);
+                marshal_write_expr(buf, off, o->v.For.target);
+                marshal_write_expr(buf, off, o->v.For.iter);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.For.body));
+                for (i = 0; i < asdl_seq_LEN(o->v.For.body); i++) {
+                        void *elt = asdl_seq_GET(o->v.For.body, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.For.orelse));
+                for (i = 0; i < asdl_seq_LEN(o->v.For.orelse); i++) {
+                        void *elt = asdl_seq_GET(o->v.For.orelse, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                break;
+        case While_kind:
+                marshal_write_int(buf, off, 9);
+                marshal_write_expr(buf, off, o->v.While.test);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.While.body));
+                for (i = 0; i < asdl_seq_LEN(o->v.While.body); i++) {
+                        void *elt = asdl_seq_GET(o->v.While.body, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.While.orelse));
+                for (i = 0; i < asdl_seq_LEN(o->v.While.orelse); i++) {
+                        void *elt = asdl_seq_GET(o->v.While.orelse, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                break;
+        case If_kind:
+                marshal_write_int(buf, off, 10);
+                marshal_write_expr(buf, off, o->v.If.test);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.If.body));
+                for (i = 0; i < asdl_seq_LEN(o->v.If.body); i++) {
+                        void *elt = asdl_seq_GET(o->v.If.body, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.If.orelse));
+                for (i = 0; i < asdl_seq_LEN(o->v.If.orelse); i++) {
+                        void *elt = asdl_seq_GET(o->v.If.orelse, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                break;
+        case Raise_kind:
+                marshal_write_int(buf, off, 11);
+                if (o->v.Raise.type) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Raise.type);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                if (o->v.Raise.inst) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Raise.inst);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                if (o->v.Raise.tback) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Raise.tback);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                break;
+        case TryExcept_kind:
+                marshal_write_int(buf, off, 12);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.TryExcept.body));
+                for (i = 0; i < asdl_seq_LEN(o->v.TryExcept.body); i++) {
+                        void *elt = asdl_seq_GET(o->v.TryExcept.body, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                marshal_write_int(buf, off,
+                                  asdl_seq_LEN(o->v.TryExcept.handlers));
+                for (i = 0; i < asdl_seq_LEN(o->v.TryExcept.handlers); i++) {
+                        void *elt = asdl_seq_GET(o->v.TryExcept.handlers, i);
+                        marshal_write_excepthandler(buf, off,
+                                                    (excepthandler_ty)elt);
+                }
+                marshal_write_int(buf, off,
+                                  asdl_seq_LEN(o->v.TryExcept.orelse));
+                for (i = 0; i < asdl_seq_LEN(o->v.TryExcept.orelse); i++) {
+                        void *elt = asdl_seq_GET(o->v.TryExcept.orelse, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                break;
+        case TryFinally_kind:
+                marshal_write_int(buf, off, 13);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.TryFinally.body));
+                for (i = 0; i < asdl_seq_LEN(o->v.TryFinally.body); i++) {
+                        void *elt = asdl_seq_GET(o->v.TryFinally.body, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                marshal_write_int(buf, off,
+                                  asdl_seq_LEN(o->v.TryFinally.finalbody));
+                for (i = 0; i < asdl_seq_LEN(o->v.TryFinally.finalbody); i++) {
+                        void *elt = asdl_seq_GET(o->v.TryFinally.finalbody, i);
+                        marshal_write_stmt(buf, off, (stmt_ty)elt);
+                }
+                break;
+        case Assert_kind:
+                marshal_write_int(buf, off, 14);
+                marshal_write_expr(buf, off, o->v.Assert.test);
+                if (o->v.Assert.msg) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Assert.msg);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                break;
+        case Import_kind:
+                marshal_write_int(buf, off, 15);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Import.names));
+                for (i = 0; i < asdl_seq_LEN(o->v.Import.names); i++) {
+                        void *elt = asdl_seq_GET(o->v.Import.names, i);
+                        marshal_write_alias(buf, off, (alias_ty)elt);
+                }
+                break;
+        case ImportFrom_kind:
+                marshal_write_int(buf, off, 16);
+                marshal_write_identifier(buf, off, o->v.ImportFrom.module);
+                marshal_write_int(buf, off,
+                                  asdl_seq_LEN(o->v.ImportFrom.names));
+                for (i = 0; i < asdl_seq_LEN(o->v.ImportFrom.names); i++) {
+                        void *elt = asdl_seq_GET(o->v.ImportFrom.names, i);
+                        marshal_write_alias(buf, off, (alias_ty)elt);
+                }
+                break;
+        case Exec_kind:
+                marshal_write_int(buf, off, 17);
+                marshal_write_expr(buf, off, o->v.Exec.body);
+                if (o->v.Exec.globals) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Exec.globals);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                if (o->v.Exec.locals) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Exec.locals);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                break;
+        case Global_kind:
+                marshal_write_int(buf, off, 18);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Global.names));
+                for (i = 0; i < asdl_seq_LEN(o->v.Global.names); i++) {
+                        void *elt = asdl_seq_GET(o->v.Global.names, i);
+                        marshal_write_identifier(buf, off, (identifier)elt);
+                }
+                break;
+        case Expr_kind:
+                marshal_write_int(buf, off, 19);
+                marshal_write_expr(buf, off, o->v.Expr.value);
+                break;
+        case Pass_kind:
+                marshal_write_int(buf, off, 20);
+                break;
+        case Break_kind:
+                marshal_write_int(buf, off, 21);
+                break;
+        case Continue_kind:
+                marshal_write_int(buf, off, 22);
+                break;
+        }
+        return 1;
+}
+
+int
+marshal_write_expr(PyObject **buf, int *off, expr_ty o)
+{
+        int i;
+        switch (o->kind) {
+        case BoolOp_kind:
+                marshal_write_int(buf, off, 1);
+                marshal_write_boolop(buf, off, o->v.BoolOp.op);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.BoolOp.values));
+                for (i = 0; i < asdl_seq_LEN(o->v.BoolOp.values); i++) {
+                        void *elt = asdl_seq_GET(o->v.BoolOp.values, i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                break;
+        case BinOp_kind:
+                marshal_write_int(buf, off, 2);
+                marshal_write_expr(buf, off, o->v.BinOp.left);
+                marshal_write_operator(buf, off, o->v.BinOp.op);
+                marshal_write_expr(buf, off, o->v.BinOp.right);
+                break;
+        case UnaryOp_kind:
+                marshal_write_int(buf, off, 3);
+                marshal_write_unaryop(buf, off, o->v.UnaryOp.op);
+                marshal_write_expr(buf, off, o->v.UnaryOp.operand);
+                break;
+        case Lambda_kind:
+                marshal_write_int(buf, off, 4);
+                marshal_write_arguments(buf, off, o->v.Lambda.args);
+                marshal_write_expr(buf, off, o->v.Lambda.body);
+                break;
+        case Dict_kind:
+                marshal_write_int(buf, off, 5);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Dict.keys));
+                for (i = 0; i < asdl_seq_LEN(o->v.Dict.keys); i++) {
+                        void *elt = asdl_seq_GET(o->v.Dict.keys, i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Dict.values));
+                for (i = 0; i < asdl_seq_LEN(o->v.Dict.values); i++) {
+                        void *elt = asdl_seq_GET(o->v.Dict.values, i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                break;
+        case ListComp_kind:
+                marshal_write_int(buf, off, 6);
+                marshal_write_expr(buf, off, o->v.ListComp.elt);
+                marshal_write_int(buf, off,
+                                  asdl_seq_LEN(o->v.ListComp.generators));
+                for (i = 0; i < asdl_seq_LEN(o->v.ListComp.generators); i++) {
+                        void *elt = asdl_seq_GET(o->v.ListComp.generators, i);
+                        marshal_write_comprehension(buf, off,
+                                                    (comprehension_ty)elt);
+                }
+                break;
+        case GeneratorExp_kind:
+                marshal_write_int(buf, off, 7);
+                marshal_write_expr(buf, off, o->v.GeneratorExp.elt);
+                marshal_write_int(buf, off,
+                                  asdl_seq_LEN(o->v.GeneratorExp.generators));
+                for (i = 0; i < asdl_seq_LEN(o->v.GeneratorExp.generators);
+                     i++) {
+                        void *elt = asdl_seq_GET(o->v.GeneratorExp.generators,
+                                                 i);
+                        marshal_write_comprehension(buf, off,
+                                                    (comprehension_ty)elt);
+                }
+                break;
+        case Yield_kind:
+                marshal_write_int(buf, off, 8);
+                if (o->v.Yield.value) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Yield.value);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                break;
+        case Compare_kind:
+                marshal_write_int(buf, off, 9);
+                marshal_write_expr(buf, off, o->v.Compare.left);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Compare.ops));
+                for (i = 0; i < asdl_seq_LEN(o->v.Compare.ops); i++) {
+                        void *elt = asdl_seq_GET(o->v.Compare.ops, i);
+                        marshal_write_cmpop(buf, off, (cmpop_ty)elt);
+                }
+                marshal_write_int(buf, off,
+                                  asdl_seq_LEN(o->v.Compare.comparators));
+                for (i = 0; i < asdl_seq_LEN(o->v.Compare.comparators); i++) {
+                        void *elt = asdl_seq_GET(o->v.Compare.comparators, i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                break;
+        case Call_kind:
+                marshal_write_int(buf, off, 10);
+                marshal_write_expr(buf, off, o->v.Call.func);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Call.args));
+                for (i = 0; i < asdl_seq_LEN(o->v.Call.args); i++) {
+                        void *elt = asdl_seq_GET(o->v.Call.args, i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Call.keywords));
+                for (i = 0; i < asdl_seq_LEN(o->v.Call.keywords); i++) {
+                        void *elt = asdl_seq_GET(o->v.Call.keywords, i);
+                        marshal_write_keyword(buf, off, (keyword_ty)elt);
+                }
+                if (o->v.Call.starargs) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Call.starargs);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                if (o->v.Call.kwargs) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Call.kwargs);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                break;
+        case Repr_kind:
+                marshal_write_int(buf, off, 11);
+                marshal_write_expr(buf, off, o->v.Repr.value);
+                break;
+        case Num_kind:
+                marshal_write_int(buf, off, 12);
+                marshal_write_object(buf, off, o->v.Num.n);
+                break;
+        case Str_kind:
+                marshal_write_int(buf, off, 13);
+                marshal_write_string(buf, off, o->v.Str.s);
+                break;
+        case Attribute_kind:
+                marshal_write_int(buf, off, 14);
+                marshal_write_expr(buf, off, o->v.Attribute.value);
+                marshal_write_identifier(buf, off, o->v.Attribute.attr);
+                marshal_write_expr_context(buf, off, o->v.Attribute.ctx);
+                break;
+        case Subscript_kind:
+                marshal_write_int(buf, off, 15);
+                marshal_write_expr(buf, off, o->v.Subscript.value);
+                marshal_write_slice(buf, off, o->v.Subscript.slice);
+                marshal_write_expr_context(buf, off, o->v.Subscript.ctx);
+                break;
+        case Name_kind:
+                marshal_write_int(buf, off, 16);
+                marshal_write_identifier(buf, off, o->v.Name.id);
+                marshal_write_expr_context(buf, off, o->v.Name.ctx);
+                break;
+        case List_kind:
+                marshal_write_int(buf, off, 17);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.List.elts));
+                for (i = 0; i < asdl_seq_LEN(o->v.List.elts); i++) {
+                        void *elt = asdl_seq_GET(o->v.List.elts, i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                marshal_write_expr_context(buf, off, o->v.List.ctx);
+                break;
+        case Tuple_kind:
+                marshal_write_int(buf, off, 18);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.Tuple.elts));
+                for (i = 0; i < asdl_seq_LEN(o->v.Tuple.elts); i++) {
+                        void *elt = asdl_seq_GET(o->v.Tuple.elts, i);
+                        marshal_write_expr(buf, off, (expr_ty)elt);
+                }
+                marshal_write_expr_context(buf, off, o->v.Tuple.ctx);
+                break;
+        }
+        return 1;
+}
+
+int
+marshal_write_expr_context(PyObject **buf, int *off, expr_context_ty o)
+{
+        int i;
+        switch (o) {
+        case Load:
+                marshal_write_int(buf, off, 1);
+                break;
+        case Store:
+                marshal_write_int(buf, off, 2);
+                break;
+        case Del:
+                marshal_write_int(buf, off, 3);
+                break;
+        case AugLoad:
+                marshal_write_int(buf, off, 4);
+                break;
+        case AugStore:
+                marshal_write_int(buf, off, 5);
+                break;
+        case Param:
+                marshal_write_int(buf, off, 6);
+                break;
+        }
+        return 1;
+}
+
+int
+marshal_write_slice(PyObject **buf, int *off, slice_ty o)
+{
+        int i;
+        switch (o->kind) {
+        case Ellipsis_kind:
+                marshal_write_int(buf, off, 1);
+                break;
+        case Slice_kind:
+                marshal_write_int(buf, off, 2);
+                if (o->v.Slice.lower) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Slice.lower);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                if (o->v.Slice.upper) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Slice.upper);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                if (o->v.Slice.step) {
+                        marshal_write_int(buf, off, 1);
+                        marshal_write_expr(buf, off, o->v.Slice.step);
+                }
+                else {
+                        marshal_write_int(buf, off, 0);
+                }
+                break;
+        case ExtSlice_kind:
+                marshal_write_int(buf, off, 3);
+                marshal_write_int(buf, off, asdl_seq_LEN(o->v.ExtSlice.dims));
+                for (i = 0; i < asdl_seq_LEN(o->v.ExtSlice.dims); i++) {
+                        void *elt = asdl_seq_GET(o->v.ExtSlice.dims, i);
+                        marshal_write_slice(buf, off, (slice_ty)elt);
+                }
+                break;
+        case Index_kind:
+                marshal_write_int(buf, off, 4);
+                marshal_write_expr(buf, off, o->v.Index.value);
+                break;
+        }
+        return 1;
+}
+
+int
+marshal_write_boolop(PyObject **buf, int *off, boolop_ty o)
+{
+        int i;
+        switch (o) {
+        case And:
+                marshal_write_int(buf, off, 1);
+                break;
+        case Or:
+                marshal_write_int(buf, off, 2);
+                break;
+        }
+        return 1;
+}
+
+int
+marshal_write_operator(PyObject **buf, int *off, operator_ty o)
+{
+        int i;
+        switch (o) {
+        case Add:
+                marshal_write_int(buf, off, 1);
+                break;
+        case Sub:
+                marshal_write_int(buf, off, 2);
+                break;
+        case Mult:
+                marshal_write_int(buf, off, 3);
+                break;
+        case Div:
+                marshal_write_int(buf, off, 4);
+                break;
+        case Mod:
+                marshal_write_int(buf, off, 5);
+                break;
+        case Pow:
+                marshal_write_int(buf, off, 6);
+                break;
+        case LShift:
+                marshal_write_int(buf, off, 7);
+                break;
+        case RShift:
+                marshal_write_int(buf, off, 8);
+                break;
+        case BitOr:
+                marshal_write_int(buf, off, 9);
+                break;
+        case BitXor:
+                marshal_write_int(buf, off, 10);
+                break;
+        case BitAnd:
+                marshal_write_int(buf, off, 11);
+                break;
+        case FloorDiv:
+                marshal_write_int(buf, off, 12);
+                break;
+        }
+        return 1;
+}
+
+int
+marshal_write_unaryop(PyObject **buf, int *off, unaryop_ty o)
+{
+        int i;
+        switch (o) {
+        case Invert:
+                marshal_write_int(buf, off, 1);
+                break;
+        case Not:
+                marshal_write_int(buf, off, 2);
+                break;
+        case UAdd:
+                marshal_write_int(buf, off, 3);
+                break;
+        case USub:
+                marshal_write_int(buf, off, 4);
+                break;
+        }
+        return 1;
+}
+
+int
+marshal_write_cmpop(PyObject **buf, int *off, cmpop_ty o)
+{
+        int i;
+        switch (o) {
+        case Eq:
+                marshal_write_int(buf, off, 1);
+                break;
+        case NotEq:
+                marshal_write_int(buf, off, 2);
+                break;
+        case Lt:
+                marshal_write_int(buf, off, 3);
+                break;
+        case LtE:
+                marshal_write_int(buf, off, 4);
+                break;
+        case Gt:
+                marshal_write_int(buf, off, 5);
+                break;
+        case GtE:
+                marshal_write_int(buf, off, 6);
+                break;
+        case Is:
+                marshal_write_int(buf, off, 7);
+                break;
+        case IsNot:
+                marshal_write_int(buf, off, 8);
+                break;
+        case In:
+                marshal_write_int(buf, off, 9);
+                break;
+        case NotIn:
+                marshal_write_int(buf, off, 10);
+                break;
+        }
+        return 1;
+}
+
+int
+marshal_write_comprehension(PyObject **buf, int *off, comprehension_ty o)
+{
+        int i;
+        marshal_write_expr(buf, off, o->target);
+        marshal_write_expr(buf, off, o->iter);
+        marshal_write_int(buf, off, asdl_seq_LEN(o->ifs));
+        for (i = 0; i < asdl_seq_LEN(o->ifs); i++) {
+                void *elt = asdl_seq_GET(o->ifs, i);
+                marshal_write_expr(buf, off, (expr_ty)elt);
+        }
+        return 1;
+}
+
+int
+marshal_write_excepthandler(PyObject **buf, int *off, excepthandler_ty o)
+{
+        int i;
+        if (o->type) {
+                marshal_write_int(buf, off, 1);
+                marshal_write_expr(buf, off, o->type);
+        }
+        else {
+                marshal_write_int(buf, off, 0);
+        }
+        if (o->name) {
+                marshal_write_int(buf, off, 1);
+                marshal_write_expr(buf, off, o->name);
+        }
+        else {
+                marshal_write_int(buf, off, 0);
+        }
+        marshal_write_int(buf, off, asdl_seq_LEN(o->body));
+        for (i = 0; i < asdl_seq_LEN(o->body); i++) {
+                void *elt = asdl_seq_GET(o->body, i);
+                marshal_write_stmt(buf, off, (stmt_ty)elt);
+        }
+        return 1;
+}
+
+int
+marshal_write_arguments(PyObject **buf, int *off, arguments_ty o)
+{
+        int i;
+        marshal_write_int(buf, off, asdl_seq_LEN(o->args));
+        for (i = 0; i < asdl_seq_LEN(o->args); i++) {
+                void *elt = asdl_seq_GET(o->args, i);
+                marshal_write_expr(buf, off, (expr_ty)elt);
+        }
+        if (o->vararg) {
+                marshal_write_int(buf, off, 1);
+                marshal_write_identifier(buf, off, o->vararg);
+        }
+        else {
+                marshal_write_int(buf, off, 0);
+        }
+        if (o->kwarg) {
+                marshal_write_int(buf, off, 1);
+                marshal_write_identifier(buf, off, o->kwarg);
+        }
+        else {
+                marshal_write_int(buf, off, 0);
+        }
+        marshal_write_int(buf, off, asdl_seq_LEN(o->defaults));
+        for (i = 0; i < asdl_seq_LEN(o->defaults); i++) {
+                void *elt = asdl_seq_GET(o->defaults, i);
+                marshal_write_expr(buf, off, (expr_ty)elt);
+        }
+        return 1;
+}
+
+int
+marshal_write_keyword(PyObject **buf, int *off, keyword_ty o)
+{
+        int i;
+        marshal_write_identifier(buf, off, o->arg);
+        marshal_write_expr(buf, off, o->value);
+        return 1;
+}
+
+int
+marshal_write_alias(PyObject **buf, int *off, alias_ty o)
+{
+        int i;
+        marshal_write_identifier(buf, off, o->name);
+        if (o->asname) {
+                marshal_write_int(buf, off, 1);
+                marshal_write_identifier(buf, off, o->asname);
+        }
+        else {
+                marshal_write_int(buf, off, 0);
+        }
+        return 1;
+}
+
diff --git a/Python/asdl.c b/Python/asdl.c
new file mode 100644
index 0000000..bb29857
--- /dev/null
+++ b/Python/asdl.c
@@ -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;
+}
diff --git a/Python/ast.c b/Python/ast.c
new file mode 100644
index 0000000..475382c
--- /dev/null
+++ b/Python/ast.c
@@ -0,0 +1,3114 @@
+/*
+ * This file includes functions to transform a concrete syntax tree (CST) to
+ * an abstract syntax tree (AST).  The main function is PyAST_FromNode().
+ *
+ */
+#include "Python.h"
+#include "Python-ast.h"
+#include "grammar.h"
+#include "node.h"
+#include "ast.h"
+#include "token.h"
+#include "parsetok.h"
+#include "graminit.h"
+
+#include <assert.h>
+
+#if 0
+#define fprintf if (0) fprintf
+#endif
+
+/* XXX TO DO
+   - re-indent this file (should be done)
+   - internal error checking (freeing memory, etc.)
+   - syntax errors
+*/
+
+
+/* Data structure used internally */
+struct compiling {
+	char *c_encoding; /* source encoding */
+};
+
+static asdl_seq *seq_for_testlist(struct compiling *, const node *);
+static expr_ty ast_for_expr(struct compiling *, const node *);
+static stmt_ty ast_for_stmt(struct compiling *, const node *);
+static asdl_seq *ast_for_suite(struct compiling *, const node *);
+static asdl_seq *ast_for_exprlist(struct compiling *, const node *, int);
+static expr_ty ast_for_testlist(struct compiling *, const node *, int);
+
+/* Note different signature for ast_for_call */
+static expr_ty ast_for_call(struct compiling *, const node *, expr_ty);
+
+static PyObject *parsenumber(const char *);
+static PyObject *parsestr(const char *s, const char *encoding);
+static PyObject *parsestrplus(struct compiling *, const node *n);
+
+extern grammar _PyParser_Grammar; /* From graminit.c */
+
+#ifndef LINENO
+#define LINENO(n)	((n)->n_lineno)
+#endif
+
+#define NEW_IDENTIFIER(n) PyString_InternFromString(STR(n))
+
+static void
+asdl_stmt_seq_free(asdl_seq* seq)
+{
+    int n, i;
+
+    if (!seq)
+	return;
+             
+    n = asdl_seq_LEN(seq);
+    for (i = 0; i < n; i++)
+	free_stmt(asdl_seq_GET(seq, i));
+    asdl_seq_free(seq);
+}
+
+static void
+asdl_expr_seq_free(asdl_seq* seq)
+{
+    int n, i;
+
+    if (!seq)
+	return;
+             
+    n = asdl_seq_LEN(seq);
+    for (i = 0; i < n; i++)
+	free_expr(asdl_seq_GET(seq, i));
+    asdl_seq_free(seq);
+}
+
+/* This routine provides an invalid object for the syntax error.
+   The outermost routine must unpack this error and create the
+   proper object.  We do this so that we don't have to pass
+   the filename to everything function.
+
+   XXX Maybe we should just pass the filename...
+*/
+
+static int
+ast_error(const node *n, const char *errstr)
+{
+    PyObject *u = Py_BuildValue("zi", errstr, LINENO(n));
+    if (!u)
+	return 0;
+    PyErr_SetObject(PyExc_SyntaxError, u);
+    Py_DECREF(u);
+    return 0;
+}
+
+static void
+ast_error_finish(const char *filename)
+{
+    PyObject *type, *value, *tback, *errstr, *loc, *tmp;
+    int lineno;
+
+    assert(PyErr_Occurred());
+    if (!PyErr_ExceptionMatches(PyExc_SyntaxError))
+	return;
+
+    PyErr_Fetch(&type, &value, &tback);
+    errstr = PyTuple_GetItem(value, 0);
+    if (!errstr)
+	return;
+    Py_INCREF(errstr);
+    lineno = PyInt_AsLong(PyTuple_GetItem(value, 1));
+    if (lineno == -1)
+	return;
+    Py_DECREF(value);
+
+    loc = PyErr_ProgramText(filename, lineno);
+    if (!loc) {
+	Py_INCREF(Py_None);
+	loc = Py_None;
+    }
+    tmp = Py_BuildValue("(ziOO)", filename, lineno, Py_None, loc);
+    Py_DECREF(loc);
+    if (!tmp)
+	return;
+    value = Py_BuildValue("(OO)", errstr, tmp);
+    Py_DECREF(errstr);
+    Py_DECREF(tmp);
+    if (!value)
+	return;
+    PyErr_Restore(type, value, tback);
+}
+
+/* num_stmts() returns number of contained statements.
+
+   Use this routine to determine how big a sequence is needed for
+   the statements in a parse tree.  Its raison d'etre is this bit of
+   grammar:
+
+   stmt: simple_stmt | compound_stmt
+   simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+
+   A simple_stmt can contain multiple small_stmt elements joined
+   by semicolons.  If the arg is a simple_stmt, the number of
+   small_stmt elements is returned.
+*/
+
+static int
+num_stmts(const node *n)
+{
+    int i, l;
+    node *ch;
+
+    switch (TYPE(n)) {
+        case single_input:
+            if (TYPE(CHILD(n, 0)) == NEWLINE)
+                return 0;
+            else
+                return num_stmts(CHILD(n, 0));
+        case file_input:
+            l = 0;
+            for (i = 0; i < NCH(n); i++) {
+                ch = CHILD(n, i);
+                if (TYPE(ch) == stmt)
+                    l += num_stmts(ch);
+            }
+            return l;
+        case stmt:
+            return num_stmts(CHILD(n, 0));
+        case compound_stmt:
+            return 1;
+        case simple_stmt:
+            return NCH(n) / 2; /* Divide by 2 to remove count of semi-colons */
+        case suite:
+            if (NCH(n) == 1)
+                return num_stmts(CHILD(n, 0));
+            else {
+                l = 0;
+                for (i = 2; i < (NCH(n) - 1); i++)
+                    l += num_stmts(CHILD(n, i));
+                return l;
+            }
+        default: {
+            char buf[128];
+
+            sprintf(buf, "Non-statement found: %d %d\n",
+                    TYPE(n), NCH(n));
+            Py_FatalError(buf);
+        }
+    }
+    assert(0);
+    return 0;
+}
+
+/* Transform the CST rooted at node * to the appropriate AST
+*/
+
+mod_ty
+PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename)
+{
+    int i, j, num;
+    asdl_seq *stmts = NULL;
+    stmt_ty s;
+    node *ch;
+    struct compiling c;
+
+    if (flags && flags->cf_flags & PyCF_SOURCE_IS_UTF8) {
+            c.c_encoding = "utf-8";
+    } else if (TYPE(n) == encoding_decl) {
+        c.c_encoding = STR(n);
+        n = CHILD(n, 0);
+    } else {
+        c.c_encoding = NULL;
+    }
+
+    switch (TYPE(n)) {
+        case file_input:
+            stmts = asdl_seq_new(num_stmts(n));
+            if (!stmts)
+                    return NULL;
+            for (i = 0; i < NCH(n) - 1; i++) {
+                ch = CHILD(n, i);
+                if (TYPE(ch) == NEWLINE)
+                    continue;
+                REQ(ch, stmt);
+                num = num_stmts(ch);
+                if (num == 1) {
+                    s = ast_for_stmt(&c, ch);
+                    if (!s)
+                        goto error;
+                    asdl_seq_APPEND(stmts, s);
+                }
+                else {
+                    ch = CHILD(ch, 0);
+                    REQ(ch, simple_stmt);
+                    for (j = 0; j < num; j++) {
+                        s = ast_for_stmt(&c, CHILD(ch, j * 2));
+                        if (!s)
+                            goto error;
+                        asdl_seq_APPEND(stmts, s);
+                    }
+                }
+            }
+            return Module(stmts);
+        case eval_input: {
+            expr_ty testlist_ast;
+
+            /* XXX Why not gen_for here? */
+            testlist_ast = ast_for_testlist(&c, CHILD(n, 0), 0);
+            if (!testlist_ast)
+                goto error;
+            return Expression(testlist_ast);
+        }
+        case single_input:
+            if (TYPE(CHILD(n, 0)) == NEWLINE) {
+                stmts = asdl_seq_new(1);
+                if (!stmts)
+		    goto error;
+                asdl_seq_SET(stmts, 0, Pass(n->n_lineno));
+                return Interactive(stmts);
+            }
+            else {
+                n = CHILD(n, 0);
+                num = num_stmts(n);
+                stmts = asdl_seq_new(num);
+                if (!stmts)
+		    goto error;
+                if (num == 1) {
+		    stmt_ty s = ast_for_stmt(&c, n);
+		    if (!s)
+			goto error;
+                    asdl_seq_SET(stmts, 0, s);
+                }
+                else {
+                    /* Only a simple_stmt can contain multiple statements. */
+                    REQ(n, simple_stmt);
+                    for (i = 0; i < NCH(n); i += 2) {
+                        stmt_ty s;
+                        if (TYPE(CHILD(n, i)) == NEWLINE)
+                            break;
+                        s = ast_for_stmt(&c, CHILD(n, i));
+                        if (!s)
+                            goto error;
+                        asdl_seq_SET(stmts, i / 2, s);
+                    }
+                }
+
+                return Interactive(stmts);
+            }
+        default:
+            goto error;
+    }
+ error:
+    if (stmts)
+	asdl_stmt_seq_free(stmts);
+    ast_error_finish(filename);
+    return NULL;
+}
+
+/* Return the AST repr. of the operator represented as syntax (|, ^, etc.)
+*/
+
+static operator_ty
+get_operator(const node *n)
+{
+    switch (TYPE(n)) {
+        case VBAR:
+            return BitOr;
+        case CIRCUMFLEX:
+            return BitXor;
+        case AMPER:
+            return BitAnd;
+        case LEFTSHIFT:
+            return LShift;
+        case RIGHTSHIFT:
+            return RShift;
+        case PLUS:
+            return Add;
+        case MINUS:
+            return Sub;
+        case STAR:
+            return Mult;
+        case SLASH:
+            return Div;
+        case DOUBLESLASH:
+            return FloorDiv;
+        case PERCENT:
+            return Mod;
+        default:
+            return 0;
+    }
+}
+
+/* Set the context ctx for expr_ty e returning 0 on success, -1 on error.
+
+   Only sets context for expr kinds that "can appear in assignment context"
+   (according to ../Parser/Python.asdl).  For other expr kinds, it sets
+   an appropriate syntax error and returns false.
+
+   If e is a sequential type, items in sequence will also have their context
+   set.
+
+*/
+
+static int
+set_context(expr_ty e, expr_context_ty ctx, const node *n)
+{
+    asdl_seq *s = NULL;
+
+    switch (e->kind) {
+        case Attribute_kind:
+	    if (ctx == Store &&
+		!strcmp(PyString_AS_STRING(e->v.Attribute.attr), "None")) {
+		    return ast_error(n, "assignment to None");
+	    }
+	    e->v.Attribute.ctx = ctx;
+	    break;
+        case Subscript_kind:
+	    e->v.Subscript.ctx = ctx;
+	    break;
+        case Name_kind:
+	    if (ctx == Store &&
+		!strcmp(PyString_AS_STRING(e->v.Name.id), "None")) {
+		    return ast_error(n, "assignment to None");
+	    }
+	    e->v.Name.ctx = ctx;
+	    break;
+        case List_kind:
+	    e->v.List.ctx = ctx;
+	    s = e->v.List.elts;
+	    break;
+        case Tuple_kind:
+            if (asdl_seq_LEN(e->v.Tuple.elts) == 0) 
+                return ast_error(n, "can't assign to ()");
+	    e->v.Tuple.ctx = ctx;
+	    s = e->v.Tuple.elts;
+	    break;
+        case Call_kind:
+	    if (ctx == Store)
+		return ast_error(n, "can't assign to function call");
+	    else if (ctx == Del)
+		return ast_error(n, "can't delete function call");
+	    else
+		return ast_error(n, "unexpected operation on function call");
+	    break;
+        case BinOp_kind:
+            return ast_error(n, "can't assign to operator");
+        case GeneratorExp_kind:
+            return ast_error(n, "assignment to generator expression "
+                             "not possible");
+        case Num_kind:
+        case Str_kind:
+	    return ast_error(n, "can't assign to literal");
+        default: {
+	   char buf[300];
+	   PyOS_snprintf(buf, sizeof(buf), 
+			 "unexpected expression in assignment %d (line %d)", 
+			 e->kind, e->lineno);
+	   return ast_error(n, buf);
+       }
+    }
+    /* If the LHS is a list or tuple, we need to set the assignment
+       context for all the tuple elements.  
+    */
+    if (s) {
+	int i;
+
+	for (i = 0; i < asdl_seq_LEN(s); i++) {
+	    if (!set_context(asdl_seq_GET(s, i), ctx, n))
+		return 0;
+	}
+    }
+    return 1;
+}
+
+static operator_ty
+ast_for_augassign(const node *n)
+{
+    REQ(n, augassign);
+    n = CHILD(n, 0);
+    switch (STR(n)[0]) {
+        case '+':
+            return Add;
+        case '-':
+            return Sub;
+        case '/':
+            if (STR(n)[1] == '/')
+                return FloorDiv;
+            else
+                return Div;
+        case '%':
+            return Mod;
+        case '<':
+            return LShift;
+        case '>':
+            return RShift;
+        case '&':
+            return BitAnd;
+        case '^':
+            return BitXor;
+        case '|':
+            return BitOr;
+        case '*':
+            if (STR(n)[1] == '*')
+                return Pow;
+            else
+                return Mult;
+        default:
+            PyErr_Format(PyExc_Exception, "invalid augassign: %s", STR(n));
+            return 0;
+    }
+}
+
+static cmpop_ty
+ast_for_comp_op(const node *n)
+{
+    /* comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'
+               |'is' 'not'
+    */
+    REQ(n, comp_op);
+    if (NCH(n) == 1) {
+	n = CHILD(n, 0);
+	switch (TYPE(n)) {
+            case LESS:
+                return Lt;
+            case GREATER:
+                return Gt;
+            case EQEQUAL:			/* == */
+            case EQUAL:
+                return Eq;
+            case LESSEQUAL:
+                return LtE;
+            case GREATEREQUAL:
+                return GtE;
+            case NOTEQUAL:
+                return NotEq;
+            case NAME:
+                if (strcmp(STR(n), "in") == 0)
+                    return In;
+                if (strcmp(STR(n), "is") == 0)
+                    return Is;
+            default:
+                PyErr_Format(PyExc_Exception, "invalid comp_op: %s",
+                             STR(n));
+                return 0;
+	}
+    }
+    else if (NCH(n) == 2) {
+	/* handle "not in" and "is not" */
+	switch (TYPE(CHILD(n, 0))) {
+            case NAME:
+                if (strcmp(STR(CHILD(n, 1)), "in") == 0)
+                    return NotIn;
+                if (strcmp(STR(CHILD(n, 0)), "is") == 0)
+                    return IsNot;
+            default:
+                PyErr_Format(PyExc_Exception, "invalid comp_op: %s %s",
+                             STR(CHILD(n, 0)), STR(CHILD(n, 1)));
+                return 0;
+	}
+    }
+    PyErr_Format(PyExc_Exception, "invalid comp_op: has %d children",
+                 NCH(n));
+    return 0;
+}
+
+static asdl_seq *
+seq_for_testlist(struct compiling *c, const node *n)
+{
+    /* testlist: test (',' test)* [','] */
+    assert(TYPE(n) == testlist
+	   || TYPE(n) == listmaker
+	   || TYPE(n) == testlist_gexp
+	   || TYPE(n) == testlist_safe
+	   );
+    asdl_seq *seq;
+    expr_ty expression;
+    int i;
+
+    seq = asdl_seq_new((NCH(n) + 1) / 2);
+    if (!seq)
+        return NULL;
+
+    for (i = 0; i < NCH(n); i += 2) {
+        REQ(CHILD(n, i), test);
+
+        expression = ast_for_expr(c, CHILD(n, i));
+        if (!expression) {
+            asdl_seq_free(seq);
+            return NULL;
+        }
+
+        assert(i / 2 < seq->size);
+        asdl_seq_SET(seq, i / 2, expression);
+    }
+    return seq;
+}
+
+static expr_ty
+compiler_complex_args(const node *n)
+{
+    int i, len = (NCH(n) + 1) / 2;
+    expr_ty result;
+    asdl_seq *args = asdl_seq_new(len);
+    if (!args)
+        return NULL;
+
+    REQ(n, fplist);
+
+    for (i = 0; i < len; i++) {
+        const node *child = CHILD(CHILD(n, 2*i), 0);
+        expr_ty arg;
+        if (TYPE(child) == NAME) {
+		if (!strcmp(STR(child), "None")) {
+			ast_error(child, "assignment to None");
+			return NULL;
+		}
+            arg = Name(NEW_IDENTIFIER(child), Store, LINENO(child));
+	}
+        else
+            arg = compiler_complex_args(CHILD(CHILD(n, 2*i), 1));
+	set_context(arg, Store, n);
+        asdl_seq_SET(args, i, arg);
+    }
+
+    result = Tuple(args, Store, LINENO(n));
+    set_context(result, Store, n);
+    return result;
+}
+
+/* Create AST for argument list.
+
+   XXX TO DO:
+       - check for invalid argument lists like normal after default
+*/
+
+static arguments_ty
+ast_for_arguments(struct compiling *c, const node *n)
+{
+    /* parameters: '(' [varargslist] ')'
+       varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME]
+            | '**' NAME) | fpdef ['=' test] (',' fpdef ['=' test])* [',']
+    */
+    int i, n_args = 0, n_defaults = 0, found_default = 0;
+    asdl_seq *args, *defaults;
+    identifier vararg = NULL, kwarg = NULL;
+    node *ch;
+
+    if (TYPE(n) == parameters) {
+	if (NCH(n) == 2) /* () as argument list */
+	    return arguments(NULL, NULL, NULL, NULL);
+	n = CHILD(n, 1);
+    }
+    REQ(n, varargslist);
+
+    /* first count the number of normal args & defaults */
+    for (i = 0; i < NCH(n); i++) {
+	ch = CHILD(n, i);
+	if (TYPE(ch) == fpdef) {
+	    n_args++;
+	}
+	if (TYPE(ch) == EQUAL)
+	    n_defaults++;
+    }
+    args = (n_args ? asdl_seq_new(n_args) : NULL);
+    if (!args && n_args)
+    	return NULL; /* Don't need to go to NULL; nothing allocated */
+    defaults = (n_defaults ? asdl_seq_new(n_defaults) : NULL);
+    if (!defaults && n_defaults)
+        goto error;
+
+    /* fpdef: NAME | '(' fplist ')'
+       fplist: fpdef (',' fpdef)* [',']
+    */
+    i = 0;
+    while (i < NCH(n)) {
+	ch = CHILD(n, i);
+	switch (TYPE(ch)) {
+            case fpdef:
+                /* XXX Need to worry about checking if TYPE(CHILD(n, i+1)) is
+                   anything other than EQUAL or a comma? */
+                /* XXX Should NCH(n) check be made a separate check? */
+                if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) {
+                    asdl_seq_APPEND(defaults, 
+				    ast_for_expr(c, CHILD(n, i + 2)));
+                    i += 2;
+		    found_default = 1;
+                }
+		else if (found_default) {
+		    ast_error(n, 
+			     "non-default argument follows default argument");
+		    goto error;
+		}
+
+                if (NCH(ch) == 3) {
+                    asdl_seq_APPEND(args, 
+                                    compiler_complex_args(CHILD(ch, 1))); 
+		}
+                else if (TYPE(CHILD(ch, 0)) == NAME) {
+		    if (!strcmp(STR(CHILD(ch, 0)), "None")) {
+			    ast_error(CHILD(ch, 0), "assignment to None");
+			    goto error;
+		    }
+                    expr_ty name = Name(NEW_IDENTIFIER(CHILD(ch, 0)),
+                                        Param, LINENO(ch));
+                    if (!name)
+                        goto error;
+                    asdl_seq_APPEND(args, name);
+					 
+		}
+                i += 2; /* the name and the comma */
+                break;
+            case STAR:
+		if (!strcmp(STR(CHILD(n, i+1)), "None")) {
+			ast_error(CHILD(n, i+1), "assignment to None");
+			goto error;
+		}
+                vararg = NEW_IDENTIFIER(CHILD(n, i+1));
+                i += 3;
+                break;
+            case DOUBLESTAR:
+		if (!strcmp(STR(CHILD(n, i+1)), "None")) {
+			ast_error(CHILD(n, i+1), "assignment to None");
+			goto error;
+		}
+                kwarg = NEW_IDENTIFIER(CHILD(n, i+1));
+                i += 3;
+                break;
+            default:
+                PyErr_Format(PyExc_Exception,
+                             "unexpected node in varargslist: %d @ %d",
+                             TYPE(ch), i);
+                goto error;
+	}
+    }
+
+    return arguments(args, vararg, kwarg, defaults);
+
+ error:
+    if (args)
+        asdl_seq_free(args);
+    if (defaults)
+        asdl_seq_free(defaults);
+    return NULL;
+}
+
+static expr_ty
+ast_for_dotted_name(struct compiling *c, const node *n)
+{
+    expr_ty e = NULL;
+    expr_ty attrib = NULL;
+    identifier id = NULL;
+    int i;
+
+    REQ(n, dotted_name);
+    
+    id = NEW_IDENTIFIER(CHILD(n, 0));
+    if (!id)
+        goto error;
+    e = Name(id, Load, LINENO(n));
+    if (!e)
+	goto error;
+    id = NULL;
+
+    for (i = 2; i < NCH(n); i+=2) {
+        id = NEW_IDENTIFIER(CHILD(n, i));
+	if (!id)
+	    goto error;
+	attrib = Attribute(e, id, Load, LINENO(CHILD(n, i)));
+	if (!attrib)
+	    goto error;
+	e = attrib;
+	attrib = NULL;
+    }
+
+    return e;
+    
+  error:
+    Py_XDECREF(id);
+    free_expr(e);
+    return NULL;
+}
+
+static expr_ty
+ast_for_decorator(struct compiling *c, const node *n)
+{
+    /* decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE */
+    expr_ty d = NULL;
+    expr_ty name_expr = NULL;
+    
+    REQ(n, decorator);
+    
+    if ((NCH(n) < 3 && NCH(n) != 5 && NCH(n) != 6)
+	|| TYPE(CHILD(n, 0)) != AT || TYPE(RCHILD(n, -1)) != NEWLINE) {
+	ast_error(n, "Invalid decorator node");
+	goto error;
+    }
+    
+    name_expr = ast_for_dotted_name(c, CHILD(n, 1));
+    if (!name_expr)
+	goto error;
+	
+    if (NCH(n) == 3) { /* No arguments */
+	d = name_expr;
+	name_expr = NULL;
+    }
+    else if (NCH(n) == 5) { /* Call with no arguments */
+	d = Call(name_expr, NULL, NULL, NULL, NULL, LINENO(n));
+	if (!d)
+	    goto error;
+	name_expr = NULL;
+    }
+    else {
+	d = ast_for_call(c, CHILD(n, 3), name_expr);
+	if (!d)
+	    goto error;
+	name_expr = NULL;
+    }
+
+    return d;
+    
+  error:
+    free_expr(name_expr);
+    free_expr(d);
+    return NULL;
+}
+
+static asdl_seq*
+ast_for_decorators(struct compiling *c, const node *n)
+{
+    asdl_seq* decorator_seq = NULL;
+    expr_ty d = NULL;
+    int i;
+    
+    REQ(n, decorators);
+
+    decorator_seq = asdl_seq_new(NCH(n));
+    if (!decorator_seq)
+        return NULL;
+	
+    for (i = 0; i < NCH(n); i++) {
+	d = ast_for_decorator(c, CHILD(n, i));
+	if (!d)
+	    goto error;
+	asdl_seq_APPEND(decorator_seq, d);
+	d = NULL;
+    }
+    return decorator_seq;
+  error:
+    asdl_expr_seq_free(decorator_seq);
+    free_expr(d);
+    return NULL;
+}
+
+static stmt_ty
+ast_for_funcdef(struct compiling *c, const node *n)
+{
+    /* funcdef: 'def' [decorators] NAME parameters ':' suite */
+    identifier name = NULL;
+    arguments_ty args = NULL;
+    asdl_seq *body = NULL;
+    asdl_seq *decorator_seq = NULL;
+    int name_i;
+
+    REQ(n, funcdef);
+
+    if (NCH(n) == 6) { /* decorators are present */
+	decorator_seq = ast_for_decorators(c, CHILD(n, 0));
+	if (!decorator_seq)
+	    goto error;
+	name_i = 2;
+    }
+    else {
+	name_i = 1;
+    }
+
+    name = NEW_IDENTIFIER(CHILD(n, name_i));
+    if (!name)
+	goto error;
+    else if (!strcmp(STR(CHILD(n, name_i)), "None")) {
+	    ast_error(CHILD(n, name_i), "assignment to None");
+	    goto error;
+    }
+    args = ast_for_arguments(c, CHILD(n, name_i + 1));
+    if (!args)
+	goto error;
+    body = ast_for_suite(c, CHILD(n, name_i + 3));
+    if (!body)
+	goto error;
+
+    return FunctionDef(name, args, body, decorator_seq, LINENO(n));
+
+error:
+    asdl_stmt_seq_free(body);
+    asdl_expr_seq_free(decorator_seq);
+    free_arguments(args);
+    Py_XDECREF(name);
+    return NULL;
+}
+
+static expr_ty
+ast_for_lambdef(struct compiling *c, const node *n)
+{
+    /* lambdef: 'lambda' [varargslist] ':' test */
+    arguments_ty args;
+    expr_ty expression;
+
+    if (NCH(n) == 3) {
+        args = arguments(NULL, NULL, NULL, NULL);
+        if (!args)
+            return NULL;
+        expression = ast_for_expr(c, CHILD(n, 2));
+        if (!expression) {
+            free_arguments(args);
+            return NULL;
+        }
+    }
+    else {
+        args = ast_for_arguments(c, CHILD(n, 1));
+        if (!args)
+            return NULL;
+        expression = ast_for_expr(c, CHILD(n, 3));
+        if (!expression) {
+            free_arguments(args);
+            return NULL;
+        }
+    }
+
+    return Lambda(args, expression, LINENO(n));
+}
+
+/* Count the number of 'for' loop in a list comprehension.
+
+   Helper for ast_for_listcomp().
+*/
+
+static int
+count_list_fors(const node *n)
+{
+    int n_fors = 0;
+    node *ch = CHILD(n, 1);
+
+ count_list_for:
+    n_fors++;
+    REQ(ch, list_for);
+    if (NCH(ch) == 5)
+	ch = CHILD(ch, 4);
+    else
+	return n_fors;
+ count_list_iter:
+    REQ(ch, list_iter);
+    ch = CHILD(ch, 0);
+    if (TYPE(ch) == list_for)
+	goto count_list_for;
+    else if (TYPE(ch) == list_if) {
+        if (NCH(ch) == 3) {
+            ch = CHILD(ch, 2);
+            goto count_list_iter;
+        }
+        else
+            return n_fors;
+    }
+    else {
+        /* Should never be reached */
+        PyErr_SetString(PyExc_Exception, "logic error in count_list_fors");
+        return -1;
+    }
+}
+
+/* Count the number of 'if' statements in a list comprehension.
+
+   Helper for ast_for_listcomp().
+*/
+
+static int
+count_list_ifs(const node *n)
+{
+    int n_ifs = 0;
+
+ count_list_iter:
+    REQ(n, list_iter);
+    if (TYPE(CHILD(n, 0)) == list_for)
+	return n_ifs;
+    n = CHILD(n, 0);
+    REQ(n, list_if);
+    n_ifs++;
+    if (NCH(n) == 2)
+	return n_ifs;
+    n = CHILD(n, 2);
+    goto count_list_iter;
+}
+
+static expr_ty
+ast_for_listcomp(struct compiling *c, const node *n)
+{
+    /* listmaker: test ( list_for | (',' test)* [','] )
+       list_for: 'for' exprlist 'in' testlist_safe [list_iter]
+       list_iter: list_for | list_if
+       list_if: 'if' test [list_iter]
+       testlist_safe: test [(',' test)+ [',']]
+    */
+    expr_ty elt;
+    asdl_seq *listcomps;
+    int i, n_fors;
+    node *ch;
+
+    REQ(n, listmaker);
+    assert(NCH(n) > 1);
+
+    elt = ast_for_expr(c, CHILD(n, 0));
+    if (!elt)
+        return NULL;
+
+    n_fors = count_list_fors(n);
+    if (n_fors == -1)
+        return NULL;
+
+    listcomps = asdl_seq_new(n_fors);
+    if (!listcomps) {
+        free_expr(elt);
+    	return NULL;
+    }
+    
+    ch = CHILD(n, 1);
+    for (i = 0; i < n_fors; i++) {
+	comprehension_ty lc;
+	asdl_seq *t;
+        expr_ty expression;
+
+	REQ(ch, list_for);
+
+	t = ast_for_exprlist(c, CHILD(ch, 1), Store);
+        if (!t) {
+            asdl_seq_free(listcomps);
+            free_expr(elt);
+            return NULL;
+        }
+        expression = ast_for_testlist(c, CHILD(ch, 3), 0);
+        if (!expression) {
+            asdl_seq_free(t);
+            asdl_seq_free(listcomps);
+            free_expr(elt);
+            return NULL;
+        }
+
+	if (asdl_seq_LEN(t) == 1)
+	    lc = comprehension(asdl_seq_GET(t, 0), expression, NULL);
+	else
+	    lc = comprehension(Tuple(t, Store, LINENO(ch)), expression, NULL);
+
+        if (!lc) {
+            asdl_seq_free(t);
+            asdl_seq_free(listcomps);
+            free_expr(expression);
+            free_expr(elt);
+            return NULL;
+        }
+
+	if (NCH(ch) == 5) {
+	    int j, n_ifs;
+	    asdl_seq *ifs;
+
+	    ch = CHILD(ch, 4);
+	    n_ifs = count_list_ifs(ch);
+            if (n_ifs == -1) {
+                asdl_seq_free(listcomps);
+                free_expr(elt);
+                return NULL;
+            }
+
+	    ifs = asdl_seq_new(n_ifs);
+	    if (!ifs) {
+		asdl_seq_free(listcomps);
+                free_expr(elt);
+		return NULL;
+	    }
+
+	    for (j = 0; j < n_ifs; j++) {
+		REQ(ch, list_iter);
+
+		ch = CHILD(ch, 0);
+		REQ(ch, list_if);
+
+		asdl_seq_APPEND(ifs, ast_for_expr(c, CHILD(ch, 1)));
+		if (NCH(ch) == 3)
+		    ch = CHILD(ch, 2);
+	    }
+	    /* on exit, must guarantee that ch is a list_for */
+	    if (TYPE(ch) == list_iter)
+		ch = CHILD(ch, 0);
+            lc->ifs = ifs;
+	}
+	asdl_seq_APPEND(listcomps, lc);
+    }
+
+    return ListComp(elt, listcomps, LINENO(n));
+}
+
+/*
+   Count the number of 'for' loops in a generator expression.
+
+   Helper for ast_for_genexp().
+*/
+
+static int
+count_gen_fors(const node *n)
+{
+	int n_fors = 0;
+	node *ch = CHILD(n, 1);
+
+ count_gen_for:
+	n_fors++;
+	REQ(ch, gen_for);
+	if (NCH(ch) == 5)
+		ch = CHILD(ch, 4);
+	else
+		return n_fors;
+ count_gen_iter:
+	REQ(ch, gen_iter);
+	ch = CHILD(ch, 0);
+	if (TYPE(ch) == gen_for)
+		goto count_gen_for;
+	else if (TYPE(ch) == gen_if) {
+		if (NCH(ch) == 3) {
+			ch = CHILD(ch, 2);
+			goto count_gen_iter;
+		}
+		else
+		    return n_fors;
+	}
+	else {
+		/* Should never be reached */
+		PyErr_SetString(PyExc_Exception, "logic error in count_gen_fors");
+		return -1;
+	}
+}
+
+/* Count the number of 'if' statements in a generator expression.
+
+   Helper for ast_for_genexp().
+*/
+
+static int
+count_gen_ifs(const node *n)
+{
+	int n_ifs = 0;
+
+	while (1) {
+		REQ(n, gen_iter);
+		if (TYPE(CHILD(n, 0)) == gen_for)
+			return n_ifs;
+		n = CHILD(n, 0);
+		REQ(n, gen_if);
+		n_ifs++;
+		if (NCH(n) == 2)
+			return n_ifs;
+		n = CHILD(n, 2);
+	}
+}
+
+static expr_ty
+ast_for_genexp(struct compiling *c, const node *n)
+{
+    /* testlist_gexp: test ( gen_for | (',' test)* [','] )
+       argument: [test '='] test [gen_for]	 # Really [keyword '='] test */
+    expr_ty elt;
+    asdl_seq *genexps;
+    int i, n_fors;
+    node *ch;
+    
+    assert(TYPE(n) == (testlist_gexp) || TYPE(n) == (argument));
+    assert(NCH(n) > 1);
+    
+    elt = ast_for_expr(c, CHILD(n, 0));
+    if (!elt)
+        return NULL;
+    
+    n_fors = count_gen_fors(n);
+    if (n_fors == -1)
+        return NULL;
+    
+    genexps = asdl_seq_new(n_fors);
+    if (!genexps) {
+        free_expr(elt);
+        return NULL;
+    }
+    
+    ch = CHILD(n, 1);
+    for (i = 0; i < n_fors; i++) {
+        comprehension_ty ge;
+        asdl_seq *t;
+        expr_ty expression;
+        
+        REQ(ch, gen_for);
+        
+        t = ast_for_exprlist(c, CHILD(ch, 1), Store);
+        if (!t) {
+            asdl_seq_free(genexps);
+            free_expr(elt);
+            return NULL;
+        }
+        expression = ast_for_testlist(c, CHILD(ch, 3), 1);
+        if (!expression) {
+            asdl_seq_free(genexps);
+            free_expr(elt);
+            return NULL;
+        }
+        
+        if (asdl_seq_LEN(t) == 1)
+            ge = comprehension(asdl_seq_GET(t, 0), expression,
+                               NULL);
+        else
+            ge = comprehension(Tuple(t, Store, LINENO(ch)),
+                               expression, NULL);
+        
+        if (!ge) {
+            asdl_seq_free(genexps);
+            free_expr(elt);
+            return NULL;
+        }
+        
+        if (NCH(ch) == 5) {
+            int j, n_ifs;
+            asdl_seq *ifs;
+            
+            ch = CHILD(ch, 4);
+            n_ifs = count_gen_ifs(ch);
+            if (n_ifs == -1) {
+                asdl_seq_free(genexps);
+                free_expr(elt);
+                return NULL;
+            }
+            
+            ifs = asdl_seq_new(n_ifs);
+            if (!ifs) {
+                asdl_seq_free(genexps);
+                free_expr(elt);
+                return NULL;
+            }
+            
+            for (j = 0; j < n_ifs; j++) {
+                REQ(ch, gen_iter);
+                ch = CHILD(ch, 0);
+                REQ(ch, gen_if);
+                
+                asdl_seq_APPEND(ifs, ast_for_expr(c, CHILD(ch, 1)));
+                if (NCH(ch) == 3)
+                    ch = CHILD(ch, 2);
+            }
+            /* on exit, must guarantee that ch is a gen_for */
+            if (TYPE(ch) == gen_iter)
+                ch = CHILD(ch, 0);
+            ge->ifs = ifs;
+        }
+        asdl_seq_APPEND(genexps, ge);
+    }
+    
+    return GeneratorExp(elt, genexps, LINENO(n));
+}
+
+static expr_ty
+ast_for_atom(struct compiling *c, const node *n)
+{
+    /* atom: '(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']'
+       | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
+    */
+    node *ch = CHILD(n, 0);
+    
+    switch (TYPE(ch)) {
+    case NAME:
+	/* All names start in Load context, but may later be
+	   changed. */
+	return Name(NEW_IDENTIFIER(ch), Load, LINENO(n));
+    case STRING: {
+	PyObject *str = parsestrplus(c, n);
+	
+	if (!str)
+	    return NULL;
+	
+	return Str(str, LINENO(n));
+    }
+    case NUMBER: {
+	PyObject *pynum = parsenumber(STR(ch));
+	
+	if (!pynum)
+	    return NULL;
+	
+	return Num(pynum, LINENO(n));
+    }
+    case LPAR: /* some parenthesized expressions */
+	ch = CHILD(n, 1);
+	
+	if (TYPE(ch) == RPAR)
+	    return Tuple(NULL, Load, LINENO(n));
+	
+	if (TYPE(ch) == yield_expr)
+	    return ast_for_expr(c, ch);
+	
+	if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for))
+	    return ast_for_genexp(c, ch);
+	
+	return ast_for_testlist(c, ch, 1);
+    case LSQB: /* list (or list comprehension) */
+	ch = CHILD(n, 1);
+	
+	if (TYPE(ch) == RSQB)
+	    return List(NULL, Load, LINENO(n));
+	
+	REQ(ch, listmaker);
+	if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {
+	    asdl_seq *elts = seq_for_testlist(c, ch);
+	    
+	    if (!elts)
+		return NULL;
+	    
+	    return List(elts, Load, LINENO(n));
+	}
+	else
+	    return ast_for_listcomp(c, ch);
+    case LBRACE: {
+	/* dictmaker: test ':' test (',' test ':' test)* [','] */
+	int i, size;
+	asdl_seq *keys, *values;
+	
+	ch = CHILD(n, 1);
+	size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */
+	keys = asdl_seq_new(size);
+	if (!keys)
+	    return NULL;
+	
+	values = asdl_seq_new(size);
+	if (!values) {
+	    asdl_seq_free(keys);
+	    return NULL;
+	}
+	
+	for (i = 0; i < NCH(ch); i += 4) {
+	    expr_ty expression;
+	    
+	    expression = ast_for_expr(c, CHILD(ch, i));
+	    if (!expression)
+		return NULL;
+	    
+	    asdl_seq_SET(keys, i / 4, expression);
+	    
+	    expression = ast_for_expr(c, CHILD(ch, i + 2));
+	    if (!expression)
+		return NULL;
+	    
+	    asdl_seq_SET(values, i / 4, expression);
+	}
+	return Dict(keys, values, LINENO(n));
+    }
+    case BACKQUOTE: { /* repr */
+	expr_ty expression = ast_for_testlist(c, CHILD(n, 1), 0);
+	
+	if (!expression)
+	    return NULL;
+	
+	return Repr(expression, LINENO(n));
+    }
+    default:
+	PyErr_Format(PyExc_Exception, "unhandled atom %d",
+		     TYPE(ch));
+	return NULL;
+    }
+}
+
+static slice_ty
+ast_for_slice(struct compiling *c, const node *n)
+{
+    node *ch;
+    expr_ty lower = NULL, upper = NULL, step = NULL;
+
+    REQ(n, subscript);
+
+    /*
+       subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
+       sliceop: ':' [test]
+    */
+    ch = CHILD(n, 0);
+    if (TYPE(ch) == DOT)
+	return Ellipsis();
+
+    if (NCH(n) == 1 && TYPE(ch) == test) {
+        /* 'step' variable hold no significance in terms of being used over
+           other vars */
+        step = ast_for_expr(c, ch); 
+        if (!step)
+            return NULL;
+            
+	return Index(step);
+    }
+
+    if (TYPE(ch) == test) {
+	lower = ast_for_expr(c, ch);
+        if (!lower)
+            return NULL;
+    }
+
+    /* If there's an upper bound it's in the second or third position. */
+    if (TYPE(ch) == COLON) {
+	if (NCH(n) > 1) {
+	    node *n2 = CHILD(n, 1);
+
+	    if (TYPE(n2) == test) {
+		upper = ast_for_expr(c, n2);
+                if (!upper)
+                    return NULL;
+            }
+	}
+    } else if (NCH(n) > 2) {
+	node *n2 = CHILD(n, 2);
+
+	if (TYPE(n2) == test) {
+	    upper = ast_for_expr(c, n2);
+            if (!upper)
+                return NULL;
+        }
+    }
+
+    ch = CHILD(n, NCH(n) - 1);
+    if (TYPE(ch) == sliceop) {
+	if (NCH(ch) == 1)
+            /* XXX: If only 1 child, then should just be a colon.  Should we
+               just skip assigning and just get to the return? */
+	    ch = CHILD(ch, 0);
+	else
+	    ch = CHILD(ch, 1);
+	if (TYPE(ch) == test) {
+	    step = ast_for_expr(c, ch);
+            if (!step)
+                return NULL;
+        }
+    }
+
+    return Slice(lower, upper, step);
+}
+
+static expr_ty
+ast_for_binop(struct compiling *c, const node *n)
+{
+	/* Must account for a sequence of expressions.
+	   How should A op B op C by represented?  
+	   BinOp(BinOp(A, op, B), op, C).
+	*/
+
+	int i, nops;
+	expr_ty expr1, expr2, result;
+        operator_ty operator;
+
+        expr1 = ast_for_expr(c, CHILD(n, 0));
+        if (!expr1)
+            return NULL;
+
+        expr2 = ast_for_expr(c, CHILD(n, 2));
+        if (!expr2)
+            return NULL;
+
+        operator = get_operator(CHILD(n, 1));
+        if (!operator)
+            return NULL;
+
+	result = BinOp(expr1, operator, expr2, LINENO(n));
+	if (!result)
+            return NULL;
+
+	nops = (NCH(n) - 1) / 2;
+	for (i = 1; i < nops; i++) {
+		expr_ty tmp_result, tmp;
+		const node* next_oper = CHILD(n, i * 2 + 1);
+
+		operator = get_operator(next_oper);
+                if (!operator)
+                    return NULL;
+
+                tmp = ast_for_expr(c, CHILD(n, i * 2 + 2));
+                if (!tmp)
+                    return NULL;
+
+                tmp_result = BinOp(result, operator, tmp, 
+				   LINENO(next_oper));
+		if (!tmp) 
+			return NULL;
+		result = tmp_result;
+	}
+	return result;
+}
+
+/* Do not name a variable 'expr'!  Will cause a compile error.
+*/
+
+static expr_ty
+ast_for_expr(struct compiling *c, const node *n)
+{
+    /* handle the full range of simple expressions
+       test: and_test ('or' and_test)* | lambdef
+       and_test: not_test ('and' not_test)*
+       not_test: 'not' not_test | comparison
+       comparison: expr (comp_op expr)*
+       expr: xor_expr ('|' xor_expr)*
+       xor_expr: and_expr ('^' and_expr)*
+       and_expr: shift_expr ('&' shift_expr)*
+       shift_expr: arith_expr (('<<'|'>>') arith_expr)*
+       arith_expr: term (('+'|'-') term)*
+       term: factor (('*'|'/'|'%'|'//') factor)*
+       factor: ('+'|'-'|'~') factor | power
+       power: atom trailer* ('**' factor)*
+    */
+
+    asdl_seq *seq;
+    int i;
+
+ loop:
+    switch (TYPE(n)) {
+        case test:
+            if (TYPE(CHILD(n, 0)) == lambdef)
+                return ast_for_lambdef(c, CHILD(n, 0));
+            /* Fall through to and_test */
+        case and_test:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            seq = asdl_seq_new((NCH(n) + 1) / 2);
+            if (!seq)
+                return NULL;
+            for (i = 0; i < NCH(n); i += 2) {
+                expr_ty e = ast_for_expr(c, CHILD(n, i));
+                if (!e)
+                    return NULL;
+                asdl_seq_SET(seq, i / 2, e);
+            }
+            if (!strcmp(STR(CHILD(n, 1)), "and"))
+                return BoolOp(And, seq, LINENO(n));
+            else {
+                assert(!strcmp(STR(CHILD(n, 1)), "or"));
+                return BoolOp(Or, seq, LINENO(n));
+            }
+            break;
+        case not_test:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            else {
+                expr_ty expression = ast_for_expr(c, CHILD(n, 1));
+                if (!expression)
+                    return NULL;
+
+                return UnaryOp(Not, expression, LINENO(n));
+            }
+        case comparison:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            else {
+                expr_ty expression;
+                asdl_seq *ops, *cmps;
+                ops = asdl_seq_new(NCH(n) / 2);
+                if (!ops)
+                    return NULL;
+                cmps = asdl_seq_new(NCH(n) / 2);
+                if (!cmps) {
+                    asdl_seq_free(ops);
+                    return NULL;
+                }
+                for (i = 1; i < NCH(n); i += 2) {
+                    /* XXX cmpop_ty is just an enum */
+                    cmpop_ty operator;
+
+                    operator = ast_for_comp_op(CHILD(n, i));
+                    if (!operator)
+                        return NULL;
+
+                    expression = ast_for_expr(c, CHILD(n, i + 1));
+                    if (!expression)
+                        return NULL;
+                        
+                    asdl_seq_SET(ops, i / 2, (void *)operator);
+                    asdl_seq_SET(cmps, i / 2, expression);
+                }
+                expression = ast_for_expr(c, CHILD(n, 0));
+                if (!expression)
+                    return NULL;
+                    
+                return Compare(expression, ops, cmps, LINENO(n));
+            }
+            break;
+
+        /* The next five cases all handle BinOps.  The main body of code
+           is the same in each case, but the switch turned inside out to
+           reuse the code for each type of operator.
+         */
+        case expr:
+        case xor_expr:
+        case and_expr:
+        case shift_expr:
+        case arith_expr:
+        case term:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            return ast_for_binop(c, n);
+        case yield_expr: {
+	    expr_ty exp = NULL;
+	    if (NCH(n) == 2) {
+		exp = ast_for_testlist(c, CHILD(n, 1), 0);
+		if (!exp)
+		    return NULL;
+	    }
+	    return Yield(exp, LINENO(n));
+	}
+        case factor: {
+            expr_ty expression;
+            
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+
+            expression = ast_for_expr(c, CHILD(n, 1));
+            if (!expression)
+                return NULL;
+
+            switch (TYPE(CHILD(n, 0))) {
+                case PLUS:
+                    return UnaryOp(UAdd, expression, LINENO(n));
+                case MINUS:
+                    return UnaryOp(USub, expression, LINENO(n));
+                case TILDE:
+                    return UnaryOp(Invert, expression, LINENO(n));
+            }
+            break;
+        }
+        case power: {
+            expr_ty e = ast_for_atom(c, CHILD(n, 0));
+	    if (!e)
+		return NULL;
+            if (NCH(n) == 1)
+                return e;
+            /* power: atom trailer* ('**' factor)*
+               trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME 
+
+               XXX What about atom trailer trailer ** factor?
+            */
+            for (i = 1; i < NCH(n); i++) {
+                expr_ty new = e;
+                node *ch = CHILD(n, i);
+                if (ch->n_str && strcmp(ch->n_str, "**") == 0)
+                    break;
+                if (TYPE(CHILD(ch, 0)) == LPAR) {
+                    if (NCH(ch) == 2)
+                        new = Call(new, NULL, NULL, NULL, NULL, LINENO(ch));
+                    else
+                        new = ast_for_call(c, CHILD(ch, 1), new);
+
+                    if (!new) {
+		        free_expr(e);
+                        return NULL;
+		    }
+                }
+                else if (TYPE(CHILD(ch, 0)) == LSQB) {
+                    REQ(CHILD(ch, 2), RSQB);
+                    ch = CHILD(ch, 1);
+                    if (NCH(ch) <= 2) {
+                        slice_ty slc = ast_for_slice(c, CHILD(ch, 0));
+                        if (!slc) {
+		            free_expr(e);
+                            return NULL;
+			}
+
+                        new = Subscript(e, slc, Load, LINENO(ch));
+                        if (!new) {
+		            free_expr(e);
+                            free_slice(slc);
+                            return NULL;
+			}
+                    }
+                    else {
+                        int j;
+                        slice_ty slc;
+                        asdl_seq *slices = asdl_seq_new((NCH(ch) + 1) / 2);
+                        if (!slices) {
+		            free_expr(e);
+                            return NULL;
+			}
+
+                        for (j = 0; j < NCH(ch); j += 2) {
+                            slc = ast_for_slice(c, CHILD(ch, j));
+                            if (!slc) {
+		                free_expr(e);
+		                asdl_seq_free(slices);
+                                return NULL;
+			    }
+                            asdl_seq_SET(slices, j / 2, slc);
+                        }
+                        new = Subscript(e, ExtSlice(slices), Load, LINENO(ch));
+                        if (!new) {
+		            free_expr(e);
+		            asdl_seq_free(slices);
+                            return NULL;
+			}
+                    }
+                }
+                else {
+                    assert(TYPE(CHILD(ch, 0)) == DOT);
+                    new = Attribute(e, NEW_IDENTIFIER(CHILD(ch, 1)), Load,
+				    LINENO(ch));
+                    if (!new) {
+		        free_expr(e);
+                        return NULL;
+		    }
+                }
+                e = new;
+            }
+            if (TYPE(CHILD(n, NCH(n) - 1)) == factor) {
+                expr_ty f = ast_for_expr(c, CHILD(n, NCH(n) - 1));
+                if (!f) {
+		    free_expr(e);
+                    return NULL;
+		}
+                return BinOp(e, Pow, f, LINENO(n));
+            }
+            return e;
+        }
+        default:
+	    abort();
+            PyErr_Format(PyExc_Exception, "unhandled expr: %d", TYPE(n));
+            return NULL;
+    }
+    /* should never get here */
+    return NULL;
+}
+
+static expr_ty
+ast_for_call(struct compiling *c, const node *n, expr_ty func)
+{
+    /*
+      arglist: (argument ',')* (argument [',']| '*' test [',' '**' test]
+               | '**' test)
+      argument: [test '='] test [gen_for]	 # Really [keyword '='] test
+    */
+
+    int i, nargs, nkeywords, ngens;
+    asdl_seq *args = NULL;
+    asdl_seq *keywords = NULL;
+    expr_ty vararg = NULL, kwarg = NULL;
+
+    REQ(n, arglist);
+
+    nargs = 0;
+    nkeywords = 0;
+    ngens = 0;
+    for (i = 0; i < NCH(n); i++) {
+	node *ch = CHILD(n, i);
+	if (TYPE(ch) == argument) {
+	    if (NCH(ch) == 1)
+		nargs++;
+	    else if (TYPE(CHILD(ch, 1)) == gen_for)
+		ngens++;
+            else
+		nkeywords++;
+	}
+    }
+    if (ngens > 1 || (ngens && (nargs || nkeywords))) {
+        ast_error(n, "Generator expression must be parenthesised "
+		  "if not sole argument");
+	return NULL;
+    }
+
+    if (nargs + nkeywords + ngens > 255) {
+      ast_error(n, "more than 255 arguments");
+      return NULL;
+    }
+
+    args = asdl_seq_new(nargs + ngens);
+    if (!args)
+        goto error;
+    keywords = asdl_seq_new(nkeywords);
+    if (!keywords)
+        goto error;
+    nargs = 0;
+    nkeywords = 0;
+    for (i = 0; i < NCH(n); i++) {
+	node *ch = CHILD(n, i);
+	if (TYPE(ch) == argument) {
+	    expr_ty e;
+	    if (NCH(ch) == 1) {
+		e = ast_for_expr(c, CHILD(ch, 0));
+                if (!e)
+                    goto error;
+		asdl_seq_SET(args, nargs++, e);
+	    }  
+	    else if (TYPE(CHILD(ch, 1)) == gen_for) {
+        	e = ast_for_genexp(c, ch);
+                if (!e)
+                    goto error;
+		asdl_seq_SET(args, nargs++, e);
+            }
+	    else {
+		keyword_ty kw;
+		identifier key;
+
+		/* CHILD(ch, 0) is test, but must be an identifier? */ 
+		e = ast_for_expr(c, CHILD(ch, 0));
+                if (!e)
+                    goto error;
+                /* f(lambda x: x[0] = 3) ends up getting parsed with
+                 * LHS test = lambda x: x[0], and RHS test = 3.
+                 * SF bug 132313 points out that complaining about a keyword
+                 * then is very confusing.
+                 */
+                if (e->kind == Lambda_kind) {
+                  ast_error(CHILD(ch, 0), "lambda cannot contain assignment");
+                  goto error;
+                } else if (e->kind != Name_kind) {
+                  ast_error(CHILD(ch, 0), "keyword can't be an expression");
+                  goto error;
+                }
+		key = e->v.Name.id;
+		free(e);
+		e = ast_for_expr(c, CHILD(ch, 2));
+                if (!e)
+                    goto error;
+		kw = keyword(key, e);
+                if (!kw)
+                    goto error;
+		asdl_seq_SET(keywords, nkeywords++, kw);
+	    }
+	}
+	else if (TYPE(ch) == STAR) {
+	    vararg = ast_for_expr(c, CHILD(n, i+1));
+	    i++;
+	}
+	else if (TYPE(ch) == DOUBLESTAR) {
+	    kwarg = ast_for_expr(c, CHILD(n, i+1));
+	    i++;
+	}
+    }
+
+    return Call(func, args, keywords, vararg, kwarg, LINENO(n));
+
+ error:
+    if (args)
+        asdl_seq_free(args);
+    if (keywords)
+        asdl_seq_free(keywords);
+    return NULL;
+}
+
+/* Unlike other ast_for_XXX() functions, this takes a flag that
+   indicates whether generator expressions are allowed.  If gexp is
+   non-zero, check for testlist_gexp instead of plain testlist.
+*/
+
+static expr_ty
+ast_for_testlist(struct compiling *c, const node* n, int gexp)
+{
+  /* testlist_gexp: test ( gen_for | (',' test)* [','] )
+     testlist: test (',' test)* [',']
+  */
+
+    assert(NCH(n) > 0);
+    if (NCH(n) == 1)
+	return ast_for_expr(c, CHILD(n, 0));
+    if (TYPE(CHILD(n, 1)) == gen_for) {
+	if (!gexp) {
+	    ast_error(n, "illegal generator expression");
+	    return NULL;
+	}
+	return ast_for_genexp(c, n);
+    }
+    else {
+        asdl_seq *tmp = seq_for_testlist(c, n);
+        if (!tmp)
+            return NULL;
+
+	return Tuple(tmp, Load, LINENO(n));
+    }
+    return NULL;  /* unreachable */
+}
+
+static stmt_ty
+ast_for_expr_stmt(struct compiling *c, const node *n)
+{
+    REQ(n, expr_stmt);
+    /* expr_stmt: testlist (augassign (yield_expr|testlist) 
+                | ('=' (yield_expr|testlist))*)
+       testlist: test (',' test)* [',']
+       augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^='
+	        | '<<=' | '>>=' | '**=' | '//='
+       test: ... here starts the operator precendence dance
+     */
+
+    if (NCH(n) == 1) {
+	expr_ty e = ast_for_testlist(c, CHILD(n, 0), 0);
+        if (!e)
+            return NULL;
+
+	return Expr(e, LINENO(n));
+    }
+    else if (TYPE(CHILD(n, 1)) == augassign) {
+        expr_ty expr1, expr2;
+        operator_ty operator;
+	node *ch = CHILD(n, 0);
+
+	if (TYPE(ch) == testlist)
+	    expr1 = ast_for_testlist(c, ch, 0);
+	else
+	    expr1 = Yield(ast_for_expr(c, CHILD(ch, 0)), LINENO(ch));
+
+        if (!expr1)
+            return NULL;
+        if (expr1->kind == GeneratorExp_kind) {
+	    ast_error(ch, "augmented assignment to generator "
+		      "expression not possible");
+	    return NULL;
+        }
+	if (expr1->kind == Name_kind) {
+		char *var_name = PyString_AS_STRING(expr1->v.Name.id);
+		if (var_name[0] == 'N' && !strcmp(var_name, "None")) {
+			ast_error(ch, "assignment to None");
+			return NULL;
+		}
+	}
+
+	ch = CHILD(n, 2);
+	if (TYPE(ch) == testlist)
+	    expr2 = ast_for_testlist(c, ch, 0);
+	else
+	    expr2 = Yield(ast_for_expr(c, ch), LINENO(ch));
+        if (!expr2)
+            return NULL;
+
+        operator = ast_for_augassign(CHILD(n, 1));
+        if (!operator)
+            return NULL;
+
+	return AugAssign(expr1, operator, expr2, LINENO(n));
+    }
+    else {
+	int i;
+	asdl_seq *targets;
+	node *value;
+        expr_ty expression;
+
+	/* a normal assignment */
+	REQ(CHILD(n, 1), EQUAL);
+	targets = asdl_seq_new(NCH(n) / 2);
+	if (!targets)
+	    return NULL;
+	for (i = 0; i < NCH(n) - 2; i += 2) {
+	    node *ch = CHILD(n, i);
+	    if (TYPE(ch) == yield_expr) {
+		ast_error(ch, "assignment to yield expression not possible");
+		goto error;
+	    }
+	    expr_ty e = ast_for_testlist(c, ch, 0);
+
+	    /* set context to assign */
+	    if (!e) 
+	      goto error;
+
+	    if (!set_context(e, Store, CHILD(n, i))) {
+              free_expr(e);
+	      goto error;
+            }
+
+	    asdl_seq_SET(targets, i / 2, e);
+	}
+	value = CHILD(n, NCH(n) - 1);
+	if (TYPE(value) == testlist)
+	    expression = ast_for_testlist(c, value, 0);
+	else
+	    expression = ast_for_expr(c, value);
+	if (!expression)
+	    return NULL;
+	return Assign(targets, expression, LINENO(n));
+    error:
+        for (i = i / 2; i >= 0; i--)
+            free_expr((expr_ty)asdl_seq_GET(targets, i));
+        asdl_seq_free(targets);
+        return NULL;
+    }
+    return NULL;
+}
+
+static stmt_ty
+ast_for_print_stmt(struct compiling *c, const node *n)
+{
+    /* print_stmt: 'print' ( [ test (',' test)* [','] ]
+                             | '>>' test [ (',' test)+ [','] ] )
+     */
+    expr_ty dest = NULL, expression;
+    asdl_seq *seq;
+    bool nl;
+    int i, start = 1;
+
+    REQ(n, print_stmt);
+    if (NCH(n) >= 2 && TYPE(CHILD(n, 1)) == RIGHTSHIFT) {
+	dest = ast_for_expr(c, CHILD(n, 2));
+        if (!dest)
+            return NULL;
+	start = 4;
+    }
+    seq = asdl_seq_new((NCH(n) + 1 - start) / 2);
+    if (!seq)
+	return NULL;
+    for (i = start; i < NCH(n); i += 2) {
+        expression = ast_for_expr(c, CHILD(n, i));
+        if (!expression) {
+	    asdl_seq_free(seq);
+            return NULL;
+	}
+
+	asdl_seq_APPEND(seq, expression);
+    }
+    nl = (TYPE(CHILD(n, NCH(n) - 1)) == COMMA) ? false : true;
+    return Print(dest, seq, nl, LINENO(n));
+}
+
+static asdl_seq *
+ast_for_exprlist(struct compiling *c, const node *n, int context)
+{
+    asdl_seq *seq;
+    int i;
+    expr_ty e;
+
+    REQ(n, exprlist);
+
+    seq = asdl_seq_new((NCH(n) + 1) / 2);
+    if (!seq)
+	return NULL;
+    for (i = 0; i < NCH(n); i += 2) {
+	e = ast_for_expr(c, CHILD(n, i));
+	if (!e) {
+	    asdl_seq_free(seq);
+	    return NULL;
+	}
+	if (context) {
+	    if (!set_context(e, context, CHILD(n, i)))
+                return NULL;
+        }
+	asdl_seq_SET(seq, i / 2, e);
+    }
+    return seq;
+}
+
+static stmt_ty
+ast_for_del_stmt(struct compiling *c, const node *n)
+{
+    asdl_seq *expr_list;
+    
+    /* del_stmt: 'del' exprlist */
+    REQ(n, del_stmt);
+
+    expr_list = ast_for_exprlist(c, CHILD(n, 1), Del);
+    if (!expr_list)
+        return NULL;
+    return Delete(expr_list, LINENO(n));
+}
+
+static stmt_ty
+ast_for_flow_stmt(struct compiling *c, const node *n)
+{
+    /*
+      flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt
+                 | yield_stmt
+      break_stmt: 'break'
+      continue_stmt: 'continue'
+      return_stmt: 'return' [testlist]
+      yield_stmt: yield_expr
+      yield_expr: 'yield' testlist
+      raise_stmt: 'raise' [test [',' test [',' test]]]
+    */
+    node *ch;
+
+    REQ(n, flow_stmt);
+    ch = CHILD(n, 0);
+    switch (TYPE(ch)) {
+        case break_stmt:
+            return Break(LINENO(n));
+        case continue_stmt:
+            return Continue(LINENO(n));
+        case yield_stmt: { /* will reduce to yield_expr */
+	    expr_ty exp = ast_for_expr(c, CHILD(ch, 0));
+	    if (!exp)
+		return NULL;
+            return Expr(exp, LINENO(n));
+        }
+        case return_stmt:
+            if (NCH(ch) == 1)
+                return Return(NULL, LINENO(n));
+            else {
+                expr_ty expression = ast_for_testlist(c, CHILD(ch, 1), 0);
+                if (!expression)
+                    return NULL;
+                return Return(expression, LINENO(n));
+            }
+        case raise_stmt:
+            if (NCH(ch) == 1)
+                return Raise(NULL, NULL, NULL, LINENO(n));
+            else if (NCH(ch) == 2) {
+                expr_ty expression = ast_for_expr(c, CHILD(ch, 1));
+                if (!expression)
+                    return NULL;
+                return Raise(expression, NULL, NULL, LINENO(n));
+            }
+            else if (NCH(ch) == 4) {
+                expr_ty expr1, expr2;
+
+                expr1 = ast_for_expr(c, CHILD(ch, 1));
+                if (!expr1)
+                    return NULL;
+                expr2 = ast_for_expr(c, CHILD(ch, 3));
+                if (!expr2)
+                    return NULL;
+
+                return Raise(expr1, expr2, NULL, LINENO(n));
+            }
+            else if (NCH(ch) == 6) {
+                expr_ty expr1, expr2, expr3;
+
+                expr1 = ast_for_expr(c, CHILD(ch, 1));
+                if (!expr1)
+                    return NULL;
+                expr2 = ast_for_expr(c, CHILD(ch, 3));
+                if (!expr2)
+                    return NULL;
+                expr3 = ast_for_expr(c, CHILD(ch, 5));
+                if (!expr3)
+                    return NULL;
+                    
+                return Raise(expr1, expr2, expr3, LINENO(n));
+            }
+        default:
+            PyErr_Format(PyExc_Exception,
+                         "unexpected flow_stmt: %d", TYPE(ch));
+            return NULL;
+    }
+}
+
+static alias_ty
+alias_for_import_name(const node *n)
+{
+    /*
+      import_as_name: NAME [NAME NAME]
+      dotted_as_name: dotted_name [NAME NAME]
+      dotted_name: NAME ('.' NAME)*
+    */
+ loop:
+    switch (TYPE(n)) {
+        case import_as_name:
+            if (NCH(n) == 3)
+                return alias(NEW_IDENTIFIER(CHILD(n, 0)),
+                             NEW_IDENTIFIER(CHILD(n, 2)));
+            else
+                return alias(NEW_IDENTIFIER(CHILD(n, 0)),
+                             NULL);
+            break;
+        case dotted_as_name:
+            if (NCH(n) == 1) {
+                n = CHILD(n, 0);
+                goto loop;
+            }
+            else {
+                alias_ty a = alias_for_import_name(CHILD(n, 0));
+                assert(!a->asname);
+                a->asname = NEW_IDENTIFIER(CHILD(n, 2));
+                return a;
+            }
+            break;
+        case dotted_name:
+            if (NCH(n) == 1)
+                return alias(NEW_IDENTIFIER(CHILD(n, 0)), NULL);
+            else {
+                /* Create a string of the form "a.b.c" */
+                int i, len;
+                PyObject *str;
+                char *s;
+
+                len = 0;
+                for (i = 0; i < NCH(n); i += 2)
+                    /* length of string plus one for the dot */
+                    len += strlen(STR(CHILD(n, i))) + 1;
+                len--; /* the last name doesn't have a dot */
+                str = PyString_FromStringAndSize(NULL, len);
+                if (!str)
+                    return NULL;
+                s = PyString_AS_STRING(str);
+                if (!s)
+                    return NULL;
+                for (i = 0; i < NCH(n); i += 2) {
+                    char *sch = STR(CHILD(n, i));
+                    strcpy(s, STR(CHILD(n, i)));
+                    s += strlen(sch);
+                    *s++ = '.';
+                }
+                --s;
+                *s = '\0';
+                PyString_InternInPlace(&str);
+                return alias(str, NULL);
+            }
+            break;
+        case STAR:
+            return alias(PyString_InternFromString("*"), NULL);
+        default:
+            PyErr_Format(PyExc_Exception,
+                         "unexpected import name: %d", TYPE(n));
+            return NULL;
+    }
+    return NULL;
+}
+
+static stmt_ty
+ast_for_import_stmt(struct compiling *c, const node *n)
+{
+    /*
+      import_stmt: import_name | import_from
+      import_name: 'import' dotted_as_names
+      import_from: 'from' dotted_name 'import' ('*' | 
+                                                '(' import_as_names ')' | 
+                                                import_as_names)
+    */
+    int i;
+    asdl_seq *aliases;
+
+    REQ(n, import_stmt);
+    n = CHILD(n, 0);
+    if (STR(CHILD(n, 0))[0] == 'i') { /* import */
+        n = CHILD(n, 1);
+	aliases = asdl_seq_new((NCH(n) + 1) / 2);
+	if (!aliases)
+		return NULL;
+	for (i = 0; i < NCH(n); i += 2) {
+            alias_ty import_alias = alias_for_import_name(CHILD(n, i));
+            if (!import_alias) {
+                asdl_seq_free(aliases);
+                return NULL;
+            }
+	    asdl_seq_SET(aliases, i / 2, import_alias);
+        }
+	return Import(aliases, LINENO(n));
+    }
+    else if (STR(CHILD(n, 0))[0] == 'f') { /* from */
+	stmt_ty import;
+        int n_children;
+        const char *from_modules;
+	int lineno = LINENO(n);
+	alias_ty mod = alias_for_import_name(CHILD(n, 1));
+	if (!mod)
+            return NULL;
+
+        /* XXX this needs to be cleaned up */
+
+        from_modules = STR(CHILD(n, 3));
+        if (!from_modules) {
+            n = CHILD(n, 3);                  /* from ... import x, y, z */
+            if (NCH(n) % 2 == 0) {
+                /* it ends with a comma, not valid but the parser allows it */
+                ast_error(n, "trailing comma not allowed without"
+                             " surrounding parentheses");
+                return NULL;
+            }
+        }
+        else if (from_modules[0] == '*') {
+            n = CHILD(n, 3); /* from ... import * */
+        }
+        else if (from_modules[0] == '(')
+            n = CHILD(n, 4);                  /* from ... import (x, y, z) */
+        else
+            return NULL;
+
+        n_children = NCH(n);
+        if (from_modules && from_modules[0] == '*')
+            n_children = 1;
+
+	aliases = asdl_seq_new((n_children + 1) / 2);
+	if (!aliases) {
+            free_alias(mod);
+            return NULL;
+	}
+
+        /* handle "from ... import *" special b/c there's no children */
+        if (from_modules && from_modules[0] == '*') {
+            alias_ty import_alias = alias_for_import_name(n);
+            if (!import_alias) {
+                asdl_seq_free(aliases);
+                free_alias(mod);
+                return NULL;
+            }
+	    asdl_seq_APPEND(aliases, import_alias);
+        }
+
+	for (i = 0; i < NCH(n); i += 2) {
+            alias_ty import_alias = alias_for_import_name(CHILD(n, i));
+            if (!import_alias) {
+                asdl_seq_free(aliases);
+                free_alias(mod);
+                return NULL;
+            }
+	    asdl_seq_APPEND(aliases, import_alias);
+        }
+        Py_INCREF(mod->name);
+	import = ImportFrom(mod->name, aliases, lineno);
+	free_alias(mod);
+	return import;
+    }
+    PyErr_Format(PyExc_Exception,
+                 "unknown import statement: starts with command '%s'",
+                 STR(CHILD(n, 0)));
+    return NULL;
+}
+
+static stmt_ty
+ast_for_global_stmt(struct compiling *c, const node *n)
+{
+    /* global_stmt: 'global' NAME (',' NAME)* */
+    identifier name;
+    asdl_seq *s;
+    int i;
+
+    REQ(n, global_stmt);
+    s = asdl_seq_new(NCH(n) / 2);
+    if (!s)
+    	return NULL;
+    for (i = 1; i < NCH(n); i += 2) {
+	name = NEW_IDENTIFIER(CHILD(n, i));
+	if (!name) {
+	    asdl_seq_free(s);
+	    return NULL;
+	}
+	asdl_seq_SET(s, i / 2, name);
+    }
+    return Global(s, LINENO(n));
+}
+
+static stmt_ty
+ast_for_exec_stmt(struct compiling *c, const node *n)
+{
+    expr_ty expr1, globals = NULL, locals = NULL;
+    int n_children = NCH(n);
+    if (n_children != 2 && n_children != 4 && n_children != 6) {
+        PyErr_Format(PyExc_Exception,
+                     "poorly formed 'exec' statement: %d parts to statement",
+                     n_children);
+        return NULL;
+    }
+
+    /* exec_stmt: 'exec' expr ['in' test [',' test]] */
+    REQ(n, exec_stmt);
+    expr1 = ast_for_expr(c, CHILD(n, 1));
+    if (!expr1)
+        return NULL;
+    if (n_children >= 4) {
+        globals = ast_for_expr(c, CHILD(n, 3));
+        if (!globals)
+            return NULL;
+    }
+    if (n_children == 6) {
+        locals = ast_for_expr(c, CHILD(n, 5));
+        if (!locals)
+            return NULL;
+    }
+
+    return Exec(expr1, globals, locals, LINENO(n));
+}
+
+static stmt_ty
+ast_for_assert_stmt(struct compiling *c, const node *n)
+{
+    /* assert_stmt: 'assert' test [',' test] */
+    REQ(n, assert_stmt);
+    if (NCH(n) == 2) {
+        expr_ty expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+	return Assert(expression, NULL, LINENO(n));
+    }
+    else if (NCH(n) == 4) {
+        expr_ty expr1, expr2;
+
+        expr1 = ast_for_expr(c, CHILD(n, 1));
+        if (!expr1)
+            return NULL;
+        expr2 = ast_for_expr(c, CHILD(n, 3));
+        if (!expr2)
+            return NULL;
+            
+	return Assert(expr1, expr2, LINENO(n));
+    }
+    PyErr_Format(PyExc_Exception,
+                 "improper number of parts to 'assert' statement: %d",
+                 NCH(n));
+    return NULL;
+}
+
+static asdl_seq *
+ast_for_suite(struct compiling *c, const node *n)
+{
+    /* suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT */
+    asdl_seq *seq = NULL;
+    stmt_ty s;
+    int i, total, num, end, pos = 0;
+    node *ch;
+
+    REQ(n, suite);
+
+    total = num_stmts(n);
+    seq = asdl_seq_new(total);
+    if (!seq)
+    	return NULL;
+    if (TYPE(CHILD(n, 0)) == simple_stmt) {
+	n = CHILD(n, 0);
+	/* simple_stmt always ends with a NEWLINE,
+	   and may have a trailing SEMI 
+	*/
+	end = NCH(n) - 1;
+	if (TYPE(CHILD(n, end - 1)) == SEMI)
+	    end--;
+        /* loop by 2 to skip semi-colons */
+	for (i = 0; i < end; i += 2) {
+	    ch = CHILD(n, i);
+	    s = ast_for_stmt(c, ch);
+	    if (!s)
+		goto error;
+	    asdl_seq_SET(seq, pos++, s);
+	}
+    }
+    else {
+	for (i = 2; i < (NCH(n) - 1); i++) {
+	    ch = CHILD(n, i);
+	    REQ(ch, stmt);
+	    num = num_stmts(ch);
+	    if (num == 1) {
+		/* small_stmt or compound_stmt with only one child */
+		s = ast_for_stmt(c, ch);
+		if (!s)
+		    goto error;
+		asdl_seq_SET(seq, pos++, s);
+	    }
+	    else {
+		int j;
+		ch = CHILD(ch, 0);
+		REQ(ch, simple_stmt);
+		for (j = 0; j < NCH(ch); j += 2) {
+		    s = ast_for_stmt(c, CHILD(ch, j));
+		    if (!s)
+			goto error;
+		    asdl_seq_SET(seq, pos++, s);
+		}
+	    }
+	}
+    }
+    assert(pos == seq->size);
+    return seq;
+ error:
+    if (seq)
+	asdl_seq_free(seq);
+    return NULL;
+}
+
+static stmt_ty
+ast_for_if_stmt(struct compiling *c, const node *n)
+{
+    /* if_stmt: 'if' test ':' suite ('elif' test ':' suite)*
+       ['else' ':' suite]
+    */
+    char *s;
+
+    REQ(n, if_stmt);
+
+    if (NCH(n) == 4) {
+        expr_ty expression;
+        asdl_seq *suite_seq;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, CHILD(n, 3)); 
+        if (!suite_seq)
+            return NULL;
+            
+	return If(expression, suite_seq, NULL, LINENO(n));
+    }
+    s = STR(CHILD(n, 4));
+    /* s[2], the third character in the string, will be
+       's' for el_s_e, or
+       'i' for el_i_f
+    */
+    if (s[2] == 's') {
+        expr_ty expression;
+        asdl_seq *seq1, *seq2;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        seq1 = ast_for_suite(c, CHILD(n, 3));
+        if (!seq1)
+            return NULL;
+        seq2 = ast_for_suite(c, CHILD(n, 6));
+        if (!seq2)
+            return NULL;
+
+	return If(expression, seq1, seq2, LINENO(n));
+    }
+    else if (s[2] == 'i') {
+	int i, n_elif, has_else = 0;
+	asdl_seq *orelse = NULL;
+	n_elif = NCH(n) - 4;
+        /* must reference the child n_elif+1 since 'else' token is third,
+           not fourth, child from the end. */
+	if (TYPE(CHILD(n, (n_elif + 1))) == NAME
+	    && STR(CHILD(n, (n_elif + 1)))[2] == 's') {
+	    has_else = 1;
+	    n_elif -= 3;
+	}
+	n_elif /= 4;
+
+	if (has_else) {
+            expr_ty expression;
+            asdl_seq *seq1, *seq2;
+
+	    orelse = asdl_seq_new(1);
+	    if (!orelse)
+		return NULL;
+            expression = ast_for_expr(c, CHILD(n, NCH(n) - 6));
+            if (!expression) {
+                asdl_seq_free(orelse);
+                return NULL;
+            }
+            seq1 = ast_for_suite(c, CHILD(n, NCH(n) - 4));
+            if (!seq1) {
+                asdl_seq_free(orelse);
+                return NULL;
+            }
+            seq2 = ast_for_suite(c, CHILD(n, NCH(n) - 1));
+            if (!seq2) {
+                asdl_seq_free(orelse);
+                return NULL;
+            }
+
+	    asdl_seq_SET(orelse, 0, If(expression, seq1, seq2, 
+				       LINENO(CHILD(n, NCH(n) - 6))));
+	    /* the just-created orelse handled the last elif */
+	    n_elif--;
+	}
+        else
+            orelse  = NULL;
+
+	for (i = 0; i < n_elif; i++) {
+	    int off = 5 + (n_elif - i - 1) * 4;
+            expr_ty expression;
+            asdl_seq *suite_seq;
+	    asdl_seq *new = asdl_seq_new(1);
+	    if (!new)
+		return NULL;
+            expression = ast_for_expr(c, CHILD(n, off));
+            if (!expression) {
+                asdl_seq_free(new);
+                return NULL;
+            }
+            suite_seq = ast_for_suite(c, CHILD(n, off + 2));
+            if (!suite_seq) {
+                asdl_seq_free(new);
+                return NULL;
+            }
+
+	    asdl_seq_SET(new, 0,
+			 If(expression, suite_seq, orelse, 
+			    LINENO(CHILD(n, off))));
+	    orelse = new;
+	}
+	return If(ast_for_expr(c, CHILD(n, 1)),
+		  ast_for_suite(c, CHILD(n, 3)),
+		  orelse, LINENO(n));
+    }
+    else {
+        PyErr_Format(PyExc_Exception,
+                     "unexpected token in 'if' statement: %s", s);
+        return NULL;
+    }
+}
+
+static stmt_ty
+ast_for_while_stmt(struct compiling *c, const node *n)
+{
+    /* while_stmt: 'while' test ':' suite ['else' ':' suite] */
+    REQ(n, while_stmt);
+
+    if (NCH(n) == 4) {
+        expr_ty expression;
+        asdl_seq *suite_seq;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, CHILD(n, 3));
+        if (!suite_seq)
+            return NULL;
+	return While(expression, suite_seq, NULL, LINENO(n));
+    }
+    else if (NCH(n) == 7) {
+        expr_ty expression;
+        asdl_seq *seq1, *seq2;
+
+        expression = ast_for_expr(c, CHILD(n, 1));
+        if (!expression)
+            return NULL;
+        seq1 = ast_for_suite(c, CHILD(n, 3));
+        if (!seq1)
+            return NULL;
+        seq2 = ast_for_suite(c, CHILD(n, 6));
+        if (!seq2)
+            return NULL;
+
+	return While(expression, seq1, seq2, LINENO(n));
+    }
+    else {
+        PyErr_Format(PyExc_Exception,
+                     "wrong number of tokens for 'while' statement: %d",
+                     NCH(n));
+        return NULL;
+    }
+}
+
+static stmt_ty
+ast_for_for_stmt(struct compiling *c, const node *n)
+{
+    asdl_seq *_target = NULL, *seq = NULL, *suite_seq = NULL;
+    expr_ty expression;
+    expr_ty target;
+    /* for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] */
+    REQ(n, for_stmt);
+
+    if (NCH(n) == 9) {
+	seq = ast_for_suite(c, CHILD(n, 8));
+        if (!seq)
+            return NULL;
+    }
+
+    _target = ast_for_exprlist(c, CHILD(n, 1), Store);
+    if (!_target)
+        return NULL;
+    if (asdl_seq_LEN(_target) == 1) {
+	target = asdl_seq_GET(_target, 0);
+	asdl_seq_free(_target);
+    }
+    else
+	target = Tuple(_target, Store, LINENO(n));
+
+    expression = ast_for_testlist(c, CHILD(n, 3), 0);
+    if (!expression)
+        return NULL;
+    suite_seq = ast_for_suite(c, CHILD(n, 5));
+    if (!suite_seq)
+        return NULL;
+
+    return For(target, expression, suite_seq, seq, LINENO(n));
+}
+
+static excepthandler_ty
+ast_for_except_clause(struct compiling *c, const node *exc, node *body)
+{
+    /* except_clause: 'except' [test [',' test]] */
+    REQ(exc, except_clause);
+    REQ(body, suite);
+
+    if (NCH(exc) == 1) {
+        asdl_seq *suite_seq = ast_for_suite(c, body);
+        if (!suite_seq)
+            return NULL;
+
+	return excepthandler(NULL, NULL, suite_seq);
+    }
+    else if (NCH(exc) == 2) {
+        expr_ty expression;
+        asdl_seq *suite_seq;
+
+        expression = ast_for_expr(c, CHILD(exc, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, body);
+        if (!suite_seq)
+            return NULL;
+
+	return excepthandler(expression, NULL, suite_seq);
+    }
+    else if (NCH(exc) == 4) {
+        asdl_seq *suite_seq;
+        expr_ty expression;
+	expr_ty e = ast_for_expr(c, CHILD(exc, 3));
+	if (!e)
+            return NULL;
+	if (!set_context(e, Store, CHILD(exc, 3)))
+            return NULL;
+        expression = ast_for_expr(c, CHILD(exc, 1));
+        if (!expression)
+            return NULL;
+        suite_seq = ast_for_suite(c, body);
+        if (!suite_seq)
+            return NULL;
+
+	return excepthandler(expression, e, suite_seq);
+    }
+    else {
+        PyErr_Format(PyExc_Exception,
+                     "wrong number of children for 'except' clause: %d",
+                     NCH(exc));
+        return NULL;
+    }
+}
+
+static stmt_ty
+ast_for_try_stmt(struct compiling *c, const node *n)
+{
+    REQ(n, try_stmt);
+
+    if (TYPE(CHILD(n, 3)) == NAME) {/* must be 'finally' */
+	/* try_stmt: 'try' ':' suite 'finally' ':' suite) */
+        asdl_seq *s1, *s2;
+        s1 = ast_for_suite(c, CHILD(n, 2));
+        if (!s1)
+            return NULL;
+        s2 = ast_for_suite(c, CHILD(n, 5));
+        if (!s2)
+            return NULL;
+            
+	return TryFinally(s1, s2, LINENO(n));
+    }
+    else if (TYPE(CHILD(n, 3)) == except_clause) {
+	/* try_stmt: ('try' ':' suite (except_clause ':' suite)+
+           ['else' ':' suite]
+	*/
+        asdl_seq *suite_seq1, *suite_seq2;
+	asdl_seq *handlers;
+	int i, has_else = 0, n_except = NCH(n) - 3;
+	if (TYPE(CHILD(n, NCH(n) - 3)) == NAME) {
+	    has_else = 1;
+	    n_except -= 3;
+	}
+	n_except /= 3;
+	handlers = asdl_seq_new(n_except);
+	if (!handlers)
+		return NULL;
+	for (i = 0; i < n_except; i++) {
+            excepthandler_ty e = ast_for_except_clause(c,
+                                                       CHILD(n, 3 + i * 3),
+                                                       CHILD(n, 5 + i * 3));
+            if (!e)
+                return NULL;
+	    asdl_seq_SET(handlers, i, e);
+        }
+
+        suite_seq1 = ast_for_suite(c, CHILD(n, 2));
+        if (!suite_seq1)
+            return NULL;
+        if (has_else) {
+            suite_seq2 = ast_for_suite(c, CHILD(n, NCH(n) - 1));
+            if (!suite_seq2)
+                return NULL;
+        }
+        else
+            suite_seq2 = NULL;
+
+	return TryExcept(suite_seq1, handlers, suite_seq2, LINENO(n));
+    }
+    else {
+        PyErr_SetString(PyExc_Exception, "malformed 'try' statement");
+        return NULL;
+    }
+}
+
+static stmt_ty
+ast_for_classdef(struct compiling *c, const node *n)
+{
+    /* classdef: 'class' NAME ['(' testlist ')'] ':' suite */
+    expr_ty _bases;
+    asdl_seq *bases, *s;
+    
+    REQ(n, classdef);
+
+    if (!strcmp(STR(CHILD(n, 1)), "None")) {
+	    ast_error(n, "assignment to None");
+	    return NULL;
+    }
+
+    if (NCH(n) == 4) {
+        s = ast_for_suite(c, CHILD(n, 3));
+        if (!s)
+            return NULL;
+	return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), NULL, s, LINENO(n));
+    }
+    /* check for empty base list */
+    if (TYPE(CHILD(n,3)) == RPAR) {
+	s = ast_for_suite(c, CHILD(n,5));
+	if (!s)
+		return NULL;
+	return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), NULL, s, LINENO(n));
+    }
+
+    /* else handle the base class list */
+    _bases = ast_for_testlist(c, CHILD(n, 3), 0);
+    if (!_bases)
+        return NULL;
+    /* XXX: I don't think we can set to diff types here, how to free???
+
+	Here's the allocation chain:
+    		Tuple (Python-ast.c:907)
+    		ast_for_testlist (ast.c:1782)
+    		ast_for_classdef (ast.c:2677)
+     */
+    if (_bases->kind == Tuple_kind)
+	bases = _bases->v.Tuple.elts;
+    else {
+	bases = asdl_seq_new(1);
+	if (!bases) {
+            free_expr(_bases);
+	    /* XXX: free _bases */
+            return NULL;
+	}
+	asdl_seq_SET(bases, 0, _bases);
+    }
+
+    s = ast_for_suite(c, CHILD(n, 6));
+    if (!s) {
+	/* XXX: I think this free is correct, but needs to change see above */
+        if (_bases->kind == Tuple_kind)
+		free_expr(_bases);
+	else {
+		free_expr(_bases);
+        	asdl_seq_free(bases);
+	}
+        return NULL;
+    }
+    return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), bases, s, LINENO(n));
+}
+
+static stmt_ty
+ast_for_stmt(struct compiling *c, const node *n)
+{
+    if (TYPE(n) == stmt) {
+	assert(NCH(n) == 1);
+	n = CHILD(n, 0);
+    }
+    if (TYPE(n) == simple_stmt) {
+	assert(num_stmts(n) == 1);
+	n = CHILD(n, 0);
+    }
+    if (TYPE(n) == small_stmt) {
+	REQ(n, small_stmt);
+	n = CHILD(n, 0);
+	/* small_stmt: expr_stmt | print_stmt  | del_stmt | pass_stmt
+	             | flow_stmt | import_stmt | global_stmt | exec_stmt
+                     | assert_stmt
+	*/
+	switch (TYPE(n)) {
+            case expr_stmt:
+                return ast_for_expr_stmt(c, n);
+            case print_stmt:
+                return ast_for_print_stmt(c, n);
+            case del_stmt:
+                return ast_for_del_stmt(c, n);
+            case pass_stmt:
+                return Pass(LINENO(n));
+            case flow_stmt:
+                return ast_for_flow_stmt(c, n);
+            case import_stmt:
+                return ast_for_import_stmt(c, n);
+            case global_stmt:
+                return ast_for_global_stmt(c, n);
+            case exec_stmt:
+                return ast_for_exec_stmt(c, n);
+            case assert_stmt:
+                return ast_for_assert_stmt(c, n);
+            default:
+                PyErr_Format(PyExc_Exception,
+                             "unhandled small_stmt: TYPE=%d NCH=%d\n",
+                             TYPE(n), NCH(n));
+                return NULL;
+        }
+    }
+    else {
+        /* compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt
+	                | funcdef | classdef
+	*/
+	node *ch = CHILD(n, 0);
+	REQ(n, compound_stmt);
+	switch (TYPE(ch)) {
+            case if_stmt:
+                return ast_for_if_stmt(c, ch);
+            case while_stmt:
+                return ast_for_while_stmt(c, ch);
+            case for_stmt:
+                return ast_for_for_stmt(c, ch);
+            case try_stmt:
+                return ast_for_try_stmt(c, ch);
+            case funcdef:
+                return ast_for_funcdef(c, ch);
+            case classdef:
+                return ast_for_classdef(c, ch);
+            default:
+                PyErr_Format(PyExc_Exception,
+                             "unhandled small_stmt: TYPE=%d NCH=%d\n",
+                             TYPE(n), NCH(n));
+                return NULL;
+	}
+    }
+}
+
+static PyObject *
+parsenumber(const char *s)
+{
+	const char *end;
+	long x;
+	double dx;
+#ifndef WITHOUT_COMPLEX
+	Py_complex c;
+	int imflag;
+#endif
+
+	errno = 0;
+	end = s + strlen(s) - 1;
+#ifndef WITHOUT_COMPLEX
+	imflag = *end == 'j' || *end == 'J';
+#endif
+	if (*end == 'l' || *end == 'L')
+		return PyLong_FromString((char *)s, (char **)0, 0);
+	if (s[0] == '0') {
+		x = (long) PyOS_strtoul((char *)s, (char **)&end, 0);
+ 		if (x < 0 && errno == 0) {
+	 			return PyLong_FromString((char *)s,
+							 (char **)0,
+							 0);
+		}
+	}
+	else
+		x = PyOS_strtol((char *)s, (char **)&end, 0);
+	if (*end == '\0') {
+		if (errno != 0)
+			return PyLong_FromString((char *)s, (char **)0, 0);
+		return PyInt_FromLong(x);
+	}
+	/* XXX Huge floats may silently fail */
+#ifndef WITHOUT_COMPLEX
+	if (imflag) {
+		c.real = 0.;
+		PyFPE_START_PROTECT("atof", return 0)
+		c.imag = atof(s);
+		PyFPE_END_PROTECT(c)
+		return PyComplex_FromCComplex(c);
+	}
+	else
+#endif
+	{
+		PyFPE_START_PROTECT("atof", return 0)
+		dx = atof(s);
+		PyFPE_END_PROTECT(dx)
+		return PyFloat_FromDouble(dx);
+	}
+}
+
+static PyObject *
+decode_utf8(const char **sPtr, const char *end, char* encoding)
+{
+#ifndef Py_USING_UNICODE
+	Py_FatalError("decode_utf8 should not be called in this build.");
+        return NULL;
+#else
+	PyObject *u, *v;
+	char *s, *t;
+	t = s = (char *)*sPtr;
+	/* while (s < end && *s != '\\') s++; */ /* inefficient for u".." */
+	while (s < end && (*s & 0x80)) s++;
+	*sPtr = s;
+	u = PyUnicode_DecodeUTF8(t, s - t, NULL);
+	if (u == NULL)
+		return NULL;
+	v = PyUnicode_AsEncodedString(u, encoding, NULL);
+	Py_DECREF(u);
+	return v;
+#endif
+}
+
+static PyObject *
+decode_unicode(const char *s, size_t len, int rawmode, const char *encoding)
+{
+	PyObject *v, *u;
+	char *buf;
+	char *p;
+	const char *end;
+	if (encoding == NULL) {
+	     	buf = (char *)s;
+		u = NULL;
+	} else if (strcmp(encoding, "iso-8859-1") == 0) {
+	     	buf = (char *)s;
+		u = NULL;
+	} else {
+		/* "\XX" may become "\u005c\uHHLL" (12 bytes) */
+		u = PyString_FromStringAndSize((char *)NULL, len * 4);
+		if (u == NULL)
+			return NULL;
+		p = buf = PyString_AsString(u);
+		end = s + len;
+		while (s < end) {
+			if (*s == '\\') {
+				*p++ = *s++;
+				if (*s & 0x80) {
+					strcpy(p, "u005c");
+					p += 5;
+				}
+			}
+			if (*s & 0x80) { /* XXX inefficient */
+				PyObject *w;
+				char *r;
+				int rn, i;
+				w = decode_utf8(&s, end, "utf-16-be");
+				if (w == NULL) {
+					Py_DECREF(u);
+					return NULL;
+				}
+				r = PyString_AsString(w);
+				rn = PyString_Size(w);
+				assert(rn % 2 == 0);
+				for (i = 0; i < rn; i += 2) {
+					sprintf(p, "\\u%02x%02x",
+						r[i + 0] & 0xFF,
+						r[i + 1] & 0xFF);
+					p += 6;
+				}
+				Py_DECREF(w);
+			} else {
+				*p++ = *s++;
+			}
+		}
+		len = p - buf;
+		s = buf;
+	}
+	if (rawmode)
+		v = PyUnicode_DecodeRawUnicodeEscape(s, len, NULL);
+	else
+		v = PyUnicode_DecodeUnicodeEscape(s, len, NULL);
+	Py_XDECREF(u);
+	return v;
+}
+
+/* s is a Python string literal, including the bracketing quote characters,
+ * and r &/or u prefixes (if any), and embedded escape sequences (if any).
+ * parsestr parses it, and returns the decoded Python string object.
+ */
+static PyObject *
+parsestr(const char *s, const char *encoding)
+{
+	PyObject *v;
+	size_t len;
+	int quote = *s;
+	int rawmode = 0;
+	int need_encoding;
+	int unicode = 0;
+
+	if (isalpha(quote) || quote == '_') {
+		if (quote == 'u' || quote == 'U') {
+			quote = *++s;
+			unicode = 1;
+		}
+		if (quote == 'r' || quote == 'R') {
+			quote = *++s;
+			rawmode = 1;
+		}
+	}
+	if (quote != '\'' && quote != '\"') {
+		PyErr_BadInternalCall();
+		return NULL;
+	}
+	s++;
+	len = strlen(s);
+	if (len > INT_MAX) {
+		PyErr_SetString(PyExc_OverflowError, 
+				"string to parse is too long");
+		return NULL;
+	}
+	if (s[--len] != quote) {
+		PyErr_BadInternalCall();
+		return NULL;
+	}
+	if (len >= 4 && s[0] == quote && s[1] == quote) {
+		s += 2;
+		len -= 2;
+		if (s[--len] != quote || s[--len] != quote) {
+			PyErr_BadInternalCall();
+			return NULL;
+		}
+	}
+#ifdef Py_USING_UNICODE
+	if (unicode || Py_UnicodeFlag) {
+		return decode_unicode(s, len, rawmode, encoding);
+	}
+#endif
+	need_encoding = (encoding != NULL &&
+			 strcmp(encoding, "utf-8") != 0 &&
+			 strcmp(encoding, "iso-8859-1") != 0);
+	if (rawmode || strchr(s, '\\') == NULL) {
+		if (need_encoding) {
+#ifndef Py_USING_UNICODE
+			/* This should not happen - we never see any other
+			   encoding. */
+			Py_FatalError("cannot deal with encodings in this build.");
+#else
+			PyObject* u = PyUnicode_DecodeUTF8(s, len, NULL);
+			if (u == NULL)
+				return NULL;
+			v = PyUnicode_AsEncodedString(u, encoding, NULL);
+			Py_DECREF(u);
+			return v;
+#endif
+		} else {
+			return PyString_FromStringAndSize(s, len);
+		}
+	}
+
+	v = PyString_DecodeEscape(s, len, NULL, unicode,
+				  need_encoding ? encoding : NULL);
+	return v;
+}
+
+/* Build a Python string object out of a STRING atom.  This takes care of
+ * compile-time literal catenation, calling parsestr() on each piece, and
+ * pasting the intermediate results together.
+ */
+static PyObject *
+parsestrplus(struct compiling *c, const node *n)
+{
+	PyObject *v;
+	int i;
+	REQ(CHILD(n, 0), STRING);
+	if ((v = parsestr(STR(CHILD(n, 0)), c->c_encoding)) != NULL) {
+		/* String literal concatenation */
+		for (i = 1; i < NCH(n); i++) {
+			PyObject *s;
+			s = parsestr(STR(CHILD(n, i)), c->c_encoding);
+			if (s == NULL)
+				goto onError;
+			if (PyString_Check(v) && PyString_Check(s)) {
+				PyString_ConcatAndDel(&v, s);
+				if (v == NULL)
+				    goto onError;
+			}
+#ifdef Py_USING_UNICODE
+			else {
+				PyObject *temp;
+				temp = PyUnicode_Concat(v, s);
+				Py_DECREF(s);
+				if (temp == NULL)
+					goto onError;
+				Py_DECREF(v);
+				v = temp;
+			}
+#endif
+		}
+	}
+	return v;
+
+ onError:
+	Py_XDECREF(v);
+	return NULL;
+}
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 3e5f4eb..2d51531 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1,9 +1,9 @@
-
 /* Built-in functions */
 
 #include "Python.h"
 
 #include "node.h"
+#include "code.h"
 #include "compile.h"
 #include "eval.h"
 
diff --git a/Python/ceval.c b/Python/ceval.c
index 38b1328..fdfe83e 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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 @@
 #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 @@
 	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 @@
 
 		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 @@
 		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 @@
 					found = 1;
 					break;
 				}
-				j++;
 			}
 			if (found == 0) {
 				c = PyCell_New(NULL);
@@ -2720,14 +2713,6 @@
 				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;
diff --git a/Python/compile.c b/Python/compile.c
index 99ccf29..10c94e7 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -1,385 +1,379 @@
-/* Compile an expression node to intermediate code */
-
-/* XXX TO DO:
-   XXX add __doc__ attribute == co_doc to code object attributes?
-   XXX   (it's currently the first item of the co_const tuple)
-   XXX Generate simple jump for break/return outside 'try...finally'
-   XXX Allow 'continue' inside finally clause of try-finally
-   XXX New opcode for loading the initial index for a for loop
-   XXX other JAR tricks?
-*/
+/*
+ * This file compiles an abstract syntax tree (AST) into Python bytecode.
+ *
+ * The primary entry point is PyAST_Compile(), which returns a
+ * PyCodeObject.  The compiler makes several passes to build the code
+ * object:
+ *   1. Checks for future statements.  See future.c
+ *   2. Builds a symbol table.  See symtable.c.
+ *   3. Generate code for basic blocks.  See compiler_mod() in this file.
+ *   4. Assemble the basic blocks into final code.  See assemble() in
+ *   this file.  
+ *
+ * Note that compiler_mod() suggests module, but the module ast type
+ * (mod_ty) has cases for expressions and interactive statements.
+ */
 
 #include "Python.h"
 
+#include "Python-ast.h"
 #include "node.h"
-#include "token.h"
-#include "graminit.h"
+#include "ast.h"
+#include "code.h"
 #include "compile.h"
 #include "symtable.h"
 #include "opcode.h"
-#include "structmember.h"
-
-#include <ctype.h>
-
-/* Three symbols from graminit.h are also defined in Python.h, with
-   Py_ prefixes to their names.  Python.h can't include graminit.h
-   (which defines too many confusing symbols), but we can check here
-   that they haven't changed (which is very unlikely, but possible). */
-#if Py_single_input != single_input
-  #error "single_input has changed -- update Py_single_input in Python.h"
-#endif
-#if Py_file_input != file_input
-  #error "file_input has changed -- update Py_file_input in Python.h"
-#endif
-#if Py_eval_input != eval_input
-  #error "eval_input has changed -- update Py_eval_input in Python.h"
-#endif
 
 int Py_OptimizeFlag = 0;
 
-#define OP_DELETE 0
-#define OP_ASSIGN 1
-#define OP_APPLY 2
+/*
+    ISSUES:
 
-#define VAR_LOAD 0
-#define VAR_STORE 1
-#define VAR_DELETE 2
+     character encodings aren't handled
 
-#define DEL_CLOSURE_ERROR \
-"can not delete variable '%.400s' referenced in nested scope"
+     ref leaks in interpreter when press return on empty line
 
-#define DUPLICATE_ARGUMENT \
-"duplicate argument '%s' in function definition"
+     opcode_stack_effect() function should be reviewed since stack depth bugs
+     could be really hard to find later.
 
-#define GLOBAL_AFTER_ASSIGN \
-"name '%.400s' is assigned to before global declaration"
+     Dead code is being generated (i.e. after unconditional jumps).
+*/
 
-#define GLOBAL_AFTER_USE \
-"name '%.400s' is used prior to global declaration"
+#define DEFAULT_BLOCK_SIZE 16
+#define DEFAULT_BLOCKS 8
+#define DEFAULT_CODE_SIZE 128
+#define DEFAULT_LNOTAB_SIZE 16
 
-#define PARAM_GLOBAL \
-"name '%.400s' is a function parameter and declared global"
-
-#define LATE_FUTURE \
-"from __future__ imports must occur at the beginning of the file"
-
-#define ASSIGN_DEBUG \
-"can not assign to __debug__"
-
-#define MANGLE_LEN 256
-
-#define OFF(x) offsetof(PyCodeObject, x)
-
-static PyMemberDef code_memberlist[] = {
-	{"co_argcount",	T_INT,		OFF(co_argcount),	READONLY},
-	{"co_nlocals",	T_INT,		OFF(co_nlocals),	READONLY},
-	{"co_stacksize",T_INT,		OFF(co_stacksize),	READONLY},
-	{"co_flags",	T_INT,		OFF(co_flags),		READONLY},
-	{"co_code",	T_OBJECT,	OFF(co_code),		READONLY},
-	{"co_consts",	T_OBJECT,	OFF(co_consts),		READONLY},
-	{"co_names",	T_OBJECT,	OFF(co_names),		READONLY},
-	{"co_varnames",	T_OBJECT,	OFF(co_varnames),	READONLY},
-	{"co_freevars",	T_OBJECT,	OFF(co_freevars),	READONLY},
-	{"co_cellvars",	T_OBJECT,	OFF(co_cellvars),	READONLY},
-	{"co_filename",	T_OBJECT,	OFF(co_filename),	READONLY},
-	{"co_name",	T_OBJECT,	OFF(co_name),		READONLY},
-	{"co_firstlineno", T_INT,	OFF(co_firstlineno),	READONLY},
-	{"co_lnotab",	T_OBJECT,	OFF(co_lnotab),		READONLY},
-	{NULL}	/* Sentinel */
+struct instr {
+	int i_jabs : 1;
+	int i_jrel : 1;
+	int i_hasarg : 1;
+	unsigned char i_opcode;
+	int i_oparg;
+	struct basicblock_ *i_target; /* target block (if jump instruction) */
+	int i_lineno;
 };
 
-/* Helper for code_new: return a shallow copy of a tuple that is
-   guaranteed to contain exact strings, by converting string subclasses
-   to exact strings and complaining if a non-string is found. */
-static PyObject*
-validate_and_copy_tuple(PyObject *tup)
+typedef struct basicblock_ {
+	/* next block in the list of blocks for a unit (don't confuse with
+	 * b_next) */
+	struct basicblock_ *b_list;
+	/* number of instructions used */
+	int b_iused;
+	/* length of instruction array (b_instr) */
+	int b_ialloc;
+	/* pointer to an array of instructions, initially NULL */
+	struct instr *b_instr;
+	/* If b_next is non-NULL, it is a pointer to the next
+	   block reached by normal control flow. */
+	struct basicblock_ *b_next;
+	/* b_seen is used to perform a DFS of basicblocks. */
+	int b_seen : 1;
+	/* b_return is true if a RETURN_VALUE opcode is inserted. */
+	int b_return : 1;
+	/* depth of stack upon entry of block, computed by stackdepth() */
+	int b_startdepth;
+	/* instruction offset for block, computed by assemble_jump_offsets() */
+        int b_offset;
+} basicblock;
+
+/* fblockinfo tracks the current frame block.
+
+   A frame block is used to handle loops, try/except, and try/finally.
+   It's called a frame block to distinguish it from a basic block in the
+   compiler IR.
+*/
+
+enum fblocktype { LOOP, EXCEPT, FINALLY_TRY, FINALLY_END };
+
+struct fblockinfo {
+        enum fblocktype fb_type;
+	basicblock *fb_block;
+};
+
+/* The following items change on entry and exit of code blocks.
+   They must be saved and restored when returning to a block.
+*/
+struct compiler_unit {
+	PySTEntryObject *u_ste;
+
+	PyObject *u_name;
+	/* The following fields are dicts that map objects to
+	   the index of them in co_XXX.  The index is used as
+	   the argument for opcodes that refer to those collections.
+	*/
+	PyObject *u_consts;    /* all constants */
+	PyObject *u_names;     /* all names */
+	PyObject *u_varnames;  /* local variables */
+	PyObject *u_cellvars;  /* cell variables */
+	PyObject *u_freevars;  /* free variables */
+
+	PyObject *u_private;	/* for private name mangling */
+
+	int u_argcount;    /* number of arguments for block */ 
+	basicblock *u_blocks; /* pointer to list of blocks */
+	basicblock *u_curblock; /* pointer to current block */
+	int u_tmpname;     /* temporary variables for list comps */
+
+	int u_nfblocks;
+	struct fblockinfo u_fblock[CO_MAXBLOCKS];
+
+	int u_firstlineno; /* the first lineno of the block */
+	int u_lineno;      /* the lineno for the current stmt */
+	bool u_lineno_set; /* boolean to indicate whether instr
+			      has been generated with current lineno */
+};
+
+/* This struct captures the global state of a compilation.  
+
+   The u pointer points to the current compilation unit, while units
+   for enclosing blocks are stored in c_stack.  The u and c_stack are
+   managed by compiler_enter_scope() and compiler_exit_scope().
+*/
+
+struct compiler {
+	const char *c_filename;
+	struct symtable *c_st;
+        PyFutureFeatures *c_future; /* pointer to module's __future__ */
+	PyCompilerFlags *c_flags;
+
+	int c_interactive;
+        int c_nestlevel;
+
+        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) */
+};
+
+struct assembler {
+	PyObject *a_bytecode;  /* string containing bytecode */
+	int a_offset;          /* offset into bytecode */
+	int a_nblocks;         /* number of reachable blocks */
+	basicblock **a_postorder; /* list of blocks in dfs postorder */
+	PyObject *a_lnotab;    /* string containing lnotab */
+	int a_lnotab_off;      /* offset into lnotab */
+	int a_lineno;          /* last lineno of emitted instruction */
+	int a_lineno_off;      /* bytecode offset of last lineno */
+};
+
+static int compiler_enter_scope(struct compiler *, identifier, void *, int);
+static void compiler_free(struct compiler *);
+static basicblock *compiler_new_block(struct compiler *);
+static int compiler_next_instr(struct compiler *, basicblock *);
+static int compiler_addop(struct compiler *, int);
+static int compiler_addop_o(struct compiler *, int, PyObject *, PyObject *);
+static int compiler_addop_i(struct compiler *, int, int);
+static int compiler_addop_j(struct compiler *, int, basicblock *, int);
+static void compiler_use_block(struct compiler *, basicblock *);
+static basicblock *compiler_use_new_block(struct compiler *);
+static int compiler_error(struct compiler *, const char *);
+static int compiler_nameop(struct compiler *, identifier, expr_context_ty);
+
+static PyCodeObject *compiler_mod(struct compiler *, mod_ty);
+static int compiler_visit_stmt(struct compiler *, stmt_ty);
+static int compiler_visit_keyword(struct compiler *, keyword_ty);
+static int compiler_visit_expr(struct compiler *, expr_ty);
+static int compiler_augassign(struct compiler *, stmt_ty);
+static int compiler_visit_slice(struct compiler *, slice_ty,
+				expr_context_ty);
+
+static int compiler_push_fblock(struct compiler *, enum fblocktype,
+				basicblock *);
+static void compiler_pop_fblock(struct compiler *, enum fblocktype,
+				basicblock *);
+
+static int inplace_binop(struct compiler *, operator_ty);
+static int expr_constant(expr_ty e);
+
+static PyCodeObject *assemble(struct compiler *, int addNone);
+static PyObject *__doc__;
+
+PyObject *
+_Py_Mangle(PyObject *private, PyObject *ident)
 {
-	PyObject *newtuple;
-	PyObject *item;
-	int i, len;
-
-	len = PyTuple_GET_SIZE(tup);
-	newtuple = PyTuple_New(len);
-	if (newtuple == NULL)
-		return NULL;
-
-	for (i = 0; i < len; i++) {
-		item = PyTuple_GET_ITEM(tup, i);
-		if (PyString_CheckExact(item)) {
-			Py_INCREF(item);
-		}
-		else if (!PyString_Check(item)) {
-			PyErr_Format(
-				PyExc_TypeError,
-				"name tuples must contain only "
-				"strings, not '%.500s'",
-				item->ob_type->tp_name);
-			Py_DECREF(newtuple);
-			return NULL;
-		}
-		else {
-			item = PyString_FromStringAndSize(
-				PyString_AS_STRING(item),
-				PyString_GET_SIZE(item));
-			if (item == NULL) {
-				Py_DECREF(newtuple);
-				return NULL;
-			}
-		}
-		PyTuple_SET_ITEM(newtuple, i, item);
-	}
-
-	return newtuple;
+	/* Name mangling: __private becomes _classname__private.
+	   This is independent from how the name is used. */
+        const char *p, *name = PyString_AsString(ident);
+        char *buffer;
+	size_t nlen, plen;
+	if (private == NULL || name == NULL || name[0] != '_' || name[1] != '_') {
+                Py_INCREF(ident);
+		return ident;
+        }
+        p = PyString_AsString(private);
+	nlen = strlen(name);
+	if (name[nlen-1] == '_' && name[nlen-2] == '_') {
+                Py_INCREF(ident);
+		return ident; /* Don't mangle __whatever__ */
+        }
+	/* Strip leading underscores from class name */
+	while (*p == '_')
+		p++;
+	if (*p == '\0') {
+                Py_INCREF(ident);
+		return ident; /* Don't mangle if class is just underscores */
+        }
+	plen = strlen(p);
+        ident = PyString_FromStringAndSize(NULL, 1 + nlen + plen);
+        if (!ident)
+            return 0;
+	/* ident = "_" + p[:plen] + name # i.e. 1+plen+nlen bytes */
+        buffer = PyString_AS_STRING(ident);
+        buffer[0] = '_';
+	strncpy(buffer+1, p, plen);
+	strcpy(buffer+1+plen, name);
+	return ident;
 }
 
-PyDoc_STRVAR(code_doc,
-"code(argcount, nlocals, stacksize, flags, codestring, constants, names,\n\
-      varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])\n\
-\n\
-Create a code object.  Not for the faint of heart.");
-
-static PyObject *
-code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
+static int
+compiler_init(struct compiler *c)
 {
-	int argcount;
-	int nlocals;
-	int stacksize;
-	int flags;
-	PyObject *co = NULL;
-	PyObject *code;
-	PyObject *consts;
-	PyObject *names, *ournames = NULL;
-	PyObject *varnames, *ourvarnames = NULL;
-	PyObject *freevars = NULL, *ourfreevars = NULL;
-	PyObject *cellvars = NULL, *ourcellvars = NULL;
-	PyObject *filename;
-	PyObject *name;
-	int firstlineno;
-	PyObject *lnotab;
+	memset(c, 0, sizeof(struct compiler));
 
-	if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code",
-			      &argcount, &nlocals, &stacksize, &flags,
-			      &code,
-			      &PyTuple_Type, &consts,
-			      &PyTuple_Type, &names,
-			      &PyTuple_Type, &varnames,
-			      &filename, &name,
-			      &firstlineno, &lnotab,
-			      &PyTuple_Type, &freevars,
-			      &PyTuple_Type, &cellvars))
+	c->c_stack = PyList_New(0);
+	if (!c->c_stack)
+		return 0;
+
+	return 1;
+}
+
+PyCodeObject *
+PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags)
+{
+	struct compiler c;
+	PyCodeObject *co = NULL;
+        PyCompilerFlags local_flags;
+        int merged;
+
+        if (!__doc__) {
+            __doc__ = PyString_InternFromString("__doc__");
+            if (!__doc__)
+                goto error;
+        }
+
+	if (!compiler_init(&c))
+		goto error;
+	c.c_filename = filename;
+	c.c_future = PyFuture_FromAST(mod, filename);
+	if (c.c_future == NULL)
+		goto error;
+	if (!flags) {
+            local_flags.cf_flags = 0;
+            flags = &local_flags;
+        }
+        merged = c.c_future->ff_features | flags->cf_flags;
+        c.c_future->ff_features = merged;
+        flags->cf_flags = merged;
+        c.c_flags = flags;
+        c.c_nestlevel = 0;
+
+	c.c_st = PySymtable_Build(mod, filename, c.c_future);
+	if (c.c_st == NULL) {
+		if (!PyErr_Occurred())
+			PyErr_SetString(PyExc_SystemError, "no symtable");
+		goto error;
+	}
+
+	/* XXX initialize to NULL for now, need to handle */
+	c.c_encoding = NULL;
+
+	co = compiler_mod(&c, mod);
+
+ error:
+	compiler_free(&c);
+	return co;
+}
+
+PyCodeObject *
+PyNode_Compile(struct _node *n, const char *filename)
+{
+	PyCodeObject *co;
+	mod_ty mod = PyAST_FromNode(n, NULL, filename);
+	if (!mod)
 		return NULL;
-
-	if (argcount < 0) {
-		PyErr_SetString(
-			PyExc_ValueError, 
-			"code: argcount must not be negative");
-		goto cleanup;
-	}
-
-	if (nlocals < 0) {
-		PyErr_SetString(
-			PyExc_ValueError, 
-			"code: nlocals must not be negative");
-		goto cleanup;
-	}
-
-	ournames = validate_and_copy_tuple(names);
-	if (ournames == NULL)
-		goto cleanup;
-	ourvarnames = validate_and_copy_tuple(varnames);
-	if (ourvarnames == NULL)
-		goto cleanup;
-	if (freevars)
-		ourfreevars = validate_and_copy_tuple(freevars);
-	else
-		ourfreevars = PyTuple_New(0);
-	if (ourfreevars == NULL)
-		goto cleanup;
-	if (cellvars)
-		ourcellvars = validate_and_copy_tuple(cellvars);
-	else
-		ourcellvars = PyTuple_New(0);
-	if (ourcellvars == NULL)
-		goto cleanup;
-
-	co = (PyObject *) PyCode_New(argcount, nlocals, stacksize, flags,
-				     code, consts, ournames, ourvarnames,
-				     ourfreevars, ourcellvars, filename,
-				     name, firstlineno, lnotab);
-  cleanup:
-	Py_XDECREF(ournames);
-	Py_XDECREF(ourvarnames);
-	Py_XDECREF(ourfreevars);
-	Py_XDECREF(ourcellvars);
+	co = PyAST_Compile(mod, filename, NULL);
+	free_mod(mod);
 	return co;
 }
 
 static void
-code_dealloc(PyCodeObject *co)
+compiler_free(struct compiler *c)
 {
-	Py_XDECREF(co->co_code);
-	Py_XDECREF(co->co_consts);
-	Py_XDECREF(co->co_names);
-	Py_XDECREF(co->co_varnames);
-	Py_XDECREF(co->co_freevars);
-	Py_XDECREF(co->co_cellvars);
-	Py_XDECREF(co->co_filename);
-	Py_XDECREF(co->co_name);
-	Py_XDECREF(co->co_lnotab);
-	PyObject_DEL(co);
+	if (c->c_st)
+		PySymtable_Free(c->c_st);
+	if (c->c_future)
+		PyObject_Free((void *)c->c_future);
+	Py_DECREF(c->c_stack);
 }
 
 static PyObject *
-code_repr(PyCodeObject *co)
+list2dict(PyObject *list)
 {
-	char buf[500];
-	int lineno = -1;
-	char *filename = "???";
-	char *name = "???";
+	int i, n;
+	PyObject *v, *k, *dict = PyDict_New();
 
-	if (co->co_firstlineno != 0)
-		lineno = co->co_firstlineno;
-	if (co->co_filename && PyString_Check(co->co_filename))
-		filename = PyString_AS_STRING(co->co_filename);
-	if (co->co_name && PyString_Check(co->co_name))
-		name = PyString_AS_STRING(co->co_name);
-	PyOS_snprintf(buf, sizeof(buf),
-		      "<code object %.100s at %p, file \"%.300s\", line %d>",
-		      name, co, filename, lineno);
-	return PyString_FromString(buf);
-}
-
-static int
-code_compare(PyCodeObject *co, PyCodeObject *cp)
-{
-	int cmp;
-	cmp = PyObject_Compare(co->co_name, cp->co_name);
-	if (cmp) return cmp;
-	cmp = co->co_argcount - cp->co_argcount;
-	if (cmp) return (cmp<0)?-1:1;
-	cmp = co->co_nlocals - cp->co_nlocals;
-	if (cmp) return (cmp<0)?-1:1;
-	cmp = co->co_flags - cp->co_flags;
-	if (cmp) return (cmp<0)?-1:1;
-	cmp = co->co_firstlineno - cp->co_firstlineno;
-	if (cmp) return (cmp<0)?-1:1;
-	cmp = PyObject_Compare(co->co_code, cp->co_code);
-	if (cmp) return cmp;
-	cmp = PyObject_Compare(co->co_consts, cp->co_consts);
-	if (cmp) return cmp;
-	cmp = PyObject_Compare(co->co_names, cp->co_names);
-	if (cmp) return cmp;
-	cmp = PyObject_Compare(co->co_varnames, cp->co_varnames);
-	if (cmp) return cmp;
-	cmp = PyObject_Compare(co->co_freevars, cp->co_freevars);
-	if (cmp) return cmp;
-	cmp = PyObject_Compare(co->co_cellvars, cp->co_cellvars);
-	return cmp;
-}
-
-static long
-code_hash(PyCodeObject *co)
-{
-	long h, h0, h1, h2, h3, h4, h5, h6;
-	h0 = PyObject_Hash(co->co_name);
-	if (h0 == -1) return -1;
-	h1 = PyObject_Hash(co->co_code);
-	if (h1 == -1) return -1;
-	h2 = PyObject_Hash(co->co_consts);
-	if (h2 == -1) return -1;
-	h3 = PyObject_Hash(co->co_names);
-	if (h3 == -1) return -1;
-	h4 = PyObject_Hash(co->co_varnames);
-	if (h4 == -1) return -1;
-	h5 = PyObject_Hash(co->co_freevars);
-	if (h5 == -1) return -1;
-	h6 = PyObject_Hash(co->co_cellvars);
-	if (h6 == -1) return -1;
-	h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
-		co->co_argcount ^ co->co_nlocals ^ co->co_flags;
-	if (h == -1) h = -2;
-	return h;
-}
-
-/* XXX code objects need to participate in GC? */
-
-PyTypeObject PyCode_Type = {
-	PyObject_HEAD_INIT(&PyType_Type)
-	0,
-	"code",
-	sizeof(PyCodeObject),
-	0,
-	(destructor)code_dealloc, 	/* tp_dealloc */
-	0,				/* tp_print */
-	0, 				/* tp_getattr */
-	0,				/* tp_setattr */
-	(cmpfunc)code_compare, 		/* tp_compare */
-	(reprfunc)code_repr,		/* tp_repr */
-	0,				/* tp_as_number */
-	0,				/* tp_as_sequence */
-	0,				/* tp_as_mapping */
-	(hashfunc)code_hash, 		/* tp_hash */
-	0,				/* tp_call */
-	0,				/* tp_str */
-	PyObject_GenericGetAttr,	/* tp_getattro */
-	0,				/* tp_setattro */
-	0,				/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,		/* tp_flags */
-	code_doc,			/* tp_doc */
-	0,				/* tp_traverse */
-	0,				/* tp_clear */
-	0,				/* tp_richcompare */
-	0,				/* tp_weaklistoffset */
-	0,				/* tp_iter */
-	0,				/* tp_iternext */
-	0,				/* tp_methods */
-	code_memberlist,		/* tp_members */
-	0,				/* tp_getset */
-	0,				/* tp_base */
-	0,				/* tp_dict */
-	0,				/* tp_descr_get */
-	0,				/* tp_descr_set */
-	0,				/* tp_dictoffset */
-	0,				/* tp_init */
-	0,				/* tp_alloc */
-	code_new,			/* tp_new */
-};
-
-#define NAME_CHARS \
-	"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
-
-/* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */
-
-static int
-all_name_chars(unsigned char *s)
-{
-	static char ok_name_char[256];
-	static unsigned char *name_chars = (unsigned char *)NAME_CHARS;
-
-	if (ok_name_char[*name_chars] == 0) {
-		unsigned char *p;
-		for (p = name_chars; *p; p++)
-			ok_name_char[*p] = 1;
-	}
-	while (*s) {
-		if (ok_name_char[*s++] == 0)
-			return 0;
-	}
-	return 1;
-}
-
-static void
-intern_strings(PyObject *tuple)
-{
-	int i;
-
-	for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
-		PyObject *v = PyTuple_GET_ITEM(tuple, i);
-		if (v == NULL || !PyString_CheckExact(v)) {
-			Py_FatalError("non-string found in code slot");
+	n = PyList_Size(list);
+	for (i = 0; i < n; i++) {
+		v = PyInt_FromLong(i);
+		if (!v) {
+			Py_DECREF(dict);
+			return NULL;
 		}
-		PyString_InternInPlace(&PyTuple_GET_ITEM(tuple, i));
+                k = PyList_GET_ITEM(list, i);
+                k = Py_BuildValue("(OO)", k, k->ob_type);
+		if (k == NULL || PyDict_SetItem(dict, k, v) < 0) {
+			Py_XDECREF(k);
+			Py_DECREF(v);
+			Py_DECREF(dict);
+			return NULL;
+		}
+		Py_DECREF(v);
 	}
+	return dict;
+}
+
+/* Return new dict containing names from src that match scope(s).
+
+   src is a symbol table dictionary.  If the scope of a name matches
+   either scope_type or flag is set, insert it into the new dict.  The
+   values are integers, starting at offset and increasing by one for
+   each key.
+*/
+
+static PyObject *
+dictbytype(PyObject *src, int scope_type, int flag, int offset)
+{
+	int pos = 0, i = offset, scope;
+	PyObject *k, *v, *dest = PyDict_New();
+
+        assert(offset >= 0);
+        if (dest == NULL)
+            return NULL;
+
+	while (PyDict_Next(src, &pos, &k, &v)) {
+            /* XXX this should probably be a macro in symtable.h */
+            assert(PyInt_Check(v));
+            scope = (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK;
+
+            if (scope == scope_type || PyInt_AS_LONG(v) & flag) {
+                PyObject *tuple, *item = PyInt_FromLong(i);
+                if (item == NULL) {
+			Py_DECREF(dest);
+			return NULL;
+		}
+                i++;
+                tuple = Py_BuildValue("(OO)", k, k->ob_type);
+		if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) {
+			Py_DECREF(item);
+			Py_DECREF(dest);
+			Py_XDECREF(tuple);
+			return NULL;
+		}
+		Py_DECREF(item);
+		Py_DECREF(tuple);
+            }
+	}
+	return dest;
 }
 
 /* Begin: Peephole optimizations ----------------------------------------- */
@@ -974,96 +968,2746 @@
 
 /* End: Peephole optimizations ----------------------------------------- */
 
-PyCodeObject *
-PyCode_New(int argcount, int nlocals, int stacksize, int flags,
-	   PyObject *code, PyObject *consts, PyObject *names,
-	   PyObject *varnames, PyObject *freevars, PyObject *cellvars,
-	   PyObject *filename, PyObject *name, int firstlineno,
-	   PyObject *lnotab) 
+/*
+
+Leave this debugging code for just a little longer.
+
+static void
+compiler_display_symbols(PyObject *name, PyObject *symbols)
+{
+	PyObject *key, *value;
+	int flags, pos = 0;
+
+	fprintf(stderr, "block %s\n", PyString_AS_STRING(name));
+	while (PyDict_Next(symbols, &pos, &key, &value)) {
+		flags = PyInt_AsLong(value);
+		fprintf(stderr, "var %s:", PyString_AS_STRING(key));
+		if (flags & DEF_GLOBAL)
+			fprintf(stderr, " declared_global");
+		if (flags & DEF_LOCAL)
+			fprintf(stderr, " local");
+		if (flags & DEF_PARAM)
+			fprintf(stderr, " param");
+		if (flags & DEF_STAR)
+			fprintf(stderr, " stararg");
+		if (flags & DEF_DOUBLESTAR)
+			fprintf(stderr, " starstar");
+		if (flags & DEF_INTUPLE)
+			fprintf(stderr, " tuple");
+		if (flags & DEF_FREE)
+			fprintf(stderr, " free");
+		if (flags & DEF_FREE_GLOBAL)
+			fprintf(stderr, " global");
+		if (flags & DEF_FREE_CLASS)
+			fprintf(stderr, " free/class");
+		if (flags & DEF_IMPORT)
+			fprintf(stderr, " import");
+		fprintf(stderr, "\n");
+	}
+	fprintf(stderr, "\n");
+}
+*/
+
+static void
+compiler_unit_check(struct compiler_unit *u)
+{
+	basicblock *block;
+	for (block = u->u_blocks; block != NULL; block = block->b_list) {
+		assert(block != (void *)0xcbcbcbcb);
+		assert(block != (void *)0xfbfbfbfb);
+		assert(block != (void *)0xdbdbdbdb);
+		if (block->b_instr != NULL) {
+			assert(block->b_ialloc > 0);
+			assert(block->b_iused > 0);
+			assert(block->b_ialloc >= block->b_iused);
+		}
+		else {
+			assert (block->b_iused == 0);
+			assert (block->b_ialloc == 0);
+		}
+	}
+}
+
+static void
+compiler_unit_free(struct compiler_unit *u)
+{
+	basicblock *b, *next;
+
+	compiler_unit_check(u);
+	b = u->u_blocks;
+	while (b != NULL) {
+		if (b->b_instr)
+			PyObject_Free((void *)b->b_instr);
+		next = b->b_list;
+		PyObject_Free((void *)b);
+		b = next;
+	}
+	Py_XDECREF(u->u_ste);
+	Py_XDECREF(u->u_name);
+	Py_XDECREF(u->u_consts);
+	Py_XDECREF(u->u_names);
+	Py_XDECREF(u->u_varnames);
+	Py_XDECREF(u->u_freevars);
+	Py_XDECREF(u->u_cellvars);
+	Py_XDECREF(u->u_private);
+	PyObject_Free(u);
+}
+
+static int
+compiler_enter_scope(struct compiler *c, identifier name, void *key,
+		     int lineno)
+{
+	struct compiler_unit *u;
+
+	u = PyObject_Malloc(sizeof(struct compiler_unit));
+        memset(u, 0, sizeof(struct compiler_unit));
+	u->u_argcount = 0;
+	u->u_ste = PySymtable_Lookup(c->c_st, key);
+	if (!u->u_ste) {
+                compiler_unit_free(u);
+		return 0;
+	}
+	Py_INCREF(name);
+	u->u_name = name;
+	u->u_varnames = list2dict(u->u_ste->ste_varnames);
+	u->u_cellvars = dictbytype(u->u_ste->ste_symbols, CELL, 0, 0);
+	u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS,
+                                   PyDict_Size(u->u_cellvars));
+
+	u->u_blocks = NULL;
+	u->u_tmpname = 0;
+	u->u_nfblocks = 0;
+	u->u_firstlineno = lineno;
+	u->u_lineno = 0;
+	u->u_lineno_set = false;
+	u->u_consts = PyDict_New();
+	if (!u->u_consts) {
+                compiler_unit_free(u);
+		return 0;
+	}
+	u->u_names = PyDict_New();
+	if (!u->u_names) {
+                compiler_unit_free(u);
+		return 0;
+	}
+
+        u->u_private = NULL;
+
+	/* Push the old compiler_unit on the stack. */
+	if (c->u) {
+		PyObject *wrapper = PyCObject_FromVoidPtr(c->u, NULL);
+		if (PyList_Append(c->c_stack, wrapper) < 0) {
+                        compiler_unit_free(u);
+			return 0;
+		}
+		Py_DECREF(wrapper);
+                u->u_private = c->u->u_private;
+                Py_XINCREF(u->u_private);
+	}
+	c->u = u;
+
+        c->c_nestlevel++;
+	if (compiler_use_new_block(c) < 0)
+		return 0;
+
+	return 1;
+}
+
+static int
+compiler_exit_scope(struct compiler *c)
+{
+	int n;
+	PyObject *wrapper;
+
+        c->c_nestlevel--;
+	compiler_unit_free(c->u);
+	/* Restore c->u to the parent unit. */
+	n = PyList_GET_SIZE(c->c_stack) - 1;
+	if (n >= 0) {
+		wrapper = PyList_GET_ITEM(c->c_stack, n);
+		c->u = (struct compiler_unit *)PyCObject_AsVoidPtr(wrapper);
+		if (PySequence_DelItem(c->c_stack, n) < 0)
+			return 0;
+		compiler_unit_check(c->u);
+	}
+	else
+		c->u = NULL;
+
+	return 1; /* XXX void? */
+}
+
+/* Allocate a new block and return a pointer to it.
+   Returns NULL on error.
+*/
+
+static basicblock *
+compiler_new_block(struct compiler *c)
+{
+	basicblock *b;
+	struct compiler_unit *u;
+
+	u = c->u;
+	b = (basicblock *)PyObject_Malloc(sizeof(basicblock));
+	if (b == NULL)
+		return NULL;
+	memset((void *)b, 0, sizeof(basicblock));
+	assert (b->b_next == NULL);
+	b->b_list = u->u_blocks;
+	u->u_blocks = b;
+	return b;
+}
+
+static void
+compiler_use_block(struct compiler *c, basicblock *block)
+{
+        assert (block != NULL);
+	c->u->u_curblock = block;
+}
+
+static basicblock *
+compiler_use_new_block(struct compiler *c)
+{
+	basicblock *block = compiler_new_block(c);
+	if (block == NULL)
+		return NULL;
+	c->u->u_curblock = block;
+	return block;
+}
+
+static basicblock *
+compiler_next_block(struct compiler *c)
+{
+	basicblock *block = compiler_new_block(c);
+	if (block == NULL)
+		return NULL;
+	c->u->u_curblock->b_next = block;
+	c->u->u_curblock = block;
+	return block;
+}
+
+static basicblock *
+compiler_use_next_block(struct compiler *c, basicblock *block)
+{
+	assert(block != NULL);
+	c->u->u_curblock->b_next = block;
+	c->u->u_curblock = block;
+	return block;
+}
+
+/* Returns the offset of the next instruction in the current block's
+   b_instr array.  Resizes the b_instr as necessary.
+   Returns -1 on failure.
+ */
+
+static int
+compiler_next_instr(struct compiler *c, basicblock *b)
+{
+	assert(b != NULL);
+        if (b->b_instr == NULL) {
+		b->b_instr = PyObject_Malloc(sizeof(struct instr) *
+					     DEFAULT_BLOCK_SIZE);
+		if (b->b_instr == NULL) {
+			PyErr_NoMemory();
+			return -1;
+		}
+		b->b_ialloc = DEFAULT_BLOCK_SIZE;
+		memset((char *)b->b_instr, 0,
+		       sizeof(struct instr) * DEFAULT_BLOCK_SIZE);
+        }
+	else if (b->b_iused == b->b_ialloc) {
+		size_t oldsize, newsize;
+		oldsize = b->b_ialloc * sizeof(struct instr);
+		newsize = oldsize << 1;
+		if (newsize == 0) {
+			PyErr_NoMemory();
+			return -1;
+		}
+		b->b_ialloc <<= 1;
+		b->b_instr = PyObject_Realloc((void *)b->b_instr, newsize);
+		if (b->b_instr == NULL)
+			return -1;
+		memset((char *)b->b_instr + oldsize, 0, newsize - oldsize);
+	}
+	return b->b_iused++;
+}
+
+static void
+compiler_set_lineno(struct compiler *c, int off)
+{
+	basicblock *b;
+	if (c->u->u_lineno_set)
+		return;
+	c->u->u_lineno_set = true;
+	b = c->u->u_curblock;
+ 	b->b_instr[off].i_lineno = c->u->u_lineno;
+}
+
+static int
+opcode_stack_effect(int opcode, int oparg)
+{
+	switch (opcode) {
+		case POP_TOP:
+			return -1;
+		case ROT_TWO:
+		case ROT_THREE:
+			return 0;
+		case DUP_TOP:
+			return 1;
+		case ROT_FOUR:
+			return 0;
+
+		case UNARY_POSITIVE:
+		case UNARY_NEGATIVE:
+		case UNARY_NOT:
+		case UNARY_CONVERT:
+		case UNARY_INVERT:
+			return 0;
+
+		case BINARY_POWER:
+		case BINARY_MULTIPLY:
+		case BINARY_DIVIDE:
+		case BINARY_MODULO:
+		case BINARY_ADD:
+		case BINARY_SUBTRACT:
+		case BINARY_SUBSCR:
+		case BINARY_FLOOR_DIVIDE:
+		case BINARY_TRUE_DIVIDE:
+			return -1;
+		case INPLACE_FLOOR_DIVIDE:
+		case INPLACE_TRUE_DIVIDE:
+			return -1;
+
+		case SLICE+0:
+			return 1;
+		case SLICE+1:
+			return 0;
+		case SLICE+2:
+			return 0;
+		case SLICE+3:
+			return -1;
+
+		case STORE_SLICE+0:
+			return -2;
+		case STORE_SLICE+1:
+			return -3;
+		case STORE_SLICE+2:
+			return -3;
+		case STORE_SLICE+3:
+			return -4;
+
+		case DELETE_SLICE+0:
+			return -1;
+		case DELETE_SLICE+1:
+			return -2;
+		case DELETE_SLICE+2:
+			return -2;
+		case DELETE_SLICE+3:
+			return -3;
+
+		case INPLACE_ADD:
+		case INPLACE_SUBTRACT:
+		case INPLACE_MULTIPLY:
+		case INPLACE_DIVIDE:
+		case INPLACE_MODULO:
+			return -1;
+		case STORE_SUBSCR:
+			return -3;
+		case DELETE_SUBSCR:
+			return -2;
+
+		case BINARY_LSHIFT:
+		case BINARY_RSHIFT:
+		case BINARY_AND:
+		case BINARY_XOR:
+		case BINARY_OR:
+			return -1;
+		case INPLACE_POWER:
+			return -1;
+		case GET_ITER:
+			return 0;
+
+		case PRINT_EXPR:
+			return -1;
+		case PRINT_ITEM:
+			return -1;
+		case PRINT_NEWLINE:
+			return 0;
+		case PRINT_ITEM_TO:
+			return -2;
+		case PRINT_NEWLINE_TO:
+			return -1;
+		case INPLACE_LSHIFT:
+		case INPLACE_RSHIFT:
+		case INPLACE_AND:
+		case INPLACE_XOR:
+		case INPLACE_OR:
+			return -1;
+		case BREAK_LOOP:
+			return 0;
+
+		case LOAD_LOCALS:
+			return 1;
+		case RETURN_VALUE:
+			return -1;
+		case IMPORT_STAR:
+			return -1;
+		case EXEC_STMT:
+			return -3;
+		case YIELD_VALUE:
+			return 0;
+
+		case POP_BLOCK:
+			return 0;
+		case END_FINALLY:
+			return -1; /* or -2 or -3 if exception occurred */
+		case BUILD_CLASS:
+			return -2;
+
+		case STORE_NAME:
+			return -1;
+		case DELETE_NAME:
+			return 0;
+		case UNPACK_SEQUENCE:
+			return oparg-1;
+		case FOR_ITER:
+			return 1;
+
+		case STORE_ATTR:
+			return -2;
+		case DELETE_ATTR:
+			return -1;
+		case STORE_GLOBAL:
+			return -1;
+		case DELETE_GLOBAL:
+			return 0;
+		case DUP_TOPX:
+			return oparg;
+		case LOAD_CONST:
+			return 1;
+		case LOAD_NAME:
+			return 1;
+		case BUILD_TUPLE:
+		case BUILD_LIST:
+			return 1-oparg;
+		case BUILD_MAP:
+			return 1;
+		case LOAD_ATTR:
+			return 0;
+		case COMPARE_OP:
+			return -1;
+		case IMPORT_NAME:
+			return 0;
+		case IMPORT_FROM:
+			return 1;
+
+		case JUMP_FORWARD:
+		case JUMP_IF_FALSE:
+		case JUMP_IF_TRUE:
+		case JUMP_ABSOLUTE:
+			return 0;
+
+		case LOAD_GLOBAL:
+			return 1;
+
+		case CONTINUE_LOOP:
+			return 0;
+		case SETUP_LOOP:
+			return 0;
+		case SETUP_EXCEPT:
+		case SETUP_FINALLY:
+			return 3; /* actually pushed by an exception */
+
+		case LOAD_FAST:
+			return 1;
+		case STORE_FAST:
+			return -1;
+		case DELETE_FAST:
+			return 0;
+
+		case RAISE_VARARGS:
+			return -oparg;
+#define NARGS(o) (((o) % 256) + 2*((o) / 256))
+		case CALL_FUNCTION:
+			return -NARGS(oparg);
+		case CALL_FUNCTION_VAR:
+		case CALL_FUNCTION_KW:
+			return -NARGS(oparg)-1;
+		case CALL_FUNCTION_VAR_KW:
+			return -NARGS(oparg)-2;
+#undef NARGS
+		case MAKE_FUNCTION:
+			return -oparg;
+		case BUILD_SLICE:
+			if (oparg == 3)
+				return -2;
+			else
+				return -1;
+
+		case MAKE_CLOSURE:
+			return -oparg;
+		case LOAD_CLOSURE:
+			return 1;
+		case LOAD_DEREF:
+			return 1;
+		case STORE_DEREF:
+			return -1;
+		default:
+			fprintf(stderr, "opcode = %d\n", opcode);
+			Py_FatalError("opcode_stack_effect()");
+
+	}
+	return 0; /* not reachable */
+}
+
+/* Add an opcode with no argument.
+   Returns 0 on failure, 1 on success.
+*/
+
+static int
+compiler_addop(struct compiler *c, int opcode)
+{
+	basicblock *b;
+	struct instr *i;
+	int off;
+	off = compiler_next_instr(c, c->u->u_curblock);
+	if (off < 0)
+		return 0;
+	b = c->u->u_curblock;
+	i = &b->b_instr[off];
+	i->i_opcode = opcode;
+	i->i_hasarg = 0;
+	if (opcode == RETURN_VALUE)
+		b->b_return = 1;
+	compiler_set_lineno(c, off);
+	return 1;
+}
+
+static int
+compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o)
+{
+	PyObject *t, *v;
+	int arg;
+
+        /* necessary to make sure types aren't coerced (e.g., int and long) */
+        /* XXX should use: t = PyTuple_Pack(2, o, o->ob_type); */
+        t = Py_BuildValue("(OO)", o, o->ob_type);
+        if (t == NULL)
+            return -1;
+
+	v = PyDict_GetItem(dict, t);
+	if (!v) {
+		arg = PyDict_Size(dict);
+		v = PyInt_FromLong(arg);
+		if (!v) {
+			Py_DECREF(t);
+			return -1;
+                }
+		if (PyDict_SetItem(dict, t, v) < 0) {
+			Py_DECREF(t);
+			Py_DECREF(v);
+			return -1;
+		}
+		Py_DECREF(v);
+	}
+	else
+		arg = PyInt_AsLong(v);
+	Py_DECREF(t);
+        return arg;
+}
+
+static int
+compiler_addop_o(struct compiler *c, int opcode, PyObject *dict,
+		     PyObject *o)
+{
+    int arg = compiler_add_o(c, dict, o);
+    if (arg < 0)
+        return 0;
+    return compiler_addop_i(c, opcode, arg);
+}
+
+static int
+compiler_addop_name(struct compiler *c, int opcode, PyObject *dict,
+                    PyObject *o)
+{
+    int arg;
+    PyObject *mangled = _Py_Mangle(c->u->u_private, o);
+    if (!mangled)
+        return 0;
+    arg = compiler_add_o(c, dict, mangled);
+    Py_DECREF(mangled);
+    if (arg < 0)
+        return 0;
+    return compiler_addop_i(c, opcode, arg);
+}
+
+/* Add an opcode with an integer argument.
+   Returns 0 on failure, 1 on success.
+*/
+
+static int
+compiler_addop_i(struct compiler *c, int opcode, int oparg)
+{
+	struct instr *i;
+	int off;
+	off = compiler_next_instr(c, c->u->u_curblock);
+	if (off < 0)
+		return 0;
+	i = &c->u->u_curblock->b_instr[off];
+	i->i_opcode = opcode;
+	i->i_oparg = oparg;
+	i->i_hasarg = 1;
+	compiler_set_lineno(c, off);
+	return 1;
+}
+
+static int
+compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
+{
+	struct instr *i;
+	int off;
+
+	assert(b != NULL);
+	off = compiler_next_instr(c, c->u->u_curblock);
+	if (off < 0)
+		return 0;
+	compiler_set_lineno(c, off);
+	i = &c->u->u_curblock->b_instr[off];
+	i->i_opcode = opcode;
+	i->i_target = b;
+	i->i_hasarg = 1;
+	if (absolute)
+		i->i_jabs = 1;
+	else
+		i->i_jrel = 1;
+	return 1;
+}
+
+/* The distinction between NEW_BLOCK and NEXT_BLOCK is subtle.  (I'd
+   like to find better names.)  NEW_BLOCK() creates a new block and sets
+   it as the current block.  NEXT_BLOCK() also creates an implicit jump
+   from the current block to the new block.
+*/
+
+/* XXX The returns inside these macros make it impossible to decref
+   objects created in the local function.
+*/
+
+
+#define NEW_BLOCK(C) { \
+        if (compiler_use_new_block((C)) == NULL) \
+	        return 0; \
+}
+
+#define NEXT_BLOCK(C) { \
+        if (compiler_next_block((C)) == NULL) \
+	        return 0; \
+}
+
+#define ADDOP(C, OP) { \
+	if (!compiler_addop((C), (OP))) \
+		return 0; \
+}
+
+#define ADDOP_O(C, OP, O, TYPE) { \
+	if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) \
+		return 0; \
+}
+
+#define ADDOP_NAME(C, OP, O, TYPE) { \
+	if (!compiler_addop_name((C), (OP), (C)->u->u_ ## TYPE, (O))) \
+		return 0; \
+}
+
+#define ADDOP_I(C, OP, O) { \
+	if (!compiler_addop_i((C), (OP), (O))) \
+		return 0; \
+}
+
+#define ADDOP_JABS(C, OP, O) { \
+	if (!compiler_addop_j((C), (OP), (O), 1)) \
+		return 0; \
+}
+
+#define ADDOP_JREL(C, OP, O) { \
+	if (!compiler_addop_j((C), (OP), (O), 0)) \
+		return 0; \
+}
+
+/* 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 VISIT(C, TYPE, V) {\
+	if (!compiler_visit_ ## TYPE((C), (V))) \
+		return 0; \
+}
+
+#define VISIT_SLICE(C, V, CTX) {\
+	if (!compiler_visit_slice((C), (V), (CTX))) \
+		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_isdocstring(stmt_ty s)
+{
+    if (s->kind != Expr_kind)
+        return 0;
+    return s->v.Expr.value->kind == Str_kind;
+}
+
+/* Compile a sequence of statements, checking for a docstring. */
+
+static int
+compiler_body(struct compiler *c, asdl_seq *stmts)
+{
+	int i = 0;
+	stmt_ty st;
+
+	if (!asdl_seq_LEN(stmts))
+		return 1;
+	st = asdl_seq_GET(stmts, 0);
+	if (compiler_isdocstring(st)) {
+		i = 1;
+		VISIT(c, expr, st->v.Expr.value);
+		if (!compiler_nameop(c, __doc__, Store))
+			return 0;
+	}
+        for (; i < asdl_seq_LEN(stmts); i++)
+            VISIT(c, stmt, asdl_seq_GET(stmts, i));
+	return 1;
+}
+
+static PyCodeObject *
+compiler_mod(struct compiler *c, mod_ty mod)
 {
 	PyCodeObject *co;
-	int i;
-	/* Check argument types */
-	if (argcount < 0 || nlocals < 0 ||
-	    code == NULL ||
-	    consts == NULL || !PyTuple_Check(consts) ||
-	    names == NULL || !PyTuple_Check(names) ||
-	    varnames == NULL || !PyTuple_Check(varnames) ||
-	    freevars == NULL || !PyTuple_Check(freevars) ||
-	    cellvars == NULL || !PyTuple_Check(cellvars) ||
-	    name == NULL || !PyString_Check(name) ||
-	    filename == NULL || !PyString_Check(filename) ||
-	    lnotab == NULL || !PyString_Check(lnotab) ||
-	    !PyObject_CheckReadBuffer(code)) {
-		PyErr_BadInternalCall();
+        int addNone = 1;
+	static PyObject *module;
+	if (!module) {
+		module = PyString_FromString("<module>");
+		if (!module)
+			return NULL;
+	}
+	if (!compiler_enter_scope(c, module, mod, 1))
 		return NULL;
+	switch (mod->kind) {
+	case Module_kind: 
+		if (!compiler_body(c, mod->v.Module.body))
+			return 0;
+		break;
+	case Interactive_kind:
+		c->c_interactive = 1;
+		VISIT_SEQ(c, stmt, mod->v.Interactive.body);
+		break;
+	case Expression_kind:
+		VISIT(c, expr, mod->v.Expression.body);
+                addNone = 0;
+		break;
+	case Suite_kind:
+		assert(0);      /* XXX: what should we do here? */
+		VISIT_SEQ(c, stmt, mod->v.Suite.body);
+		break;
+        default:
+            assert(0);
 	}
-	intern_strings(names);
-	intern_strings(varnames);
-	intern_strings(freevars);
-	intern_strings(cellvars);
-	/* Intern selected string constants */
-	for (i = PyTuple_Size(consts); --i >= 0; ) {
-		PyObject *v = PyTuple_GetItem(consts, i);
-		if (!PyString_Check(v))
-			continue;
-		if (!all_name_chars((unsigned char *)PyString_AS_STRING(v)))
-			continue;
-		PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i));
-	}
-	co = PyObject_NEW(PyCodeObject, &PyCode_Type);
-	if (co != NULL) {
-		co->co_argcount = argcount;
-		co->co_nlocals = nlocals;
-		co->co_stacksize = stacksize;
-		co->co_flags = flags;
-		Py_INCREF(code);
-		co->co_code = code;
-		Py_INCREF(consts);
-		co->co_consts = consts;
-		Py_INCREF(names);
-		co->co_names = names;
-		Py_INCREF(varnames);
-		co->co_varnames = varnames;
-		Py_INCREF(freevars);
-		co->co_freevars = freevars;
-		Py_INCREF(cellvars);
-		co->co_cellvars = cellvars;
-		Py_INCREF(filename);
-		co->co_filename = filename;
-		Py_INCREF(name);
-		co->co_name = name;
-		co->co_firstlineno = firstlineno;
-		Py_INCREF(lnotab);
-		co->co_lnotab = lnotab;
-		if (PyTuple_GET_SIZE(freevars) == 0 &&
-		    PyTuple_GET_SIZE(cellvars) == 0)
-		    co->co_flags |= CO_NOFREE;
-	}
+	co = assemble(c, addNone);
+	compiler_exit_scope(c);
 	return co;
 }
 
-
-/* Data structure used internally */
-
-/* The compiler uses two passes to generate bytecodes.  The first pass
-   builds the symbol table.  The second pass generates the bytecode.
-
-   The first pass uses a single symtable struct.  The second pass uses
-   a compiling struct for each code block.  The compiling structs
-   share a reference to the symtable.
-
-   The two passes communicate via symtable_load_symbols() and via
-   is_local() and is_global().  The former initializes several slots
-   in the compiling struct: c_varnames, c_locals, c_nlocals,
-   c_argcount, c_globals, and c_flags.
+/* The test for LOCAL must come before the test for FREE in order to
+   handle classes where name is both local and free.  The local var is
+   a method and the free var is a free var referenced within a method.
 */
 
-/* All about c_lnotab.
+static int
+get_ref_type(struct compiler *c, PyObject *name)
+{
+	int scope = PyST_GetScope(c->u->u_ste, name);
+        if (scope == 0) {
+            char buf[350];
+            PyOS_snprintf(buf, sizeof(buf),
+                          "unknown scope for %.100s in %.100s(%s) in %s\n"
+                          "symbols: %s\nlocals: %s\nglobals: %s\n",
+                          PyString_AS_STRING(name), 
+                          PyString_AS_STRING(c->u->u_name), 
+                          PyObject_REPR(c->u->u_ste->ste_id),
+                          c->c_filename,
+                          PyObject_REPR(c->u->u_ste->ste_symbols),
+                          PyObject_REPR(c->u->u_varnames),
+                          PyObject_REPR(c->u->u_names)
+		);
+            Py_FatalError(buf);
+        }
 
-c_lnotab is an array of unsigned bytes disguised as a Python string.  Since
-version 2.3, SET_LINENO opcodes are never generated and bytecode offsets are
-mapped to source code line #s via c_lnotab instead.
+        return scope;
+}
+
+static int
+compiler_lookup_arg(PyObject *dict, PyObject *name)
+{
+    PyObject *k, *v;
+    k = Py_BuildValue("(OO)", name, name->ob_type);
+    if (k == NULL)
+        return -1;
+    v = PyDict_GetItem(dict, k);
+    if (v == NULL)
+        return -1;
+    return PyInt_AS_LONG(v);
+}
+
+static int
+compiler_make_closure(struct compiler *c, PyCodeObject *co, int args)
+{
+	int i, free = PyCode_GetNumFree(co);
+	if (free == 0) {
+            ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts);
+            ADDOP_I(c, MAKE_FUNCTION, args);
+            return 1;
+        }
+	for (i = 0; i < free; ++i) {
+		/* Bypass com_addop_varname because it will generate
+		   LOAD_DEREF but LOAD_CLOSURE is needed. 
+		*/
+		PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
+		int arg, reftype;
+
+		/* Special case: If a class contains a method with a
+		   free variable that has the same name as a method,
+		   the name will be considered free *and* local in the
+		   class.  It should be handled by the closure, as
+		   well as by the normal name loookup logic.
+		*/
+		reftype = get_ref_type(c, name);
+		if (reftype == CELL)
+			arg = compiler_lookup_arg(c->u->u_cellvars, name);
+		else /* (reftype == FREE) */
+			arg = compiler_lookup_arg(c->u->u_freevars, name);
+		if (arg == -1) {
+			printf("lookup %s in %s %d %d\n"
+				"freevars of %s: %s\n",
+				PyObject_REPR(name), 
+				PyString_AS_STRING(c->u->u_name), 
+				reftype, arg,
+				PyString_AS_STRING(co->co_name),
+				PyObject_REPR(co->co_freevars));
+			Py_FatalError("compiler_make_closure()");
+		}
+		ADDOP_I(c, LOAD_CLOSURE, arg);
+	}
+        ADDOP_I(c, BUILD_TUPLE, free);
+	ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts);
+        ADDOP_I(c, MAKE_CLOSURE, args);
+        return 1;
+}
+
+static int
+compiler_decorators(struct compiler *c, asdl_seq* decos)
+{
+	int i;
+
+	if (!decos)
+		return 1;
+
+	for (i = 0; i < asdl_seq_LEN(decos); i++) {
+		VISIT(c, expr, asdl_seq_GET(decos, i));
+	}
+	return 1;
+}
+
+static int
+compiler_arguments(struct compiler *c, arguments_ty args)
+{
+	int i;
+	int n = asdl_seq_LEN(args->args);
+	/* Correctly handle nested argument lists */
+	for (i = 0; i < n; i++) {
+		expr_ty arg = asdl_seq_GET(args->args, i);
+		if (arg->kind == Tuple_kind) {
+			PyObject *id = PyString_FromFormat(".%d", i);
+			if (id == NULL) {
+				return 0;
+			}
+			if (!compiler_nameop(c, id, Load)) {
+				Py_DECREF(id);
+				return 0;
+			}
+			Py_DECREF(id);
+                	VISIT(c, expr, arg);
+		}
+	}
+	return 1;
+}
+
+static int
+compiler_function(struct compiler *c, stmt_ty s)
+{
+	PyCodeObject *co;
+        PyObject *first_const = Py_None;
+	arguments_ty args = s->v.FunctionDef.args;
+	asdl_seq* decos = s->v.FunctionDef.decorators;
+        stmt_ty st;
+	int i, n, docstring;
+
+	assert(s->kind == FunctionDef_kind);
+
+	if (!compiler_decorators(c, decos))
+		return 0;
+	if (args->defaults)
+		VISIT_SEQ(c, expr, args->defaults);
+	if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s,
+				  s->lineno))
+		return 0;
+
+        st = asdl_seq_GET(s->v.FunctionDef.body, 0);
+        docstring = compiler_isdocstring(st);
+        if (docstring)
+            first_const = st->v.Expr.value->v.Str.s;
+        if (compiler_add_o(c, c->u->u_consts, first_const) < 0)
+            return 0;
+
+        /* unpack nested arguments */
+	compiler_arguments(c, args);
+
+	c->u->u_argcount = asdl_seq_LEN(args->args);
+	n = asdl_seq_LEN(s->v.FunctionDef.body);
+        /* if there was a docstring, we need to skip the first statement */
+	for (i = docstring; i < n; i++) {
+		stmt_ty s2 = asdl_seq_GET(s->v.FunctionDef.body, i);
+		if (i == 0 && s2->kind == Expr_kind &&
+		    s2->v.Expr.value->kind == Str_kind)
+			continue;
+		VISIT(c, stmt, s2);
+	}
+	co = assemble(c, 1);
+	if (co == NULL)
+		return 0;
+	compiler_exit_scope(c);
+
+        compiler_make_closure(c, co, asdl_seq_LEN(args->defaults));
+
+	for (i = 0; i < asdl_seq_LEN(decos); i++) {
+		ADDOP_I(c, CALL_FUNCTION, 1);
+	}
+
+	return compiler_nameop(c, s->v.FunctionDef.name, Store);
+}
+
+static int
+compiler_class(struct compiler *c, stmt_ty s)
+{
+	int n;
+	PyCodeObject *co;
+        PyObject *str;
+	/* push class name on stack, needed by BUILD_CLASS */
+	ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts);
+	/* push the tuple of base classes on the stack */
+	n = asdl_seq_LEN(s->v.ClassDef.bases);
+	if (n > 0)
+		VISIT_SEQ(c, expr, s->v.ClassDef.bases);
+	ADDOP_I(c, BUILD_TUPLE, n);
+	if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s,
+				  s->lineno))
+		return 0;
+        c->u->u_private = s->v.ClassDef.name;
+        Py_INCREF(c->u->u_private);
+        str = PyString_InternFromString("__name__");
+	if (!str || !compiler_nameop(c, str, Load)) {
+		Py_XDECREF(str);
+		return 0;
+        }
+        
+        Py_DECREF(str);
+        str = PyString_InternFromString("__module__");
+	if (!str || !compiler_nameop(c, str, Store)) {
+		Py_XDECREF(str);
+		return 0;
+        }
+        Py_DECREF(str);
+
+	if (!compiler_body(c, s->v.ClassDef.body))
+		return 0;
+
+	ADDOP(c, LOAD_LOCALS);
+	ADDOP(c, RETURN_VALUE);
+	co = assemble(c, 1);
+	if (co == NULL)
+		return 0;
+	compiler_exit_scope(c);
+
+        compiler_make_closure(c, co, 0);
+	ADDOP_I(c, CALL_FUNCTION, 0);
+	ADDOP(c, BUILD_CLASS);
+	if (!compiler_nameop(c, s->v.ClassDef.name, Store))
+		return 0;
+	return 1;
+}
+
+static int
+compiler_lambda(struct compiler *c, expr_ty e)
+{
+	PyCodeObject *co;
+	identifier name;
+	arguments_ty args = e->v.Lambda.args;
+	assert(e->kind == Lambda_kind);
+
+	name = PyString_InternFromString("lambda");
+	if (!name)
+		return 0;
+
+	if (args->defaults)
+		VISIT_SEQ(c, expr, args->defaults);
+	if (!compiler_enter_scope(c, name, (void *)e, e->lineno))
+		return 0;
+		
+        /* unpack nested arguments */
+	compiler_arguments(c, args);
+	
+	c->u->u_argcount = asdl_seq_LEN(args->args);
+	VISIT(c, expr, e->v.Lambda.body);
+	ADDOP(c, RETURN_VALUE);
+	co = assemble(c, 1);
+	if (co == NULL)
+		return 0;
+	compiler_exit_scope(c);
+
+        compiler_make_closure(c, co, asdl_seq_LEN(args->defaults));
+	Py_DECREF(name);
+
+	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++) {
+		expr_ty e = (expr_ty)asdl_seq_GET(s->v.Print.values, i);
+		if (dest) {
+			ADDOP(c, DUP_TOP);
+			VISIT(c, expr, e);
+			ADDOP(c, ROT_TWO);
+			ADDOP(c, PRINT_ITEM_TO);
+		}
+		else {
+			VISIT(c, expr, e);
+			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_if(struct compiler *c, stmt_ty s)
+{
+	basicblock *end, *next;
+
+	assert(s->kind == If_kind);
+	end = compiler_new_block(c);
+	if (end == NULL)
+		return 0;
+        next = compiler_new_block(c);
+        if (next == NULL)
+            return 0;
+        VISIT(c, expr, s->v.If.test);
+        ADDOP_JREL(c, JUMP_IF_FALSE, next);
+        ADDOP(c, POP_TOP);
+        VISIT_SEQ(c, stmt, s->v.If.body);
+        ADDOP_JREL(c, JUMP_FORWARD, end);
+        compiler_use_next_block(c, next);
+        ADDOP(c, POP_TOP);
+        if (s->v.If.orelse)
+            VISIT_SEQ(c, stmt, s->v.If.orelse);
+	compiler_use_next_block(c, end);
+	return 1;
+}
+
+static int
+compiler_for(struct compiler *c, stmt_ty s)
+{
+	basicblock *start, *cleanup, *end;
+
+	start = compiler_new_block(c);
+	cleanup = compiler_new_block(c);
+	end = compiler_new_block(c);
+	if (start == NULL || end == NULL || cleanup == NULL)
+		return 0;
+	ADDOP_JREL(c, SETUP_LOOP, end);
+	if (!compiler_push_fblock(c, LOOP, start))
+		return 0;
+	VISIT(c, expr, s->v.For.iter);
+	ADDOP(c, GET_ITER);
+	compiler_use_next_block(c, start);
+	ADDOP_JREL(c, FOR_ITER, cleanup);
+	VISIT(c, expr, s->v.For.target);
+	VISIT_SEQ(c, stmt, s->v.For.body);
+	ADDOP_JABS(c, JUMP_ABSOLUTE, start);
+	compiler_use_next_block(c, cleanup);
+	ADDOP(c, POP_BLOCK);
+	compiler_pop_fblock(c, LOOP, start);
+	VISIT_SEQ(c, stmt, s->v.For.orelse);
+	compiler_use_next_block(c, end);
+	return 1;
+}
+
+static int
+compiler_while(struct compiler *c, stmt_ty s)
+{
+	basicblock *loop, *orelse, *end, *anchor = NULL;
+	int constant = expr_constant(s->v.While.test);
+
+	if (constant == 0)
+		return 1;
+	loop = compiler_new_block(c);
+	end = compiler_new_block(c);
+	if (constant == -1) {
+		anchor = compiler_new_block(c);
+		if (anchor == NULL)
+			return 0;
+	}
+	if (loop == NULL || end == NULL)
+		return 0;
+	if (s->v.While.orelse) {
+		orelse = compiler_new_block(c);
+		if (orelse == NULL)
+			return 0;
+	}
+	else
+		orelse = NULL;
+
+	ADDOP_JREL(c, SETUP_LOOP, end);
+	compiler_use_next_block(c, loop);
+	if (!compiler_push_fblock(c, LOOP, loop))
+		return 0;
+	if (constant == -1) {
+		VISIT(c, expr, s->v.While.test);
+		ADDOP_JREL(c, JUMP_IF_FALSE, anchor);
+		ADDOP(c, POP_TOP);
+	}
+	VISIT_SEQ(c, stmt, s->v.While.body);
+	ADDOP_JABS(c, JUMP_ABSOLUTE, loop);
+
+	/* XXX should the two POP instructions be in a separate block
+	   if there is no else clause ?
+	*/
+
+	if (constant == -1) {
+		compiler_use_next_block(c, anchor);
+		ADDOP(c, POP_TOP);
+		ADDOP(c, POP_BLOCK);
+	}
+	compiler_pop_fblock(c, LOOP, loop);
+	if (orelse != NULL)
+		VISIT_SEQ(c, stmt, s->v.While.orelse);
+	compiler_use_next_block(c, end);
+
+	return 1;
+}
+
+static int
+compiler_continue(struct compiler *c)
+{
+	static const char LOOP_ERROR_MSG[] = "'continue' not properly in loop";
+	int i;
+
+	if (!c->u->u_nfblocks)
+		return compiler_error(c, LOOP_ERROR_MSG);
+	i = c->u->u_nfblocks - 1;
+	switch (c->u->u_fblock[i].fb_type) {
+	case LOOP:
+		ADDOP_JABS(c, JUMP_ABSOLUTE, c->u->u_fblock[i].fb_block);
+		break;
+	case EXCEPT:
+	case FINALLY_TRY:
+		while (--i >= 0 && c->u->u_fblock[i].fb_type != LOOP)
+			;
+		if (i == -1)
+			return compiler_error(c, LOOP_ERROR_MSG);
+		ADDOP_JABS(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block);
+		break;
+	case FINALLY_END:
+	        return compiler_error(c,
+			"'continue' not supported inside 'finally' clause");
+	}
+
+	return 1;
+}
+
+/* Code generated for "try: <body> finally: <finalbody>" is as follows:
+   
+		SETUP_FINALLY	L
+		<code for body>
+		POP_BLOCK
+		LOAD_CONST	<None>
+	L:	<code for finalbody>
+		END_FINALLY
+   
+   The special instructions use the block stack.  Each block
+   stack entry contains the instruction that created it (here
+   SETUP_FINALLY), the level of the value stack at the time the
+   block stack entry was created, and a label (here L).
+   
+   SETUP_FINALLY:
+	Pushes the current value stack level and the label
+	onto the block stack.
+   POP_BLOCK:
+	Pops en entry from the block stack, and pops the value
+	stack until its level is the same as indicated on the
+	block stack.  (The label is ignored.)
+   END_FINALLY:
+	Pops a variable number of entries from the *value* stack
+	and re-raises the exception they specify.  The number of
+	entries popped depends on the (pseudo) exception type.
+   
+   The block stack is unwound when an exception is raised:
+   when a SETUP_FINALLY entry is found, the exception is pushed
+   onto the value stack (and the exception condition is cleared),
+   and the interpreter jumps to the label gotten from the block
+   stack.
+*/
+
+static int
+compiler_try_finally(struct compiler *c, stmt_ty s)
+{
+	basicblock *body, *end;
+	body = compiler_new_block(c);
+	end = compiler_new_block(c);
+	if (body == NULL || end == NULL)
+		return 0;
+
+	ADDOP_JREL(c, SETUP_FINALLY, end);
+	compiler_use_next_block(c, body);
+	if (!compiler_push_fblock(c, FINALLY_TRY, body))
+		return 0;
+	VISIT_SEQ(c, stmt, s->v.TryFinally.body);
+	ADDOP(c, POP_BLOCK);
+	compiler_pop_fblock(c, FINALLY_TRY, body);
+
+	ADDOP_O(c, LOAD_CONST, Py_None, consts);
+	compiler_use_next_block(c, end);
+	if (!compiler_push_fblock(c, FINALLY_END, end))
+		return 0;
+	VISIT_SEQ(c, stmt, s->v.TryFinally.finalbody);
+	ADDOP(c, END_FINALLY);
+	compiler_pop_fblock(c, FINALLY_END, end);
+
+	return 1;
+}
+
+/*
+   Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...":
+   (The contents of the value stack is shown in [], with the top
+   at the right; 'tb' is trace-back info, 'val' the exception's
+   associated value, and 'exc' the exception.)
+   
+   Value stack		Label	Instruction	Argument
+   []				SETUP_EXCEPT	L1
+   []				<code for S>
+   []				POP_BLOCK
+   []				JUMP_FORWARD	L0
+   
+   [tb, val, exc]	L1:	DUP				)
+   [tb, val, exc, exc]		<evaluate E1>			)
+   [tb, val, exc, exc, E1]	COMPARE_OP	EXC_MATCH	) only if E1
+   [tb, val, exc, 1-or-0]	JUMP_IF_FALSE	L2		)
+   [tb, val, exc, 1]		POP				)
+   [tb, val, exc]		POP
+   [tb, val]			<assign to V1>	(or POP if no V1)
+   [tb]				POP
+   []				<code for S1>
+   				JUMP_FORWARD	L0
+   
+   [tb, val, exc, 0]	L2:	POP
+   [tb, val, exc]		DUP
+   .............................etc.......................
+
+   [tb, val, exc, 0]	Ln+1:	POP
+   [tb, val, exc]	   	END_FINALLY	# re-raise exception
+   
+   []			L0:	<next statement>
+   
+   Of course, parts are not generated if Vi or Ei is not present.
+*/
+static int
+compiler_try_except(struct compiler *c, stmt_ty s)
+{
+        basicblock *body, *orelse, *except, *end;
+	int i, n;
+
+	body = compiler_new_block(c);
+	except = compiler_new_block(c);
+	orelse = compiler_new_block(c);
+	end = compiler_new_block(c);
+	if (body == NULL || except == NULL || orelse == NULL || end == NULL)
+		return 0;
+	ADDOP_JREL(c, SETUP_EXCEPT, except);
+	compiler_use_next_block(c, body);
+	if (!compiler_push_fblock(c, EXCEPT, body))
+		return 0;
+	VISIT_SEQ(c, stmt, s->v.TryExcept.body);
+	ADDOP(c, POP_BLOCK);
+	compiler_pop_fblock(c, EXCEPT, body);
+	ADDOP_JREL(c, JUMP_FORWARD, orelse);
+	n = asdl_seq_LEN(s->v.TryExcept.handlers);
+	compiler_use_next_block(c, except);
+	for (i = 0; i < n; i++) {
+		excepthandler_ty handler = asdl_seq_GET(
+						s->v.TryExcept.handlers, i);
+		if (!handler->type && i < n-1)
+		    return compiler_error(c, "default 'except:' must be last");
+		except = compiler_new_block(c);
+		if (except == NULL)
+			return 0;
+		if (handler->type) {
+			ADDOP(c, DUP_TOP);
+			VISIT(c, expr, handler->type);
+			ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH);
+			ADDOP_JREL(c, JUMP_IF_FALSE, except);
+			ADDOP(c, POP_TOP);
+		}
+		ADDOP(c, POP_TOP);
+		if (handler->name) {
+			VISIT(c, expr, handler->name);
+		}
+		else {
+			ADDOP(c, POP_TOP);
+		}
+		ADDOP(c, POP_TOP);
+		VISIT_SEQ(c, stmt, handler->body);
+		ADDOP_JREL(c, JUMP_FORWARD, end);
+		compiler_use_next_block(c, except);
+		if (handler->type)
+			ADDOP(c, POP_TOP);
+	}
+	ADDOP(c, END_FINALLY);
+	compiler_use_next_block(c, orelse);
+	VISIT_SEQ(c, stmt, s->v.TryExcept.orelse);
+	compiler_use_next_block(c, end);
+	return 1;
+}
+
+static int
+compiler_import_as(struct compiler *c, identifier name, identifier asname)
+{
+	/* The IMPORT_NAME opcode was already generated.  This function
+	   merely needs to bind the result to a name.
+
+	   If there is a dot in name, we need to split it and emit a 
+	   LOAD_ATTR for each name.
+	*/
+	const char *src = PyString_AS_STRING(name);
+	const char *dot = strchr(src, '.');
+	if (dot) {
+		/* Consume the base module name to get the first attribute */
+		src = dot + 1;
+		while (dot) {
+			/* NB src is only defined when dot != NULL */
+			dot = strchr(src, '.');
+			PyObject *attr = PyString_FromStringAndSize(src, 
+					    dot ? dot - src : strlen(src));
+			ADDOP_O(c, LOAD_ATTR, attr, names);
+			src = dot + 1;
+		}
+	}
+	return compiler_nameop(c, asname, Store);
+}
+
+static int
+compiler_import(struct compiler *c, stmt_ty s)
+{
+	/* The Import node stores a module name like a.b.c as a single
+	   string.  This is convenient for all cases except
+	     import a.b.c as d
+	   where we need to parse that string to extract the individual
+	   module names.  
+	   XXX Perhaps change the representation to make this case simpler?
+	 */
+	int i, n = asdl_seq_LEN(s->v.Import.names);
+	for (i = 0; i < n; i++) {
+		alias_ty alias = asdl_seq_GET(s->v.Import.names, i);
+		int r;
+
+		ADDOP_O(c, LOAD_CONST, Py_None, consts);
+		ADDOP_NAME(c, IMPORT_NAME, alias->name, names);
+
+		if (alias->asname) {
+			return compiler_import_as(c, 
+						  alias->name, alias->asname);
+                }
+                else {
+			identifier tmp = alias->name;
+			const char *base = PyString_AS_STRING(alias->name);
+			char *dot = strchr(base, '.');
+			if (dot)
+				tmp = PyString_FromStringAndSize(base, 
+								 dot - base);
+			r = compiler_nameop(c, tmp, Store);
+			if (dot) {
+				Py_DECREF(tmp);
+			}
+			if (!r)
+				return r;
+		}
+	}
+	return 1;
+}
+
+static int
+compiler_from_import(struct compiler *c, stmt_ty s)
+{
+	int i, n = asdl_seq_LEN(s->v.ImportFrom.names);
+	int star = 0;
+
+	PyObject *names = PyTuple_New(n);
+	if (!names)
+		return 0;
+
+	/* build up the names */
+	for (i = 0; i < n; i++) {
+		alias_ty alias = asdl_seq_GET(s->v.ImportFrom.names, i);
+		Py_INCREF(alias->name);
+		PyTuple_SET_ITEM(names, i, alias->name);
+	}
+
+	if (s->lineno > c->c_future->ff_lineno) {
+		if (!strcmp(PyString_AS_STRING(s->v.ImportFrom.module),
+			    "__future__")) {
+			Py_DECREF(names);
+			return compiler_error(c, 
+				      "from __future__ imports must occur "
+                                      "at the beginning of the file");
+
+		}
+	}
+
+	ADDOP_O(c, LOAD_CONST, names, consts);
+	ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names);
+	for (i = 0; i < n; i++) {
+		alias_ty alias = asdl_seq_GET(s->v.ImportFrom.names, i);
+		identifier store_name;
+
+		if (i == 0 && *PyString_AS_STRING(alias->name) == '*') {
+			assert(n == 1);
+			ADDOP(c, IMPORT_STAR);
+			star = 1;
+			break;
+		}
+		    
+		ADDOP_NAME(c, IMPORT_FROM, alias->name, names);
+		store_name = alias->name;
+		if (alias->asname)
+			store_name = alias->asname;
+
+		if (!compiler_nameop(c, store_name, Store)) {
+			Py_DECREF(names);
+			return 0;
+		}
+	}
+	if (!star) 
+		/* remove imported module */
+		ADDOP(c, POP_TOP);
+	return 1;
+}
+
+static int
+compiler_assert(struct compiler *c, stmt_ty s)
+{
+	static PyObject *assertion_error = NULL;
+	basicblock *end;
+
+	if (Py_OptimizeFlag)
+		return 1;
+	if (assertion_error == NULL) {
+		assertion_error = PyString_FromString("AssertionError");
+		if (assertion_error == NULL)
+			return 0;
+	}
+	VISIT(c, expr, s->v.Assert.test);
+	end = compiler_new_block(c);
+	if (end == NULL)
+		return 0;
+	ADDOP_JREL(c, JUMP_IF_TRUE, end);
+	ADDOP(c, POP_TOP);
+	ADDOP_O(c, LOAD_GLOBAL, assertion_error, names);
+	if (s->v.Assert.msg) {
+		VISIT(c, expr, s->v.Assert.msg);
+		ADDOP_I(c, RAISE_VARARGS, 2);
+	}
+	else {
+		ADDOP_I(c, RAISE_VARARGS, 1);
+	}
+	compiler_use_block(c, end);
+	ADDOP(c, POP_TOP);
+	return 1;
+}
+
+static int
+compiler_visit_stmt(struct compiler *c, stmt_ty s)
+{
+	int i, n;
+
+	c->u->u_lineno = s->lineno;
+	c->u->u_lineno_set = false;
+	switch (s->kind) {
+        case FunctionDef_kind:
+		return compiler_function(c, s);
+        case ClassDef_kind:
+		return compiler_class(c, s);
+        case Return_kind:
+		if (c->u->u_ste->ste_type != FunctionBlock)
+			return compiler_error(c, "'return' outside function");
+		if (s->v.Return.value) {
+			if (c->u->u_ste->ste_generator) {
+				return compiler_error(c,
+				    "'return' with argument inside generator");
+			}
+			VISIT(c, expr, s->v.Return.value);
+		}
+		else
+			ADDOP_O(c, LOAD_CONST, Py_None, consts);
+		ADDOP(c, RETURN_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,
+			      (expr_ty)asdl_seq_GET(s->v.Assign.targets, i));
+		}
+		break;
+        case AugAssign_kind:
+		return compiler_augassign(c, s);
+        case Print_kind:
+		return compiler_print(c, s);
+        case For_kind:
+		return compiler_for(c, s);
+        case While_kind:
+		return compiler_while(c, s);
+        case If_kind:
+		return compiler_if(c, s);
+        case Raise_kind:
+		n = 0;
+		if (s->v.Raise.type) {
+			VISIT(c, expr, s->v.Raise.type);
+			n++;
+			if (s->v.Raise.inst) {
+				VISIT(c, expr, s->v.Raise.inst);
+				n++;
+				if (s->v.Raise.tback) {
+					VISIT(c, expr, s->v.Raise.tback);
+					n++;
+				}
+			}
+		}
+		ADDOP_I(c, RAISE_VARARGS, n);
+		break;
+        case TryExcept_kind:
+		return compiler_try_except(c, s);
+        case TryFinally_kind:
+		return compiler_try_finally(c, s);
+        case Assert_kind:
+		return compiler_assert(c, s);
+        case Import_kind:
+		return compiler_import(c, s);
+        case ImportFrom_kind:
+		return compiler_from_import(c, s);
+        case Exec_kind:
+		VISIT(c, expr, s->v.Exec.body);
+		if (s->v.Exec.globals) {
+			VISIT(c, expr, s->v.Exec.globals);
+			if (s->v.Exec.locals) {
+				VISIT(c, expr, s->v.Exec.locals);
+			} else {
+				ADDOP(c, DUP_TOP);
+			}
+		} else {
+			ADDOP_O(c, LOAD_CONST, Py_None, consts);
+			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 && c->c_nestlevel <= 1) {
+			ADDOP(c, PRINT_EXPR);
+		}
+		else {
+			ADDOP(c, POP_TOP);
+		}
+		break;
+        case Pass_kind:
+		break;
+        case Break_kind:
+		if (!c->u->u_nfblocks)
+			return compiler_error(c, "'break' outside loop");
+		ADDOP(c, BREAK_LOOP);
+		break;
+        case Continue_kind:
+		return compiler_continue(c);
+	}
+	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;
+	}
+	return 0;
+}
+
+static int
+binop(struct compiler *c, 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 && c->c_flags->cf_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;
+	}
+	return 0;
+}
+
+static int
+cmpop(cmpop_ty op)
+{
+	switch (op) {
+	case Eq:
+		return PyCmp_EQ;
+	case NotEq:
+		return PyCmp_NE;
+	case Lt:
+		return PyCmp_LT;
+	case LtE:
+		return PyCmp_LE;
+	case Gt:
+		return PyCmp_GT;
+	case GtE:
+		return PyCmp_GE;
+	case Is:
+		return PyCmp_IS;
+	case IsNot:
+		return PyCmp_IS_NOT;
+	case In:
+		return PyCmp_IN;
+	case NotIn:
+		return PyCmp_NOT_IN;
+	}
+	return PyCmp_BAD;
+}
+
+static int
+inplace_binop(struct compiler *c, operator_ty op)
+{
+	switch (op) {
+	case Add:
+		return INPLACE_ADD;
+	case Sub:
+		return INPLACE_SUBTRACT;
+	case Mult:
+		return INPLACE_MULTIPLY;
+	case Div:
+		if (c->c_flags && c->c_flags->cf_flags & CO_FUTURE_DIVISION)
+			return INPLACE_TRUE_DIVIDE;
+		else
+			return INPLACE_DIVIDE;
+	case Mod:
+		return INPLACE_MODULO;
+	case Pow:
+		return INPLACE_POWER;
+	case LShift:
+		return INPLACE_LSHIFT;
+	case RShift:
+		return INPLACE_RSHIFT;
+	case BitOr:
+		return INPLACE_OR;
+	case BitXor:
+		return INPLACE_XOR;
+	case BitAnd:
+		return INPLACE_AND;
+	case FloorDiv:
+		return INPLACE_FLOOR_DIVIDE;
+	}
+	assert(0);
+	return 0;
+}
+
+static int
+compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
+{
+	int op, scope;
+	enum { OP_FAST, OP_GLOBAL, OP_DEREF, OP_NAME } optype;
+
+        PyObject *dict = c->u->u_names;
+	/* XXX AugStore isn't used anywhere! */
+
+	/* First check for assignment to __debug__. Param? */
+	if ((ctx == Store || ctx == AugStore || ctx == Del)
+	    && !strcmp(PyString_AS_STRING(name), "__debug__")) {
+		return compiler_error(c, "can not assign to __debug__");
+	}
+
+	op = 0;
+	optype = OP_NAME;
+	scope = PyST_GetScope(c->u->u_ste, name);
+	switch (scope) {
+	case FREE:
+                dict = c->u->u_freevars;
+		optype = OP_DEREF;
+		break;
+	case CELL:
+                dict = c->u->u_cellvars;
+		optype = OP_DEREF;
+		break;
+	case LOCAL:
+		if (c->u->u_ste->ste_type == FunctionBlock)
+			optype = OP_FAST;
+		break;
+	case GLOBAL_IMPLICIT:
+		if (!c->u->u_ste->ste_unoptimized)
+			optype = OP_GLOBAL;
+		break;
+	case GLOBAL_EXPLICIT:
+		optype = OP_GLOBAL;
+		break;
+	}
+
+	/* XXX Leave assert here, but handle __doc__ and the like better */
+	assert(scope || PyString_AS_STRING(name)[0] == '_');
+
+	switch (optype) {
+	case OP_DEREF:
+		switch (ctx) {
+		case Load: op = LOAD_DEREF; break;
+		case Store: op = STORE_DEREF; break;
+		case AugLoad:
+		case AugStore:
+			break;
+		case Del:
+			PyErr_Format(PyExc_SyntaxError,
+				     "can not delete variable '%s' referenced "
+				     "in nested scope",
+				     PyString_AS_STRING(name));
+			return 0;
+			break;
+		case Param:
+			assert(0); /* impossible */
+		}
+		break;
+	case OP_FAST:
+		switch (ctx) {
+		case Load: op = LOAD_FAST; break;
+		case Store: op = STORE_FAST; break;
+		case Del: op = DELETE_FAST; break;
+		case AugLoad:
+		case AugStore:
+			break;
+		case Param:
+			assert(0); /* impossible */
+		}
+		ADDOP_O(c, op, name, varnames);
+		return 1;
+	case OP_GLOBAL:
+		switch (ctx) {
+		case Load: op = LOAD_GLOBAL; break;
+		case Store: op = STORE_GLOBAL; break;
+		case Del: op = DELETE_GLOBAL; break;
+		case AugLoad:
+		case AugStore:
+			break;
+		case Param:
+			assert(0); /* impossible */
+		}
+		break;
+	case OP_NAME:
+		switch (ctx) {
+		case Load: op = LOAD_NAME; break;
+		case Store: op = STORE_NAME; break;
+		case Del: op = DELETE_NAME; break;
+		case AugLoad:
+		case AugStore:
+			break;
+		case Param:
+			assert(0); /* impossible */
+		}
+		break;
+	}
+
+	assert(op);
+	return compiler_addop_name(c, op, dict, name);
+}
+
+static int
+compiler_boolop(struct compiler *c, expr_ty e)
+{
+	basicblock *end;
+	int jumpi, i, n;
+	asdl_seq *s;
+
+	assert(e->kind == BoolOp_kind);
+	if (e->v.BoolOp.op == And)
+		jumpi = JUMP_IF_FALSE;
+	else
+		jumpi = JUMP_IF_TRUE;
+	end = compiler_new_block(c);
+	if (end < 0)
+		return 0;
+	s = e->v.BoolOp.values;
+	n = asdl_seq_LEN(s) - 1;
+	for (i = 0; i < n; ++i) {
+		VISIT(c, expr, asdl_seq_GET(s, i));
+		ADDOP_JREL(c, jumpi, end);
+		ADDOP(c, POP_TOP)
+	}
+	VISIT(c, expr, asdl_seq_GET(s, n));
+	compiler_use_next_block(c, end);
+	return 1;
+}
+
+static int
+compiler_list(struct compiler *c, expr_ty e)
+{
+	int n = asdl_seq_LEN(e->v.List.elts);
+	if (e->v.List.ctx == Store) {
+		ADDOP_I(c, UNPACK_SEQUENCE, n);
+	}
+	VISIT_SEQ(c, expr, e->v.List.elts);
+	if (e->v.List.ctx == Load) {
+		ADDOP_I(c, BUILD_LIST, n);
+	}
+	return 1;
+}
+
+static int
+compiler_tuple(struct compiler *c, expr_ty e)
+{
+	int n = asdl_seq_LEN(e->v.Tuple.elts);
+	if (e->v.Tuple.ctx == Store) {
+		ADDOP_I(c, UNPACK_SEQUENCE, n);
+	}
+	VISIT_SEQ(c, expr, e->v.Tuple.elts);
+	if (e->v.Tuple.ctx == Load) {
+		ADDOP_I(c, BUILD_TUPLE, n);
+	}
+	return 1;
+}
+
+static int
+compiler_compare(struct compiler *c, expr_ty e)
+{
+	int i, n;
+        basicblock *cleanup = NULL;
+
+	/* XXX the logic can be cleaned up for 1 or multiple comparisons */
+	VISIT(c, expr, e->v.Compare.left);
+	n = asdl_seq_LEN(e->v.Compare.ops);
+	assert(n > 0);
+	if (n > 1) {
+		cleanup = compiler_new_block(c);
+                if (cleanup == NULL)
+                    return 0;
+		VISIT(c, expr, asdl_seq_GET(e->v.Compare.comparators, 0));
+	}
+	for (i = 1; i < n; i++) {
+		ADDOP(c, DUP_TOP);
+		ADDOP(c, ROT_THREE);
+		/* XXX We're casting a void* to cmpop_ty in the next stmt. */
+		ADDOP_I(c, COMPARE_OP,
+			cmpop((cmpop_ty)asdl_seq_GET(e->v.Compare.ops, i - 1)));
+		ADDOP_JREL(c, JUMP_IF_FALSE, cleanup);
+		NEXT_BLOCK(c);
+		ADDOP(c, POP_TOP);
+		if (i < (n - 1))
+		    VISIT(c, expr, asdl_seq_GET(e->v.Compare.comparators, i));
+	}
+	VISIT(c, expr, asdl_seq_GET(e->v.Compare.comparators, n - 1));
+	ADDOP_I(c, COMPARE_OP,
+		/* XXX We're casting a void* to cmpop_ty in the next stmt. */
+	       cmpop((cmpop_ty)asdl_seq_GET(e->v.Compare.ops, n - 1)));
+	if (n > 1) {
+		basicblock *end = compiler_new_block(c);
+                if (end == NULL)
+                    return 0;
+		ADDOP_JREL(c, JUMP_FORWARD, end);
+		compiler_use_next_block(c, cleanup);
+		ADDOP(c, ROT_TWO);
+		ADDOP(c, POP_TOP);
+		compiler_use_next_block(c, end);
+	}
+	return 1;
+}
+
+static int
+compiler_call(struct compiler *c, expr_ty e)
+{
+	int n, code = 0;
+
+	VISIT(c, expr, e->v.Call.func);
+	n = asdl_seq_LEN(e->v.Call.args);
+	VISIT_SEQ(c, expr, e->v.Call.args);
+	if (e->v.Call.keywords) {
+		VISIT_SEQ(c, keyword, e->v.Call.keywords);
+		n |= asdl_seq_LEN(e->v.Call.keywords) << 8;
+	}
+	if (e->v.Call.starargs) {
+		VISIT(c, expr, e->v.Call.starargs);
+		code |= 1;
+	}
+	if (e->v.Call.kwargs) {
+		VISIT(c, expr, e->v.Call.kwargs);
+		code |= 2;
+	}
+	switch (code) {
+	case 0:
+		ADDOP_I(c, CALL_FUNCTION, n);
+		break;
+	case 1:
+		ADDOP_I(c, CALL_FUNCTION_VAR, n);
+		break;
+	case 2:
+		ADDOP_I(c, CALL_FUNCTION_KW, n);
+		break;
+	case 3:
+		ADDOP_I(c, CALL_FUNCTION_VAR_KW, n);
+		break;
+	}
+	return 1;
+}
+
+static int
+compiler_listcomp_generator(struct compiler *c, PyObject *tmpname,
+                            asdl_seq *generators, int gen_index, 
+                            expr_ty elt)
+{
+	/* generate code for the iterator, then each of the ifs,
+	   and then write to the element */
+
+	comprehension_ty l;
+	basicblock *start, *anchor, *skip, *if_cleanup;
+        int i, n;
+
+	start = compiler_new_block(c);
+	skip = compiler_new_block(c);
+	if_cleanup = compiler_new_block(c);
+	anchor = compiler_new_block(c);
+
+        if (start == NULL || skip == NULL || if_cleanup == NULL ||
+                anchor == NULL)
+            return 0;
+
+	l = asdl_seq_GET(generators, gen_index);
+	VISIT(c, expr, l->iter);
+	ADDOP(c, GET_ITER);
+	compiler_use_next_block(c, start);
+	ADDOP_JREL(c, FOR_ITER, anchor);
+	NEXT_BLOCK(c);
+	VISIT(c, expr, l->target);
+
+        /* XXX this needs to be cleaned up...a lot! */
+	n = asdl_seq_LEN(l->ifs);
+	for (i = 0; i < n; i++) {
+		expr_ty e = asdl_seq_GET(l->ifs, i);
+		VISIT(c, expr, e);
+		ADDOP_JREL(c, JUMP_IF_FALSE, if_cleanup);
+		NEXT_BLOCK(c);
+		ADDOP(c, POP_TOP);
+	} 
+
+        if (++gen_index < asdl_seq_LEN(generators))
+            if (!compiler_listcomp_generator(c, tmpname, 
+                                             generators, gen_index, elt))
+                return 0;
+
+        /* only append after the last for generator */
+        if (gen_index >= asdl_seq_LEN(generators)) {
+            if (!compiler_nameop(c, tmpname, Load))
+		return 0;
+            VISIT(c, expr, elt);
+            ADDOP_I(c, CALL_FUNCTION, 1);
+            ADDOP(c, POP_TOP);
+
+            compiler_use_next_block(c, skip);
+        }
+	for (i = 0; i < n; i++) {
+		ADDOP_I(c, JUMP_FORWARD, 1);
+                if (i == 0)
+                    compiler_use_next_block(c, if_cleanup);
+		ADDOP(c, POP_TOP);
+	} 
+	ADDOP_JABS(c, JUMP_ABSOLUTE, start);
+	compiler_use_next_block(c, anchor);
+        /* delete the append method added to locals */
+	if (gen_index == 1)
+            if (!compiler_nameop(c, tmpname, Del))
+		return 0;
+	
+	return 1;
+}
+
+static int
+compiler_listcomp(struct compiler *c, expr_ty e)
+{
+	char tmpname[256];
+	identifier tmp;
+        int rc = 0;
+	static identifier append;
+	asdl_seq *generators = e->v.ListComp.generators;
+
+	assert(e->kind == ListComp_kind);
+	if (!append) {
+		append = PyString_InternFromString("append");
+		if (!append)
+			return 0;
+	}
+	PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->u->u_tmpname);
+	tmp = PyString_FromString(tmpname);
+	if (!tmp)
+		return 0;
+	ADDOP_I(c, BUILD_LIST, 0);
+	ADDOP(c, DUP_TOP);
+	ADDOP_O(c, LOAD_ATTR, append, names);
+	if (compiler_nameop(c, tmp, Store))
+            rc = compiler_listcomp_generator(c, tmp, generators, 0, 
+                                             e->v.ListComp.elt);
+        Py_DECREF(tmp);
+	return rc;
+}
+
+static int
+compiler_genexp_generator(struct compiler *c,
+                          asdl_seq *generators, int gen_index, 
+                          expr_ty elt)
+{
+	/* generate code for the iterator, then each of the ifs,
+	   and then write to the element */
+
+	comprehension_ty ge;
+	basicblock *start, *anchor, *skip, *if_cleanup, *end;
+        int i, n;
+
+	start = compiler_new_block(c);
+	skip = compiler_new_block(c);
+	if_cleanup = compiler_new_block(c);
+	anchor = compiler_new_block(c);
+	end = compiler_new_block(c);
+
+        if (start == NULL || skip == NULL || if_cleanup == NULL ||
+	    anchor == NULL || end == NULL)
+		return 0;
+
+	ge = asdl_seq_GET(generators, gen_index);
+	ADDOP_JREL(c, SETUP_LOOP, end);
+	if (!compiler_push_fblock(c, LOOP, start))
+		return 0;
+
+	if (gen_index == 0) {
+		/* Receive outermost iter as an implicit argument */
+		c->u->u_argcount = 1;
+		ADDOP_I(c, LOAD_FAST, 0);
+	}
+	else {
+		/* Sub-iter - calculate on the fly */
+		VISIT(c, expr, ge->iter);
+		ADDOP(c, GET_ITER);
+	}
+	compiler_use_next_block(c, start);
+	ADDOP_JREL(c, FOR_ITER, anchor);
+	NEXT_BLOCK(c);
+	VISIT(c, expr, ge->target);
+
+        /* XXX this needs to be cleaned up...a lot! */
+	n = asdl_seq_LEN(ge->ifs);
+	for (i = 0; i < n; i++) {
+		expr_ty e = asdl_seq_GET(ge->ifs, i);
+		VISIT(c, expr, e);
+		ADDOP_JREL(c, JUMP_IF_FALSE, if_cleanup);
+		NEXT_BLOCK(c);
+		ADDOP(c, POP_TOP);
+	} 
+
+        if (++gen_index < asdl_seq_LEN(generators))
+		if (!compiler_genexp_generator(c, generators, gen_index, elt))
+			return 0;
+
+        /* only append after the last 'for' generator */
+        if (gen_index >= asdl_seq_LEN(generators)) {
+		VISIT(c, expr, elt);
+		ADDOP(c, YIELD_VALUE);
+		ADDOP(c, POP_TOP);
+
+		compiler_use_next_block(c, skip);
+        }
+	for (i = 0; i < n; i++) {
+		ADDOP_I(c, JUMP_FORWARD, 1);
+                if (i == 0)
+			compiler_use_next_block(c, if_cleanup);
+
+		ADDOP(c, POP_TOP);
+	} 
+	ADDOP_JABS(c, JUMP_ABSOLUTE, start);
+	compiler_use_next_block(c, anchor);
+	ADDOP(c, POP_BLOCK);
+	compiler_pop_fblock(c, LOOP, start);
+	compiler_use_next_block(c, end);
+
+	return 1;
+}
+
+static int
+compiler_genexp(struct compiler *c, expr_ty e)
+{
+	PyObject *name;
+	PyCodeObject *co;
+	expr_ty outermost_iter = ((comprehension_ty)
+				 (asdl_seq_GET(e->v.GeneratorExp.generators,
+					       0)))->iter;
+
+	name = PyString_FromString("<generator expression>");
+	if (!name)
+		return 0;
+
+	if (!compiler_enter_scope(c, name, (void *)e, e->lineno))
+		return 0;
+	compiler_genexp_generator(c, e->v.GeneratorExp.generators, 0,
+				  e->v.GeneratorExp.elt);
+	co = assemble(c, 1);
+	if (co == NULL)
+		return 0;
+	compiler_exit_scope(c);
+
+        compiler_make_closure(c, co, 0);
+	VISIT(c, expr, outermost_iter);
+	ADDOP(c, GET_ITER);
+	ADDOP_I(c, CALL_FUNCTION, 1);
+	Py_DECREF(name);
+	Py_DECREF(co);
+
+	return 1;
+}
+
+static int
+compiler_visit_keyword(struct compiler *c, keyword_ty k)
+{
+	ADDOP_O(c, LOAD_CONST, k->arg, consts);
+	VISIT(c, expr, k->value);
+	return 1;
+}
+
+/* Test whether expression is constant.  For constants, report
+   whether they are true or false.
+
+   Return values: 1 for true, 0 for false, -1 for non-constant.
+ */
+
+static int
+expr_constant(expr_ty e)
+{
+	switch (e->kind) {
+	case Num_kind:
+		return PyObject_IsTrue(e->v.Num.n);
+	case Str_kind:
+		return PyObject_IsTrue(e->v.Str.s);
+	default:
+		return -1;
+	}
+}
+
+static int
+compiler_visit_expr(struct compiler *c, expr_ty e)
+{
+	int i, n;
+
+	if (e->lineno > c->u->u_lineno) {
+		c->u->u_lineno = e->lineno;
+		c->u->u_lineno_set = false;
+	}
+	switch (e->kind) {
+        case BoolOp_kind:
+		return compiler_boolop(c, e);
+        case BinOp_kind:
+		VISIT(c, expr, e->v.BinOp.left);
+		VISIT(c, expr, e->v.BinOp.right);
+		ADDOP(c, binop(c, 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:
+		return compiler_lambda(c, e);
+        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:
+		return compiler_listcomp(c, e);
+        case GeneratorExp_kind:
+		return compiler_genexp(c, e);
+	case Yield_kind:
+		if (c->u->u_ste->ste_type != FunctionBlock)
+                        return compiler_error(c, "'yield' outside function");
+		/*
+		for (i = 0; i < c->u->u_nfblocks; i++) {
+			if (c->u->u_fblock[i].fb_type == FINALLY_TRY)
+				return compiler_error(
+					c, "'yield' not allowed in a 'try' "
+					"block with a 'finally' clause");
+		}
+		*/
+		if (e->v.Yield.value) {
+			VISIT(c, expr, e->v.Yield.value);
+		}
+		else {
+			ADDOP_O(c, LOAD_CONST, Py_None, consts);
+		}
+		ADDOP(c, YIELD_VALUE);
+		break;
+        case Compare_kind:
+		return compiler_compare(c, e);
+        case Call_kind:
+		return compiler_call(c, e);
+        case Repr_kind:
+		VISIT(c, expr, e->v.Repr.value);
+		ADDOP(c, UNARY_CONVERT);
+		break;
+        case Num_kind:
+		ADDOP_O(c, LOAD_CONST, e->v.Num.n, consts);
+		break;
+        case Str_kind:
+		ADDOP_O(c, LOAD_CONST, e->v.Str.s, consts);
+		break;
+	/* The following exprs can be assignment targets. */
+        case Attribute_kind:
+		if (e->v.Attribute.ctx != AugStore)
+			VISIT(c, expr, e->v.Attribute.value);
+		switch (e->v.Attribute.ctx) {
+		case AugLoad:
+			ADDOP(c, DUP_TOP);
+			/* Fall through to load */
+		case Load:
+			ADDOP_NAME(c, LOAD_ATTR, e->v.Attribute.attr, names);
+			break;
+		case AugStore:
+			ADDOP(c, ROT_TWO);
+			/* Fall through to save */
+		case Store:
+			ADDOP_NAME(c, STORE_ATTR, e->v.Attribute.attr, names);
+			break;
+		case Del:
+			ADDOP_NAME(c, DELETE_ATTR, e->v.Attribute.attr, names);
+			break;
+		case Param:
+			assert(0);
+			break;
+		}
+		break;
+        case Subscript_kind:
+		switch (e->v.Subscript.ctx) {
+		case AugLoad:
+			VISIT(c, expr, e->v.Subscript.value);
+			VISIT_SLICE(c, e->v.Subscript.slice, AugLoad);
+			break;
+		case Load:
+			VISIT(c, expr, e->v.Subscript.value);
+			VISIT_SLICE(c, e->v.Subscript.slice, Load);
+			break;
+		case AugStore:
+			VISIT_SLICE(c, e->v.Subscript.slice, AugStore);
+			break;
+		case Store:
+			VISIT(c, expr, e->v.Subscript.value);
+			VISIT_SLICE(c, e->v.Subscript.slice, Store);
+			break;
+		case Del:
+			VISIT(c, expr, e->v.Subscript.value);
+			VISIT_SLICE(c, e->v.Subscript.slice, Del);
+			break;
+		case Param:
+			assert(0);
+			break;
+		}
+		break;
+        case Name_kind:
+		return compiler_nameop(c, e->v.Name.id, e->v.Name.ctx);
+	/* child nodes of List and Tuple will have expr_context set */
+        case List_kind:
+		return compiler_list(c, e);
+        case Tuple_kind:
+		return compiler_tuple(c, e);
+	}
+	return 1;
+}
+
+static int
+compiler_augassign(struct compiler *c, stmt_ty s)
+{
+	expr_ty e = s->v.AugAssign.target;
+	expr_ty auge;
+
+	assert(s->kind == AugAssign_kind);
+
+	switch (e->kind) {
+                case Attribute_kind:
+		auge = Attribute(e->v.Attribute.value, e->v.Attribute.attr,
+				 AugLoad, e->lineno);
+                if (auge == NULL)
+                    return 0;
+		VISIT(c, expr, auge);
+		VISIT(c, expr, s->v.AugAssign.value);
+		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);
+                if (auge == NULL)
+                    return 0;
+		VISIT(c, expr, auge);
+		VISIT(c, expr, s->v.AugAssign.value);
+		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);
+		VISIT(c, expr, s->v.AugAssign.value);
+		ADDOP(c, inplace_binop(c, s->v.AugAssign.op));
+		return compiler_nameop(c, e->v.Name.id, Store);
+	default:
+                fprintf(stderr, 
+                        "invalid node type for augmented assignment\n");
+                return 0;
+	}
+	return 1;
+}
+
+static int
+compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b)
+{
+	struct fblockinfo *f;
+	if (c->u->u_nfblocks >= CO_MAXBLOCKS)
+		return 0;
+	f = &c->u->u_fblock[c->u->u_nfblocks++];
+	f->fb_type = t;
+	f->fb_block = b;
+	return 1;
+}
+
+static void
+compiler_pop_fblock(struct compiler *c, enum fblocktype t, basicblock *b)
+{
+	struct compiler_unit *u = c->u;
+	assert(u->u_nfblocks > 0);
+	u->u_nfblocks--;
+	assert(u->u_fblock[u->u_nfblocks].fb_type == t);
+	assert(u->u_fblock[u->u_nfblocks].fb_block == b);
+}
+
+/* Raises a SyntaxError and returns 0.
+   If something goes wrong, a different exception may be raised.
+*/
+
+static int
+compiler_error(struct compiler *c, const char *errstr)
+{
+	PyObject *loc;
+	PyObject *u = NULL, *v = NULL;
+
+	loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno);
+	if (!loc) {
+		Py_INCREF(Py_None);
+		loc = Py_None;
+	}
+	u = Py_BuildValue("(ziOO)", c->c_filename, c->u->u_lineno,
+			  Py_None, loc);
+	if (!u)
+		goto exit;
+	v = Py_BuildValue("(zO)", errstr, u);
+	if (!v)
+		goto exit;
+	PyErr_SetObject(PyExc_SyntaxError, v);
+ exit:
+	Py_DECREF(loc);
+	Py_XDECREF(u);
+	Py_XDECREF(v);
+	return 0;
+}
+
+static int
+compiler_handle_subscr(struct compiler *c, const char *kind, 
+                       expr_context_ty ctx) 
+{
+        int op = 0;
+
+        /* XXX this code is duplicated */
+        switch (ctx) {
+                case AugLoad: /* fall through to Load */
+                case Load:    op = BINARY_SUBSCR; break;
+                case AugStore:/* fall through to Store */
+                case Store:   op = STORE_SUBSCR; break;
+                case Del:     op = DELETE_SUBSCR; break;
+                case Param:
+                        fprintf(stderr, 
+                                "invalid %s kind %d in subscript\n", 
+                                kind, ctx);
+                        return 0;
+        }
+        if (ctx == AugLoad) {
+                ADDOP_I(c, DUP_TOPX, 2);
+        }
+        else if (ctx == AugStore) {
+                ADDOP(c, ROT_THREE);
+        }
+        ADDOP(c, op);
+        return 1;
+}
+
+static int
+compiler_slice(struct compiler *c, slice_ty s, expr_context_ty ctx)
+{
+	int n = 2;
+	assert(s->kind == Slice_kind);
+
+	/* only handles the cases where BUILD_SLICE is emitted */
+	if (s->v.Slice.lower) {
+                VISIT(c, expr, s->v.Slice.lower);
+	}
+	else {
+                ADDOP_O(c, LOAD_CONST, Py_None, consts);
+	}
+                
+	if (s->v.Slice.upper) {
+                VISIT(c, expr, s->v.Slice.upper);
+	}
+	else {
+                ADDOP_O(c, LOAD_CONST, Py_None, consts);
+	}
+
+	if (s->v.Slice.step) {
+		n++;
+		VISIT(c, expr, s->v.Slice.step);
+	}
+	ADDOP_I(c, BUILD_SLICE, n);
+	return 1;
+}
+
+static int
+compiler_simple_slice(struct compiler *c, slice_ty s, expr_context_ty ctx)
+{
+	int op = 0, slice_offset = 0, stack_count = 0;
+
+	assert(s->v.Slice.step == NULL);
+	if (s->v.Slice.lower) {
+		slice_offset++;
+		stack_count++;
+		if (ctx != AugStore) 
+			VISIT(c, expr, s->v.Slice.lower);
+	}
+	if (s->v.Slice.upper) {
+		slice_offset += 2;
+		stack_count++;
+		if (ctx != AugStore) 
+			VISIT(c, expr, s->v.Slice.upper);
+	}
+
+ 	if (ctx == AugLoad) {
+ 		switch (stack_count) {
+ 		case 0: ADDOP(c, DUP_TOP); break;
+ 		case 1: ADDOP_I(c, DUP_TOPX, 2); break;
+ 		case 2: ADDOP_I(c, DUP_TOPX, 3); break;
+ 		}
+  	}
+ 	else if (ctx == AugStore) {
+ 		switch (stack_count) {
+ 		case 0: ADDOP(c, ROT_TWO); break;
+ 		case 1: ADDOP(c, ROT_THREE); break;
+ 		case 2: ADDOP(c, ROT_FOUR); break;
+  		}
+  	}
+
+	switch (ctx) {
+	case AugLoad: /* fall through to Load */
+	case Load: op = SLICE; break;
+	case AugStore:/* fall through to Store */
+	case Store: op = STORE_SLICE; break;
+	case Del: op = DELETE_SLICE; break;
+	case Param:  /* XXX impossible? */
+		fprintf(stderr, "param invalid\n");
+		assert(0);
+	}
+
+	ADDOP(c, op + slice_offset);
+	return 1;
+}
+
+static int
+compiler_visit_nested_slice(struct compiler *c, slice_ty s, 
+			    expr_context_ty ctx)
+{
+	switch (s->kind) {
+	case Ellipsis_kind:
+		ADDOP_O(c, LOAD_CONST, Py_Ellipsis, consts);
+		break;
+	case Slice_kind:
+		return compiler_slice(c, s, ctx);
+		break;
+	case Index_kind:
+		VISIT(c, expr, s->v.Index.value);
+		break;
+	case ExtSlice_kind:
+		assert(0);
+		break;
+	}
+	return 1;
+}
+
+
+static int
+compiler_visit_slice(struct compiler *c, slice_ty s, expr_context_ty ctx)
+{
+	switch (s->kind) {
+	case Ellipsis_kind:
+		ADDOP_O(c, LOAD_CONST, Py_Ellipsis, consts);
+		break;
+	case Slice_kind:
+		if (!s->v.Slice.step) 
+			return compiler_simple_slice(c, s, ctx);
+                if (!compiler_slice(c, s, ctx))
+			return 0;
+		if (ctx == AugLoad) {
+			ADDOP_I(c, DUP_TOPX, 2);
+		}
+		else if (ctx == AugStore) {
+			ADDOP(c, ROT_THREE);
+		}
+		return compiler_handle_subscr(c, "slice", ctx);
+		break;
+	case ExtSlice_kind: {
+		int i, n = asdl_seq_LEN(s->v.ExtSlice.dims);
+		for (i = 0; i < n; i++) {
+			slice_ty sub = asdl_seq_GET(s->v.ExtSlice.dims, i);
+			if (!compiler_visit_nested_slice(c, sub, ctx))
+				return 0;
+		}
+		ADDOP_I(c, BUILD_TUPLE, n);
+                return compiler_handle_subscr(c, "extended slice", ctx);
+		break;
+	}
+	case Index_kind:
+                if (ctx != AugStore)
+			VISIT(c, expr, s->v.Index.value);
+                return compiler_handle_subscr(c, "index", ctx);
+	}
+	return 1;
+}
+
+/* do depth-first search of basic block graph, starting with block.
+   post records the block indices in post-order.
+
+   XXX must handle implicit jumps from one block to next
+*/
+
+static void
+dfs(struct compiler *c, basicblock *b, struct assembler *a)
+{
+	int i;
+	struct instr *instr = NULL;
+
+	if (b->b_seen)
+		return;
+	b->b_seen = 1;
+	if (b->b_next != NULL)
+		dfs(c, b->b_next, a);
+	for (i = 0; i < b->b_iused; i++) {
+		instr = &b->b_instr[i];
+		if (instr->i_jrel || instr->i_jabs)
+			dfs(c, instr->i_target, a);
+	}
+	a->a_postorder[a->a_nblocks++] = b;
+}
+
+int
+stackdepth_walk(struct compiler *c, basicblock *b, int depth, int maxdepth)
+{
+	int i;
+	struct instr *instr;
+	if (b->b_seen || b->b_startdepth >= depth)
+		return maxdepth;
+	b->b_seen = 1;
+	b->b_startdepth = depth;
+	for (i = 0; i < b->b_iused; i++) {
+		instr = &b->b_instr[i];
+		depth += opcode_stack_effect(instr->i_opcode, instr->i_oparg);
+		if (depth > maxdepth)
+			maxdepth = depth;
+		assert(depth >= 0); /* invalid code or bug in stackdepth() */
+		if (instr->i_jrel || instr->i_jabs) {
+			maxdepth = stackdepth_walk(c, instr->i_target,
+						   depth, maxdepth);
+			if (instr->i_opcode == JUMP_ABSOLUTE ||
+			    instr->i_opcode == JUMP_FORWARD) {
+				goto out; /* remaining code is dead */
+			}
+		}
+	}
+	if (b->b_next)
+		maxdepth = stackdepth_walk(c, b->b_next, depth, maxdepth);
+out:
+	b->b_seen = 0;
+	return maxdepth;
+}
+
+/* Find the flow path that needs the largest stack.  We assume that
+ * cycles in the flow graph have no net effect on the stack depth.
+ */
+static int
+stackdepth(struct compiler *c)
+{
+	basicblock *b, *entryblock;
+	entryblock = NULL;
+	for (b = c->u->u_blocks; b != NULL; b = b->b_list) {
+		b->b_seen = 0;
+		b->b_startdepth = INT_MIN;
+		entryblock = b;
+	}
+	return stackdepth_walk(c, entryblock, 0, 0);
+}
+
+static int
+assemble_init(struct assembler *a, int nblocks, int firstlineno)
+{
+	memset(a, 0, sizeof(struct assembler));
+	a->a_lineno = firstlineno;
+	a->a_bytecode = PyString_FromStringAndSize(NULL, DEFAULT_CODE_SIZE);
+	if (!a->a_bytecode)
+		return 0;
+	a->a_lnotab = PyString_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE);
+	if (!a->a_lnotab)
+		return 0;
+	a->a_postorder = (basicblock **)PyObject_Malloc(
+                                            sizeof(basicblock *) * nblocks);
+	if (!a->a_postorder)
+		return 0;
+	return 1;
+}
+
+static void
+assemble_free(struct assembler *a)
+{
+	Py_XDECREF(a->a_bytecode);
+	Py_XDECREF(a->a_lnotab);
+	if (a->a_postorder)
+		PyObject_Free(a->a_postorder);
+}
+
+/* Return the size of a basic block in bytes. */
+
+static int
+instrsize(struct instr *instr)
+{
+	int size = 1;
+	if (instr->i_hasarg) {
+		size += 2;
+		if (instr->i_oparg >> 16)
+			size += 2;
+	}
+	return size;
+}
+
+static int
+blocksize(basicblock *b)
+{
+	int i;
+	int size = 0;
+
+	for (i = 0; i < b->b_iused; i++)
+		size += instrsize(&b->b_instr[i]);
+	return size;
+}
+
+/* All about a_lnotab.
+
+c_lnotab is an array of unsigned bytes disguised as a Python string.
+It is used to map bytecode offsets to source code line #s (when needed
+for tracebacks).
 
 The array is conceptually a list of
     (bytecode offset increment, line number increment)
@@ -1104,4027 +3748,164 @@
 255, 0,  45, 255,  0, 45.
 */
 
-struct compiling {
-	PyObject *c_code;	/* string */
-	PyObject *c_consts;	/* list of objects */
-	PyObject *c_const_dict; /* inverse of c_consts */
-	PyObject *c_names;	/* list of strings (names) */
-	PyObject *c_name_dict;  /* inverse of c_names */
-	PyObject *c_globals;	/* dictionary (value=None or True) */
-	PyObject *c_locals;	/* dictionary (value=localID) */
-	PyObject *c_varnames;	/* list (inverse of c_locals) */
-	PyObject *c_freevars;	/* dictionary (value=None) */
-	PyObject *c_cellvars;	/* dictionary */
-	int c_nlocals;		/* index of next local */
-	int c_argcount;		/* number of top-level arguments */
-	int c_flags;		/* same as co_flags */
-	int c_nexti;		/* index into c_code */
-	int c_errors;		/* counts errors occurred */
-	int c_infunction;	/* set when compiling a function */
-	int c_interactive;	/* generating code for interactive command */
-	int c_loops;		/* counts nested loops */
-	int c_begin;		/* begin of current loop, for 'continue' */
-	int c_block[CO_MAXBLOCKS]; /* stack of block types */
-	int c_nblocks;		/* current block stack level */
-	const char *c_filename;	/* filename of current node */
-	char *c_name;		/* name of object (e.g. function) */
-	int c_lineno;		/* Current line number */
-	int c_stacklevel;	/* Current stack level */
-	int c_maxstacklevel;	/* Maximum stack level */
-	int c_firstlineno;
-	PyObject *c_lnotab;	/* Table mapping address to line number */
-	int c_last_addr;	/* last op addr seen and recorded in lnotab */
-	int c_last_line;	/* last line seen and recorded in lnotab */
-	int c_lnotab_next;	/* current length of lnotab */
-	int c_lnotab_last;	/* start of last lnotab record added */
-	char *c_private;	/* for private name mangling */
-	int c_tmpname;		/* temporary local name counter */
-	int c_nested;		/* Is block nested funcdef or lamdef? */
-	int c_closure;		/* Is nested w/freevars? */
-	struct symtable *c_symtable; /* pointer to module symbol table */
-        PyFutureFeatures *c_future; /* pointer to module's __future__ */
-	char *c_encoding;	/* source encoding (a borrowed reference) */
-};
-
 static int
-is_free(int v)
+assemble_lnotab(struct assembler *a, struct instr *i)
 {
-	if ((v & (USE | DEF_FREE))
-	    && !(v & (DEF_LOCAL | DEF_PARAM | DEF_GLOBAL)))
+	int d_bytecode, d_lineno;
+	int len;
+	char *lnotab;
+
+	d_bytecode = a->a_offset - a->a_lineno_off;
+	d_lineno = i->i_lineno - a->a_lineno;
+
+	assert(d_bytecode >= 0);
+	assert(d_lineno >= 0);
+
+	if (d_lineno == 0)
 		return 1;
-	if (v & DEF_FREE_CLASS)
-		return 1;
-	return 0;
-}
 
-static void
-com_error(struct compiling *c, PyObject *exc, char *msg)
-{
-	PyObject *t = NULL, *v = NULL, *w = NULL, *line = NULL;
-
-	if (c == NULL) {
-		/* Error occurred via symtable call to
-		   is_constant_false */
-		PyErr_SetString(exc, msg);
-		return;
-	}
-	c->c_errors++;
-	if (c->c_lineno < 1 || c->c_interactive) { 
-		/* Unknown line number or interactive input */
-		PyErr_SetString(exc, msg);
-		return;
-	}
-	v = PyString_FromString(msg);
-	if (v == NULL)
-		return; /* MemoryError, too bad */
-
-	line = PyErr_ProgramText(c->c_filename, c->c_lineno);
-	if (line == NULL) {
-		Py_INCREF(Py_None);
-		line = Py_None;
-	}
-	if (exc == PyExc_SyntaxError) {
-		t = Py_BuildValue("(ziOO)", c->c_filename, c->c_lineno,
-				  Py_None, line);
-		if (t == NULL)
-			goto exit;
-		w = PyTuple_Pack(2, v, t);
-		if (w == NULL)
-			goto exit;
-		PyErr_SetObject(exc, w);
-	} else {
-		/* Make sure additional exceptions are printed with
-		   file and line, also. */
-		PyErr_SetObject(exc, v);
-		PyErr_SyntaxLocation(c->c_filename, c->c_lineno);
-	}
- exit:
-	Py_XDECREF(t);
-	Py_XDECREF(v);
-	Py_XDECREF(w);
-	Py_XDECREF(line);
-}
-
-/* Interface to the block stack */
-
-static void
-block_push(struct compiling *c, int type)
-{
-	if (c->c_nblocks >= CO_MAXBLOCKS) {
-		com_error(c, PyExc_SystemError,
-			  "too many statically nested blocks");
-	}
-	else {
-		c->c_block[c->c_nblocks++] = type;
-	}
-}
-
-static void
-block_pop(struct compiling *c, int type)
-{
-	if (c->c_nblocks > 0)
-		c->c_nblocks--;
-	if (c->c_block[c->c_nblocks] != type && c->c_errors == 0) {
-		com_error(c, PyExc_SystemError, "bad block pop");
-	}
-}
-
-/* Prototype forward declarations */
-
-static int issue_warning(const char *, const char *, int);
-static int com_init(struct compiling *, const char *);
-static void com_free(struct compiling *);
-static void com_push(struct compiling *, int);
-static void com_pop(struct compiling *, int);
-static void com_done(struct compiling *);
-static void com_node(struct compiling *, node *);
-static void com_factor(struct compiling *, node *);
-static void com_addbyte(struct compiling *, int);
-static void com_addint(struct compiling *, int);
-static void com_addoparg(struct compiling *, int, int);
-static void com_addfwref(struct compiling *, int, int *);
-static void com_backpatch(struct compiling *, int);
-static int com_add(struct compiling *, PyObject *, PyObject *, PyObject *);
-static int com_addconst(struct compiling *, PyObject *);
-static int com_addname(struct compiling *, PyObject *);
-static void com_addopname(struct compiling *, int, node *);
-static void com_test(struct compiling *c, node *n);
-static void com_list(struct compiling *, node *, int);
-static void com_list_iter(struct compiling *, node *, node *, char *);
-static void com_gen_iter(struct compiling *, node *, node *);
-static int com_argdefs(struct compiling *, node *);
-static void com_assign(struct compiling *, node *, int, node *);
-static void com_assign_name(struct compiling *, node *, int);
-static int com_make_closure(struct compiling *c, PyCodeObject *co);
-
-static PyCodeObject *icompile(node *, struct compiling *);
-static PyCodeObject *jcompile(node *, const char *, struct compiling *,
-			      PyCompilerFlags *);
-static PyObject *parsestrplus(struct compiling*, node *);
-static PyObject *parsestr(struct compiling *, char *);
-static node *get_rawdocstring(node *);
-
-static int get_ref_type(struct compiling *, char *);
-
-/* symtable operations */
-static int symtable_lookup(struct symtable *st, char *name);
-static struct symtable *symtable_build(node *, PyFutureFeatures *,
-				       const char *filename);
-static int symtable_load_symbols(struct compiling *);
-static struct symtable *symtable_init(void);
-static void symtable_enter_scope(struct symtable *, char *, int, int);
-static int symtable_exit_scope(struct symtable *);
-static int symtable_add_def(struct symtable *, char *, int);
-static int symtable_add_def_o(struct symtable *, PyObject *, PyObject *, int);
-
-static void symtable_node(struct symtable *, node *);
-static void symtable_funcdef(struct symtable *, node *);
-static void symtable_default_args(struct symtable *, node *);
-static void symtable_params(struct symtable *, node *);
-static void symtable_params_fplist(struct symtable *, node *n);
-static void symtable_global(struct symtable *, node *);
-static void symtable_import(struct symtable *, node *);
-static void symtable_assign(struct symtable *, node *, int);
-static void symtable_list_comprehension(struct symtable *, node *);
-static void symtable_generator_expression(struct symtable *, node *);
-static void symtable_list_for(struct symtable *, node *);
-static void symtable_gen_for(struct symtable *, node *, int);
-static void symtable_gen_iter(struct symtable *, node *);
-
-static int symtable_update_free_vars(struct symtable *);
-static int symtable_undo_free(struct symtable *, PyObject *, PyObject *);
-static int symtable_check_global(struct symtable *, PyObject *, PyObject *);
-
-/* helper */
-static void
-do_pad(int pad)
-{
-	int i;
-	for (i = 0; i < pad; ++i)
-		fprintf(stderr, "  ");
-}
-
-static void
-dump(node *n, int pad, int depth)
-{
-	int i;
-	if (depth == 0)
-	    return;
-	do_pad(pad);
-	fprintf(stderr, "%d: %s\n", TYPE(n), STR(n));
-	if (depth > 0)
-	    depth--;
-	for (i = 0; i < NCH(n); ++i)
-		dump(CHILD(n, i), pad + 1, depth);
-}
-
-static int
-com_init(struct compiling *c, const char *filename)
-{
-	memset((void *)c, '\0', sizeof(struct compiling));
-	if ((c->c_code = PyString_FromStringAndSize((char *)NULL,
-						    1000)) == NULL)
-		goto fail;
-	if ((c->c_consts = PyList_New(0)) == NULL)
-		goto fail;
-	if ((c->c_const_dict = PyDict_New()) == NULL)
-		goto fail;
-	if ((c->c_names = PyList_New(0)) == NULL)
-		goto fail;
-	if ((c->c_name_dict = PyDict_New()) == NULL)
-		goto fail;
-	if ((c->c_locals = PyDict_New()) == NULL)
-		goto fail;
-	if ((c->c_lnotab = PyString_FromStringAndSize((char *)NULL,
-						      1000)) == NULL)
-		goto fail;
-	c->c_globals = NULL;
-	c->c_varnames = NULL;
-	c->c_freevars = NULL;
-	c->c_cellvars = NULL;
-	c->c_nlocals = 0;
-	c->c_argcount = 0;
-	c->c_flags = 0;
-	c->c_nexti = 0;
-	c->c_errors = 0;
-	c->c_infunction = 0;
-	c->c_interactive = 0;
-	c->c_loops = 0;
-	c->c_begin = 0;
-	c->c_nblocks = 0;
-	c->c_filename = filename;
-	c->c_name = "?";
-	c->c_lineno = 0;
-	c->c_stacklevel = 0;
-	c->c_maxstacklevel = 0;
-	c->c_firstlineno = 0;
-	c->c_last_addr = 0;
-	c->c_last_line = 0;
-	c->c_lnotab_next = 0;
-	c->c_lnotab_last = 0;
-	c->c_tmpname = 0;
-	c->c_nested = 0;
-	c->c_closure = 0;
-	c->c_symtable = NULL;
-	return 1;
-	
-  fail:
-	com_free(c);
- 	return 0;
-}
-
-static void
-com_free(struct compiling *c)
-{
-	Py_XDECREF(c->c_code);
-	Py_XDECREF(c->c_consts);
-	Py_XDECREF(c->c_const_dict);
-	Py_XDECREF(c->c_names);
-	Py_XDECREF(c->c_name_dict);
-	Py_XDECREF(c->c_globals);
-	Py_XDECREF(c->c_locals);
-	Py_XDECREF(c->c_varnames);
-	Py_XDECREF(c->c_freevars);
-	Py_XDECREF(c->c_cellvars);
-	Py_XDECREF(c->c_lnotab);
-	if (c->c_future)
-		PyObject_FREE((void *)c->c_future);
-}
-
-static void
-com_push(struct compiling *c, int n)
-{
-	c->c_stacklevel += n;
-	if (c->c_stacklevel > c->c_maxstacklevel) {
-		c->c_maxstacklevel = c->c_stacklevel;
-		/*
-		fprintf(stderr, "%s:%s:%d max stack nexti=%d level=%d n=%d\n",
-			c->c_filename, c->c_name, c->c_lineno,
-			c->c_nexti, c->c_stacklevel, n);
-		*/
-	}
-}
-
-static void
-com_pop(struct compiling *c, int n)
-{
-	if (c->c_stacklevel < n) 
-		c->c_stacklevel = 0;
-	else
-		c->c_stacklevel -= n;
-}
-
-static void
-com_done(struct compiling *c)
-{
-	if (c->c_code != NULL)
-		_PyString_Resize(&c->c_code, c->c_nexti);
-	if (c->c_lnotab != NULL)
-		_PyString_Resize(&c->c_lnotab, c->c_lnotab_next);
-}
-
-static int
-com_check_size(PyObject **s, int offset)
-{
-	int len = PyString_GET_SIZE(*s);
-	if (offset >= len) 
-		return _PyString_Resize(s, len * 2);
-	return 0;
-}
-
-static void
-com_addbyte(struct compiling *c, int byte)
-{
-	/*fprintf(stderr, "%3d: %3d\n", c->c_nexti, byte);*/
-	assert(byte >= 0 && byte <= 255);
-	assert(c->c_code != 0);
-	if (com_check_size(&c->c_code, c->c_nexti)) {
-		c->c_errors++;
-		return;
-	}
-	PyString_AS_STRING(c->c_code)[c->c_nexti++] = byte;
-}
-
-static void
-com_addint(struct compiling *c, int x)
-{
-	com_addbyte(c, x & 0xff);
-	com_addbyte(c, x >> 8); /* XXX x should be positive */
-}
-
-static void
-com_add_lnotab(struct compiling *c, int addr, int line)
-{
-	char *p;
-	if (c->c_lnotab == NULL)
-		return;
-	if (com_check_size(&c->c_lnotab, c->c_lnotab_next + 2)) {
-		c->c_errors++;
-		return;
-	}
-	p = PyString_AS_STRING(c->c_lnotab) + c->c_lnotab_next;
-	*p++ = addr;
-	*p++ = line;
-	c->c_lnotab_next += 2;
-}
-
-static void
-com_set_lineno(struct compiling *c, int lineno)
-{
-	c->c_lineno = lineno;
-	if (c->c_firstlineno == 0) {
-		c->c_firstlineno = c->c_last_line = lineno;
-	}
-	else {
-		int incr_addr = c->c_nexti - c->c_last_addr;
-		int incr_line = lineno - c->c_last_line;
-		c->c_lnotab_last = c->c_lnotab_next;
-		while (incr_addr > 255) {
-			com_add_lnotab(c, 255, 0);
-			incr_addr -= 255;
-		}
-		while (incr_line > 255) {
-			com_add_lnotab(c, incr_addr, 255);
-			incr_line -=255;
-			incr_addr = 0;
-		}
-		if (incr_addr > 0 || incr_line > 0)
-			com_add_lnotab(c, incr_addr, incr_line);
-		c->c_last_addr = c->c_nexti;
-		c->c_last_line = lineno;
-	}
-}
-
-static void
-com_strip_lnotab(struct compiling *c)
-{
-	/* strip the last lnotab entry if no opcode were emitted.
-	 * This prevents a line number to be generated on a final
-	 * pass, like in the following example:
-	 *
-	 *    if a:
-	 *        print 5
-	 *    else:
-	 *        pass
-	 *
-	 * Without the fix, a line trace event would be generated
-	 * on the pass even if a is true (because of the implicit
-	 * return).
-	 */
-	if (c->c_nexti == c->c_last_addr && c->c_lnotab_last > 0) {
-		c->c_lnotab_next = c->c_lnotab_last;
-	}
-}
-
-static void
-com_addoparg(struct compiling *c, int op, int arg)
-{
-	int extended_arg = arg >> 16;
-	if (extended_arg){
-		com_addbyte(c, EXTENDED_ARG);
-		com_addint(c, extended_arg);
-		arg &= 0xffff;
-	}
-	com_addbyte(c, op);
-	com_addint(c, arg);
-}
-
-static void
-com_addfwref(struct compiling *c, int op, int *p_anchor)
-{
-	/* Compile a forward reference for backpatching */
-	int here;
-	int anchor;
-	com_addbyte(c, op);
-	here = c->c_nexti;
-	anchor = *p_anchor;
-	*p_anchor = here;
-	com_addint(c, anchor == 0 ? 0 : here - anchor);
-}
-
-static void
-com_backpatch(struct compiling *c, int anchor)
-{
-	unsigned char *code = (unsigned char *) PyString_AS_STRING(c->c_code);
-	int target = c->c_nexti;
-	int dist;
-	int prev;
-	for (;;) {
-		/* Make the JUMP instruction at anchor point to target */
-		prev = code[anchor] + (code[anchor+1] << 8);
-		dist = target - (anchor+2);
-		code[anchor] = dist & 0xff;
-		dist >>= 8;
-		code[anchor+1] = dist;
-		dist >>= 8;
-		if (dist) {
-			com_error(c, PyExc_SystemError,
-				  "com_backpatch: offset too large");
-			break;
-		}
-		if (!prev)
-			break;
-		anchor -= prev;
-	}
-}
-
-/* Handle literals and names uniformly */
-
-static int
-com_add(struct compiling *c, PyObject *list, PyObject *dict, PyObject *v)
-{
-	PyObject *w, *t, *np=NULL;
-	long n;
-	
-	t = PyTuple_Pack(2, v, v->ob_type);
-	if (t == NULL)
-	    goto fail;
-	w = PyDict_GetItem(dict, t);
-	if (w != NULL) {
-		n = PyInt_AsLong(w);
-	} else {
-		n = PyList_Size(list);
-		np = PyInt_FromLong(n);
-		if (np == NULL)
-		    goto fail;
-		if (PyList_Append(list, v) != 0)
-		    goto fail;
-		if (PyDict_SetItem(dict, t, np) != 0)
-		    goto fail;
-		Py_DECREF(np);
-	}
-	Py_DECREF(t);
-	return n;
-  fail:
-	Py_XDECREF(np);
-	Py_XDECREF(t);
-	c->c_errors++;
-	return 0;
-}
-
-static int
-com_addconst(struct compiling *c, PyObject *v)
-{
-	return com_add(c, c->c_consts, c->c_const_dict, v);
-}
-
-static int
-com_addname(struct compiling *c, PyObject *v)
-{
-	return com_add(c, c->c_names, c->c_name_dict, v);
-}
-
-int
-_Py_Mangle(char *p, char *name, char *buffer, size_t maxlen)
-{
-	/* Name mangling: __private becomes _classname__private.
-	   This is independent from how the name is used. */
-	size_t nlen, plen;
-	if (p == NULL || name == NULL || name[0] != '_' || name[1] != '_')
-		return 0;
-	nlen = strlen(name);
-	if (nlen+2 >= maxlen)
-		return 0; /* Don't mangle __extremely_long_names */
-	if (name[nlen-1] == '_' && name[nlen-2] == '_')
-		return 0; /* Don't mangle __whatever__ */
-	/* Strip leading underscores from class name */
-	while (*p == '_')
-		p++;
-	if (*p == '\0')
-		return 0; /* Don't mangle if class is just underscores */
-	plen = strlen(p);
-	if (plen + nlen >= maxlen)
-		plen = maxlen-nlen-2; /* Truncate class name if too long */
-	/* buffer = "_" + p[:plen] + name # i.e. 1+plen+nlen bytes */
-	buffer[0] = '_';
-	strncpy(buffer+1, p, plen);
-	strcpy(buffer+1+plen, name);
-	return 1;
-}
-
-static void
-com_addop_name(struct compiling *c, int op, char *name)
-{
-	PyObject *v;
-	int i;
-	char buffer[MANGLE_LEN];
-
-	if (_Py_Mangle(c->c_private, name, buffer, sizeof(buffer)))
-		name = buffer;
-	if (name == NULL || (v = PyString_InternFromString(name)) == NULL) {
-		c->c_errors++;
-		i = 255;
-	}
-	else {
-		i = com_addname(c, v);
-		Py_DECREF(v);
-	}
-	com_addoparg(c, op, i);
-}
-
-#define NAME_LOCAL 0
-#define NAME_GLOBAL 1
-#define NAME_DEFAULT 2
-#define NAME_CLOSURE 3
-
-static int
-com_lookup_arg(PyObject *dict, PyObject *name)
-{
-	PyObject *v = PyDict_GetItem(dict, name);
-	if (v == NULL)
-		return -1;
-	else
-		return PyInt_AS_LONG(v);
-}
-
-static int
-none_assignment_check(struct compiling *c, char *name, int assigning)
-{
-	if (name[0] == 'N' && strcmp(name, "None") == 0) {
-		char *msg;
-		if (assigning)
-			msg = "assignment to None";
-		else
-			msg = "deleting None";
-		com_error(c, PyExc_SyntaxError, msg);
-		return -1;
-	}
-	return 0;
-}
-
-static void
-com_addop_varname(struct compiling *c, int kind, char *name)
-{
-	PyObject *v;
-	int i, reftype;
-	int scope = NAME_DEFAULT;
-	int op = STOP_CODE;
-	char buffer[MANGLE_LEN];
-
-	if (kind != VAR_LOAD &&
-	    none_assignment_check(c, name, kind == VAR_STORE))
-	{
-		i = 255;
-		goto done;
-	}
-	if (_Py_Mangle(c->c_private, name, buffer, sizeof(buffer)))
-		name = buffer;
-	if (name == NULL || (v = PyString_InternFromString(name)) == NULL) {
-		c->c_errors++;
-		i = 255;
-		goto done;
-	}
-
-	reftype = get_ref_type(c, name);
-	switch (reftype) {
-	case LOCAL:
-		if (c->c_symtable->st_cur->ste_type == TYPE_FUNCTION)
-			scope = NAME_LOCAL;
-		break;
-	case GLOBAL_EXPLICIT:
-		scope = NAME_GLOBAL;
-		break;
-	case GLOBAL_IMPLICIT:
-		if (c->c_flags & CO_OPTIMIZED)
-			scope = NAME_GLOBAL;
-		break;
-	case FREE:
-	case CELL:
-		scope = NAME_CLOSURE;
-		break;
-	}
-
-	i = com_addname(c, v);
-	if (scope == NAME_LOCAL)
-		i = com_lookup_arg(c->c_locals, v);
-	else if (reftype == FREE)
-		i = com_lookup_arg(c->c_freevars, v);
-	else if (reftype == CELL)
-		i = com_lookup_arg(c->c_cellvars, v);
-	if (i == -1) {
-		c->c_errors++; /* XXX no exception set */
-		i = 255;
-		goto done;
-	}
-	Py_DECREF(v);
-
-	switch (kind) {
-	case VAR_LOAD:
-		switch (scope) {
-		case NAME_LOCAL:
-			op = LOAD_FAST;
-			break;
-		case NAME_GLOBAL:
-			op = LOAD_GLOBAL;
-			break;
-		case NAME_DEFAULT:
-			op = LOAD_NAME;
-			break;
-		case NAME_CLOSURE:
-			op = LOAD_DEREF;
-			break;
-		}
-		break;
-	case VAR_STORE:
-		switch (scope) {
-		case NAME_LOCAL:
-			op = STORE_FAST;
-			break;
-		case NAME_GLOBAL:
-			op = STORE_GLOBAL;
-			break;
-		case NAME_DEFAULT:
-			op = STORE_NAME;
-			break;
-		case NAME_CLOSURE:
-			op = STORE_DEREF;
-			break;
-		}
-		break;
-	case VAR_DELETE:
-		switch (scope) {
-		case NAME_LOCAL:
-			op = DELETE_FAST;
-			break;
-		case NAME_GLOBAL:
-			op = DELETE_GLOBAL;
-			break;
-		case NAME_DEFAULT:
-			op = DELETE_NAME;
-			break;
-		case NAME_CLOSURE: {
-			char buf[500];
-			PyOS_snprintf(buf, sizeof(buf),
-				      DEL_CLOSURE_ERROR, name);
-			com_error(c, PyExc_SyntaxError, buf);
-			i = 255;
-			break;
-		}
-		}
-		break;
-	}
-done:
-	com_addoparg(c, op, i);
-}
-
-static void
-com_addopname(struct compiling *c, int op, node *n)
-{
-	char *name;
-	char buffer[1000];
-	/* XXX it is possible to write this code without the 1000
-	   chars on the total length of dotted names, I just can't be
-	   bothered right now */
-	if (TYPE(n) == STAR)
-		name = "*";
-	else if (TYPE(n) == dotted_name) {
-		char *p = buffer;
-		int i;
-		name = buffer;
-		for (i = 0; i < NCH(n); i += 2) {
-			char *s = STR(CHILD(n, i));
-			if (p + strlen(s) > buffer + (sizeof buffer) - 2) {
-				com_error(c, PyExc_MemoryError,
-					  "dotted_name too long");
-				name = NULL;
-				break;
-			}
-			if (p != buffer)
-				*p++ = '.';
-			strcpy(p, s);
-			p = strchr(p, '\0');
-		}
-	}
-	else {
-		REQ(n, NAME);
-		name = STR(n);
-	}
-	com_addop_name(c, op, name);
-}
-
-static PyObject *
-parsenumber(struct compiling *c, char *s)
-{
-	char *end;
-	long x;
-	double dx;
-#ifndef WITHOUT_COMPLEX
-	int imflag;
-#endif
-
-	errno = 0;
-	end = s + strlen(s) - 1;
-#ifndef WITHOUT_COMPLEX
-	imflag = *end == 'j' || *end == 'J';
-#endif
-	if (*end == 'l' || *end == 'L')
-		return PyLong_FromString(s, (char **)0, 0);
-	if (s[0] == '0') {
-		x = (long) PyOS_strtoul(s, &end, 0);
-		if (x < 0 && errno == 0) {
-			return PyLong_FromString(s, (char **)0, 0);
-		}
-	}
-	else
-		x = PyOS_strtol(s, &end, 0);
-	if (*end == '\0') {
-		if (errno != 0)
-			return PyLong_FromString(s, (char **)0, 0);
-		return PyInt_FromLong(x);
-	}
-	/* XXX Huge floats may silently fail */
-#ifndef WITHOUT_COMPLEX
-	if (imflag) {
-		Py_complex z;
-		z.real = 0.;
-		PyFPE_START_PROTECT("atof", return 0)
-		z.imag = PyOS_ascii_atof(s);
-		PyFPE_END_PROTECT(z)
-		return PyComplex_FromCComplex(z);
-	}
-	else
-#endif
-	{
-		PyFPE_START_PROTECT("atof", return 0)
-		dx = PyOS_ascii_atof(s);
-		PyFPE_END_PROTECT(dx)
-		return PyFloat_FromDouble(dx);
-	}
-}
-
-static PyObject *
-decode_utf8(char **sPtr, char *end, char* encoding)
-{
-#ifndef Py_USING_UNICODE
-	Py_FatalError("decode_utf8 should not be called in this build.");
-        return NULL;
-#else
-	PyObject *u, *v;
-	char *s, *t;
-	t = s = *sPtr;
-	/* while (s < end && *s != '\\') s++; */ /* inefficient for u".." */
-	while (s < end && (*s & 0x80)) s++;
-	*sPtr = s;
-	u = PyUnicode_DecodeUTF8(t, s - t, NULL);
-	if (u == NULL)
-		return NULL;
-	v = PyUnicode_AsEncodedString(u, encoding, NULL);
-	Py_DECREF(u);
-	return v;
-#endif
-}
-
-/* compiler.transformer.Transformer.decode_literal depends on what 
-   might seem like minor details of this function -- changes here 
-   must be reflected there. */
-static PyObject *
-parsestr(struct compiling *c, char *s)
-{
-	PyObject *v;
-	size_t len;
-	int quote = *s;
-	int rawmode = 0;
-	char* encoding = ((c == NULL) ? NULL : c->c_encoding);
-	int need_encoding;
-	int unicode = 0;
-
-	if (isalpha(quote) || quote == '_') {
-		if (quote == 'u' || quote == 'U') {
-			quote = *++s;
-			unicode = 1;
-		}
-		if (quote == 'r' || quote == 'R') {
-			quote = *++s;
-			rawmode = 1;
-		}
-	}
-	if (quote != '\'' && quote != '\"') {
-		PyErr_BadInternalCall();
-		return NULL;
-	}
-	s++;
-	len = strlen(s);
-	if (len > INT_MAX) {
-		com_error(c, PyExc_OverflowError, 
-			  "string to parse is too long");
-		return NULL;
-	}
-	if (s[--len] != quote) {
-		PyErr_BadInternalCall();
-		return NULL;
-	}
-	if (len >= 4 && s[0] == quote && s[1] == quote) {
-		s += 2;
-		len -= 2;
-		if (s[--len] != quote || s[--len] != quote) {
-			PyErr_BadInternalCall();
-			return NULL;
-		}
-	}
-#ifdef Py_USING_UNICODE
-	if (unicode || Py_UnicodeFlag) {
-		PyObject *u, *w;
-		char *buf;
-		char *p;
-		char *end;
-		if (encoding == NULL) {
-			buf = s;
-			u = NULL;
-		} else if (strcmp(encoding, "iso-8859-1") == 0) {
-			buf = s;
-			u = NULL;
-		} else {
-			/* "\XX" may become "\u005c\uHHLL" (12 bytes) */
-			u = PyString_FromStringAndSize((char *)NULL, len * 4);
-			if (u == NULL)
-				return NULL;
-			p = buf = PyString_AsString(u);
-			end = s + len;
-			while (s < end) {
-				if (*s == '\\') {
-					*p++ = *s++;
-					if (*s & 0x80) {
-						strcpy(p, "u005c");
-						p += 5;
-					}
-				}
-				if (*s & 0x80) { /* XXX inefficient */
-					char *r;
-					int rn, i;
-					w = decode_utf8(&s, end, "utf-16-be");
-					if (w == NULL) {
-						Py_DECREF(u);
-						return NULL;
-					}
-					r = PyString_AsString(w);
-					rn = PyString_Size(w);
-					assert(rn % 2 == 0);
-					for (i = 0; i < rn; i += 2) {
-						sprintf(p, "\\u%02x%02x",
-							r[i + 0] & 0xFF,
-							r[i + 1] & 0xFF);
-						p += 6;
-					}
-					Py_DECREF(w);
-				} else {
-					*p++ = *s++;
-				}
-			}
-			len = p - buf;
-		}
-		if (rawmode)
-			v = PyUnicode_DecodeRawUnicodeEscape(buf, len, NULL);
-		else
-			v = PyUnicode_DecodeUnicodeEscape(buf, len, NULL);
-		Py_XDECREF(u);
-		if (v == NULL)
-			PyErr_SyntaxLocation(c->c_filename, c->c_lineno);
-		return v;
-			
-	}
-#endif
-	need_encoding = (encoding != NULL &&
-			 strcmp(encoding, "utf-8") != 0 &&
-			 strcmp(encoding, "iso-8859-1") != 0);
-	if (rawmode || strchr(s, '\\') == NULL) {
-		if (need_encoding) {
-#ifndef Py_USING_UNICODE
-			/* This should not happen - we never see any other
-			   encoding. */
-			Py_FatalError("cannot deal with encodings in this build.");
-#else
-			PyObject* u = PyUnicode_DecodeUTF8(s, len, NULL);
-			if (u == NULL)
-				return NULL;
-			v = PyUnicode_AsEncodedString(u, encoding, NULL);
-			Py_DECREF(u);
-			return v;
-#endif
-		} else {
-			return PyString_FromStringAndSize(s, len);
-		}
-	}
-
-	v = PyString_DecodeEscape(s, len, NULL, unicode,
-				  need_encoding ? encoding : NULL);
-	if (v == NULL)
-		PyErr_SyntaxLocation(c->c_filename, c->c_lineno);
-	return v;
-}
-
-static PyObject *
-parsestrplus(struct compiling* c, node *n)
-{
-	PyObject *v;
-	int i;
-	REQ(CHILD(n, 0), STRING);
-	if ((v = parsestr(c, STR(CHILD(n, 0)))) != NULL) {
-		/* String literal concatenation */
-		for (i = 1; i < NCH(n); i++) {
-		    PyObject *s;
-		    s = parsestr(c, STR(CHILD(n, i)));
-		    if (s == NULL)
-			goto onError;
-		    if (PyString_Check(v) && PyString_Check(s)) {
-			PyString_ConcatAndDel(&v, s);
-			if (v == NULL)
-			    goto onError;
-		    }
-#ifdef Py_USING_UNICODE
-		    else {
-			PyObject *temp;
-			temp = PyUnicode_Concat(v, s);
-			Py_DECREF(s);
-			if (temp == NULL)
-			    goto onError;
-			Py_DECREF(v);
-			v = temp;
-		    }
-#endif
-		}
-	}
-	return v;
-
- onError:
-	Py_XDECREF(v);
-	return NULL;
-}
-
-static void
-com_list_for(struct compiling *c, node *n, node *e, char *t)
-{
-	int anchor = 0;
-	int save_begin = c->c_begin;
-
-	/* list_for: for v in expr [list_iter] */
-	com_node(c, CHILD(n, 3)); /* expr */
-	com_addbyte(c, GET_ITER);
-	c->c_begin = c->c_nexti;
-	com_addfwref(c, FOR_ITER, &anchor);
-	com_push(c, 1);
-	com_assign(c, CHILD(n, 1), OP_ASSIGN, NULL);
-	c->c_loops++;
-	com_list_iter(c, n, e, t);
-	c->c_loops--;
-	com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
-	c->c_begin = save_begin;
-	com_backpatch(c, anchor);
-	com_pop(c, 1); /* FOR_ITER has popped this */
-}  
-
-static void
-com_gen_for(struct compiling *c, node *n, node *t, int is_outmost)
-{
-	int break_anchor = 0;
-	int anchor = 0;
-	int save_begin = c->c_begin;
-
-	REQ(n, gen_for);
-	/* gen_for: for v in test [gen_iter] */
-
-	com_addfwref(c, SETUP_LOOP, &break_anchor);
-	block_push(c, SETUP_LOOP);
-
-	if (is_outmost) {
-		com_addop_varname(c, VAR_LOAD, "[outmost-iterable]");
-		com_push(c, 1);
-	}
-	else {
-		com_node(c, CHILD(n, 3));
-		com_addbyte(c, GET_ITER); 
-	}
-
-	c->c_begin = c->c_nexti;
-	com_set_lineno(c, c->c_last_line);
-	com_addfwref(c, FOR_ITER, &anchor);
-	com_push(c, 1);
-	com_assign(c, CHILD(n, 1), OP_ASSIGN, NULL);
-
-	if (NCH(n) == 5) 
-		com_gen_iter(c, CHILD(n, 4), t);
-	else {
-		com_test(c, t);
-		com_addbyte(c, YIELD_VALUE);
-		com_addbyte(c, POP_TOP);
-		com_pop(c, 1);
-	}
-
-	com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
-	c->c_begin = save_begin;
-
-	com_backpatch(c, anchor);
-	com_pop(c, 1); /* FOR_ITER has popped this */
-	com_addbyte(c, POP_BLOCK);
-	block_pop(c, SETUP_LOOP);
-	com_backpatch(c, break_anchor);
-}
-
-static void
-com_list_if(struct compiling *c, node *n, node *e, char *t)
-{
-	int anchor = 0;
-	int a = 0;
-	/* list_iter: 'if' test [list_iter] */
-	com_node(c, CHILD(n, 1));
-	com_addfwref(c, JUMP_IF_FALSE, &a);
-	com_addbyte(c, POP_TOP);
-	com_pop(c, 1);
-	com_list_iter(c, n, e, t);
-	com_addfwref(c, JUMP_FORWARD, &anchor);
-	com_backpatch(c, a);
-	/* We jump here with an extra entry which we now pop */
-	com_addbyte(c, POP_TOP);
-	com_backpatch(c, anchor);
-}
-
-static void
-com_gen_if(struct compiling *c, node *n, node *t)
-{
-	/* gen_if: 'if' test [gen_iter] */
-	int anchor = 0;
-	int a=0;
-
-	com_node(c, CHILD(n, 1));
-	com_addfwref(c, JUMP_IF_FALSE, &a);
-	com_addbyte(c, POP_TOP);
-	com_pop(c, 1);
-
-	if (NCH(n) == 3)
-		com_gen_iter(c, CHILD(n, 2), t);
-	else {
-		com_test(c, t);
-		com_addbyte(c, YIELD_VALUE);
-		com_addbyte(c, POP_TOP);
-		com_pop(c, 1);
-	}
-	com_addfwref(c, JUMP_FORWARD, &anchor);
-	com_backpatch(c, a);
-	/* We jump here with an extra entry which we now pop */
-	com_addbyte(c, POP_TOP);
-	com_backpatch(c, anchor);
-}
-
-static void
-com_list_iter(struct compiling *c,
-	      node *p,		/* parent of list_iter node */
-	      node *e,		/* element expression node */
-	      char *t		/* name of result list temp local */)
-{
-	/* list_iter is the last child in a listmaker, list_for, or list_if */
-	node *n = CHILD(p, NCH(p)-1);
-	if (TYPE(n) == list_iter) {
-		n = CHILD(n, 0);
-		switch (TYPE(n)) {
-		case list_for: 
-			com_list_for(c, n, e, t);
-			break;
-		case list_if:
-			com_list_if(c, n, e, t);
-			break;
-		default:
-			com_error(c, PyExc_SystemError,
-				  "invalid list_iter node type");
-		}
-	}
-	else {
-		com_addop_varname(c, VAR_LOAD, t);
-		com_push(c, 1);
-		com_node(c, e);
-		com_addbyte(c, LIST_APPEND);
-		com_pop(c, 2);
-	}
-}
-
-static void
-com_gen_iter(struct compiling *c, node *n, node *t)
-{
-	/* gen_iter: gen_for | gen_if */
-	node *ch;
-	REQ(n, gen_iter);
-
-	ch = CHILD(n, 0);
-
-	switch (TYPE(ch)) {
-	case gen_for:
-		com_gen_for(c, ch, t, 0);
-		break;
-	case gen_if:
-		com_gen_if(c, ch, t);
-		break;
-	default:
-		com_error(c, PyExc_SystemError,
-			  "invalid gen_iter node type");
-	}
-}
-
-static void
-com_list_comprehension(struct compiling *c, node *n)
-{
-	/* listmaker: test list_for */
-	char tmpname[30];
-
-	REQ(n, listmaker);
-	PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->c_tmpname);
-	com_addoparg(c, BUILD_LIST, 0);
-	com_addbyte(c, DUP_TOP); /* leave the result on the stack */
-	com_push(c, 2);
-	com_addop_varname(c, VAR_STORE, tmpname);
-	com_pop(c, 1);
-	com_list_for(c, CHILD(n, 1), CHILD(n, 0), tmpname);
-	com_addop_varname(c, VAR_DELETE, tmpname);
-	--c->c_tmpname;
-}
-
-static void
-com_listmaker(struct compiling *c, node *n)
-{
-	/* listmaker: test ( list_for | (',' test)* [','] ) */
-	if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == list_for)
-		com_list_comprehension(c, n);
-	else {
-		int len = 0;
-		int i;
-		for (i = 0; i < NCH(n); i += 2, len++)
-			com_node(c, CHILD(n, i));
-		com_addoparg(c, BUILD_LIST, len);
-		com_pop(c, len-1);
-	}
-}
-
-static void
-com_generator_expression(struct compiling *c, node *n)
-{
-	/* testlist_gexp: test gen_for */
-	/* argument: test gen_for */
-	PyCodeObject *co;
-
-	REQ(CHILD(n, 0), test); 
-	REQ(CHILD(n, 1), gen_for); 
-
-	symtable_enter_scope(c->c_symtable, "<genexpr>", TYPE(n),
-		             n->n_lineno);
-	co = icompile(n, c);
-	symtable_exit_scope(c->c_symtable);
-
-	if (co == NULL)
-		c->c_errors++;
-	else {
-		int closure = com_make_closure(c, co);
-		int i = com_addconst(c, (PyObject *)co);
-
-		com_addoparg(c, LOAD_CONST, i);
-		com_push(c, 1);
-		if (closure)
-			com_addoparg(c, MAKE_CLOSURE, 0);
-		else
-			com_addoparg(c, MAKE_FUNCTION, 0);
-
-		com_test(c, CHILD(CHILD(n, 1), 3));
-		com_addbyte(c, GET_ITER);
-		com_addoparg(c, CALL_FUNCTION, 1);
-		com_pop(c, 1);
-
-		Py_DECREF(co);
-	}
-}
-
-static void
-com_testlist_gexp(struct compiling *c, node *n)
-{
-	/* testlist_gexp: test ( gen_for | (',' test)* [','] ) */
-	if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == gen_for)
-		com_generator_expression(c, n);
-	else com_list(c, n, 0);
-}
-
-
-static void
-com_dictmaker(struct compiling *c, node *n)
-{
-	int i;
-	/* dictmaker: test ':' test (',' test ':' value)* [','] */
-	for (i = 0; i+2 < NCH(n); i += 4) {
-		/* We must arrange things just right for STORE_SUBSCR.
-		   It wants the stack to look like (value) (dict) (key) */
-		com_addbyte(c, DUP_TOP);
-		com_push(c, 1);
-		com_node(c, CHILD(n, i)); /* key */
-		com_node(c, CHILD(n, i+2)); /* value */
-		com_addbyte(c, ROT_THREE);
-		com_addbyte(c, STORE_SUBSCR);
-		com_pop(c, 3);
-	}
-}
-
-
-/* forward reference */
-static void com_yield_expr(struct compiling *c, node *n);
-
-static void
-com_atom(struct compiling *c, node *n)
-{
-	node *ch;
-	PyObject *v;
-	int i;
-	REQ(n, atom);
-	ch = CHILD(n, 0);
-	switch (TYPE(ch)) {
-	case LPAR:
-		if (TYPE(CHILD(n, 1)) == RPAR) {
-			com_addoparg(c, BUILD_TUPLE, 0);
-			com_push(c, 1);
-		}
-		else
-			if (TYPE(CHILD(n, 1)) == yield_expr)
-				com_yield_expr(c, CHILD(n, 1));
+	if (d_bytecode > 255) {
+		int i, nbytes, ncodes = d_bytecode / 255;
+		nbytes = a->a_lnotab_off + 2 * ncodes;
+		len = PyString_GET_SIZE(a->a_lnotab);
+		if (nbytes >= len) {
+			if (len * 2 < nbytes)
+				len = nbytes;
 			else
-				com_testlist_gexp(c, CHILD(n, 1));
-		break;
-	case LSQB: /* '[' [listmaker] ']' */
-		if (TYPE(CHILD(n, 1)) == RSQB) {
-			com_addoparg(c, BUILD_LIST, 0);
-			com_push(c, 1);
+				len *= 2;
+			if (_PyString_Resize(&a->a_lnotab, len) < 0)
+				return 0;
 		}
-		else
-			com_listmaker(c, CHILD(n, 1));
-		break;
-	case LBRACE: /* '{' [dictmaker] '}' */
-		com_addoparg(c, BUILD_MAP, 0);
-		com_push(c, 1);
-		if (TYPE(CHILD(n, 1)) == dictmaker)
-			com_dictmaker(c, CHILD(n, 1));
-		break;
-	case BACKQUOTE:
-		com_node(c, CHILD(n, 1));
-		com_addbyte(c, UNARY_CONVERT);
-		break;
-	case NUMBER:
-		if ((v = parsenumber(c, STR(ch))) == NULL) {
-			i = 255;
+		lnotab = PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off;
+		for (i = 0; i < ncodes; i++) {
+			*lnotab++ = 255;
+			*lnotab++ = 0;
 		}
-		else {
-			i = com_addconst(c, v);
-			Py_DECREF(v);
-		}
-		com_addoparg(c, LOAD_CONST, i);
-		com_push(c, 1);
-		break;
-	case STRING:
-		v = parsestrplus(c, n);
-		if (v == NULL) {
-			c->c_errors++;
-			i = 255;
-		}
-		else {
-			i = com_addconst(c, v);
-			Py_DECREF(v);
-		}
-		com_addoparg(c, LOAD_CONST, i);
-		com_push(c, 1);
-		break;
-	case NAME:
-		com_addop_varname(c, VAR_LOAD, STR(ch));
-		com_push(c, 1);
-		break;
-	default:
-		com_error(c, PyExc_SystemError,
-			  "com_atom: unexpected node type");
+		d_bytecode -= ncodes * 255;
+		a->a_lnotab_off += ncodes * 2;
 	}
-}
-
-static void
-com_slice(struct compiling *c, node *n, int op)
-{
-	if (NCH(n) == 1) {
-		com_addbyte(c, op);
-	}
-	else if (NCH(n) == 2) {
-		if (TYPE(CHILD(n, 0)) != COLON) {
-			com_node(c, CHILD(n, 0));
-			com_addbyte(c, op+1);
-		}
-		else {
-			com_node(c, CHILD(n, 1));
-			com_addbyte(c, op+2);
-		}
-		com_pop(c, 1);
-	}
-	else {
-		com_node(c, CHILD(n, 0));
-		com_node(c, CHILD(n, 2));
-		com_addbyte(c, op+3);
-		com_pop(c, 2);
-	}
-}
-
-static void
-com_augassign_slice(struct compiling *c, node *n, int opcode, node *augn)
-{
-	if (NCH(n) == 1) {
-		com_addbyte(c, DUP_TOP);
-		com_push(c, 1);
-		com_addbyte(c, SLICE);
-		com_node(c, augn);
-		com_addbyte(c, opcode);
-		com_pop(c, 1);
-		com_addbyte(c, ROT_TWO);
-		com_addbyte(c, STORE_SLICE);
-		com_pop(c, 2);
-	} else if (NCH(n) == 2 && TYPE(CHILD(n, 0)) != COLON) {
-		com_node(c, CHILD(n, 0));
-		com_addoparg(c, DUP_TOPX, 2);
-		com_push(c, 2);
-		com_addbyte(c, SLICE+1);
-		com_pop(c, 1);
-		com_node(c, augn);
-		com_addbyte(c, opcode);
-		com_pop(c, 1);
-		com_addbyte(c, ROT_THREE);
-		com_addbyte(c, STORE_SLICE+1);
-		com_pop(c, 3);
-	} else if (NCH(n) == 2) {
-		com_node(c, CHILD(n, 1));
-		com_addoparg(c, DUP_TOPX, 2);
-		com_push(c, 2);
-		com_addbyte(c, SLICE+2);
-		com_pop(c, 1);
-		com_node(c, augn);
-		com_addbyte(c, opcode);
-		com_pop(c, 1);
-		com_addbyte(c, ROT_THREE);
-		com_addbyte(c, STORE_SLICE+2);
-		com_pop(c, 3);
-	} else {
-		com_node(c, CHILD(n, 0));
-		com_node(c, CHILD(n, 2));
-		com_addoparg(c, DUP_TOPX, 3);
-		com_push(c, 3);
-		com_addbyte(c, SLICE+3);
-		com_pop(c, 2);
-		com_node(c, augn);
-		com_addbyte(c, opcode);
-		com_pop(c, 1);
-		com_addbyte(c, ROT_FOUR);
-		com_addbyte(c, STORE_SLICE+3);
-		com_pop(c, 4);
-	}
-}
-
-static void
-com_argument(struct compiling *c, node *n, PyObject **pkeywords)
-{
-	node *m;
-	REQ(n, argument); /* [test '='] test [gen_for]; really [keyword '='] test */
-	if (NCH(n) == 1) {
-		if (*pkeywords != NULL) {
-			com_error(c, PyExc_SyntaxError,
-				  "non-keyword arg after keyword arg");
-		}
-		else {
-			com_node(c, CHILD(n, 0));
-		}
-		return;
-	}
-	if (NCH(n) == 2) {
-		com_generator_expression(c, n);
-		return;
-	}
-
-	m = n;
-	do {
-		m = CHILD(m, 0);
-	} while (NCH(m) == 1);
-	if (TYPE(m) != NAME) {
-		/* f(lambda x: x[0] = 3) ends up getting parsed with
-		 * LHS test = lambda x: x[0], and RHS test = 3.
-		 * SF bug 132313 points out that complaining about a keyword
-		 * then is very confusing.
-		 */
-		com_error(c, PyExc_SyntaxError,
-			  TYPE(m) == lambdef ?
-				  "lambda cannot contain assignment" :
-				  "keyword can't be an expression");
-	}
-	else {
-		PyObject *v = PyString_InternFromString(STR(m));
-		(void) none_assignment_check(c, STR(m), 1);
-		if (v != NULL && *pkeywords == NULL)
-			*pkeywords = PyDict_New();
-		if (v == NULL)
-			c->c_errors++;
-		else if (*pkeywords == NULL) {
-			c->c_errors++;
-			Py_DECREF(v);
-		} else {
-			if (PyDict_GetItem(*pkeywords, v) != NULL)
-				com_error(c, PyExc_SyntaxError,
-					  "duplicate keyword argument");
+	assert(d_bytecode <= 255);
+	if (d_lineno > 255) {
+		int i, nbytes, ncodes = d_lineno / 255;
+		nbytes = a->a_lnotab_off + 2 * ncodes;
+		len = PyString_GET_SIZE(a->a_lnotab);
+		if (nbytes >= len) {
+			if (len * 2 < nbytes)
+				len = nbytes;
 			else
-				if (PyDict_SetItem(*pkeywords, v, v) != 0)
-					c->c_errors++;
-			com_addoparg(c, LOAD_CONST, com_addconst(c, v));
-			com_push(c, 1);
-			Py_DECREF(v);
+				len *= 2;
+			if (_PyString_Resize(&a->a_lnotab, len) < 0)
+				return 0;
 		}
-	}
-	com_node(c, CHILD(n, 2));
-}
-
-static void
-com_call_function(struct compiling *c, node *n)
-{
-	if (TYPE(n) == RPAR) {
-		com_addoparg(c, CALL_FUNCTION, 0);
-	}
-	else {
-		PyObject *keywords = NULL;
-		int i, na, nk;
-		int lineno = n->n_lineno;
-		int star_flag = 0;
-		int starstar_flag = 0;
-		int opcode;
-		REQ(n, arglist);
-		na = 0;
-		nk = 0;
-		for (i = 0; i < NCH(n); i += 2) {
-			node *ch = CHILD(n, i);
-			if (TYPE(ch) == STAR ||
-			    TYPE(ch) == DOUBLESTAR)
-			  break;
-			if (ch->n_lineno != lineno) {
-				lineno = ch->n_lineno;
-				com_set_lineno(c, lineno);
-			}
-			com_argument(c, ch, &keywords);
-			if (keywords == NULL)
-				na++;
-			else
-				nk++;
+		lnotab = PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off;
+		*lnotab++ = 255;
+		*lnotab++ = d_bytecode;
+		d_bytecode = 0;
+		for (i = 1; i < ncodes; i++) {
+			*lnotab++ = 255;
+			*lnotab++ = 0;
 		}
-		Py_XDECREF(keywords);
-		while (i < NCH(n)) {
-		    node *tok = CHILD(n, i);
-		    node *ch = CHILD(n, i+1);
-		    i += 3;
-		    switch (TYPE(tok)) {
-		    case STAR:       star_flag = 1;     break;
-		    case DOUBLESTAR: starstar_flag = 1;	break;
-		    }
-		    com_node(c, ch);
-		}
-		if (na > 255 || nk > 255) {
-			com_error(c, PyExc_SyntaxError,
-				  "more than 255 arguments");
-		}
-		if (star_flag || starstar_flag)
-		    opcode = CALL_FUNCTION_VAR - 1 + 
-			star_flag + (starstar_flag << 1);
-		else
-		    opcode = CALL_FUNCTION;
-		com_addoparg(c, opcode, na | (nk << 8));
-		com_pop(c, na + 2*nk + star_flag + starstar_flag);
+		d_lineno -= ncodes * 255;
+		a->a_lnotab_off += ncodes * 2;
 	}
-}
 
-static void
-com_select_member(struct compiling *c, node *n)
-{
-	com_addopname(c, LOAD_ATTR, n);
-}
-
-static void
-com_sliceobj(struct compiling *c, node *n)
-{
-	int i=0;
-	int ns=2; /* number of slice arguments */
-	node *ch;
-
-	/* first argument */
-	if (TYPE(CHILD(n,i)) == COLON) {
-		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-		com_push(c, 1);
-		i++;
-	}
-	else {
-		com_node(c, CHILD(n,i));
-		i++;
-		REQ(CHILD(n,i),COLON);
-		i++;
-	}
-	/* second argument */
-	if (i < NCH(n) && TYPE(CHILD(n,i)) == test) {
-		com_node(c, CHILD(n,i));
-		i++;
-	}
-	else {
-		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-		com_push(c, 1);
-	}
-	/* remaining arguments */
-	for (; i < NCH(n); i++) {
-		ns++;
-		ch=CHILD(n,i);
-		REQ(ch, sliceop);
-		if (NCH(ch) == 1) {
-			/* right argument of ':' missing */
-			com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-			com_push(c, 1);
-		}
-		else
-			com_node(c, CHILD(ch,1));
-	}
-	com_addoparg(c, BUILD_SLICE, ns);
-	com_pop(c, 1 + (ns == 3));
-}
-
-static void
-com_subscript(struct compiling *c, node *n)
-{
-	node *ch;
-	REQ(n, subscript);
-	ch = CHILD(n,0);
-	/* check for rubber index */
-	if (TYPE(ch) == DOT && TYPE(CHILD(n,1)) == DOT) {
-		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_Ellipsis));
-		com_push(c, 1);
-	}
-	else {
-		/* check for slice */
-		if ((TYPE(ch) == COLON || NCH(n) > 1))
-			com_sliceobj(c, n);
-		else {
-			REQ(ch, test);
-			com_node(c, ch);
-		}
-	}
-}
-
-static void
-com_subscriptlist(struct compiling *c, node *n, int assigning, node *augn)
-{
-	int i, op;
-	REQ(n, subscriptlist);
-	/* Check to make backward compatible slice behavior for '[i:j]' */
-	if (NCH(n) == 1) {
-		node *sub = CHILD(n, 0); /* subscript */
-		/* 'Basic' slice, should have exactly one colon. */
-		if ((TYPE(CHILD(sub, 0)) == COLON
-		     || (NCH(sub) > 1 && TYPE(CHILD(sub, 1)) == COLON))
-		    && (TYPE(CHILD(sub,NCH(sub)-1)) != sliceop))
-		{
-			switch (assigning) {
-			case OP_DELETE:
-				op = DELETE_SLICE;
-				break;
-			case OP_ASSIGN:
-				op = STORE_SLICE;
-				break;
-			case OP_APPLY:
-				op = SLICE;
-				break;
-			default:
-				com_augassign_slice(c, sub, assigning, augn);
-				return;
-			}
-			com_slice(c, sub, op);
-			if (op == STORE_SLICE)
-				com_pop(c, 2);
-			else if (op == DELETE_SLICE)
-				com_pop(c, 1);
-			return;
-		}
-	}
-	/* Else normal subscriptlist.  Compile each subscript. */
-	for (i = 0; i < NCH(n); i += 2)
-		com_subscript(c, CHILD(n, i));
-	/* Put multiple subscripts into a tuple */
-	if (NCH(n) > 1) {
-		i = (NCH(n)+1) / 2;
-		com_addoparg(c, BUILD_TUPLE, i);
-		com_pop(c, i-1);
-	}
-	switch (assigning) {
-	case OP_DELETE:
-		op = DELETE_SUBSCR;
-		i = 2;
-		break;
-	default:
-	case OP_ASSIGN:
-		op = STORE_SUBSCR;
-		i = 3;
-		break;
-	case OP_APPLY:
-		op = BINARY_SUBSCR;
-		i = 1;
-		break;
-	}
-	if (assigning > OP_APPLY) {
-		com_addoparg(c, DUP_TOPX, 2);
-		com_push(c, 2);
-		com_addbyte(c, BINARY_SUBSCR);
-		com_pop(c, 1);
-		com_node(c, augn);
-		com_addbyte(c, assigning);
-		com_pop(c, 1);
-		com_addbyte(c, ROT_THREE);
-	}
-	com_addbyte(c, op);
-	com_pop(c, i);
-}
-
-static void
-com_apply_trailer(struct compiling *c, node *n)
-{
-	REQ(n, trailer);
-	switch (TYPE(CHILD(n, 0))) {
-	case LPAR:
-		com_call_function(c, CHILD(n, 1));
-		break;
-	case DOT:
-		com_select_member(c, CHILD(n, 1));
-		break;
-	case LSQB:
-		com_subscriptlist(c, CHILD(n, 1), OP_APPLY, NULL);
-		break;
-	default:
-		com_error(c, PyExc_SystemError,
-			  "com_apply_trailer: unknown trailer type");
-	}
-}
-
-static void
-com_power(struct compiling *c, node *n)
-{
-	int i;
-	REQ(n, power);
-	com_atom(c, CHILD(n, 0));
-	for (i = 1; i < NCH(n); i++) {
-		if (TYPE(CHILD(n, i)) == DOUBLESTAR) {
-			com_factor(c, CHILD(n, i+1));
-			com_addbyte(c, BINARY_POWER);
-			com_pop(c, 1);
-			break;
-		}
-		else
-			com_apply_trailer(c, CHILD(n, i));
-	}
-}
-
-static void
-com_invert_constant(struct compiling *c, node *n)
-{
-	/* Compute the inverse of int and longs and use them directly,
-	   but be prepared to generate code for all other
-	   possibilities (invalid numbers, floats, complex).
-	*/
-	PyObject *num, *inv = NULL;
-	int i;
-
-	REQ(n, NUMBER);
-	num = parsenumber(c, STR(n));
-	if (num == NULL) 
-		i = 255;
-	else {
-		inv = PyNumber_Invert(num);
-		if (inv == NULL) {
-			PyErr_Clear();
-			i = com_addconst(c, num);
-		} else {
-			i = com_addconst(c, inv);
-			Py_DECREF(inv);
-		}
-		Py_DECREF(num);
-	}
-	com_addoparg(c, LOAD_CONST, i);
-	com_push(c, 1);
-	if (num != NULL && inv == NULL)
-		com_addbyte(c, UNARY_INVERT);
-}
-
-static int
-is_float_zero(const char *p)
-{
-	int found_radix_point = 0;
-	int ch;
-	while ((ch = Py_CHARMASK(*p++)) != '\0') {
-		switch (ch) {
-		case '0':
-			/* no reason to believe it's not 0 -- continue */
-			break;
-
-		case 'e': case 'E': case 'j': case 'J':
-			/* If this was a hex constant, we already would have
-			   returned 0 due to the 'x' or 'X', so 'e' or 'E'
-			   must be an exponent marker, and we haven't yet
-			   seen a non-zero digit, and it doesn't matter what
-			   the exponent is then.  For 'j' or 'J' similarly,
-			   except that this is an imaginary 0 then. */
-			return 1;
-
-		case '.':
-			found_radix_point = 1;
-			break;
-
-		default:
+	len = PyString_GET_SIZE(a->a_lnotab);
+	if (a->a_lnotab_off + 2 >= len) {
+		if (_PyString_Resize(&a->a_lnotab, len * 2) < 0)
 			return 0;
-		}
 	}
-	return found_radix_point;
-}
+	lnotab = PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off;
 
-static void
-com_factor(struct compiling *c, node *n)
-{
-	int childtype = TYPE(CHILD(n, 0));
-	node *pfactor, *ppower, *patom, *pnum;
-	REQ(n, factor);
-	/* If the unary +, -, or ~ operator is applied to a constant,
-	   don't generate a UNARY_xxx opcode.  Just store the
-	   approriate value as a constant.  If the value is negative,
-	   extend the string containing the constant and insert a
-	   negative in the 0th position -- unless we're doing unary minus
-	   of a floating zero!  In that case the sign is significant, but
-	   the const dict can't distinguish +0.0 from -0.0.
-	 */
-	if ((childtype == PLUS || childtype == MINUS || childtype == TILDE)
-	    && NCH(n) == 2
-	    && TYPE((pfactor = CHILD(n, 1))) == factor
- 	    && NCH(pfactor) == 1
-	    && TYPE((ppower = CHILD(pfactor, 0))) == power
- 	    && NCH(ppower) == 1
-	    && TYPE((patom = CHILD(ppower, 0))) == atom
-	    && TYPE((pnum = CHILD(patom, 0))) == NUMBER
-	    && !(childtype == MINUS &&
-		 (STR(pnum)[0] == '0' || is_float_zero(STR(pnum))))) {
-		if (childtype == TILDE) {
-			com_invert_constant(c, pnum);
-			return;
-		}
-		if (childtype == MINUS) {
-			char *s = PyObject_MALLOC(strlen(STR(pnum)) + 2);
-			if (s == NULL) {
-				com_error(c, PyExc_MemoryError, "");
-				com_addbyte(c, 255);
-				return;
-			}
-			s[0] = '-';
-			strcpy(s + 1, STR(pnum));
-			PyObject_FREE(STR(pnum));
-			STR(pnum) = s;
-		}
-		com_atom(c, patom);
+	a->a_lnotab_off += 2;
+	if (d_bytecode) {
+		*lnotab++ = d_bytecode;
+		*lnotab++ = d_lineno;
 	}
-	else if (childtype == PLUS) {
-		com_factor(c, CHILD(n, 1));
-		com_addbyte(c, UNARY_POSITIVE);
+	else {  /* First line of a block; def stmt, etc. */
+		*lnotab++ = 0;
+		*lnotab++ = d_lineno;
 	}
-	else if (childtype == MINUS) {
-		com_factor(c, CHILD(n, 1));
-		com_addbyte(c, UNARY_NEGATIVE);
-	}
-	else if (childtype == TILDE) {
-		com_factor(c, CHILD(n, 1));
-		com_addbyte(c, UNARY_INVERT);
-	}
-	else {
-		com_power(c, CHILD(n, 0));
-	}
-}
-
-static void
-com_term(struct compiling *c, node *n)
-{
-	int i;
-	int op;
-	REQ(n, term);
-	com_factor(c, CHILD(n, 0));
-	for (i = 2; i < NCH(n); i += 2) {
-		com_factor(c, CHILD(n, i));
-		switch (TYPE(CHILD(n, i-1))) {
-		case STAR:
-			op = BINARY_MULTIPLY;
-			break;
-		case SLASH:
-			if (c->c_flags & CO_FUTURE_DIVISION)
-				op = BINARY_TRUE_DIVIDE;
-			else
-				op = BINARY_DIVIDE;
-			break;
-		case PERCENT:
-			op = BINARY_MODULO;
-			break;
-		case DOUBLESLASH:
-			op = BINARY_FLOOR_DIVIDE;
-			break;
-		default:
-			com_error(c, PyExc_SystemError,
-				  "com_term: operator not *, /, // or %");
-			op = 255;
-		}
-		com_addbyte(c, op);
-		com_pop(c, 1);
-	}
-}
-
-static void
-com_arith_expr(struct compiling *c, node *n)
-{
-	int i;
-	int op;
-	REQ(n, arith_expr);
-	com_term(c, CHILD(n, 0));
-	for (i = 2; i < NCH(n); i += 2) {
-		com_term(c, CHILD(n, i));
-		switch (TYPE(CHILD(n, i-1))) {
-		case PLUS:
-			op = BINARY_ADD;
-			break;
-		case MINUS:
-			op = BINARY_SUBTRACT;
-			break;
-		default:
-			com_error(c, PyExc_SystemError,
-				  "com_arith_expr: operator not + or -");
-			op = 255;
-		}
-		com_addbyte(c, op);
-		com_pop(c, 1);
-	}
-}
-
-static void
-com_shift_expr(struct compiling *c, node *n)
-{
-	int i;
-	int op;
-	REQ(n, shift_expr);
-	com_arith_expr(c, CHILD(n, 0));
-	for (i = 2; i < NCH(n); i += 2) {
-		com_arith_expr(c, CHILD(n, i));
-		switch (TYPE(CHILD(n, i-1))) {
-		case LEFTSHIFT:
-			op = BINARY_LSHIFT;
-			break;
-		case RIGHTSHIFT:
-			op = BINARY_RSHIFT;
-			break;
-		default:
-			com_error(c, PyExc_SystemError,
-				  "com_shift_expr: operator not << or >>");
-			op = 255;
-		}
-		com_addbyte(c, op);
-		com_pop(c, 1);
-	}
-}
-
-static void
-com_and_expr(struct compiling *c, node *n)
-{
-	int i;
-	int op;
-	REQ(n, and_expr);
-	com_shift_expr(c, CHILD(n, 0));
-	for (i = 2; i < NCH(n); i += 2) {
-		com_shift_expr(c, CHILD(n, i));
-		if (TYPE(CHILD(n, i-1)) == AMPER) {
-			op = BINARY_AND;
-		}
-		else {
-			com_error(c, PyExc_SystemError,
-				  "com_and_expr: operator not &");
-			op = 255;
-		}
-		com_addbyte(c, op);
-		com_pop(c, 1);
-	}
-}
-
-static void
-com_xor_expr(struct compiling *c, node *n)
-{
-	int i;
-	int op;
-	REQ(n, xor_expr);
-	com_and_expr(c, CHILD(n, 0));
-	for (i = 2; i < NCH(n); i += 2) {
-		com_and_expr(c, CHILD(n, i));
-		if (TYPE(CHILD(n, i-1)) == CIRCUMFLEX) {
-			op = BINARY_XOR;
-		}
-		else {
-			com_error(c, PyExc_SystemError,
-				  "com_xor_expr: operator not ^");
-			op = 255;
-		}
-		com_addbyte(c, op);
-		com_pop(c, 1);
-	}
-}
-
-static void
-com_expr(struct compiling *c, node *n)
-{
-	int i;
-	int op;
-	REQ(n, expr);
-	com_xor_expr(c, CHILD(n, 0));
-	for (i = 2; i < NCH(n); i += 2) {
-		com_xor_expr(c, CHILD(n, i));
-		if (TYPE(CHILD(n, i-1)) == VBAR) {
-			op = BINARY_OR;
-		}
-		else {
-			com_error(c, PyExc_SystemError,
-				  "com_expr: expr operator not |");
-			op = 255;
-		}
-		com_addbyte(c, op);
-		com_pop(c, 1);
-	}
-}
-
-static enum cmp_op
-cmp_type(node *n)
-{
-	REQ(n, comp_op);
-	/* comp_op: '<' | '>' | '>=' | '<=' | '<>' | '!=' | '=='
-	          | 'in' | 'not' 'in' | 'is' | 'is' not' */
-	if (NCH(n) == 1) {
-		n = CHILD(n, 0);
-		switch (TYPE(n)) {
-		case LESS:	return PyCmp_LT;
-		case GREATER:	return PyCmp_GT;
-		case EQEQUAL:	return PyCmp_EQ;
-		case LESSEQUAL:	return PyCmp_LE;
-		case GREATEREQUAL: return PyCmp_GE;
-		case NOTEQUAL:	return PyCmp_NE;	/* <> or != */
-		case NAME:	if (strcmp(STR(n), "in") == 0) return PyCmp_IN;
-				if (strcmp(STR(n), "is") == 0) return PyCmp_IS;
-		}
-	}
-	else if (NCH(n) == 2) {
-		switch (TYPE(CHILD(n, 0))) {
-		case NAME:	if (strcmp(STR(CHILD(n, 1)), "in") == 0)
-					return PyCmp_NOT_IN;
-				if (strcmp(STR(CHILD(n, 0)), "is") == 0)
-					return PyCmp_IS_NOT;
-		}
-	}
-	return PyCmp_BAD;
-}
-
-static void
-com_comparison(struct compiling *c, node *n)
-{
-	int i;
-	enum cmp_op op;
-	int anchor;
-	REQ(n, comparison); /* comparison: expr (comp_op expr)* */
-	com_expr(c, CHILD(n, 0));
-	if (NCH(n) == 1)
-		return;
-	
-	/****************************************************************
-	   The following code is generated for all but the last
-	   comparison in a chain:
-	   
-	   label:	on stack:	opcode:		jump to:
-	   
-			a		<code to load b>
-			a, b		DUP_TOP
-			a, b, b		ROT_THREE
-			b, a, b		COMPARE_OP
-			b, 0-or-1	JUMP_IF_FALSE	L1
-			b, 1		POP_TOP
-			b		
-	
-	   We are now ready to repeat this sequence for the next
-	   comparison in the chain.
-	   
-	   For the last we generate:
-	   
-	   		b		<code to load c>
-	   		b, c		COMPARE_OP
-	   		0-or-1		
-	   
-	   If there were any jumps to L1 (i.e., there was more than one
-	   comparison), we generate:
-	   
-	   		0-or-1		JUMP_FORWARD	L2
-	   L1:		b, 0		ROT_TWO
-	   		0, b		POP_TOP
-	   		0
-	   L2:		0-or-1
-	****************************************************************/
-	
-	anchor = 0;
-	
-	for (i = 2; i < NCH(n); i += 2) {
-		com_expr(c, CHILD(n, i));
-		if (i+2 < NCH(n)) {
-			com_addbyte(c, DUP_TOP);
-			com_push(c, 1);
-			com_addbyte(c, ROT_THREE);
-		}
-		op = cmp_type(CHILD(n, i-1));
-		if (op == PyCmp_BAD) {
-			com_error(c, PyExc_SystemError,
-				  "com_comparison: unknown comparison op");
-		}
-		com_addoparg(c, COMPARE_OP, op);
-		com_pop(c, 1);
-		if (i+2 < NCH(n)) {
-			com_addfwref(c, JUMP_IF_FALSE, &anchor);
-			com_addbyte(c, POP_TOP);
-			com_pop(c, 1);
-		}
-	}
-	
-	if (anchor) {
-		int anchor2 = 0;
-		com_addfwref(c, JUMP_FORWARD, &anchor2);
-		com_backpatch(c, anchor);
-		com_addbyte(c, ROT_TWO);
-		com_addbyte(c, POP_TOP);
-		com_backpatch(c, anchor2);
-	}
-}
-
-static void
-com_not_test(struct compiling *c, node *n)
-{
-	REQ(n, not_test); /* 'not' not_test | comparison */
-	if (NCH(n) == 1) {
-		com_comparison(c, CHILD(n, 0));
-	}
-	else {
-		com_not_test(c, CHILD(n, 1));
-		com_addbyte(c, UNARY_NOT);
-	}
-}
-
-static void
-com_and_test(struct compiling *c, node *n)
-{
-	int i;
-	int anchor;
-	REQ(n, and_test); /* not_test ('and' not_test)* */
-	anchor = 0;
-	i = 0;
-	for (;;) {
-		com_not_test(c, CHILD(n, i));
-		if ((i += 2) >= NCH(n))
-			break;
-		com_addfwref(c, JUMP_IF_FALSE, &anchor);
-		com_addbyte(c, POP_TOP);
-		com_pop(c, 1);
-	}
-	if (anchor)
-		com_backpatch(c, anchor);
-}
-
-static int
-com_make_closure(struct compiling *c, PyCodeObject *co)
-{
-	int i, free = PyCode_GetNumFree(co);
-	if (free == 0)
-		return 0;
-	for (i = 0; i < free; ++i) {
-		/* Bypass com_addop_varname because it will generate
-		   LOAD_DEREF but LOAD_CLOSURE is needed. 
-		*/
-		PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
-		int arg, reftype;
-
-		/* Special case: If a class contains a method with a
-		   free variable that has the same name as a method,
-		   the name will be considered free *and* local in the
-		   class.  It should be handled by the closure, as
-		   well as by the normal name loookup logic.
-		*/
-		reftype = get_ref_type(c, PyString_AS_STRING(name));	
-		if (reftype == CELL)
-			arg = com_lookup_arg(c->c_cellvars, name);
-		else /* (reftype == FREE) */
-			arg = com_lookup_arg(c->c_freevars, name);
-		if (arg == -1) {
-			fprintf(stderr, "lookup %s in %s %d %d\n"
-				"freevars of %s: %s\n",
-				PyObject_REPR(name), 
-				c->c_name, 
-				reftype, arg,
-				PyString_AS_STRING(co->co_name),
-				PyObject_REPR(co->co_freevars));
-			Py_FatalError("com_make_closure()");
-		}
-		com_addoparg(c, LOAD_CLOSURE, arg);
-
-	}
-	com_push(c, free);
+	a->a_lineno = i->i_lineno;
+	a->a_lineno_off = a->a_offset;
 	return 1;
 }
 
-static void
-com_test(struct compiling *c, node *n)
-{
-	REQ(n, test); /* and_test ('or' and_test)* | lambdef */
-	if (NCH(n) == 1 && TYPE(CHILD(n, 0)) == lambdef) {
-		PyCodeObject *co;
-		int i, closure;
-		int ndefs = com_argdefs(c, CHILD(n, 0));
-		symtable_enter_scope(c->c_symtable, "lambda", lambdef,
-				     n->n_lineno);
-		co = icompile(CHILD(n, 0), c);
-		if (co == NULL) {
-			c->c_errors++;
-			return;
-		}
-		symtable_exit_scope(c->c_symtable);
-		i = com_addconst(c, (PyObject *)co);
-		closure = com_make_closure(c, co);
-		com_addoparg(c, LOAD_CONST, i);
-		com_push(c, 1);
-		if (closure) {
-			com_addoparg(c, MAKE_CLOSURE, ndefs);
-			com_pop(c, PyCode_GetNumFree(co));
-		} else
-			com_addoparg(c, MAKE_FUNCTION, ndefs);
-		Py_DECREF(co);
-		com_pop(c, ndefs);
-	}
-	else {
-		int anchor = 0;
-		int i = 0;
-		for (;;) {
-			com_and_test(c, CHILD(n, i));
-			if ((i += 2) >= NCH(n))
-				break;
-			com_addfwref(c, JUMP_IF_TRUE, &anchor);
-			com_addbyte(c, POP_TOP);
-			com_pop(c, 1);
-		}
-		if (anchor)
-			com_backpatch(c, anchor);
-	}
-}
-
-static void
-com_list(struct compiling *c, node *n, int toplevel)
-{
-	/* exprlist: expr (',' expr)* [',']; likewise for testlist */
-	if (NCH(n) == 1 && !toplevel) {
-		com_node(c, CHILD(n, 0));
-	}
-	else {
-		int i;
-		int len;
-		len = (NCH(n) + 1) / 2;
-		for (i = 0; i < NCH(n); i += 2)
-			com_node(c, CHILD(n, i));
-		com_addoparg(c, BUILD_TUPLE, len);
-		com_pop(c, len-1);
-	}
-}
-
-
-/* Begin of assignment compilation */
-
-
-static void
-com_augassign_attr(struct compiling *c, node *n, int opcode, node *augn)
-{
-	com_addbyte(c, DUP_TOP);
-	com_push(c, 1);
-	com_addopname(c, LOAD_ATTR, n);
-	com_node(c, augn);
-	com_addbyte(c, opcode);
-	com_pop(c, 1);
-	com_addbyte(c, ROT_TWO);
-	com_addopname(c, STORE_ATTR, n);
-	com_pop(c, 2);
-}
-
-static void
-com_assign_attr(struct compiling *c, node *n, int assigning)
-{
-	if (none_assignment_check(c, STR(n), assigning))
-		return;
-	com_addopname(c, assigning ? STORE_ATTR : DELETE_ATTR, n);
-	com_pop(c, assigning ? 2 : 1);
-}
-
-static void
-com_assign_trailer(struct compiling *c, node *n, int assigning, node *augn)
-{
-	REQ(n, trailer);
-	switch (TYPE(CHILD(n, 0))) {
-	case LPAR: /* '(' [exprlist] ')' */
-		if (assigning == OP_DELETE)
-			com_error(c, PyExc_SyntaxError,
-				  "can't delete function call");
-		else
-			com_error(c, PyExc_SyntaxError,
-				  "can't assign to function call");
-		break;
-	case DOT: /* '.' NAME */
-		if (assigning > OP_APPLY)
-			com_augassign_attr(c, CHILD(n, 1), assigning, augn);
-		else
-			com_assign_attr(c, CHILD(n, 1), assigning);
-		break;
-	case LSQB: /* '[' subscriptlist ']' */
-		com_subscriptlist(c, CHILD(n, 1), assigning, augn);
-		break;
-	default:
-		com_error(c, PyExc_SystemError, "unknown trailer type");
-	}
-}
-
-static void
-com_assign_sequence(struct compiling *c, node *n, int assigning)
-{
-	int i;
-	if (TYPE(n) != testlist && TYPE(n) != testlist_gexp &&
-	    TYPE(n) != listmaker)
-		REQ(n, exprlist);
-	if (assigning) {
-		i = (NCH(n)+1)/2;
-		com_addoparg(c, UNPACK_SEQUENCE, i);
-		com_push(c, i-1);
-	}
-	for (i = 0; i < NCH(n); i += 2)
-		com_assign(c, CHILD(n, i), assigning, NULL);
-}
-
-static void
-com_augassign_name(struct compiling *c, node *n, int opcode, node *augn)
-{
-	REQ(n, NAME);
-	com_addop_varname(c, VAR_LOAD, STR(n));
-	com_push(c, 1);
-	com_node(c, augn);
-	com_addbyte(c, opcode);
-	com_pop(c, 1);
-	com_assign_name(c, n, OP_ASSIGN);
-}
-
-static void
-com_assign_name(struct compiling *c, node *n, int assigning)
-{
-	REQ(n, NAME);
-	com_addop_varname(c, assigning ? VAR_STORE : VAR_DELETE, STR(n));
-	if (assigning)
-		com_pop(c, 1);
-}
-
-static void
-com_assign(struct compiling *c, node *n, int assigning, node *augn)
-{
-	/* Loop to avoid trivial recursion */
-	for (;;) {
-		switch (TYPE(n)) {
-		
-		case exprlist:
-		case testlist:
-		case testlist1:
-		case testlist_gexp:
-			if (NCH(n) > 1) {
-				if (TYPE(CHILD(n, 1)) == gen_for) {
-					com_error(c, PyExc_SyntaxError,
-				  "assign to generator expression not possible");
-					return;
-				}
-				if (assigning > OP_APPLY) {
-					com_error(c, PyExc_SyntaxError,
-				  "augmented assign to generator expression not possible");
-					return;
-				}
-				com_assign_sequence(c, n, assigning);
-				return;
-			}
-			n = CHILD(n, 0);
-			break;
-		case yield_expr:
-			com_error(c, PyExc_SyntaxError,
-			  "assignment to yield expression not possible");
-			return;
-					
-		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:
-			if (NCH(n) > 1) {
-				com_error(c, PyExc_SyntaxError,
-					  "can't assign to operator");
-				return;
-			}
-			n = CHILD(n, 0);
-			break;
-		
-		case power: /* atom trailer* ('**' power)*
-                              ('+'|'-'|'~') factor | atom trailer* */
-			if (TYPE(CHILD(n, 0)) != atom) {
-				com_error(c, PyExc_SyntaxError,
-					  "can't assign to operator");
-				return;
-			}
-			if (NCH(n) > 1) { /* trailer or exponent present */
-				int i;
-				com_node(c, CHILD(n, 0));
-				for (i = 1; i+1 < NCH(n); i++) {
-					if (TYPE(CHILD(n, i)) == DOUBLESTAR) {
-						com_error(c, PyExc_SyntaxError,
-						  "can't assign to operator");
-						return;
-					}
-					com_apply_trailer(c, CHILD(n, i));
-				} /* NB i is still alive */
-				com_assign_trailer(c,
-						CHILD(n, i), assigning, augn);
-				return;
-			}
-			n = CHILD(n, 0);
-			break;
-		
-		case atom:
-			switch (TYPE(CHILD(n, 0))) {
-			case LPAR:
-				n = CHILD(n, 1);
-				if (TYPE(n) == RPAR) {
-					/* XXX Should allow () = () ??? */
-					com_error(c, PyExc_SyntaxError,
-						  "can't assign to ()");
-					return;
-				}
-				if (assigning > OP_APPLY) {
-					com_error(c, PyExc_SyntaxError,
-				  "augmented assign to tuple literal, yield, or generator expression not possible");
-					return;
-				}
-				break;
-			case LSQB:
-				n = CHILD(n, 1);
-				if (TYPE(n) == RSQB) {
-					com_error(c, PyExc_SyntaxError,
-						  "can't assign to []");
-					return;
-				}
-				if (assigning > OP_APPLY) {
-					com_error(c, PyExc_SyntaxError,
-				  "augmented assign to list literal or comprehension not possible");
-					return;
-				}
-				if (NCH(n) > 1 
-				    && TYPE(CHILD(n, 1)) == list_for) {
-					com_error(c, PyExc_SyntaxError,
-				  "can't assign to list comprehension");
-					return;
-				}
-				com_assign_sequence(c, n, assigning);
-				return;
-			case NAME:
-				if (assigning > OP_APPLY)
-					com_augassign_name(c, CHILD(n, 0),
-							   assigning, augn);
-				else
-					com_assign_name(c, CHILD(n, 0),
-							assigning);
-				return;
-			default:
-				com_error(c, PyExc_SyntaxError,
-					  "can't assign to literal");
-				return;
-			}
-			break;
-
-		case lambdef:
-			com_error(c, PyExc_SyntaxError,
-				  "can't assign to lambda");
-			return;
-		
-		default:
-			com_error(c, PyExc_SystemError,
-				  "com_assign: bad node");
-			return;
-		
-		}
-	}
-}
-
-static void
-com_augassign(struct compiling *c, node *n)
-{
-	int opcode;
-
-	switch (STR(CHILD(CHILD(n, 1), 0))[0]) {
-	case '+': opcode = INPLACE_ADD; break;
-	case '-': opcode = INPLACE_SUBTRACT; break;
-	case '/':
-		if (STR(CHILD(CHILD(n, 1), 0))[1] == '/')
-			opcode = INPLACE_FLOOR_DIVIDE;
-		else if (c->c_flags & CO_FUTURE_DIVISION)
-			opcode = INPLACE_TRUE_DIVIDE;
-		else
-			opcode = INPLACE_DIVIDE;
-		break;
-	case '%': opcode = INPLACE_MODULO; break;
-	case '<': opcode = INPLACE_LSHIFT; break;
-	case '>': opcode = INPLACE_RSHIFT; break;
-	case '&': opcode = INPLACE_AND; break;
-	case '^': opcode = INPLACE_XOR; break;
-	case '|': opcode = INPLACE_OR; break;
-	case '*':
-		if (STR(CHILD(CHILD(n, 1), 0))[1] == '*')
-			opcode = INPLACE_POWER;
-		else
-			opcode = INPLACE_MULTIPLY;
-		break;
-	default:
-		com_error(c, PyExc_SystemError, "com_augassign: bad operator");
-		return;
-	}
-	com_assign(c, CHILD(n, 0), opcode, CHILD(n, 2));
-}
-
-static void
-com_expr_stmt(struct compiling *c, node *n)
-{
-	REQ(n, expr_stmt);
-	/* testlist (('=' testlist)* | augassign testlist) */
-	/* Forget it if we have just a doc string here */
-	if (!c->c_interactive && NCH(n) == 1 && get_rawdocstring(n) != NULL)
-		return;
- 	if (NCH(n) == 1) {
-		com_node(c, CHILD(n, NCH(n)-1));
-		if (c->c_interactive)
-			com_addbyte(c, PRINT_EXPR);
-		else
-			com_addbyte(c, POP_TOP);
-		com_pop(c, 1);
-	}
-	else if (TYPE(CHILD(n,1)) == augassign)
-		com_augassign(c, n);
-	else {
-		int i;
-		com_node(c, CHILD(n, NCH(n)-1));
-		for (i = 0; i < NCH(n)-2; i+=2) {
-			if (i+2 < NCH(n)-2) {
-				com_addbyte(c, DUP_TOP);
-				com_push(c, 1);
-			}
-			com_assign(c, CHILD(n, i), OP_ASSIGN, NULL);
-		}
-	}
-}
-
-static void
-com_assert_stmt(struct compiling *c, node *n)
-{
-	int a = 0;
-	int i;
-	REQ(n, assert_stmt); /* 'assert' test [',' test] */
-	if (Py_OptimizeFlag)
-		return;
-	/* Generate code like
-	   
-	     if not <test>:
-	         raise AssertionError [, <message>]
-
-	   where <message> is the second test, if present.
-	*/
-	com_node(c, CHILD(n, 1));
-	com_addfwref(c, JUMP_IF_TRUE, &a);
-	com_addbyte(c, POP_TOP);
-	com_pop(c, 1);
-	/* Raise that exception! */
-	com_addop_name(c, LOAD_GLOBAL, "AssertionError");
-	com_push(c, 1);
-	i = NCH(n)/2; /* Either 2 or 4 */
-	if (i > 1)
-		com_node(c, CHILD(n, 3));
-	com_addoparg(c, RAISE_VARARGS, i);
-	com_pop(c, i);
-	/* The interpreter does not fall through */
-	/* Jump ends up here */
-	com_backpatch(c, a);
-	com_addbyte(c, POP_TOP);
-}
-
-static void
-com_print_stmt(struct compiling *c, node *n)
-{
-	int i = 1;
-	node* stream = NULL;
-
-	REQ(n, print_stmt); /* 'print' (test ',')* [test] */
-
-	/* are we using the extended print form? */
-	if (NCH(n) >= 2 && TYPE(CHILD(n, 1)) == RIGHTSHIFT) {
-		stream = CHILD(n, 2);
-		com_node(c, stream);
-		/* stack: [...] => [... stream] */
-		com_push(c, 1);
-		if (NCH(n) > 3 && TYPE(CHILD(n, 3)) == COMMA)
-			i = 4;
-		else
-			i = 3;
-	}
-	for (; i < NCH(n); i += 2) {
-		if (stream != NULL) {
-			com_addbyte(c, DUP_TOP);
-			/* stack: [stream] => [stream stream] */
-			com_push(c, 1);
-			com_node(c, CHILD(n, i));
-			/* stack: [stream stream] => [stream stream obj] */
-			com_addbyte(c, ROT_TWO);
-			/* stack: [stream stream obj] => [stream obj stream] */
-			com_addbyte(c, PRINT_ITEM_TO);
-			/* stack: [stream obj stream] => [stream] */
-			com_pop(c, 2);
-		}
-		else {
-			com_node(c, CHILD(n, i));
-			/* stack: [...] => [... obj] */
-			com_addbyte(c, PRINT_ITEM);
-			com_pop(c, 1);
-		}
-	}
-	/* XXX Alternatively, LOAD_CONST '\n' and then PRINT_ITEM */
-	if (TYPE(CHILD(n, NCH(n)-1)) == COMMA) {
-		if (stream != NULL) {
-			/* must pop the extra stream object off the stack */
-			com_addbyte(c, POP_TOP);
-			/* stack: [... stream] => [...] */
-			com_pop(c, 1);
-		}
-	}
-	else {
-		if (stream != NULL) {
-			/* this consumes the last stream object on stack */
-			com_addbyte(c, PRINT_NEWLINE_TO);
-			/* stack: [... stream] => [...] */
-			com_pop(c, 1);
-		}
-		else
-			com_addbyte(c, PRINT_NEWLINE);
-	}
-}
-
-static void
-com_return_stmt(struct compiling *c, node *n)
-{
-	REQ(n, return_stmt); /* 'return' [testlist] */
-	if (!c->c_infunction) {
-		com_error(c, PyExc_SyntaxError, "'return' outside function");
-	}
-	if (c->c_flags & CO_GENERATOR) {
-		if (NCH(n) > 1) {
-			com_error(c, PyExc_SyntaxError,
-				  "'return' with argument inside generator");
-		}
-	}
-	if (NCH(n) < 2) {
-		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-		com_push(c, 1);
-	}
-	else
-		com_node(c, CHILD(n, 1));
-	com_addbyte(c, RETURN_VALUE);
-	com_pop(c, 1);
-}
-
-static void
-com_yield_expr(struct compiling *c, node *n)
-{
-	REQ(n, yield_expr); /* 'yield' testlist */
-	if (!c->c_infunction) {
-		com_error(c, PyExc_SyntaxError, "'yield' outside function");
-	}
-	
-	/* for (i = 0; i < c->c_nblocks; ++i) {
-		if (c->c_block[i] == SETUP_FINALLY) {
-			com_error(c, PyExc_SyntaxError,
-				  "'yield' not allowed in a 'try' block "
-				  "with a 'finally' clause");
-			return;
-		}
-	} */
-
-	if (NCH(n) < 2) {
-		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-		com_push(c, 1);
-	}
-	else
-		com_node(c, CHILD(n, 1));
-	com_addbyte(c, YIELD_VALUE);
-}
-
-static void
-com_yield_stmt(struct compiling *c, node *n)
-{
-	REQ(n, yield_stmt); /* yield_expr */
-	com_node(c, CHILD(n, 0));
-	com_addbyte(c, POP_TOP);
-	com_pop(c, 1);
-}
-
-
-static void
-com_raise_stmt(struct compiling *c, node *n)
-{
-	int i;
-	REQ(n, raise_stmt); /* 'raise' [test [',' test [',' test]]] */
-	if (NCH(n) > 1) {
-		com_node(c, CHILD(n, 1));
-		if (NCH(n) > 3) {
-			com_node(c, CHILD(n, 3));
-			if (NCH(n) > 5)
-				com_node(c, CHILD(n, 5));
-		}
-	}
-	i = NCH(n)/2;
-	com_addoparg(c, RAISE_VARARGS, i);
-	com_pop(c, i);
-}
-
-static void
-com_from_import(struct compiling *c, node *n)
-{
-	com_addopname(c, IMPORT_FROM, CHILD(n, 0));
-	com_push(c, 1);
-	if (NCH(n) > 1) {
-		if (strcmp(STR(CHILD(n, 1)), "as") != 0) {
-			com_error(c, PyExc_SyntaxError, "invalid syntax");
-			return;
-		}
-		com_addop_varname(c, VAR_STORE, STR(CHILD(n, 2)));
-	} else
-		com_addop_varname(c, VAR_STORE, STR(CHILD(n, 0)));
-	com_pop(c, 1);
-}
-
-static void
-com_import_stmt(struct compiling *c, node *n)
-{
-	node *nn;
-	int i;
-	REQ(n, import_stmt);
-	n = CHILD(n, 0);
-	/* import_stmt: import_name | import_from */
-	if (TYPE(n) == import_from) {
-		/* 'from' dotted_name 'import' ('*' |
-		     '(' import_as_names ')' | import_as_names) */
-		PyObject *tup;
-		REQ(CHILD(n, 1), dotted_name);
-		nn = CHILD(n, 3 + (TYPE(CHILD(n, 3)) == LPAR));
-		if (TYPE(nn) == STAR)
-			tup = Py_BuildValue("(s)", "*");
-		else {
-			if (TYPE(CHILD(nn, NCH(nn) - 1)) == COMMA &&
-			    TYPE(CHILD(n, 3)) != LPAR) {
-				com_error(c, PyExc_SyntaxError,
-				    "trailing comma not allowed "
-				    "without surrounding parentheses");
-				return;
-			}
-			REQ(nn, import_as_names);
-			tup = PyTuple_New((NCH(nn) + 1) / 2);
-            for (i = 0; i < NCH(nn); i += 2) {
-                PyObject *s = PyString_FromString(
-                    STR(CHILD(CHILD(nn, i), 0)));
-                if (s == NULL) {
-                    Py_CLEAR(tup);
-                    break;
-                } else
-                    PyTuple_SET_ITEM(tup, i / 2, s);
-            }
-            if (tup == NULL) {
-                /* Assume that failue above was MemoryError */
-                com_error(c, PyExc_MemoryError, "");
-                return;
-            }
-		}
-		com_addoparg(c, LOAD_CONST, com_addconst(c, tup));
-		Py_DECREF(tup);
-		com_push(c, 1);
-		com_addopname(c, IMPORT_NAME, CHILD(n, 1));
-		if (TYPE(nn) == STAR)
-			com_addbyte(c, IMPORT_STAR);
-		else {
-			for (i = 0; i < NCH(nn); i += 2)
-				com_from_import(c, CHILD(nn, i));
-			com_addbyte(c, POP_TOP);
-		}
-		com_pop(c, 1);
-	}
-	else {
-		/* 'import' dotted_as_names */
-		nn = CHILD(n, 1);
-		REQ(nn, dotted_as_names);
-		for (i = 0; i < NCH(nn); i += 2) {
-			node *subn = CHILD(nn, i);
-			REQ(subn, dotted_as_name);
-			com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-			com_push(c, 1);
-			com_addopname(c, IMPORT_NAME, CHILD(subn, 0));
-			if (NCH(subn) > 1) {
-				int j;
-				if (strcmp(STR(CHILD(subn, 1)), "as") != 0) {
-					com_error(c, PyExc_SyntaxError,
-						  "invalid syntax");
-					return;
-				}
-				for (j=2 ; j < NCH(CHILD(subn, 0)); j += 2)
-					com_addopname(c, LOAD_ATTR,
-						      CHILD(CHILD(subn, 0),
-							    j));
-				com_addop_varname(c, VAR_STORE,
-						  STR(CHILD(subn, 2)));
-			} else
-				com_addop_varname(c, VAR_STORE,
-						  STR(CHILD(CHILD(subn, 0),
-							    0))); 
-			com_pop(c, 1);
-		}
-	}
-}
-
-static void
-com_exec_stmt(struct compiling *c, node *n)
-{
-	REQ(n, exec_stmt);
-	/* exec_stmt: 'exec' expr ['in' expr [',' expr]] */
-	com_node(c, CHILD(n, 1));
-	if (NCH(n) >= 4)
-		com_node(c, CHILD(n, 3));
-	else {
-		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-		com_push(c, 1);
-	}
-	if (NCH(n) >= 6)
-		com_node(c, CHILD(n, 5));
-	else {
-		com_addbyte(c, DUP_TOP);
-		com_push(c, 1);
-	}
-	com_addbyte(c, EXEC_STMT);
-	com_pop(c, 3);
-}
-
-static int
-is_constant_false(struct compiling *c, node *n)
-{
-	PyObject *v;
-	int i;
-	/* argument c will be NULL when called from symtable_node() */
-
-  /* Label to avoid tail recursion */
-  next:
-	switch (TYPE(n)) {
-
-	case suite:
-		if (NCH(n) == 1) {
-			n = CHILD(n, 0);
-			goto next;
-		}
-		/* Fall through */
-	case file_input:
-		for (i = 0; i < NCH(n); i++) {
-			node *ch = CHILD(n, i);
-			if (TYPE(ch) == stmt) {
-				n = ch;
-				goto next;
-			}
-		}
-		break;
-
-	case stmt:
-	case simple_stmt:
-	case small_stmt:
-		n = CHILD(n, 0);
-		goto next;
-
-	case expr_stmt:
-	case testlist:
-	case testlist1:
-	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:
-	case atom:
-		if (NCH(n) == 1) {
-			n = CHILD(n, 0);
-			goto next;
-		}
-		break;
-
-	case NAME:
-		if (Py_OptimizeFlag && strcmp(STR(n), "__debug__") == 0)
-			return 1;
-		break;
-
-	case NUMBER:
-		v = parsenumber(c, STR(n));
-		if (v == NULL) {
-			PyErr_Clear();
-			break;
-		}
-		i = PyObject_IsTrue(v);
-		Py_DECREF(v);
-		return i == 0;
-
-	case STRING:
-		v = parsestr(c, STR(n));
-		if (v == NULL) {
-			PyErr_Clear();
-			break;
-		}
-		i = PyObject_IsTrue(v);
-		Py_DECREF(v);
-		return i == 0;
-
-	}
-	return 0;
-}
-
-
-/* Look under n for a return stmt with an expression.
- * This hack is used to find illegal returns under "if 0:" blocks in
- * functions already known to be generators (as determined by the symtable
- * pass).
- * Return the offending return node if found, else NULL.
- */
-static node *
-look_for_offending_return(node *n)
-{
-	int i;
-
-	for (i = 0; i < NCH(n); ++i) {
-		node *kid = CHILD(n, i);
-
-		switch (TYPE(kid)) {
-			case classdef:
-			case funcdef:
-			case lambdef:
-				/* Stuff in nested functions & classes doesn't
-				   affect the code block we started in. */
-				return NULL;
-
-			case return_stmt:
-				if (NCH(kid) > 1)
-					return kid;
-				break;
-
-			default: {
-				node *bad = look_for_offending_return(kid);
-				if (bad != NULL)
-					return bad;
-			}
-		}
-	}
-
-	return NULL;
-}			
-
-static void
-com_if_stmt(struct compiling *c, node *n)
-{
-	int i;
-	int anchor = 0;
-	REQ(n, if_stmt);
-	/*'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] */
-	for (i = 0; i+3 < NCH(n); i+=4) {
-		int a = 0;
-		node *ch = CHILD(n, i+1);
-		if (is_constant_false(c, ch)) {
-			/* We're going to skip this block.  However, if this
-			   is a generator, we have to check the dead code
-			   anyway to make sure there aren't any return stmts
-			   with expressions, in the same scope. */
-			if (c->c_flags & CO_GENERATOR) {
-				node *p = look_for_offending_return(n);
-				if (p != NULL) {
-					int savelineno = c->c_lineno;
-					c->c_lineno = p->n_lineno;
-					com_error(c, PyExc_SyntaxError,
-			  	   		"'return' with argument "
-			  	   		"inside generator");
-			  	   	c->c_lineno = savelineno;
-				}
-			}
-			continue;
-		}
-		if (i > 0)
-			com_set_lineno(c, ch->n_lineno);
-		com_node(c, ch);
-		com_addfwref(c, JUMP_IF_FALSE, &a);
-		com_addbyte(c, POP_TOP);
-		com_pop(c, 1);
-		com_node(c, CHILD(n, i+3));
-		com_addfwref(c, JUMP_FORWARD, &anchor);
-		com_backpatch(c, a);
-		/* We jump here with an extra entry which we now pop */
-		com_addbyte(c, POP_TOP);
-	}
-	if (i+2 < NCH(n))
-		com_node(c, CHILD(n, i+2));
-	if (anchor)
-		com_backpatch(c, anchor);
-}
-
-static void
-com_while_stmt(struct compiling *c, node *n)
-{
-	int break_anchor = 0;
-	int anchor = 0;
-	int save_begin = c->c_begin;
-	REQ(n, while_stmt); /* 'while' test ':' suite ['else' ':' suite] */
-	com_addfwref(c, SETUP_LOOP, &break_anchor);
-	block_push(c, SETUP_LOOP);
-	c->c_begin = c->c_nexti;
-	com_set_lineno(c, n->n_lineno);
-	com_node(c, CHILD(n, 1));
-	com_addfwref(c, JUMP_IF_FALSE, &anchor);
-	com_addbyte(c, POP_TOP);
-	com_pop(c, 1);
-	c->c_loops++;
-	com_node(c, CHILD(n, 3));
-	c->c_loops--;
-	com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
-	c->c_begin = save_begin;
-	com_backpatch(c, anchor);
-	/* We jump here with one entry more on the stack */
-	com_addbyte(c, POP_TOP);
-	com_addbyte(c, POP_BLOCK);
-	block_pop(c, SETUP_LOOP);
-	if (NCH(n) > 4)
-		com_node(c, CHILD(n, 6));
-	com_backpatch(c, break_anchor);
-}
-
-static void
-com_for_stmt(struct compiling *c, node *n)
-{
-	int break_anchor = 0;
-	int anchor = 0;
-	int save_begin = c->c_begin;
-	REQ(n, for_stmt);
-	/* 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] */
-	com_addfwref(c, SETUP_LOOP, &break_anchor);
-	block_push(c, SETUP_LOOP);
-	com_node(c, CHILD(n, 3));
-	com_addbyte(c, GET_ITER);
-	c->c_begin = c->c_nexti;
-	com_set_lineno(c, c->c_last_line);
-	com_addfwref(c, FOR_ITER, &anchor);
-	com_push(c, 1);
-	com_assign(c, CHILD(n, 1), OP_ASSIGN, NULL);
-	c->c_loops++;
-	com_node(c, CHILD(n, 5));
-	c->c_loops--;
-	com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
-	c->c_begin = save_begin;
-	com_backpatch(c, anchor);
-	com_pop(c, 1); /* FOR_ITER has popped this */
-	com_addbyte(c, POP_BLOCK);
-	block_pop(c, SETUP_LOOP);
-	if (NCH(n) > 8)
-		com_node(c, CHILD(n, 8));
-	com_backpatch(c, break_anchor);
-}
-
-/* Code generated for "try: S finally: Sf" is as follows:
-   
-		SETUP_FINALLY	L
-		<code for S>
-		POP_BLOCK
-		LOAD_CONST	<nil>
-	L:	<code for Sf>
-		END_FINALLY
-   
-   The special instructions use the block stack.  Each block
-   stack entry contains the instruction that created it (here
-   SETUP_FINALLY), the level of the value stack at the time the
-   block stack entry was created, and a label (here L).
-   
-   SETUP_FINALLY:
-	Pushes the current value stack level and the label
-	onto the block stack.
-   POP_BLOCK:
-	Pops en entry from the block stack, and pops the value
-	stack until its level is the same as indicated on the
-	block stack.  (The label is ignored.)
-   END_FINALLY:
-	Pops a variable number of entries from the *value* stack
-	and re-raises the exception they specify.  The number of
-	entries popped depends on the (pseudo) exception type.
-   
-   The block stack is unwound when an exception is raised:
-   when a SETUP_FINALLY entry is found, the exception is pushed
-   onto the value stack (and the exception condition is cleared),
-   and the interpreter jumps to the label gotten from the block
-   stack.
-   
-   Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...":
-   (The contents of the value stack is shown in [], with the top
-   at the right; 'tb' is trace-back info, 'val' the exception's
-   associated value, and 'exc' the exception.)
-   
-   Value stack		Label	Instruction	Argument
-   []				SETUP_EXCEPT	L1
-   []				<code for S>
-   []				POP_BLOCK
-   []				JUMP_FORWARD	L0
-   
-   [tb, val, exc]	L1:	DUP				)
-   [tb, val, exc, exc]		<evaluate E1>			)
-   [tb, val, exc, exc, E1]	COMPARE_OP	EXC_MATCH	) only if E1
-   [tb, val, exc, 1-or-0]	JUMP_IF_FALSE	L2		)
-   [tb, val, exc, 1]		POP				)
-   [tb, val, exc]		POP
-   [tb, val]			<assign to V1>	(or POP if no V1)
-   [tb]				POP
-   []				<code for S1>
-   				JUMP_FORWARD	L0
-   
-   [tb, val, exc, 0]	L2:	POP
-   [tb, val, exc]		DUP
-   .............................etc.......................
-
-   [tb, val, exc, 0]	Ln+1:	POP
-   [tb, val, exc]	   	END_FINALLY	# re-raise exception
-   
-   []			L0:	<next statement>
-   
-   Of course, parts are not generated if Vi or Ei is not present.
-*/
-
-static void
-com_try_except(struct compiling *c, node *n)
-{
-	int except_anchor = 0;
-	int end_anchor = 0;
-	int else_anchor = 0;
-	int i;
-	node *ch;
-
-	com_addfwref(c, SETUP_EXCEPT, &except_anchor);
-	block_push(c, SETUP_EXCEPT);
-	com_node(c, CHILD(n, 2));
-	com_addbyte(c, POP_BLOCK);
-	block_pop(c, SETUP_EXCEPT);
-	com_addfwref(c, JUMP_FORWARD, &else_anchor);
-	com_backpatch(c, except_anchor);
-	for (i = 3;
-	     i < NCH(n) && TYPE(ch = CHILD(n, i)) == except_clause;
-	     i += 3) {
-		/* except_clause: 'except' [expr [',' var]] */
-		if (except_anchor == 0) {
-			com_error(c, PyExc_SyntaxError,
-				  "default 'except:' must be last");
-			break;
-		}
-		except_anchor = 0;
-		com_push(c, 3); /* tb, val, exc pushed by exception */
-		com_set_lineno(c, ch->n_lineno);
-		if (NCH(ch) > 1) {
-			com_addbyte(c, DUP_TOP);
-			com_push(c, 1);
-			com_node(c, CHILD(ch, 1));
-			com_addoparg(c, COMPARE_OP, PyCmp_EXC_MATCH);
-			com_pop(c, 1);
-			com_addfwref(c, JUMP_IF_FALSE, &except_anchor);
-			com_addbyte(c, POP_TOP);
-			com_pop(c, 1);
-		}
-		com_addbyte(c, POP_TOP);
-		com_pop(c, 1);
-		if (NCH(ch) > 3)
-			com_assign(c, CHILD(ch, 3), OP_ASSIGN, NULL);
-		else {
-			com_addbyte(c, POP_TOP);
-			com_pop(c, 1);
-		}
-		com_addbyte(c, POP_TOP);
-		com_pop(c, 1);
-		com_node(c, CHILD(n, i+2));
-		com_addfwref(c, JUMP_FORWARD, &end_anchor);
-		if (except_anchor) {
-			com_backpatch(c, except_anchor);
-			/* We come in with [tb, val, exc, 0] on the
-			   stack; one pop and it's the same as
-			   expected at the start of the loop */
-			com_addbyte(c, POP_TOP);
-		}
-	}
-	/* We actually come in here with [tb, val, exc] but the
-	   END_FINALLY will zap those and jump around.
-	   The c_stacklevel does not reflect them so we need not pop
-	   anything. */
-	com_addbyte(c, END_FINALLY);
-	com_backpatch(c, else_anchor);
-	if (i < NCH(n))
-		com_node(c, CHILD(n, i+2));
-	com_backpatch(c, end_anchor);
-}
-
-static void
-com_try_finally(struct compiling *c, node *n)
-{
-	int finally_anchor = 0;
-	node *ch;
-
-	com_addfwref(c, SETUP_FINALLY, &finally_anchor);
-	block_push(c, SETUP_FINALLY);
-	com_node(c, CHILD(n, 2));
-	com_addbyte(c, POP_BLOCK);
-	block_pop(c, SETUP_FINALLY);
-	block_push(c, END_FINALLY);
-	com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-	/* While the generated code pushes only one item,
-	   the try-finally handling can enter here with
-	   up to three items.  OK, here are the details:
-	   3 for an exception, 2 for RETURN, 1 for BREAK. */
-	com_push(c, 3);
-	com_backpatch(c, finally_anchor);
-	ch = CHILD(n, NCH(n)-1);
-	com_set_lineno(c, ch->n_lineno);
-	com_node(c, ch);
-	com_addbyte(c, END_FINALLY);
-	block_pop(c, END_FINALLY);
-	com_pop(c, 3); /* Matches the com_push above */
-}
-
-static void
-com_try_stmt(struct compiling *c, node *n)
-{
-	REQ(n, try_stmt);
-	/* 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
-	 | 'try' ':' suite 'finally' ':' suite */
-	if (TYPE(CHILD(n, 3)) != except_clause)
-		com_try_finally(c, n);
-	else
-		com_try_except(c, n);
-}
-
-static node *
-get_rawdocstring(node *n)
-{
-	int i;
-
-  /* Label to avoid tail recursion */
-  next:
-	switch (TYPE(n)) {
-
-	case suite:
-		if (NCH(n) == 1) {
-			n = CHILD(n, 0);
-			goto next;
-		}
-		/* Fall through */
-	case file_input:
-		for (i = 0; i < NCH(n); i++) {
-			node *ch = CHILD(n, i);
-			if (TYPE(ch) == stmt) {
-				n = ch;
-				goto next;
-			}
-		}
-		break;
-
-	case stmt:
-	case simple_stmt:
-	case small_stmt:
-		n = CHILD(n, 0);
-		goto next;
-
-	case expr_stmt:
-	case testlist:
-	case testlist1:
-	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 next;
-		}
-		break;
-
-	case atom:
-		if (TYPE(CHILD(n, 0)) == STRING)
-			return n;
-		break;
-
-	}
-	return NULL;
-}
-
-static PyObject *
-get_docstring(struct compiling *c, node *n)
-{
-	/* Don't generate doc-strings if run with -OO */
-	if (Py_OptimizeFlag > 1)
-		return NULL;
-	n = get_rawdocstring(n);
-	if (n == NULL)
-		return NULL;
-	return parsestrplus(c, n);
-}
-
-static void
-com_suite(struct compiling *c, node *n)
-{
-	REQ(n, suite);
-	/* simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT */
-	if (NCH(n) == 1) {
-		com_node(c, CHILD(n, 0));
-	}
-	else {
-		int i;
-		for (i = 0; i < NCH(n) && c->c_errors == 0; i++) {
-			node *ch = CHILD(n, i);
-			if (TYPE(ch) == stmt)
-				com_node(c, ch);
-		}
-	}
-}
-
-/* ARGSUSED */
-static void
-com_continue_stmt(struct compiling *c, node *n)
-{
-	int i = c->c_nblocks;
-	if (i-- > 0 && c->c_block[i] == SETUP_LOOP) {
-		com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
-	}
-	else if (i <= 0) {
-		/* at the outer level */
-		com_error(c, PyExc_SyntaxError,
-			  "'continue' not properly in loop");
-	}
-	else {
-		int j;
-		for (j = i-1; j >= 0; --j) {
-			if (c->c_block[j] == SETUP_LOOP)
-				break;
-		}
-		if (j >= 0) {
-			/* there is a loop, but something interferes */
-			for (; i > j; --i) {
-				if (c->c_block[i] == SETUP_EXCEPT ||
-				    c->c_block[i] == SETUP_FINALLY) {
-					com_addoparg(c, CONTINUE_LOOP,
-						     c->c_begin);
-					return;
-				}
-				if (c->c_block[i] == END_FINALLY) {
-					com_error(c, PyExc_SyntaxError,
-			  "'continue' not supported inside 'finally' clause");
-			  		return;
-			  	}
-			}
-		}
-		com_error(c, PyExc_SyntaxError,
-			  "'continue' not properly in loop");
-	}
-	/* XXX Could allow it inside a 'finally' clause
-	   XXX if we could pop the exception still on the stack */
-}
-
-/* Return the number of default values in the argument list.
-
-   If a non-default argument follows a default argument, set an
-   exception and return -1.
+/* assemble_emit()
+   Extend the bytecode with a new instruction.
+   Update lnotab if necessary.
 */
 
 static int
-com_argdefs(struct compiling *c, node *n)
+assemble_emit(struct assembler *a, struct instr *i)
 {
-	int i, nch, ndefs;
-	if (TYPE(n) == lambdef) {
-		/* lambdef: 'lambda' [varargslist] ':' test */
-		n = CHILD(n, 1);
-	}
+	int arg = 0, size = 0, ext = i->i_oparg >> 16;
+	int len = PyString_GET_SIZE(a->a_bytecode);
+	char *code;
+
+	if (!i->i_hasarg)
+		size = 1;
 	else {
-		REQ(n, funcdef);
-		/* funcdef: [decorators] 'def' NAME parameters ':' suite */
-		n = RCHILD(n, -3);
-		REQ(n, parameters); /* parameters: '(' [varargslist] ')' */
-		n = CHILD(n, 1);
+		if (ext)
+			size = 6;
+		else
+			size = 3;
+		arg = i->i_oparg;
 	}
-	if (TYPE(n) != varargslist)
+	if (i->i_lineno && !assemble_lnotab(a, i))
+			return 0;
+	if (a->a_offset + size >= len) {
+		if (_PyString_Resize(&a->a_bytecode, len * 2) < 0)
 		    return 0;
-	/* varargslist:
-		(fpdef ['=' test] ',')* '*' ....... |
-		fpdef ['=' test] (',' fpdef ['=' test])* [','] */
-	nch = NCH(n);
-	ndefs = 0;
-	for (i = 0; i < nch; i++) {
-		int t;
-		if (TYPE(CHILD(n, i)) == STAR ||
-		    TYPE(CHILD(n, i)) == DOUBLESTAR)
-			break;
-		i++;
-		if (i >= nch)
-			t = RPAR; /* Anything except EQUAL or COMMA */
-		else
-			t = TYPE(CHILD(n, i));
-		if (t == EQUAL) {
-			i++;
-			ndefs++;
-			com_node(c, CHILD(n, i));
-			i++;
-			if (i >= nch)
-				break;
-			t = TYPE(CHILD(n, i));
-		}
-		else {
-			/* Treat "(a=1, b)" as an error */
-			if (ndefs) {
-				com_error(c, PyExc_SyntaxError,
-			    "non-default argument follows default argument");
-				return -1;
-			}
-		}
-		if (t != COMMA)
-			break;
 	}
-	return ndefs;
-}
-
-static void
-com_decorator_name(struct compiling *c, node *n)
-{
-	/* dotted_name: NAME ('.' NAME)* */
-	
-	int i, nch;
-	node *varname;
-
-	REQ(n, dotted_name);
-	nch = NCH(n);
-	assert(nch >= 1 && nch % 2 == 1);
-
-	varname = CHILD(n, 0);
-	REQ(varname, NAME);
-	com_addop_varname(c, VAR_LOAD, STR(varname));
-	com_push(c, 1);
-		
-	for (i = 1; i < nch; i += 2) {
-		node *attrname;
-		
-		REQ(CHILD(n, i), DOT);
-
-		attrname = CHILD(n, i + 1);
-		REQ(attrname, NAME);
-		com_addop_name(c, LOAD_ATTR, STR(attrname));
+	code = PyString_AS_STRING(a->a_bytecode) + a->a_offset;
+	a->a_offset += size;
+	if (ext > 0) {
+	    *code++ = (char)EXTENDED_ARG;
+	    *code++ = ext & 0xff;
+	    *code++ = ext >> 8;
+	    arg &= 0xffff;
 	}
-}
-
-static void
-com_decorator(struct compiling *c, node *n)
-{
-	/* decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE */
-	int nch = NCH(n);
-	assert(nch >= 3);
-	REQ(CHILD(n, 0), AT);
-	REQ(RCHILD(n, -1), NEWLINE);
-	com_decorator_name(c, CHILD(n, 1));
-
-	if (nch > 3) {
-		assert(nch == 5 || nch == 6);
-		REQ(CHILD(n, 2), LPAR);
-		REQ(RCHILD(n, -2), RPAR);
-		com_call_function(c, CHILD(n, 3));
-	}
+	*code++ = i->i_opcode;
+	if (size == 1)
+		return 1;
+	*code++ = arg & 0xff;
+	*code++ = arg >> 8;
+	return 1;
 }
 
 static int
-com_decorators(struct compiling *c, node *n)
+assemble_jump_offsets(struct assembler *a, struct compiler *c)
 {
-	int i, nch;
-	
-	/* decorator+ */
-	nch = NCH(n);
-	assert(nch >= 1);
-
-	for (i = 0; i < nch; ++i) {
-		node *ch = CHILD(n, i);
-		REQ(ch, decorator);
-
-		com_decorator(c, ch);
-	}
-
-	return nch;
-}
-
-static void
-com_funcdef(struct compiling *c, node *n)
-{
-	PyObject *co;
-	int ndefs, ndecorators;
-	
-	REQ(n, funcdef);
-	/*          -6            -5   -4   -3         -2  -1
-	   funcdef: [decorators] 'def' NAME parameters ':' suite */
-
-	if (NCH(n) == 6)
-		ndecorators = com_decorators(c, CHILD(n, 0));
-	else
-		ndecorators = 0;
-
-	ndefs = com_argdefs(c, n);
-	if (ndefs < 0)
-		return;
-	symtable_enter_scope(c->c_symtable, STR(RCHILD(n, -4)), TYPE(n),
-			     n->n_lineno);
-	co = (PyObject *)icompile(n, c);
-	symtable_exit_scope(c->c_symtable);
-	if (co == NULL)
-		c->c_errors++;
-	else {
-		int closure = com_make_closure(c, (PyCodeObject *)co);
-		int i = com_addconst(c, co);
-		com_addoparg(c, LOAD_CONST, i);
-		com_push(c, 1);
-		if (closure)
-			com_addoparg(c, MAKE_CLOSURE, ndefs);
-		else
-			com_addoparg(c, MAKE_FUNCTION, ndefs);
-		com_pop(c, ndefs);
-
-		while (ndecorators > 0) {
-			com_addoparg(c, CALL_FUNCTION, 1);
-			com_pop(c, 1);
-			--ndecorators;
-		}
-
-		com_addop_varname(c, VAR_STORE, STR(RCHILD(n, -4)));
-		com_pop(c, 1);
-		Py_DECREF(co);
-	}
-}
-
-static void
-com_bases(struct compiling *c, node *n)
-{
+	basicblock *b;
+	int bsize, totsize = 0;
 	int i;
-	REQ(n, testlist);
-	/* testlist: test (',' test)* [','] */
-	for (i = 0; i < NCH(n); i += 2)
-		com_node(c, CHILD(n, i));
-	i = (NCH(n)+1) / 2;
-	com_addoparg(c, BUILD_TUPLE, i);
-	com_pop(c, i-1);
-}
 
-static void
-com_classdef(struct compiling *c, node *n)
-{
-	int i;
-	PyObject *v;
-	PyCodeObject *co;
-	char *name;
-
-	REQ(n, classdef);
-	/* classdef: class NAME ['(' [testlist] ')'] ':' suite */
-	if ((v = PyString_InternFromString(STR(CHILD(n, 1)))) == NULL) {
-		c->c_errors++;
-		return;
+	/* Compute the size of each block and fixup jump args.
+	   Replace block pointer with position in bytecode. */
+	for (i = a->a_nblocks - 1; i >= 0; i--) {
+		basicblock *b = a->a_postorder[i];
+		bsize = blocksize(b);
+		b->b_offset = totsize;
+		totsize += bsize;
 	}
-	/* Push the class name on the stack */
-	i = com_addconst(c, v);
-	com_addoparg(c, LOAD_CONST, i);
-	com_push(c, 1);
-	Py_DECREF(v);
-	/* Push the tuple of base classes on the stack */
-	if (TYPE(CHILD(n, 2)) != LPAR ||
-			TYPE(CHILD(n, 3)) == RPAR) {
-		com_addoparg(c, BUILD_TUPLE, 0);
-		com_push(c, 1);
-	}
-	else
-		com_bases(c, CHILD(n, 3));
-	name = STR(CHILD(n, 1));
-	symtable_enter_scope(c->c_symtable, name, TYPE(n), n->n_lineno);
-	co = icompile(n, c);
-	symtable_exit_scope(c->c_symtable);
-	if (co == NULL)
-		c->c_errors++;
-	else {
-		int closure = com_make_closure(c, co);
-		i = com_addconst(c, (PyObject *)co);
-		com_addoparg(c, LOAD_CONST, i);
-		com_push(c, 1);
-		if (closure) {
-			com_addoparg(c, MAKE_CLOSURE, 0);
-			com_pop(c, PyCode_GetNumFree(co));
-		} else
-			com_addoparg(c, MAKE_FUNCTION, 0);
-		com_addoparg(c, CALL_FUNCTION, 0);
-		com_addbyte(c, BUILD_CLASS);
-		com_pop(c, 2);
-		com_addop_varname(c, VAR_STORE, STR(CHILD(n, 1)));
-		com_pop(c, 1);
-		Py_DECREF(co);
-	}
-}
-
-static void
-com_node(struct compiling *c, node *n)
-{
- loop:
-	if (c->c_errors)
-		return;
-	switch (TYPE(n)) {
-	
-	/* Definition nodes */
-
-	case funcdef:
-		com_funcdef(c, n);
-		break;
-	case classdef:
-		com_classdef(c, n);
-		break;
-	
-	/* Trivial parse tree nodes */
-	
-	case stmt:
-	case small_stmt:
-	case flow_stmt:
-		n = CHILD(n, 0);
-		goto loop;
-
-	case simple_stmt:
-		/* small_stmt (';' small_stmt)* [';'] NEWLINE */
-		com_set_lineno(c, n->n_lineno);
-		{
-			int i;
-			for (i = 0; i < NCH(n)-1; i += 2)
-				com_node(c, CHILD(n, i));
-		}
-		break;
-	
-	case compound_stmt:
-		com_set_lineno(c, n->n_lineno);
-		n = CHILD(n, 0);
-		goto loop;
-
-	/* Statement nodes */
-	
-	case expr_stmt:
-		com_expr_stmt(c, n);
-		break;
-	case print_stmt:
-		com_print_stmt(c, n);
-		break;
-	case del_stmt: /* 'del' exprlist */
-		com_assign(c, CHILD(n, 1), OP_DELETE, NULL);
-		break;
-	case pass_stmt:
-		break;
-	case break_stmt:
-		if (c->c_loops == 0) {
-			com_error(c, PyExc_SyntaxError,
-				  "'break' outside loop");
-		}
-		com_addbyte(c, BREAK_LOOP);
-		break;
-	case continue_stmt:
-		com_continue_stmt(c, n);
-		break;
-	case return_stmt:
-		com_return_stmt(c, n);
-		break;
-	case yield_stmt:
-		com_yield_stmt(c, n);
-		break;
-	case raise_stmt:
-		com_raise_stmt(c, n);
-		break;
-	case import_stmt:
-		com_import_stmt(c, n);
-		break;
-	case global_stmt:
-		break;
-	case exec_stmt:
-		com_exec_stmt(c, n);
-		break;
-	case assert_stmt:
-		com_assert_stmt(c, n);
-		break;
-	case if_stmt:
-		com_if_stmt(c, n);
-		break;
-	case while_stmt:
-		com_while_stmt(c, n);
-		break;
-	case for_stmt:
-		com_for_stmt(c, n);
-		break;
-	case try_stmt:
-		com_try_stmt(c, n);
-		break;
-	case suite:
-		com_suite(c, n);
-		break;
-	
-	/* Expression nodes */
-	
-	case yield_expr:
-		com_yield_expr(c, n);
-		break;
-
-	case testlist:
-	case testlist1:
-	case testlist_safe:
-		com_list(c, n, 0);
-		break;
-	case test:
-		com_test(c, n);
-		break;
-	case and_test:
-		com_and_test(c, n);
-		break;
-	case not_test:
-		com_not_test(c, n);
-		break;
-	case comparison:
-		com_comparison(c, n);
-		break;
-	case exprlist:
-		com_list(c, n, 0);
-		break;
-	case expr:
-		com_expr(c, n);
-		break;
-	case xor_expr:
-		com_xor_expr(c, n);
-		break;
-	case and_expr:
-		com_and_expr(c, n);
-		break;
-	case shift_expr:
-		com_shift_expr(c, n);
-		break;
-	case arith_expr:
-		com_arith_expr(c, n);
-		break;
-	case term:
-		com_term(c, n);
-		break;
-	case factor:
-		com_factor(c, n);
-		break;
-	case power:
-		com_power(c, n);
-		break;
-	case atom:
-		com_atom(c, n);
-		break;
-	
-	default:
-		com_error(c, PyExc_SystemError,
-			  "com_node: unexpected node type");
-	}
-}
-
-static void com_fplist(struct compiling *, node *);
-
-static void
-com_fpdef(struct compiling *c, node *n)
-{
-	REQ(n, fpdef); /* fpdef: NAME | '(' fplist ')' */
-	if (TYPE(CHILD(n, 0)) == LPAR)
-		com_fplist(c, CHILD(n, 1));
-	else {
-		com_addop_varname(c, VAR_STORE, STR(CHILD(n, 0)));
-		com_pop(c, 1);
-	}
-}
-
-static void
-com_fplist(struct compiling *c, node *n)
-{
-	REQ(n, fplist); /* fplist: fpdef (',' fpdef)* [','] */
-	if (NCH(n) == 1) {
-		com_fpdef(c, CHILD(n, 0));
-	}
-	else {
-		int i = (NCH(n)+1)/2;
-		com_addoparg(c, UNPACK_SEQUENCE, i);
-		com_push(c, i-1);
-		for (i = 0; i < NCH(n); i += 2)
-			com_fpdef(c, CHILD(n, i));
-	}
-}
-
-static void
-com_arglist(struct compiling *c, node *n)
-{
-	int nch, i, narg;
-	int complex = 0;
-	char nbuf[30];
-	REQ(n, varargslist);
-	/* varargslist:
-		(fpdef ['=' test] ',')* (fpdef ['=' test] | '*' .....) */
-	nch = NCH(n);
-	/* Enter all arguments in table of locals */
-	for (i = 0, narg = 0; i < nch; i++) {
-		node *ch = CHILD(n, i);
-		node *fp;
-		if (TYPE(ch) == STAR || TYPE(ch) == DOUBLESTAR)
-			break;
-		REQ(ch, fpdef); /* fpdef: NAME | '(' fplist ')' */
-		fp = CHILD(ch, 0);
-		if (TYPE(fp) != NAME) {
-			PyOS_snprintf(nbuf, sizeof(nbuf), ".%d", i);
-			complex = 1;
-		}
-		narg++;
-		/* all name updates handled by symtable */
-		if (++i >= nch)
-			break;
-		ch = CHILD(n, i);
-		if (TYPE(ch) == EQUAL)
-			i += 2;
-		else
-			REQ(ch, COMMA);
-	}
-	if (complex) {
-		/* Generate code for complex arguments only after
-		   having counted the simple arguments */
-		int ilocal = 0;
-		for (i = 0; i < nch; i++) {
-			node *ch = CHILD(n, i);
-			node *fp;
-			if (TYPE(ch) == STAR || TYPE(ch) == DOUBLESTAR)
-				break;
-			REQ(ch, fpdef); /* fpdef: NAME | '(' fplist ')' */
-			fp = CHILD(ch, 0);
-			if (TYPE(fp) != NAME) {
-				com_addoparg(c, LOAD_FAST, ilocal);
-				com_push(c, 1);
-				com_fpdef(c, ch);
+	for (b = c->u->u_blocks; b != NULL; b = b->b_list) {
+		bsize = b->b_offset;
+		for (i = 0; i < b->b_iused; i++) {
+			struct instr *instr = &b->b_instr[i];
+			/* Relative jumps are computed relative to
+			   the instruction pointer after fetching
+			   the jump instruction.
+			*/
+			bsize += instrsize(instr);
+			if (instr->i_jabs)
+				instr->i_oparg = instr->i_target->b_offset;
+			else if (instr->i_jrel) {
+				int delta = instr->i_target->b_offset - bsize;
+				instr->i_oparg = delta;
 			}
-			ilocal++;
-			if (++i >= nch)
-				break;
-			ch = CHILD(n, i);
-			if (TYPE(ch) == EQUAL)
-				i += 2;
-			else
-				REQ(ch, COMMA);
 		}
 	}
-}
-
-static void
-com_file_input(struct compiling *c, node *n)
-{
-	int i;
-	PyObject *doc;
-	REQ(n, file_input); /* (NEWLINE | stmt)* ENDMARKER */
-	doc = get_docstring(c, n);
-	if (doc != NULL) {
-		int i = com_addconst(c, doc);
-		Py_DECREF(doc);
-		com_addoparg(c, LOAD_CONST, i);
-		com_push(c, 1);
-		com_addop_name(c, STORE_NAME, "__doc__");
-		com_pop(c, 1);
-	}
-	for (i = 0; i < NCH(n); i++) {
-		node *ch = CHILD(n, i);
-		if (TYPE(ch) != ENDMARKER && TYPE(ch) != NEWLINE)
-			com_node(c, ch);
-	}
-}
-
-/* Top-level compile-node interface */
-
-static void
-compile_funcdef(struct compiling *c, node *n)
-{
-	PyObject *doc;
-	node *ch;
-	REQ(n, funcdef);
-	/*          -6            -5   -4   -3         -2  -1
-	   funcdef: [decorators] 'def' NAME parameters ':' suite */
-	c->c_name = STR(RCHILD(n, -4));
-	doc = get_docstring(c, RCHILD(n, -1));
-	if (doc != NULL) {
-		(void) com_addconst(c, doc);
-		Py_DECREF(doc);
-	}
-	else
-		(void) com_addconst(c, Py_None); /* No docstring */
-	ch = RCHILD(n, -3); /* parameters: '(' [varargslist] ')' */
-	ch = CHILD(ch, 1); /* ')' | varargslist */
-	if (TYPE(ch) == varargslist)
-		com_arglist(c, ch);
-	c->c_infunction = 1;
-	com_node(c, RCHILD(n, -1));
-	c->c_infunction = 0;
-	com_strip_lnotab(c);
-	com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-	com_push(c, 1);
-	com_addbyte(c, RETURN_VALUE);
-	com_pop(c, 1);
-}
-
-static void
-compile_lambdef(struct compiling *c, node *n)
-{
-	node *ch;
-	REQ(n, lambdef); /* lambdef: 'lambda' [varargslist] ':' test */
-	c->c_name = "<lambda>";
-
-	ch = CHILD(n, 1);
-	(void) com_addconst(c, Py_None); /* No docstring */
-	if (TYPE(ch) == varargslist) {
-		com_arglist(c, ch);
-		ch = CHILD(n, 3);
-	}
-	else
-		ch = CHILD(n, 2);
-	com_node(c, ch);
-	com_addbyte(c, RETURN_VALUE);
-	com_pop(c, 1);
-}
-
-static void
-compile_classdef(struct compiling *c, node *n)
-{
-	node *ch;
-	PyObject *doc;
-	REQ(n, classdef);
-	/* classdef: 'class' NAME ['(' testlist ')'] ':' suite */
-	c->c_name = STR(CHILD(n, 1));
-	c->c_private = c->c_name;
-	/* Initialize local __module__ from global __name__ */
-	com_addop_name(c, LOAD_GLOBAL, "__name__");
-	com_addop_name(c, STORE_NAME, "__module__");
-	ch = CHILD(n, NCH(n)-1); /* The suite */
-	doc = get_docstring(c, ch);
-	if (doc != NULL) {
-		int i = com_addconst(c, doc);
-		Py_DECREF(doc);
-		com_addoparg(c, LOAD_CONST, i);
-		com_push(c, 1);
-		com_addop_name(c, STORE_NAME, "__doc__");
-		com_pop(c, 1);
-	}
-	else
-		(void) com_addconst(c, Py_None);
-	com_node(c, ch);
-	com_strip_lnotab(c);
-	com_addbyte(c, LOAD_LOCALS);
-	com_push(c, 1);
-	com_addbyte(c, RETURN_VALUE);
-	com_pop(c, 1);
-}
-
-static void
-compile_generator_expression(struct compiling *c, node *n)
-{
-	/* testlist_gexp: test gen_for */
-	/* argument: test gen_for */
-	REQ(CHILD(n, 0), test); 
-	REQ(CHILD(n, 1), gen_for); 
-
-	c->c_name = "<generator expression>";
-	c->c_infunction = 1;
-	com_gen_for(c, CHILD(n, 1), CHILD(n, 0), 1);
-	c->c_infunction = 0;
-
-	com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-	com_push(c, 1);
-	com_addbyte(c, RETURN_VALUE);
-	com_pop(c, 1);
-}
-
-static void
-compile_node(struct compiling *c, node *n)
-{
-	com_set_lineno(c, n->n_lineno);
-	
-	switch (TYPE(n)) {
-	
-	case single_input: /* One interactive command */
-		/* NEWLINE | simple_stmt | compound_stmt NEWLINE */
-		c->c_interactive++;
-		n = CHILD(n, 0);
-		if (TYPE(n) != NEWLINE)
-			com_node(c, n);
-		com_strip_lnotab(c);
-		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-		com_push(c, 1);
-		com_addbyte(c, RETURN_VALUE);
-		com_pop(c, 1);
-		c->c_interactive--;
-		break;
-	
-	case file_input: /* A whole file, or built-in function exec() */
-		com_file_input(c, n);
-		com_strip_lnotab(c);
-		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-		com_push(c, 1);
-		com_addbyte(c, RETURN_VALUE);
-		com_pop(c, 1);
-		break;
-	
-	case eval_input: /* Built-in function input() */
-		com_node(c, CHILD(n, 0));
-		com_addbyte(c, RETURN_VALUE);
-		com_pop(c, 1);
-		break;
-	
-	case lambdef: /* anonymous function definition */
-		compile_lambdef(c, n);
-		break;
-
-	case funcdef: /* A function definition */
-		compile_funcdef(c, n);
-		break;
-	
-	case classdef: /* A class definition */
-		compile_classdef(c, n);
-		break;
-	
-	case testlist_gexp: /* A generator expression */
-	case argument:      /* A generator expression */
-		compile_generator_expression(c, n);
-		break;
-
-	default:
-		com_error(c, PyExc_SystemError,
-			  "compile_node: unexpected node type");
-	}
+	return 1;
 }
 
 static PyObject *
@@ -5138,1685 +3919,171 @@
 		return NULL;
 	while (PyDict_Next(dict, &pos, &k, &v)) {
 		i = PyInt_AS_LONG(v);
+                k = PyTuple_GET_ITEM(k, 0);
 		Py_INCREF(k);
 		assert((i - offset) < size);
+                assert((i - offset) >= 0);
 		PyTuple_SET_ITEM(tuple, i - offset, k);
 	}
 	return tuple;
 }
 
-PyCodeObject *
-PyNode_Compile(node *n, const char *filename)
-{
-	return PyNode_CompileFlags(n, filename, NULL);
-}
-
-PyCodeObject *
-PyNode_CompileFlags(node *n, const char *filename, PyCompilerFlags *flags)
-{
-	return jcompile(n, filename, NULL, flags);
-}
-
-struct symtable *
-PyNode_CompileSymtable(node *n, const char *filename)
-{
-	struct symtable *st;
-	PyFutureFeatures *ff;
-
-	ff = PyNode_Future(n, filename);
-	if (ff == NULL)
-		return NULL;
-	st = symtable_build(n, ff, filename);
-	if (st == NULL) {
-		PyObject_FREE((void *)ff);
-		return NULL;
-	}
-	return st;
-}
-
-static PyCodeObject *
-icompile(node *n, struct compiling *base)
-{
-	return jcompile(n, base->c_filename, base, NULL);
-}
-
-static PyCodeObject *
-jcompile(node *n, const char *filename, struct compiling *base,
-	 PyCompilerFlags *flags)
-{
-	struct compiling sc;
-	PyCodeObject *co;
-	if (!com_init(&sc, filename))
-		return NULL;
-	if (flags && flags->cf_flags & PyCF_SOURCE_IS_UTF8) {
-		sc.c_encoding = "utf-8";
-	} else if (TYPE(n) == encoding_decl) {
-		sc.c_encoding = STR(n);
-		n = CHILD(n, 0);
-	} else {
-		sc.c_encoding = NULL;
-	}
-	if (base) {
-		sc.c_private = base->c_private;
-		sc.c_symtable = base->c_symtable;
-		/* c_symtable still points to parent's symbols */
-		if (base->c_nested 
-		    || (sc.c_symtable->st_cur->ste_type == TYPE_FUNCTION))
-			sc.c_nested = 1;
-		sc.c_flags |= base->c_flags & PyCF_MASK;
-		if (base->c_encoding != NULL) {
-			assert(sc.c_encoding == NULL);
-			sc.c_encoding = base->c_encoding;
-		}
-	} else {
-		sc.c_private = NULL;
-		sc.c_future = PyNode_Future(n, filename);
-		if (sc.c_future == NULL) {
-			com_free(&sc);
-			return NULL;
-		}
-		if (flags) {
-			int merged = sc.c_future->ff_features |
-				flags->cf_flags;
-			sc.c_future->ff_features = merged;
-			flags->cf_flags = merged;
-		}
-		sc.c_symtable = symtable_build(n, sc.c_future, sc.c_filename);
-		if (sc.c_symtable == NULL) {
-			com_free(&sc);
-			return NULL;
-		}
-		/* reset symbol table for second pass */
-		sc.c_symtable->st_nscopes = 1;
-		sc.c_symtable->st_pass = 2;
-	}
-	co = NULL;
-	if (symtable_load_symbols(&sc) < 0) {
-		sc.c_errors++;
-		goto exit;
-	}
-	compile_node(&sc, n);
-	com_done(&sc);
-	if (sc.c_errors == 0) {
-		PyObject *consts, *names, *varnames, *filename, *name,
-			*freevars, *cellvars, *code;
-		names = PyList_AsTuple(sc.c_names);
-		varnames = PyList_AsTuple(sc.c_varnames);
-		cellvars = dict_keys_inorder(sc.c_cellvars, 0);
-		freevars = dict_keys_inorder(sc.c_freevars,
-					     PyTuple_GET_SIZE(cellvars));
-		filename = PyString_InternFromString(sc.c_filename);
-		name = PyString_InternFromString(sc.c_name);
-		code = optimize_code(sc.c_code, sc.c_consts, names, sc.c_lnotab);
-		consts = PyList_AsTuple(sc.c_consts);
-		if (!PyErr_Occurred())
-			co = PyCode_New(sc.c_argcount,
-					sc.c_nlocals,
-					sc.c_maxstacklevel,
-					sc.c_flags,
-					code,
-					consts,
-					names,
-					varnames,
-					freevars,
-					cellvars,
-					filename,
-					name,
-					sc.c_firstlineno,
-					sc.c_lnotab);
-		Py_XDECREF(consts);
-		Py_XDECREF(names);
-		Py_XDECREF(varnames);
-		Py_XDECREF(freevars);
-		Py_XDECREF(cellvars);
-		Py_XDECREF(filename);
-		Py_XDECREF(name);
-		Py_XDECREF(code);
-	}
-	else if (!PyErr_Occurred()) {
-		/* This could happen if someone called PyErr_Clear() after an
-		   error was reported above.  That's not supposed to happen,
-		   but I just plugged one case and I'm not sure there can't be
-		   others.  In that case, raise SystemError so that at least
-		   it gets reported instead dumping core. */
-		PyErr_SetString(PyExc_SystemError, "lost syntax error");
-	}
- exit:
-	if (base == NULL) {
-		PySymtable_Free(sc.c_symtable);
-		sc.c_symtable = NULL;
-	}
-	com_free(&sc);
-	return co;
-}
-
-int
-PyCode_Addr2Line(PyCodeObject *co, int addrq)
-{
-	int size = PyString_Size(co->co_lnotab) / 2;
-	unsigned char *p = (unsigned char*)PyString_AsString(co->co_lnotab);
-	int line = co->co_firstlineno;
-	int addr = 0;
-	while (--size >= 0) {
-		addr += *p++;
-		if (addr > addrq)
-			break;
-		line += *p++;
-	}
-	return line;
-}
-
-/* The test for LOCAL must come before the test for FREE in order to
-   handle classes where name is both local and free.  The local var is
-   a method and the free var is a free var referenced within a method.
-*/
-
 static int
-get_ref_type(struct compiling *c, char *name)
+compute_code_flags(struct compiler *c)
 {
-	char buf[350];
-	PyObject *v;
-
-	if (PyDict_GetItemString(c->c_cellvars, name) != NULL)
-		return CELL;
-	if (PyDict_GetItemString(c->c_locals, name) != NULL)
-		return LOCAL;
-	if (PyDict_GetItemString(c->c_freevars, name) != NULL)
-		return FREE;
-	v = PyDict_GetItemString(c->c_globals, name);
-	if (v) {
-		if (v == Py_None)
-			return GLOBAL_EXPLICIT;
-		else {
-			return GLOBAL_IMPLICIT;
-		}
+	PySTEntryObject *ste = c->u->u_ste;
+	int flags = 0, n;
+	if (ste->ste_type != ModuleBlock)
+		flags |= CO_NEWLOCALS;
+	if (ste->ste_type == FunctionBlock) {
+		if (!ste->ste_unoptimized)
+			flags |= CO_OPTIMIZED;
+		if (ste->ste_nested)
+			flags |= CO_NESTED;
+		if (ste->ste_generator)
+			flags |= CO_GENERATOR;
 	}
-	PyOS_snprintf(buf, sizeof(buf),
-		"unknown scope for %.100s in %.100s(%s) "
-		"in %s\nsymbols: %s\nlocals: %s\nglobals: %s\n",
-		name, c->c_name, 
-		PyObject_REPR(c->c_symtable->st_cur->ste_id),
-		c->c_filename,
-		PyObject_REPR(c->c_symtable->st_cur->ste_symbols),
-		PyObject_REPR(c->c_locals),
-		PyObject_REPR(c->c_globals)
-		);
-
-	Py_FatalError(buf);
-	return -1;
-}
-
-/* Helper functions to issue warnings */
-
-static int
-issue_warning(const char *msg, const char *filename, int lineno)
-{
-	if (PyErr_Occurred()) {
-		/* This can happen because symtable_node continues
-		   processing even after raising a SyntaxError.
-		   Calling PyErr_WarnExplicit now would clobber the
-		   pending exception; instead we fail and let that
-		   exception propagate.
-		*/
-		return -1;
-	}
-	if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, filename,
-			       lineno, NULL, NULL) < 0)	{
-		if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
-			PyErr_SetString(PyExc_SyntaxError, msg);
-			PyErr_SyntaxLocation(filename, lineno);
-		}
-		return -1;
-	}
-	return 0;
-}
-
-static int
-symtable_warn(struct symtable *st, char *msg)
-{
-	if (issue_warning(msg, st->st_filename, st->st_cur->ste_lineno) < 0) {
-		st->st_errors++;
-		return -1;
-	}
-	return 0;
-}
-
-/* Helper function for setting lineno and filename */
-
-static struct symtable *
-symtable_build(node *n, PyFutureFeatures *ff, const char *filename)
-{
-	struct symtable *st;
-
-	st = symtable_init();
-	if (st == NULL)
-		return NULL;
-	st->st_future = ff;
-	st->st_filename = filename;
-	symtable_enter_scope(st, TOP, TYPE(n), n->n_lineno);
-	if (st->st_errors > 0)
-		goto fail;
-	symtable_node(st, n);
-	if (st->st_errors > 0)
-		goto fail;
-	return st;
- fail:
-	if (!PyErr_Occurred()) {
-		/* This could happen because after a syntax error is
-		   detected, the symbol-table-building continues for
-		   a while, and PyErr_Clear() might erroneously be
-		   called during that process.  One such case has been
-		   fixed, but there might be more (now or later).
-		*/
-		PyErr_SetString(PyExc_SystemError, "lost exception");
-	}
-	st->st_future = NULL;
-	st->st_filename = NULL;
-	PySymtable_Free(st);
-	return NULL;
-}
-
-static int
-symtable_init_compiling_symbols(struct compiling *c)
-{
-	PyObject *varnames;
-
-	varnames = c->c_symtable->st_cur->ste_varnames;
-	if (varnames == NULL) {
-		varnames = PyList_New(0);
-		if (varnames == NULL)
-			return -1;
-		c->c_symtable->st_cur->ste_varnames = varnames;
-		Py_INCREF(varnames);
-	} else
-		Py_INCREF(varnames);
-	c->c_varnames = varnames;
-
-	c->c_globals = PyDict_New();
-	if (c->c_globals == NULL)
-		return -1;
-	c->c_freevars = PyDict_New();
-	if (c->c_freevars == NULL)
-		return -1;
-	c->c_cellvars = PyDict_New();
-	if (c->c_cellvars == NULL)
-		return -1;
-	return 0;
-}
-
-struct symbol_info {
-	int si_nlocals;
-	int si_ncells;
-	int si_nfrees;
-	int si_nimplicit;
-};
-
-static void
-symtable_init_info(struct symbol_info *si)
-{
-	si->si_nlocals = 0;
-	si->si_ncells = 0;
-	si->si_nfrees = 0;
-	si->si_nimplicit = 0;
-}
-
-static int
-symtable_resolve_free(struct compiling *c, PyObject *name, int flags,
-		      struct symbol_info *si)
-{
-	PyObject *dict, *v;
-
-	/* Seperate logic for DEF_FREE.  If it occurs in a function,
-	   it indicates a local that we must allocate storage for (a
-	   cell var).  If it occurs in a class, then the class has a
-	   method and a free variable with the same name.
-	*/
-	if (c->c_symtable->st_cur->ste_type == TYPE_FUNCTION) {
-		/* If it isn't declared locally, it can't be a cell. */
-		if (!(flags & (DEF_LOCAL | DEF_PARAM)))
-			return 0;
-		v = PyInt_FromLong(si->si_ncells++);
-		dict = c->c_cellvars;
-	} else {
-		/* If it is free anyway, then there is no need to do
-		   anything here.
-		*/
-		if (is_free(flags ^ DEF_FREE_CLASS) 
-		    || (flags == DEF_FREE_CLASS))
-			return 0;
-		v = PyInt_FromLong(si->si_nfrees++);
-		dict = c->c_freevars;
-	}
-	if (v == NULL)
-		return -1;
-	if (PyDict_SetItem(dict, name, v) < 0) {
-		Py_DECREF(v);
-		return -1;
-	}
-	Py_DECREF(v);
-	return 0;
-}
-
-/* If a variable is a cell and an argument, make sure that appears in
-   co_cellvars before any variable to its right in varnames. 
-*/
-
-
-static int
-symtable_cellvar_offsets(PyObject **cellvars, int argcount, 
-			 PyObject *varnames, int flags) 
-{
-	PyObject *v = NULL;
-	PyObject *w, *d, *list = NULL;
-	int i, pos;
-
-	if (flags & CO_VARARGS)
-		argcount++;
-	if (flags & CO_VARKEYWORDS)
-		argcount++;
-	for (i = argcount; --i >= 0; ) {
-		v = PyList_GET_ITEM(varnames, i);
-		if (PyDict_GetItem(*cellvars, v)) {
-			if (list == NULL) {
-				list = PyList_New(1);
-				if (list == NULL)
-					return -1;
-				PyList_SET_ITEM(list, 0, v);
-				Py_INCREF(v);
-			} else {
-				if (PyList_Insert(list, 0, v) < 0) {
-					Py_DECREF(list);
-					return -1;
-				}
-			}
-		}
-	}
-	if (list == NULL)
-		return 0;
-
-	/* There are cellvars that are also arguments.  Create a dict
-	   to replace cellvars and put the args at the front.
-	*/
-	d = PyDict_New();
-	if (d == NULL)
-		return -1;
-	for (i = PyList_GET_SIZE(list); --i >= 0; ) {
-		v = PyInt_FromLong(i);
-		if (v == NULL) 
-			goto fail;
-		if (PyDict_SetItem(d, PyList_GET_ITEM(list, i), v) < 0)
-			goto fail;
-		if (PyDict_DelItem(*cellvars, PyList_GET_ITEM(list, i)) < 0)
-			goto fail;
-		Py_DECREF(v);
-	}
-	pos = 0;
-	i = PyList_GET_SIZE(list);
-	Py_DECREF(list);
-	while (PyDict_Next(*cellvars, &pos, &v, &w)) {
-		w = PyInt_FromLong(i++);  /* don't care about the old key */
-		if (w == NULL)
-			goto fail;
-		if (PyDict_SetItem(d, v, w) < 0) {
-			Py_DECREF(w);
-			v = NULL;
-			goto fail;
-		}
-		Py_DECREF(w);
-	}
-	Py_DECREF(*cellvars);
-	*cellvars = d;
-	return 1;
- fail:
-	Py_DECREF(d);
-	Py_XDECREF(v);
-	return -1;
-}
-
-static int
-symtable_freevar_offsets(PyObject *freevars, int offset)
-{
-	PyObject *name, *v;
-	int pos;
-
-	/* The cell vars are the first elements of the closure,
-	   followed by the free vars.  Update the offsets in
-	   c_freevars to account for number of cellvars. */  
-	pos = 0;
-	while (PyDict_Next(freevars, &pos, &name, &v)) {
-		int i = PyInt_AS_LONG(v) + offset;
-		PyObject *o = PyInt_FromLong(i);
-		if (o == NULL)
-			return -1;
-		if (PyDict_SetItem(freevars, name, o) < 0) {
-			Py_DECREF(o);
-			return -1;
-		}
-		Py_DECREF(o);
-	}
-	return 0;
-}
-
-static int
-symtable_check_unoptimized(struct compiling *c,
-			   PySymtableEntryObject *ste, 
-			   struct symbol_info *si)
-{
-	char buf[300];
-
-	if (!(si->si_ncells || si->si_nfrees || ste->ste_child_free
-	      || (ste->ste_nested && si->si_nimplicit)))
-		return 0;
-
-#define ILLEGAL_CONTAINS "contains a nested function with free variables"
-
-#define ILLEGAL_IS "is a nested function"
-
-#define ILLEGAL_IMPORT_STAR \
-"import * is not allowed in function '%.100s' because it %s"
-
-#define ILLEGAL_BARE_EXEC \
-"unqualified exec is not allowed in function '%.100s' it %s"
-
-#define ILLEGAL_EXEC_AND_IMPORT_STAR \
-"function '%.100s' uses import * and bare exec, which are illegal " \
-"because it %s"
-
-	/* XXX perhaps the linenos for these opt-breaking statements
-	   should be stored so the exception can point to them. */
-
-	if (ste->ste_child_free) {
-		if (ste->ste_optimized == OPT_IMPORT_STAR)
-			PyOS_snprintf(buf, sizeof(buf),
-				      ILLEGAL_IMPORT_STAR, 
-				      PyString_AS_STRING(ste->ste_name),
-				      ILLEGAL_CONTAINS);
-		else if (ste->ste_optimized == (OPT_BARE_EXEC | OPT_EXEC))
-			PyOS_snprintf(buf, sizeof(buf),
-				      ILLEGAL_BARE_EXEC,
-				      PyString_AS_STRING(ste->ste_name),
-				      ILLEGAL_CONTAINS);
-		else {
-			PyOS_snprintf(buf, sizeof(buf),
-				      ILLEGAL_EXEC_AND_IMPORT_STAR,
-				      PyString_AS_STRING(ste->ste_name),
-				      ILLEGAL_CONTAINS);
-		}
-	} else {
-		if (ste->ste_optimized == OPT_IMPORT_STAR)
-			PyOS_snprintf(buf, sizeof(buf),
-				      ILLEGAL_IMPORT_STAR, 
-				      PyString_AS_STRING(ste->ste_name),
-				      ILLEGAL_IS);
-		else if (ste->ste_optimized == (OPT_BARE_EXEC | OPT_EXEC))
-			PyOS_snprintf(buf, sizeof(buf),
-				      ILLEGAL_BARE_EXEC,
-				      PyString_AS_STRING(ste->ste_name),
-				      ILLEGAL_IS);
-		else {
-			PyOS_snprintf(buf, sizeof(buf),
-				      ILLEGAL_EXEC_AND_IMPORT_STAR,
-				      PyString_AS_STRING(ste->ste_name),
-				      ILLEGAL_IS);
-		}
-	}
-
-	PyErr_SetString(PyExc_SyntaxError, buf);
-	PyErr_SyntaxLocation(c->c_symtable->st_filename,
-			     ste->ste_opt_lineno);
-	return -1;
-}
-
-static int
-symtable_update_flags(struct compiling *c, PySymtableEntryObject *ste,
-		      struct symbol_info *si)
-{
-	if (c->c_future)
-		c->c_flags |= c->c_future->ff_features;
+	if (ste->ste_varargs)
+		flags |= CO_VARARGS;
+	if (ste->ste_varkeywords)
+		flags |= CO_VARKEYWORDS;
 	if (ste->ste_generator)
-		c->c_flags |= CO_GENERATOR;
-	if (ste->ste_type != TYPE_MODULE)
-		c->c_flags |= CO_NEWLOCALS;
-	if (ste->ste_type == TYPE_FUNCTION) {
-		c->c_nlocals = si->si_nlocals;
-		if (ste->ste_optimized == 0)
-			c->c_flags |= CO_OPTIMIZED;
-		else if (ste->ste_optimized != OPT_EXEC) 
-			return symtable_check_unoptimized(c, ste, si);
-	}
-	return 0;
-}
-
-static int
-symtable_error(struct symtable *st, int lineno)
-{
-	if (lineno == 0)
-		lineno = st->st_cur->ste_lineno;
-	PyErr_SyntaxLocation(st->st_filename, lineno);
-	st->st_errors++;
-	return -1;
-}
-
-static int
-symtable_load_symbols(struct compiling *c)
-{
-	struct symtable *st = c->c_symtable;
-	PySymtableEntryObject *ste = st->st_cur;
-	PyObject *name, *varnames, *v;
-	int i, flags, pos;
-	struct symbol_info si;
-
-	v = NULL;
-
-	if (symtable_init_compiling_symbols(c) < 0)
-		goto fail;
-	symtable_init_info(&si);
-	varnames = st->st_cur->ste_varnames;
-	si.si_nlocals = PyList_GET_SIZE(varnames);
-	c->c_argcount = si.si_nlocals;
-
-	for (i = 0; i < si.si_nlocals; ++i) {
-		v = PyInt_FromLong(i);
-		if (v == NULL)
-			goto fail;
-		if (PyDict_SetItem(c->c_locals, 
-				   PyList_GET_ITEM(varnames, i), v) < 0)
-			goto fail;
-		Py_DECREF(v);
-	}
-
-	/* XXX The cases below define the rules for whether a name is
-	   local or global.  The logic could probably be clearer. */
-	pos = 0;
-	while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) {
-		flags = PyInt_AS_LONG(v);
-
-		if (flags & DEF_FREE_GLOBAL)
-			/* undo the original DEF_FREE */
-			flags &= ~(DEF_FREE | DEF_FREE_CLASS);
-
-		/* Deal with names that need two actions:
-		   1. Cell variables that are also locals.
-		   2. Free variables in methods that are also class
-		   variables or declared global.
-		*/
-		if (flags & (DEF_FREE | DEF_FREE_CLASS))
-			symtable_resolve_free(c, name, flags, &si);
-
-		if (flags & DEF_STAR) {
-			c->c_argcount--;
-			c->c_flags |= CO_VARARGS;
-		} else if (flags & DEF_DOUBLESTAR) {
-			c->c_argcount--;
-			c->c_flags |= CO_VARKEYWORDS;
-		} else if (flags & DEF_INTUPLE) 
-			c->c_argcount--;
-		else if (flags & DEF_GLOBAL) {
-			if (flags & DEF_PARAM) {
-				PyErr_Format(PyExc_SyntaxError, PARAM_GLOBAL,
-					     PyString_AS_STRING(name));
-				symtable_error(st, 0);
-				goto fail;
-			}
-			if (PyDict_SetItem(c->c_globals, name, Py_None) < 0)
-				goto fail;
-		} else if (flags & DEF_FREE_GLOBAL) {
-			si.si_nimplicit++;
-			if (PyDict_SetItem(c->c_globals, name, Py_True) < 0)
-				goto fail;
-		} else if ((flags & DEF_LOCAL) && !(flags & DEF_PARAM)) {
-			v = PyInt_FromLong(si.si_nlocals++);
-			if (v == NULL)
-				goto fail;
-			if (PyDict_SetItem(c->c_locals, name, v) < 0)
-				goto fail;
-			Py_DECREF(v);
-			if (ste->ste_type != TYPE_CLASS) 
-				if (PyList_Append(c->c_varnames, name) < 0)
-					goto fail;
-		} else if (is_free(flags)) {
-			if (ste->ste_nested) {
-				v = PyInt_FromLong(si.si_nfrees++);
-				if (v == NULL)
-					goto fail;
-				if (PyDict_SetItem(c->c_freevars, name, v) < 0)
-					goto fail;
-				Py_DECREF(v);
-			} else {
-				si.si_nimplicit++;
- 				if (PyDict_SetItem(c->c_globals, name,
- 						   Py_True) < 0)
- 					goto fail;
- 				if (st->st_nscopes != 1) {
- 					v = PyInt_FromLong(flags);
-					if (v == NULL)
-						goto fail;
- 					if (PyDict_SetItem(st->st_global, 
- 							   name, v)) 
- 						goto fail;
- 					Py_DECREF(v);
- 				}
-			}
-		}
-	}
-	assert(PyDict_Size(c->c_freevars) == si.si_nfrees);
-
-	if (si.si_ncells > 1) { /* one cell is always in order */
-		if (symtable_cellvar_offsets(&c->c_cellvars, c->c_argcount,
-					     c->c_varnames, c->c_flags) < 0)
-			return -1;
-	}
-	if (symtable_freevar_offsets(c->c_freevars, si.si_ncells) < 0)
+		flags |= CO_GENERATOR;
+        if (c->c_flags->cf_flags & CO_FUTURE_DIVISION)
+                flags |= CO_FUTURE_DIVISION;
+	n = PyDict_Size(c->u->u_freevars);
+	if (n < 0)
+	    return -1;
+	if (n == 0) {
+	    n = PyDict_Size(c->u->u_cellvars);
+	    if (n < 0)
 		return -1;
-	return symtable_update_flags(c, ste, &si);
- fail:
-	/* is this always the right thing to do? */
-	Py_XDECREF(v);
-	return -1;
-}
-
-static struct symtable *
-symtable_init()
-{
-	struct symtable *st;
-
-	st = (struct symtable *)PyObject_MALLOC(sizeof(struct symtable));
-	if (st == NULL)
-		return NULL;
-	st->st_pass = 1;
-
-	st->st_filename = NULL;
-	st->st_symbols = NULL;
-	if ((st->st_stack = PyList_New(0)) == NULL)
-		goto fail;
-	if ((st->st_symbols = PyDict_New()) == NULL)
-		goto fail; 
-	st->st_cur = NULL;
-	st->st_nscopes = 0;
-	st->st_errors = 0;
-	st->st_private = NULL;
-	return st;
- fail:
-	PySymtable_Free(st);
-	return NULL;
-}
-
-void
-PySymtable_Free(struct symtable *st)
-{
-	Py_XDECREF(st->st_symbols);
-	Py_XDECREF(st->st_stack);
-	Py_XDECREF(st->st_cur);
-	PyObject_FREE((void *)st);
-}
-
-/* When the compiler exits a scope, it must should update the scope's
-   free variable information with the list of free variables in its
-   children.
-
-   Variables that are free in children and defined in the current
-   scope are cellvars.
-
-   If the scope being exited is defined at the top-level (ste_nested is
-   false), free variables in children that are not defined here are
-   implicit globals.
-
-*/
-
-static int
-symtable_update_free_vars(struct symtable *st)
-{
-	int i, j, def;
-	PyObject *o, *name, *list = NULL;
-	PySymtableEntryObject *child, *ste = st->st_cur;
-
-	if (ste->ste_type == TYPE_CLASS)
-		def = DEF_FREE_CLASS;
-	else
-		def = DEF_FREE;
-	for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) {
-		int pos = 0;
-
-		if (list && PyList_SetSlice(list, 0, 
-					    PyList_GET_SIZE(list), 0) < 0)
-				return -1;
-		child = (PySymtableEntryObject *)
-			PyList_GET_ITEM(ste->ste_children, i);
-		while (PyDict_Next(child->ste_symbols, &pos, &name, &o)) {
-			int flags = PyInt_AS_LONG(o);
-			if (!(is_free(flags)))
-				continue; /* avoids indentation */
-			if (list == NULL) {
-				list = PyList_New(0);
-				if (list == NULL)
-					return -1;
-			}
-			ste->ste_child_free = 1;
-			if (PyList_Append(list, name) < 0) {
-				Py_DECREF(list);
-				return -1;
-			}
-		}
-		for (j = 0; list && j < PyList_GET_SIZE(list); j++) {
-			PyObject *v;
-			name = PyList_GET_ITEM(list, j);
-			v = PyDict_GetItem(ste->ste_symbols, name);
-			/* If a name N is declared global in scope A and
-			   referenced in scope B contained (perhaps
-			   indirectly) in A and there are no scopes
-			   with bindings for N between B and A, then N
-			   is global in B.  Unless A is a class scope,
-			   because class scopes are not considered for
-			   nested scopes.
-			*/
-			if (v && (ste->ste_type != TYPE_CLASS)) {
-				int flags = PyInt_AS_LONG(v); 
-				if (flags & DEF_GLOBAL) {
-					symtable_undo_free(st, child->ste_id,
-							   name);
-					continue;
-				}
-			}
-			if (ste->ste_nested) {
-				if (symtable_add_def_o(st, ste->ste_symbols,
-						       name, def) < 0) {
-				    Py_DECREF(list);
-				    return -1;
-				}
-			} else {
-				if (symtable_check_global(st, child->ste_id, 
-							  name) < 0) {
-				    Py_DECREF(list);
-				    return -1;
-				}
-			}
-		}
+	    if (n == 0) {
+		flags |= CO_NOFREE;
+	    }
 	}
 
-	Py_XDECREF(list);
-	return 0;
-}
-
-/* If the current scope is a non-nested class or if name is not
-   defined in the current, non-nested scope, then it is an implicit
-   global in all nested scopes.
-*/
-
-static int
-symtable_check_global(struct symtable *st, PyObject *child, PyObject *name)
-{
-	PyObject *o;
-	int v;
-	PySymtableEntryObject *ste = st->st_cur;
-			
-	if (ste->ste_type == TYPE_CLASS)
-		return symtable_undo_free(st, child, name);
-	o = PyDict_GetItem(ste->ste_symbols, name);
-	if (o == NULL)
-		return symtable_undo_free(st, child, name);
-	v = PyInt_AS_LONG(o);
-
-	if (is_free(v) || (v & DEF_GLOBAL)) 
-		return symtable_undo_free(st, child, name);
-	else
-		return symtable_add_def_o(st, ste->ste_symbols,
-					  name, DEF_FREE);
-}
-
-static int
-symtable_undo_free(struct symtable *st, PyObject *id, 
-		      PyObject *name)
-{
-	int i, v, x;
-	PyObject *info;
-	PySymtableEntryObject *ste;
-
-	ste = (PySymtableEntryObject *)PyDict_GetItem(st->st_symbols, id);
-	if (ste == NULL)
-		return -1;
-
-	info = PyDict_GetItem(ste->ste_symbols, name);
-	if (info == NULL)
-		return 0;
-	v = PyInt_AS_LONG(info);
-	if (is_free(v)) {
-		if (symtable_add_def_o(st, ste->ste_symbols, name,
-				       DEF_FREE_GLOBAL) < 0)
-			return -1;
-	} else
-		/* If the name is defined here or declared global,
-		   then the recursion stops. */
-		return 0;
-	
-	for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) {
-		PySymtableEntryObject *child;
-		child = (PySymtableEntryObject *)
-			PyList_GET_ITEM(ste->ste_children, i);
-		x = symtable_undo_free(st, child->ste_id, name);
-		if (x < 0)
-			return x;
-	}
-	return 0;
-}
-
-/* symtable_enter_scope() gets a reference via PySymtableEntry_New().
-   This reference is released when the scope is exited, via the DECREF
-   in symtable_exit_scope().
-*/
-
-static int
-symtable_exit_scope(struct symtable *st)
-{
-	int end;
-
-	if (st->st_pass == 1)
-		symtable_update_free_vars(st);
-	Py_DECREF(st->st_cur);
-	end = PyList_GET_SIZE(st->st_stack) - 1;
-	st->st_cur = (PySymtableEntryObject *)PyList_GET_ITEM(st->st_stack, 
-							      end);
-	if (PySequence_DelItem(st->st_stack, end) < 0)
-		return -1;
-	return 0;
-}
-
-static void
-symtable_enter_scope(struct symtable *st, char *name, int type,
-		     int lineno)
-{
-	PySymtableEntryObject *prev = NULL;
-
-	if (st->st_cur) {
-		prev = st->st_cur;
-		if (PyList_Append(st->st_stack, (PyObject *)st->st_cur) < 0) {
-			st->st_errors++;
-			return;
-		}
-	}
-	st->st_cur = (PySymtableEntryObject *)
-		PySymtableEntry_New(st, name, type, lineno);
-	if (st->st_cur == NULL) {
-		st->st_errors++;
-		return;
-	}
-	if (strcmp(name, TOP) == 0)
-		st->st_global = st->st_cur->ste_symbols;
-	if (prev && st->st_pass == 1) {
-		if (PyList_Append(prev->ste_children, 
-				  (PyObject *)st->st_cur) < 0)
-			st->st_errors++;
-	}
-}
-
-static int
-symtable_lookup(struct symtable *st, char *name)
-{
-	char buffer[MANGLE_LEN];
-	PyObject *v;
-	int flags;
-
-	if (_Py_Mangle(st->st_private, name, buffer, sizeof(buffer)))
-		name = buffer;
-	v = PyDict_GetItemString(st->st_cur->ste_symbols, name);
-	if (v == NULL) {
-		if (PyErr_Occurred())
-			return -1;
-		else
-			return 0;
-	}
-
-	flags = PyInt_AS_LONG(v);
 	return flags;
 }
 
-static int
-symtable_add_def(struct symtable *st, char *name, int flag)
+static PyCodeObject *
+makecode(struct compiler *c, struct assembler *a)
 {
-	PyObject *s;
-	char buffer[MANGLE_LEN];
-	int ret;
+	PyObject *tmp;
+	PyCodeObject *co = NULL;
+	PyObject *consts = NULL;
+	PyObject *names = NULL;
+	PyObject *varnames = NULL;
+	PyObject *filename = NULL;
+	PyObject *name = NULL;
+	PyObject *freevars = NULL;
+	PyObject *cellvars = NULL;
+        PyObject *bytecode = NULL;
+	int nlocals, flags;
 
-	/* Warn about None, except inside a tuple (where the assignment
-	   code already issues a warning). */
-	if ((flag & DEF_PARAM) && !(flag & DEF_INTUPLE) &&
-	    *name == 'N' && strcmp(name, "None") == 0)
-	{
-		PyErr_SetString(PyExc_SyntaxError, 
-			"Invalid syntax.  Assignment to None.");
-		symtable_error(st, 0);
-		return  -1;
-	}
-	if (_Py_Mangle(st->st_private, name, buffer, sizeof(buffer)))
-		name = buffer;
-	if ((s = PyString_InternFromString(name)) == NULL)
-		return -1;
-	ret = symtable_add_def_o(st, st->st_cur->ste_symbols, s, flag);
-	Py_DECREF(s);
-	return ret;
+	tmp = dict_keys_inorder(c->u->u_consts, 0);
+	if (!tmp)
+		goto error;
+	consts = PySequence_List(tmp); /* optimize_code requires a list */
+	Py_DECREF(tmp);
+
+	names = dict_keys_inorder(c->u->u_names, 0);
+	varnames = dict_keys_inorder(c->u->u_varnames, 0);
+	if (!consts || !names || !varnames)
+		goto error;
+      
+        cellvars = dict_keys_inorder(c->u->u_cellvars, 0);
+        if (!cellvars)
+            goto error;
+        freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars));
+        if (!freevars)
+            goto error;
+	filename = PyString_FromString(c->c_filename);
+	if (!filename)
+		goto error;
+
+        nlocals = PyDict_Size(c->u->u_varnames);
+	flags = compute_code_flags(c);
+	if (flags < 0)
+		goto error;
+
+	bytecode = optimize_code(a->a_bytecode, consts, names, a->a_lnotab);
+	if (!bytecode)
+		goto error;
+
+	tmp = PyList_AsTuple(consts); /* PyCode_New requires a tuple */
+	if (!tmp)
+		goto error;
+	Py_DECREF(consts);
+	consts = tmp;
+
+	co = PyCode_New(c->u->u_argcount, nlocals, stackdepth(c), flags,
+			bytecode, consts, names, varnames,
+			freevars, cellvars,
+			filename, c->u->u_name,
+			c->u->u_firstlineno,
+			a->a_lnotab);
+ error:
+	Py_XDECREF(consts);
+	Py_XDECREF(names);
+	Py_XDECREF(varnames);
+	Py_XDECREF(filename);
+	Py_XDECREF(name);
+	Py_XDECREF(freevars);
+	Py_XDECREF(cellvars);
+	Py_XDECREF(bytecode);
+	return co;
 }
 
-/* Must only be called with mangled names */
-
-static int
-symtable_add_def_o(struct symtable *st, PyObject *dict, 
-		   PyObject *name, int flag) 
+static PyCodeObject *
+assemble(struct compiler *c, int addNone)
 {
-	PyObject *o;
-	int val;
+	basicblock *b, *entryblock;
+	struct assembler a;
+	int i, j, nblocks;
+	PyCodeObject *co = NULL;
 
-	if ((o = PyDict_GetItem(dict, name))) {
-	    val = PyInt_AS_LONG(o);
-	    if ((flag & DEF_PARAM) && (val & DEF_PARAM)) {
-		    PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT,
-				 PyString_AsString(name));
-		    return symtable_error(st, 0);
-	    }
-	    val |= flag;
-	} else
-	    val = flag;
-	o = PyInt_FromLong(val);
-	if (o == NULL)
-		return -1;
-	if (PyDict_SetItem(dict, name, o) < 0) {
-		Py_DECREF(o);
-		return -1;
+	/* Make sure every block that falls off the end returns None.
+	   XXX NEXT_BLOCK() isn't quite right, because if the last
+	   block ends with a jump or return b_next shouldn't set.
+	 */
+	if (!c->u->u_curblock->b_return) {
+		NEXT_BLOCK(c);
+		if (addNone)
+			ADDOP_O(c, LOAD_CONST, Py_None, consts);
+		ADDOP(c, RETURN_VALUE);
 	}
-	Py_DECREF(o);
 
-	if (flag & DEF_PARAM) {
-		if (PyList_Append(st->st_cur->ste_varnames, name) < 0) 
-			return -1;
-	} else	if (flag & DEF_GLOBAL) {
-		/* XXX need to update DEF_GLOBAL for other flags too;
-		   perhaps only DEF_FREE_GLOBAL */
-		if ((o = PyDict_GetItem(st->st_global, name))) {
-			val = PyInt_AS_LONG(o);
-			val |= flag;
-		} else
-			val = flag;
-		o = PyInt_FromLong(val);
-		if (o == NULL)
-			return -1;
-		if (PyDict_SetItem(st->st_global, name, o) < 0) {
-			Py_DECREF(o);
-			return -1;
-		}
-		Py_DECREF(o);
+	nblocks = 0;
+	entryblock = NULL;
+	for (b = c->u->u_blocks; b != NULL; b = b->b_list) {
+		nblocks++;
+		entryblock = b; 
 	}
-	return 0;
-}
 
-#define symtable_add_use(ST, NAME) symtable_add_def((ST), (NAME), USE)
+	if (!assemble_init(&a, nblocks, c->u->u_firstlineno))
+		goto error;
+	dfs(c, entryblock, &a);
 
-/* Look for a yield stmt or expr under n.  Return 1 if found, else 0.
-   This hack is used to look inside "if 0:" blocks (which are normally
-   ignored) in case those are the only places a yield occurs (so that this
-   function is a generator). */
-static int
-look_for_yield(node *n)
-{
-	int i;
+	/* Can't modify the bytecode after computing jump offsets. */
+	if (!assemble_jump_offsets(&a, c))
+		goto error;
 
-	for (i = 0; i < NCH(n); ++i) {
-		node *kid = CHILD(n, i);
-
-		switch (TYPE(kid)) {
-
-		case classdef:
-		case funcdef:
-		case lambdef:
-			/* Stuff in nested functions and classes can't make
-			   the parent a generator. */
-			return 0;
-
-		case yield_stmt:
-		case yield_expr:
-			return GENERATOR;
-
-		default:
-			if (look_for_yield(kid))
-				return GENERATOR;
-		}
+	/* Emit code in reverse postorder from dfs. */
+	for (i = a.a_nblocks - 1; i >= 0; i--) {
+		basicblock *b = a.a_postorder[i];
+		for (j = 0; j < b->b_iused; j++)
+			if (!assemble_emit(&a, &b->b_instr[j]))
+				goto error;
 	}
-	return 0;
-}			
 
-static void
-symtable_node(struct symtable *st, node *n)
-{
-	int i;
+	if (_PyString_Resize(&a.a_lnotab, a.a_lnotab_off) < 0)
+		goto error;
+	if (_PyString_Resize(&a.a_bytecode, a.a_offset) < 0)
+		goto error;
 
- loop:
-	switch (TYPE(n)) {
-	case funcdef: {
-		char *func_name;
-		if (NCH(n) == 6)
-			symtable_node(st, CHILD(n, 0));
-		func_name = STR(RCHILD(n, -4));
-		symtable_add_def(st, func_name, DEF_LOCAL);
-		symtable_default_args(st, RCHILD(n, -3));
-		symtable_enter_scope(st, func_name, TYPE(n), n->n_lineno);
-		symtable_funcdef(st, n);
-		symtable_exit_scope(st);
-		break;
-	}
-	case lambdef:
-		if (NCH(n) == 4)
-			symtable_default_args(st, CHILD(n, 1));
-		symtable_enter_scope(st, "lambda", TYPE(n), n->n_lineno);
-		symtable_funcdef(st, n);
-		symtable_exit_scope(st);
-		break;
-	case classdef: {
-		char *tmp, *class_name = STR(CHILD(n, 1));
-		symtable_add_def(st, class_name, DEF_LOCAL);
-		if (TYPE(CHILD(n, 2)) == LPAR) {
-			node *bases = CHILD(n, 3);
-			int i;
-			for (i = 0; i < NCH(bases); i += 2) {
-				symtable_node(st, CHILD(bases, i));
-			}
-		}
-		symtable_enter_scope(st, class_name, TYPE(n), n->n_lineno);
-		tmp = st->st_private;
-		st->st_private = class_name;
-		symtable_node(st, CHILD(n, NCH(n) - 1));
-		st->st_private = tmp;
-		symtable_exit_scope(st);
-		break;
-	}
-	case if_stmt:
-		for (i = 0; i + 3 < NCH(n); i += 4) {
-			if (is_constant_false(NULL, (CHILD(n, i + 1)))) {
-				if (st->st_cur->ste_generator == 0)
-					st->st_cur->ste_generator =
-						look_for_yield(CHILD(n, i+3));
-				continue;
-			}
-			symtable_node(st, CHILD(n, i + 1));
-			symtable_node(st, CHILD(n, i + 3));
-		}
-		if (i + 2 < NCH(n))
-			symtable_node(st, CHILD(n, i + 2));
-		break;
-	case global_stmt:
-		symtable_global(st, n);
-		break;
-	case import_stmt:
-		symtable_import(st, n);
-		break;
-	case exec_stmt: {
-		st->st_cur->ste_optimized |= OPT_EXEC;
-		symtable_node(st, CHILD(n, 1));
-		if (NCH(n) > 2)
-			symtable_node(st, CHILD(n, 3));
-		else {
-			st->st_cur->ste_optimized |= OPT_BARE_EXEC;
-			st->st_cur->ste_opt_lineno = n->n_lineno;
-		}
-		if (NCH(n) > 4)
-			symtable_node(st, CHILD(n, 5));
-		break;
-
-	}
-	case assert_stmt: 
-		if (Py_OptimizeFlag)
-			return;
-		if (NCH(n) == 2) {
-			n = CHILD(n, 1);
-			goto loop;
-		} else {
-			symtable_node(st, CHILD(n, 1));
-			n = CHILD(n, 3);
-			goto loop;
-		}
-	case except_clause:
-		if (NCH(n) == 4)
-			symtable_assign(st, CHILD(n, 3), 0);
-		if (NCH(n) > 1) {
-			n = CHILD(n, 1);
-			goto loop;
-		}
-		break;
-	case del_stmt:
-		symtable_assign(st, CHILD(n, 1), 0);
-		break;
-	case yield_expr:
-		st->st_cur->ste_generator = 1;
-		if (NCH(n)==1) 
-			break;
-		n = CHILD(n, 1);
-		goto loop;
-	case expr_stmt:
-		if (NCH(n) == 1)
-			n = CHILD(n, 0);
-		else {
-			if (TYPE(CHILD(n, 1)) == augassign) {
-				symtable_assign(st, CHILD(n, 0), 0);
-				symtable_node(st, CHILD(n, 2));
-				break;
-			} else {
-				int i;
-				for (i = 0; i < NCH(n) - 2; i += 2) 
-					symtable_assign(st, CHILD(n, i), 0);
-				n = CHILD(n, NCH(n) - 1);
-			}
-		}
-		goto loop;
-	case list_iter:
-		/* only occurs when there are multiple for loops
-		   in a list comprehension */
-		n = CHILD(n, 0);
-		if (TYPE(n) == list_for)
-			symtable_list_for(st, n);
-		else {
-			REQ(n, list_if);
-			symtable_node(st, CHILD(n, 1));
-			if (NCH(n) == 3) {
-				n = CHILD(n, 2); 
-				goto loop;
-			}
-		}
-		break;
-	case for_stmt:
-		symtable_assign(st, CHILD(n, 1), 0);
-		for (i = 3; i < NCH(n); ++i)
-			if (TYPE(CHILD(n, i)) >= single_input)
-				symtable_node(st, CHILD(n, i));
-		break;
-	case arglist:
-		if (NCH(n) > 1)
-			for (i = 0; i < NCH(n); ++i) {
-				node *ch = CHILD(n, i);
-				if (TYPE(ch) == argument && NCH(ch) == 2 &&
-				    TYPE(CHILD(ch, 1)) == gen_for) {
-					PyErr_SetString(PyExc_SyntaxError,
-							"invalid syntax");
-					symtable_error(st, n->n_lineno);
-					return;
-				}
-			}
-	/* The remaining cases fall through to default except in
-	   special circumstances.  This requires the individual cases
-	   to be coded with great care, even though they look like
-	   rather innocuous.  Each case must double-check TYPE(n).
-	*/
-	case decorator:
-		if (TYPE(n) == decorator) {
-			/* decorator: '@' dotted_name [ '(' [arglist] ')' ] */
-			node *name, *varname;
-			name = CHILD(n, 1);
-			REQ(name, dotted_name);
-			varname = CHILD(name, 0);
-			REQ(varname, NAME);
-			symtable_add_use(st, STR(varname));
-		}
-		/* fall through */
-	case argument:
-		if (TYPE(n) == argument && NCH(n) == 3) {
-			n = CHILD(n, 2);
-			goto loop;
-		}
-		else if (TYPE(n) == argument && NCH(n) == 2 &&
-			TYPE(CHILD(n, 1)) == gen_for) {
-			symtable_generator_expression(st, n);
-			break;
-		}
-		/* fall through */
-	case listmaker:
-		if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == list_for) {
-			symtable_list_comprehension(st, n);
-			break;
-		}
-		/* fall through */
-	case testlist_gexp:
-		if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == gen_for) {
-			symtable_generator_expression(st, n); 
-			break;
-		}
-		/* fall through */
-
-	case atom:
-		if (TYPE(n) == atom) {
-			if (TYPE(CHILD(n, 0)) == NAME) {
-				symtable_add_use(st, STR(CHILD(n, 0)));
-				break;
-			}
-			else if (TYPE(CHILD(n,0)) == LPAR) {
-				n = CHILD(n,1);
-				goto loop;
-			}
-		}
-		/* fall through */
-	default:
-		/* Walk over every non-token child with a special case
-		   for one child.
-		*/
-		if (NCH(n) == 1) {
-			n = CHILD(n, 0);
-			goto loop;
-		}
-		for (i = 0; i < NCH(n); ++i)
-			if (TYPE(CHILD(n, i)) >= single_input)
-				symtable_node(st, CHILD(n, i));
-	}
-}
-
-static void
-symtable_funcdef(struct symtable *st, node *n)
-{
-	node *body;
-
-	if (TYPE(n) == lambdef) {
-		if (NCH(n) == 4)
-			symtable_params(st, CHILD(n, 1));
-	} else
-		symtable_params(st, RCHILD(n, -3));
-	body = CHILD(n, NCH(n) - 1);
-	symtable_node(st, body);
-}
-
-/* The next two functions parse the argument tuple.
-   symtable_default_args() checks for names in the default arguments,
-   which are references in the defining scope.  symtable_params()
-   parses the parameter names, which are defined in the function's
-   body. 
-
-   varargslist: 
-       (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) 
-	| fpdef ['=' test] (',' fpdef ['=' test])* [',']
-*/
-
-static void
-symtable_default_args(struct symtable *st, node *n)
-{
-	node *c;
-	int i;
-
-	if (TYPE(n) == parameters) {
-		n = CHILD(n, 1);
-		if (TYPE(n) == RPAR)
-			return;
-	}
-	REQ(n, varargslist);
-	for (i = 0; i < NCH(n); i += 2) {
-		c = CHILD(n, i);
-		if (TYPE(c) == STAR || TYPE(c) == DOUBLESTAR) {
-			break;
-		}
-		if (i > 0 && (TYPE(CHILD(n, i - 1)) == EQUAL))
-			symtable_node(st, CHILD(n, i));
-	}
-}
-
-static void
-symtable_params(struct symtable *st, node *n)
-{
-	int i, complex = -1, ext = 0;
-	node *c = NULL;
-
-	if (TYPE(n) == parameters) {
-		n = CHILD(n, 1);
-		if (TYPE(n) == RPAR)
-			return;
-	}
-	REQ(n, varargslist);
-	for (i = 0; i < NCH(n); i += 2) {
-		c = CHILD(n, i);
-		if (TYPE(c) == STAR || TYPE(c) == DOUBLESTAR) {
-			ext = 1;
-			break;
-		}
-		if (TYPE(c) == test) {
-			continue;
-		}
-		if (TYPE(CHILD(c, 0)) == NAME)
-			symtable_add_def(st, STR(CHILD(c, 0)), DEF_PARAM);
-		else {
-			char nbuf[30];
-			PyOS_snprintf(nbuf, sizeof(nbuf), ".%d", i);
-			symtable_add_def(st, nbuf, DEF_PARAM);
-			complex = i;
-		}
-	}
-	if (ext) {
-		c = CHILD(n, i);
-		if (TYPE(c) == STAR) {
-			i++;
-			symtable_add_def(st, STR(CHILD(n, i)), 
-					 DEF_PARAM | DEF_STAR);
-			i += 2;
-			if (i >= NCH(n))
-				c = NULL;
-			else
-				c = CHILD(n, i);
-		}
-		if (c && TYPE(c) == DOUBLESTAR) {
-			i++;
-			symtable_add_def(st, STR(CHILD(n, i)), 
-					 DEF_PARAM | DEF_DOUBLESTAR);
-		}
-	}
-	if (complex >= 0) {
-		int j;
-		for (j = 0; j <= complex; j++) {
-			c = CHILD(n, j);
-			if (TYPE(c) == COMMA)
-				c = CHILD(n, ++j);
-			else if (TYPE(c) == EQUAL)
-				c = CHILD(n, j += 3);
-			if (TYPE(CHILD(c, 0)) == LPAR)
-				symtable_params_fplist(st, CHILD(c, 1));
-		} 
-	}
-}
-
-static void
-symtable_params_fplist(struct symtable *st, node *n)
-{
-	int i;
-	node *c;
-
-	REQ(n, fplist);
-	for (i = 0; i < NCH(n); i += 2) {
-		c = CHILD(n, i);
-		REQ(c, fpdef);
-		if (NCH(c) == 1)
-			symtable_add_def(st, STR(CHILD(c, 0)), 
-					 DEF_PARAM | DEF_INTUPLE);
-		else
-			symtable_params_fplist(st, CHILD(c, 1));
-	}
-	
-}
-
-static void
-symtable_global(struct symtable *st, node *n)
-{
-	int i;
-
-	/* XXX It might be helpful to warn about module-level global
-	   statements, but it's hard to tell the difference between
-	   module-level and a string passed to exec.
-	*/
-
-	for (i = 1; i < NCH(n); i += 2) {
-		char *name = STR(CHILD(n, i));
-		int flags;
-
-		flags = symtable_lookup(st, name);
-		if (flags < 0)
-			continue;
-		if (flags && flags != DEF_GLOBAL) {
-			char buf[500];
-			if (flags & DEF_PARAM) {
-				PyErr_Format(PyExc_SyntaxError, PARAM_GLOBAL,
-					     name);
-				symtable_error(st, 0);
-				return;
-			}
-			else {
-				if (flags & DEF_LOCAL)
-					PyOS_snprintf(buf, sizeof(buf),
-						      GLOBAL_AFTER_ASSIGN,
-						      name);
-				else
-					PyOS_snprintf(buf, sizeof(buf),
-						      GLOBAL_AFTER_USE, name);
-				symtable_warn(st, buf);
-			}
-		}
-		symtable_add_def(st, name, DEF_GLOBAL);
-	}
-}
-
-static void
-symtable_list_comprehension(struct symtable *st, node *n)
-{
-	/* listmaker: test list_for */
-	char tmpname[30];
-
-	REQ(n, listmaker);
-	PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", 
-		      ++st->st_cur->ste_tmpname);
-	symtable_add_def(st, tmpname, DEF_LOCAL);
-	symtable_list_for(st, CHILD(n, 1));
-	symtable_node(st, CHILD(n, 0));
-	--st->st_cur->ste_tmpname;
-}
-
-static void
-symtable_generator_expression(struct symtable *st, node *n)
-{
-	/* testlist_gexp: test gen_for */
-	REQ(CHILD(n, 0), test);
-	REQ(CHILD(n, 1), gen_for);
-
-	symtable_enter_scope(st, "<genexpr>", TYPE(n), n->n_lineno);
-	st->st_cur->ste_generator = GENERATOR_EXPRESSION;
-
-	symtable_add_def(st, "[outmost-iterable]", DEF_PARAM);
-	
-	symtable_gen_for(st, CHILD(n, 1), 1);
-	symtable_node(st, CHILD(n, 0));
-	symtable_exit_scope(st);
-
-	/* for outmost iterable precomputation */
-	symtable_node(st, CHILD(CHILD(n, 1), 3)); 
-}
-
-static void
-symtable_list_for(struct symtable *st, node *n)
-{
-	REQ(n, list_for);
-	/* list_for: for v in expr [list_iter] */
-	symtable_assign(st, CHILD(n, 1), 0);
-	symtable_node(st, CHILD(n, 3));
-	if (NCH(n) == 5)
-		symtable_node(st, CHILD(n, 4));
-}
-
-static void
-symtable_gen_for(struct symtable *st, node *n, int is_outmost)
-{
-	REQ(n, gen_for);
-
-	/* gen_for: for v in test [gen_iter] */
-	symtable_assign(st, CHILD(n, 1), 0);
-	if (is_outmost)
-		symtable_add_use(st, "[outmost-iterable]");
-	else
-		symtable_node(st, CHILD(n, 3));
-
-	if (NCH(n) == 5)
-		symtable_gen_iter(st, CHILD(n, 4));
-}
-
-static void
-symtable_gen_iter(struct symtable *st, node *n)
-{
-	REQ(n, gen_iter);
-
-	n = CHILD(n, 0);
-	if (TYPE(n) == gen_for)
-		symtable_gen_for(st, n, 0);
-	else {
-		REQ(n, gen_if);
-		symtable_node(st, CHILD(n, 1));
-
-		if (NCH(n) == 3)
-			symtable_gen_iter(st, CHILD(n, 2));
-	}
-}
-
-static void
-symtable_import(struct symtable *st, node *n)
-{
-	node *nn;
-	int i;
-	/* import_stmt: import_name | import_from */
-	n = CHILD(n, 0);
-	if (TYPE(n) == import_from) {
-		/* import_from: 'from' dotted_name 'import' ('*' |
-		     | '(' import_as_names ')' | import_as_names) */
-		node *dotname = CHILD(n, 1);
-		REQ(dotname, dotted_name);
-		if (strcmp(STR(CHILD(dotname, 0)), "__future__") == 0) {
-			/* check for bogus imports */
-			if (n->n_lineno >= st->st_future->ff_last_lineno) {
-				PyErr_SetString(PyExc_SyntaxError,
-						LATE_FUTURE);
-				symtable_error(st, n->n_lineno);
-				return;
-			}
-		}
-		nn = CHILD(n, 3 + (TYPE(CHILD(n, 3)) == LPAR));
-		if (TYPE(nn) == STAR) {
-			if (st->st_cur->ste_type != TYPE_MODULE) {
-				if (symtable_warn(st,
-				  "import * only allowed at module level") < 0)
-					return;
-			}
-			st->st_cur->ste_optimized |= OPT_IMPORT_STAR;
-			st->st_cur->ste_opt_lineno = n->n_lineno;
-		} else {
-			REQ(nn, import_as_names);
-			for (i = 0; i < NCH(nn); i += 2) {
-				node *c = CHILD(nn, i);
-				if (NCH(c) > 1) /* import as */
-					symtable_assign(st, CHILD(c, 2),
-							DEF_IMPORT);
-				else
-					symtable_assign(st, CHILD(c, 0),
-							DEF_IMPORT);
-			}
-		}
-	} else {
-		/* 'import' dotted_as_names */
-		nn = CHILD(n, 1);
-		REQ(nn, dotted_as_names);
-		for (i = 0; i < NCH(nn); i += 2)
-			symtable_assign(st, CHILD(nn, i), DEF_IMPORT);
-	}
-}
-
-/* The third argument to symatble_assign() is a flag to be passed to
-   symtable_add_def() if it is eventually called.  The flag is useful
-   to specify the particular type of assignment that should be
-   recorded, e.g. an assignment caused by import.
- */
-
-static void 
-symtable_assign(struct symtable *st, node *n, int def_flag)
-{
-	node *tmp;
-	int i;
-
- loop:
-	switch (TYPE(n)) {
-	case lambdef:
-		/* invalid assignment, e.g. lambda x:x=2.  The next
-		   pass will catch this error. */
-		return;
-	case power:
-		if (NCH(n) > 2) {
-			for (i = 2; i < NCH(n); ++i)
-				if (TYPE(CHILD(n, i)) != DOUBLESTAR)
-					symtable_node(st, CHILD(n, i));
-		}
-		if (NCH(n) > 1) { 
-			symtable_node(st, CHILD(n, 0));
-			symtable_node(st, CHILD(n, 1));
-		} else {
-			n = CHILD(n, 0);
-			goto loop;
-		}
-		return;
-	case listmaker:
-		if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == list_for) {
-			/* XXX This is an error, but the next pass
-			   will catch it. */ 
-			return;
-		} else {
-			for (i = 0; i < NCH(n); i += 2)
-				symtable_assign(st, CHILD(n, i), def_flag);
-		}
-		return;
-	case testlist_gexp:
-		if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == gen_for) {
-			/* XXX This is an error, but the next pass
-			   will catch it. */ 
-			return;
-		} else {
-			for (i = 0; i < NCH(n); i += 2)
-				symtable_assign(st, CHILD(n, i), def_flag);
-		}
-		return;
-
-	case exprlist:
-	case testlist:
-	case testlist1:
-		if (NCH(n) == 1) {
-			n = CHILD(n, 0);
-			goto loop;
-		}
-		else {
-			int i;
-			for (i = 0; i < NCH(n); i += 2)
-				symtable_assign(st, CHILD(n, i), def_flag);
-			return;
-		}
-	case atom:
-		tmp = CHILD(n, 0);
-		if (TYPE(tmp) == LPAR || TYPE(tmp) == LSQB) {
-			n = CHILD(n, 1);
-			goto loop;
-		} else if (TYPE(tmp) == NAME) {
-			if (strcmp(STR(tmp), "__debug__") == 0) {
-				PyErr_SetString(PyExc_SyntaxError, 
-						ASSIGN_DEBUG);
-				symtable_error(st, n->n_lineno);
-				return;
-			}
-			symtable_add_def(st, STR(tmp), DEF_LOCAL | def_flag);
-		}
-		return;
-
-	case yield_expr:
-		st->st_cur->ste_generator = 1;
-		if (NCH(n)==2) {
-			n = CHILD(n, 1);
-			goto loop;
-		}
-		return;
-
-	case dotted_as_name:
-		if (NCH(n) == 3)
-			symtable_add_def(st, STR(CHILD(n, 2)),
-					 DEF_LOCAL | def_flag);
-		else
-			symtable_add_def(st,
-					 STR(CHILD(CHILD(n,
-							 0), 0)),
-					 DEF_LOCAL | def_flag);
-		return;
-	case dotted_name:
-		symtable_add_def(st, STR(CHILD(n, 0)), DEF_LOCAL | def_flag);
-		return;
-	case NAME:
-		symtable_add_def(st, STR(n), DEF_LOCAL | def_flag);
-		return;
-	default:
-		if (NCH(n) == 0)
-			return;
-		if (NCH(n) == 1) {
-			n = CHILD(n, 0);
-			goto loop;
-		}
-		/* Should only occur for errors like x + 1 = 1,
-		   which will be caught in the next pass. */
-		for (i = 0; i < NCH(n); ++i)
-			if (TYPE(CHILD(n, i)) >= single_input)
-				symtable_assign(st, CHILD(n, i), def_flag);
-	}
+	co = makecode(c, &a);
+ error:
+	assemble_free(&a);
+	return co;
 }
diff --git a/Python/future.c b/Python/future.c
index 95d6a5c..a0cfeac 100644
--- a/Python/future.c
+++ b/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 @@
 		} 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;
 	}
diff --git a/Python/import.c b/Python/import.c
index 35de13e..dcbca38 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -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 @@
 /* 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;
+	PyCodeObject *co = NULL;
+	mod_ty mod;
 
-	n = PyParser_SimpleParseFile(fp, pathname, Py_file_input);
-	if (n == NULL)
-		return NULL;
-	co = PyNode_Compile(n, pathname);
-	PyNode_Free(n);
-
+	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;
 }
 
diff --git a/Python/marshal.c b/Python/marshal.c
index 20d637d..4114c8e 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -6,6 +6,7 @@
 
 #include "Python.h"
 #include "longintrepr.h"
+#include "code.h"
 #include "compile.h"
 #include "marshal.h"
 
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index e007f98..ad837d2 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -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 @@
 /* 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 @@
 /* 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)
@@ -668,12 +653,6 @@
 }
 
 int
-PyRun_InteractiveLoop(FILE *fp, const char *filename)
-{
-	return PyRun_InteractiveLoopFlags(fp, filename, NULL);
-}
-
-int
 PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
 {
 	PyObject *v;
@@ -708,12 +687,6 @@
 	}
 }
 
-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 @@
 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 @@
 		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 @@
 	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. */
 
@@ -820,12 +786,6 @@
 }
 
 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)
 {
@@ -874,12 +834,6 @@
 }
 
 int
-PyRun_SimpleString(const char *command)
-{
-	return PyRun_SimpleStringFlags(command, NULL);
-}
-
-int
 PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags)
 {
 	PyObject *m, *d, *v;
@@ -1054,6 +1008,8 @@
 		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 @@
 }
 
 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 @@
 }
 
 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;
@@ -1303,41 +1233,77 @@
 }
 
 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 @@
 					(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 *
@@ -1373,12 +1334,6 @@
 }
 
 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 @@
 	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 @@
 	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 @@
 		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 @@
 	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);
+}
diff --git a/Python/symtable.c b/Python/symtable.c
index 5ca2041..bd41202 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -1,48 +1,35 @@
 #include "Python.h"
+#include "Python-ast.h"
+#include "code.h"
 #include "compile.h"
 #include "symtable.h"
-#include "graminit.h"
 #include "structmember.h"
 
-/* The compiler uses this function to load a PySymtableEntry object
-   for a code block.  Each block is loaded twice, once during the
-   symbol table pass and once during the code gen pass.  Entries
-   created during the first pass are cached for the second pass, using
-   the st_symbols dictionary.  
+/* two error strings used for warnings */
+#define GLOBAL_AFTER_ASSIGN \
+"name '%.400s' is assigned to before global declaration"
 
-   The cache is keyed by st_nscopes.  Each code block node in a
-   module's parse tree can be assigned a unique id based on the order
-   in which the nodes are visited by the compiler.  This strategy
-   works so long as the symbol table and codegen passes visit the same
-   nodes in the same order.
-*/
+#define GLOBAL_AFTER_USE \
+"name '%.400s' is used prior to global declaration"
 
-
-PyObject *
-PySymtableEntry_New(struct symtable *st, char *name, int type, int lineno)
+PySTEntryObject *
+PySTEntry_New(struct symtable *st, identifier name, block_ty block,
+	      void *key, int lineno)
 {
-	PySymtableEntryObject *ste = NULL;
+	PySTEntryObject *ste = NULL;
 	PyObject *k, *v;
 
-	k = PyInt_FromLong(st->st_nscopes++);
+	k = PyLong_FromVoidPtr(key);
 	if (k == NULL)
 		goto fail;
-	v = PyDict_GetItem(st->st_symbols, k);
-	if (v) {
-		Py_DECREF(k);
-		Py_INCREF(v);
-		return v;
-	}
-	
-	ste = (PySymtableEntryObject *)PyObject_New(PySymtableEntryObject,
-						    &PySymtableEntry_Type);
+	ste = (PySTEntryObject *)PyObject_New(PySTEntryObject,
+					      &PySTEntry_Type);
 	ste->ste_table = st;
 	ste->ste_id = k;
+	ste->ste_tmpname = 0;
 
-	v = PyString_FromString(name);
-	if (v == NULL)
-		goto fail;
-	ste->ste_name = v;
+	ste->ste_name = name;
+	Py_INCREF(name);
 	
 	v = PyDict_New();
 	if (v == NULL)
@@ -59,61 +46,46 @@
 	    goto fail;
 	ste->ste_children = v;
 
-	ste->ste_optimized = 0;
+	ste->ste_type = block;
+	ste->ste_unoptimized = 0;
+	ste->ste_nested = 0;
+	ste->ste_free = 0;
+	ste->ste_varargs = 0;
+	ste->ste_varkeywords = 0;
 	ste->ste_opt_lineno = 0;
 	ste->ste_tmpname = 0;
 	ste->ste_lineno = lineno;
-	switch (type) {
-	case funcdef:
-	case lambdef:
-	case testlist_gexp: /* generator expression */
-	case argument:      /* generator expression */
-		ste->ste_type = TYPE_FUNCTION;
-		break;
-	case classdef:
-		ste->ste_type = TYPE_CLASS;
-		break;
-	case single_input:
-	case eval_input:
-	case file_input:
-		ste->ste_type = TYPE_MODULE;
-		break;
-	}
 
-	if (st->st_cur == NULL)
-		ste->ste_nested = 0;
-	else if (st->st_cur->ste_nested 
-		 || st->st_cur->ste_type == TYPE_FUNCTION)
+	if (st->st_cur != NULL &&
+	    (st->st_cur->ste_nested ||
+	     st->st_cur->ste_type == FunctionBlock))
 		ste->ste_nested = 1;
-	else
-		ste->ste_nested = 0;
 	ste->ste_child_free = 0;
 	ste->ste_generator = 0;
 
 	if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0)
 	    goto fail;
 	
-	return (PyObject *)ste;
+	return ste;
  fail:
 	Py_XDECREF(ste);
 	return NULL;
 }
 
 static PyObject *
-ste_repr(PySymtableEntryObject *ste)
+ste_repr(PySTEntryObject *ste)
 {
 	char buf[256];
 
 	PyOS_snprintf(buf, sizeof(buf),
 		      "<symtable entry %.100s(%ld), line %d>",
 		      PyString_AS_STRING(ste->ste_name),
-		      PyInt_AS_LONG(ste->ste_id),
-		      ste->ste_lineno);
+		      PyInt_AS_LONG(ste->ste_id), ste->ste_lineno);
 	return PyString_FromString(buf);
 }
 
 static void
-ste_dealloc(PySymtableEntryObject *ste)
+ste_dealloc(PySTEntryObject *ste)
 {
 	ste->ste_table = NULL;
 	Py_XDECREF(ste->ste_id);
@@ -124,7 +96,7 @@
 	PyObject_Del(ste);
 }
 
-#define OFF(x) offsetof(PySymtableEntryObject, x)
+#define OFF(x) offsetof(PySTEntryObject, x)
 
 static PyMemberDef ste_memberlist[] = {
 	{"id",       T_OBJECT, OFF(ste_id), READONLY},
@@ -134,16 +106,14 @@
 	{"children", T_OBJECT, OFF(ste_children), READONLY},
 	{"type",     T_INT,    OFF(ste_type), READONLY},
 	{"lineno",   T_INT,    OFF(ste_lineno), READONLY},
-	{"optimized",T_INT,    OFF(ste_optimized), READONLY},
-	{"nested",   T_INT,    OFF(ste_nested), READONLY},
 	{NULL}
 };
 
-PyTypeObject PySymtableEntry_Type = {
+PyTypeObject PySTEntry_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
 	"symtable entry",
-	sizeof(PySymtableEntryObject),
+	sizeof(PySTEntryObject),
 	0,
 	(destructor)ste_dealloc,                /* tp_dealloc */
 	0,                                      /* tp_print */
@@ -180,3 +150,1148 @@
 	0,					/* tp_alloc */
 	0,					/* tp_new */
 };
+
+static int symtable_analyze(struct symtable *st);
+static int symtable_warn(struct symtable *st, char *msg);
+static int symtable_enter_block(struct symtable *st, identifier name, 
+				block_ty block, void *ast, int lineno);
+static int symtable_exit_block(struct symtable *st, void *ast);
+static int symtable_visit_stmt(struct symtable *st, stmt_ty s);
+static int symtable_visit_expr(struct symtable *st, expr_ty s);
+static int symtable_visit_genexp(struct symtable *st, expr_ty s);
+static int symtable_visit_arguments(struct symtable *st, arguments_ty);
+static int symtable_visit_excepthandler(struct symtable *st, excepthandler_ty);
+static int symtable_visit_alias(struct symtable *st, alias_ty);
+static int symtable_visit_comprehension(struct symtable *st, comprehension_ty);
+static int symtable_visit_keyword(struct symtable *st, keyword_ty);
+static int symtable_visit_slice(struct symtable *st, slice_ty);
+static int symtable_visit_params(struct symtable *st, asdl_seq *args, int top);
+static int symtable_visit_params_nested(struct symtable *st, asdl_seq *args);
+static int symtable_implicit_arg(struct symtable *st, int pos);
+
+
+static identifier top = NULL, lambda = NULL;
+
+#define GET_IDENTIFIER(VAR) \
+	((VAR) ? (VAR) : ((VAR) = PyString_InternFromString(# VAR)))
+
+#define DUPLICATE_ARGUMENT \
+"duplicate argument '%s' in function definition"
+
+static struct symtable *
+symtable_new(void)
+{
+	struct symtable *st;
+
+	st = (struct symtable *)PyMem_Malloc(sizeof(struct symtable));
+	if (st == NULL)
+		return NULL;
+
+	st->st_filename = NULL;
+	if ((st->st_stack = PyList_New(0)) == NULL)
+		goto fail;
+	if ((st->st_symbols = PyDict_New()) == NULL)
+		goto fail; 
+	st->st_cur = NULL;
+	st->st_tmpname = 0;
+	st->st_private = NULL;
+	return st;
+ fail:
+	PySymtable_Free(st);
+	return NULL;
+}
+
+struct symtable *
+PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
+{
+	struct symtable *st = symtable_new();
+	asdl_seq *seq;
+	int i;
+
+	if (st == NULL)
+		return st;
+	st->st_filename = filename;
+	st->st_future = future;
+	symtable_enter_block(st, GET_IDENTIFIER(top), ModuleBlock, 
+			     (void *)mod, 0);
+	st->st_top = st->st_cur;
+	st->st_cur->ste_unoptimized = OPT_TOPLEVEL;
+	/* Any other top-level initialization? */
+	switch (mod->kind) {
+	case Module_kind:
+		seq = mod->v.Module.body;
+		for (i = 0; i < asdl_seq_LEN(seq); i++)
+			if (!symtable_visit_stmt(st, asdl_seq_GET(seq, i)))
+				goto error;
+		break;
+	case Expression_kind:
+		if (!symtable_visit_expr(st, mod->v.Expression.body))
+			goto error;
+		break;
+	case Interactive_kind:
+		seq = mod->v.Interactive.body;
+		for (i = 0; i < asdl_seq_LEN(seq); i++)
+			if (!symtable_visit_stmt(st, asdl_seq_GET(seq, i)))
+				goto error;
+		break;
+	case Suite_kind:
+		PyErr_SetString(PyExc_RuntimeError,
+				"this compiler does not handle Suites");
+		return NULL;
+	}
+	if (!symtable_exit_block(st, (void *)mod))
+		return NULL;
+	if (symtable_analyze(st))
+		return st;
+ error:
+	PySymtable_Free(st);
+	return NULL;
+}
+
+void
+PySymtable_Free(struct symtable *st)
+{
+	Py_XDECREF(st->st_symbols);
+	Py_XDECREF(st->st_stack);
+	PyMem_Free((void *)st);
+}
+
+PySTEntryObject *
+PySymtable_Lookup(struct symtable *st, void *key)
+{
+	PyObject *k, *v;
+
+	k = PyLong_FromVoidPtr(key);
+	if (k == NULL)
+		return NULL;
+	v = PyDict_GetItem(st->st_symbols, k);
+	if (v) {
+		assert(PySTEntry_Check(v));
+		Py_DECREF(k);
+		Py_INCREF(v);
+		return (PySTEntryObject *)v;
+	}
+	else {
+		PyErr_SetString(PyExc_KeyError,
+				"unknown symbol table entry");
+		return NULL;
+	}
+}
+
+int 
+PyST_GetScope(PySTEntryObject *ste, PyObject *name)
+{
+	PyObject *v = PyDict_GetItem(ste->ste_symbols, name);
+	if (!v)
+		return 0;
+	assert(PyInt_Check(v));
+	return (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK;
+}
+
+
+/* Analyze raw symbol information to determine scope of each name.
+
+   The next several functions are helpers for PySymtable_Analyze(),
+   which determines whether a name is local, global, or free.  In addition, 
+   it determines which local variables are cell variables; they provide
+   bindings that are used for free variables in enclosed blocks.  
+
+   There are also two kinds of free variables, implicit and explicit.  An 
+   explicit global is declared with the global statement.  An implicit
+   global is a free variable for which the compiler has found no binding
+   in an enclosing function scope.  The implicit global is either a global
+   or a builtin.  Python's module and class blocks use the xxx_NAME opcodes
+   to handle these names to implement slightly odd semantics.  In such a
+   block, the name is treated as global until it is assigned to; then it
+   is treated as a local.
+
+   The symbol table requires two passes to determine the scope of each name.
+   The first pass collects raw facts from the AST: the name is a parameter 
+   here, the name is used by not defined here, etc.  The second pass analyzes
+   these facts during a pass over the PySTEntryObjects created during pass 1.
+
+   When a function is entered during the second pass, the parent passes
+   the set of all name bindings visible to its children.  These bindings 
+   are used to determine if the variable is free or an implicit global.
+   After doing the local analysis, it analyzes each of its child blocks
+   using an updated set of name bindings.  
+
+   The children update the free variable set.  If a local variable is free 
+   in a child, the variable is marked as a cell.  The current function must 
+   provide runtime storage for the variable that may outlive the function's 
+   frame.  Cell variables are removed from the free set before the analyze
+   function returns to its parent.
+   
+   The sets of bound and free variables are implemented as dictionaries
+   mapping strings to None.
+*/
+
+#define SET_SCOPE(DICT, NAME, I) { \
+	PyObject *o = PyInt_FromLong(I); \
+	if (!o) \
+		return 0; \
+	if (PyDict_SetItem((DICT), (NAME), o) < 0) \
+		return 0; \
+}
+
+/* Decide on scope of name, given flags.
+
+   The dicts passed in as arguments are modified as necessary.
+   ste is passed so that flags can be updated.
+*/
+
+static int 
+analyze_name(PySTEntryObject *ste, PyObject *dict, PyObject *name, int flags,
+	     PyObject *bound, PyObject *local, PyObject *free, 
+	     PyObject *global)
+{
+	if (flags & DEF_GLOBAL) {
+		if (flags & DEF_PARAM) {
+			PyErr_Format(PyExc_SyntaxError,
+				     "name '%s' is local and global",
+				     PyString_AS_STRING(name));
+			return 0;
+		}
+		SET_SCOPE(dict, name, GLOBAL_EXPLICIT);
+		if (PyDict_SetItem(global, name, Py_None) < 0)
+			return 0;
+		if (bound && PyDict_GetItem(bound, name)) {
+			if (PyDict_DelItem(bound, name) < 0)
+				return 0;
+		}
+		return 1;
+	}
+	if (flags & DEF_BOUND) {
+		SET_SCOPE(dict, name, LOCAL);
+		if (PyDict_SetItem(local, name, Py_None) < 0)
+			return 0;
+		if (PyDict_GetItem(global, name)) {
+			if (PyDict_DelItem(global, name) < 0)
+				return 0;
+		}
+		return 1;
+	}
+	/* If an enclosing block has a binding for this name, it
+	   is a free variable rather than a global variable.
+	   Note that having a non-NULL bound implies that the block
+	   is nested.
+	*/
+	if (bound && PyDict_GetItem(bound, name)) {
+		SET_SCOPE(dict, name, FREE);
+		ste->ste_free = 1;
+		if (PyDict_SetItem(free, name, Py_None) < 0)
+			return 0;
+		return 1;
+	}
+	/* If a parent has a global statement, then call it global
+	   explicit?  It could also be global implicit.
+	 */
+	else if (global && PyDict_GetItem(global, name)) {
+		SET_SCOPE(dict, name, GLOBAL_EXPLICIT);
+		return 1;
+	}
+	else {
+		if (ste->ste_nested)
+			ste->ste_free = 1;
+		SET_SCOPE(dict, name, GLOBAL_IMPLICIT);
+		return 1;
+	}
+	return 0; /* Can't get here */
+}
+
+#undef SET_SCOPE
+
+/* If a name is defined in free and also in locals, then this block
+   provides the binding for the free variable.  The name should be
+   marked CELL in this block and removed from the free list.
+
+   Note that the current block's free variables are included in free.
+   That's safe because no name can be free and local in the same scope.
+*/
+
+static int
+analyze_cells(PyObject *scope, PyObject *free)
+{
+        PyObject *name, *v, *w;
+	int flags, pos = 0, success = 0;
+
+	w = PyInt_FromLong(CELL);
+	if (!w)
+		return 0;
+	while (PyDict_Next(scope, &pos, &name, &v)) {
+		assert(PyInt_Check(v));
+		flags = PyInt_AS_LONG(v);
+		if (flags != LOCAL)
+			continue;
+		if (!PyDict_GetItem(free, name))
+			continue;
+		/* Replace LOCAL with CELL for this name, and remove
+		   from free. It is safe to replace the value of name 
+		   in the dict, because it will not cause a resize.
+		 */
+		if (PyDict_SetItem(scope, name, w) < 0)
+			goto error;
+		if (!PyDict_DelItem(free, name) < 0)
+			goto error;
+	}
+	success = 1;
+ error:
+	Py_DECREF(w);
+	return success;
+}
+
+/* Check for illegal statements in unoptimized namespaces */
+static int
+check_unoptimized(const PySTEntryObject* ste) {
+	char buf[300];
+
+	if (ste->ste_type == ModuleBlock || !ste->ste_unoptimized
+	    || !(ste->ste_free || ste->ste_child_free))
+		return 1;
+
+	const char* trailer = (ste->ste_child_free ? 
+		       "contains a nested function with free variables" :
+			       "is a nested function");
+
+	switch (ste->ste_unoptimized) {
+	case OPT_TOPLEVEL: /* exec / import * at top-level is fine */
+	case OPT_EXEC: /* qualified exec is fine */
+		return 1;
+	case OPT_IMPORT_STAR:
+		PyOS_snprintf(buf, sizeof(buf), 
+			      "import * is not allowed in function '%.100s' "
+			      "because it is %s",
+			      PyString_AS_STRING(ste->ste_name), trailer);
+		break;
+	case OPT_BARE_EXEC:
+		PyOS_snprintf(buf, sizeof(buf),
+			      "unqualified exec is not allowed in function "
+			      "'%.100s' it %s",
+			      PyString_AS_STRING(ste->ste_name), trailer);
+		break;
+	default:
+		PyOS_snprintf(buf, sizeof(buf), 
+			      "function '%.100s' uses import * and bare exec, "
+			      "which are illegal because it %s",
+			      PyString_AS_STRING(ste->ste_name), trailer);
+		break;
+	}
+
+	PyErr_SetString(PyExc_SyntaxError, buf);
+	PyErr_SyntaxLocation(ste->ste_table->st_filename, 
+			     ste->ste_opt_lineno);
+	return 0;
+}
+
+/* Enter the final scope information into the st_symbols dict. 
+ * 
+ * All arguments are dicts.  Modifies symbols, others are read-only.
+*/
+static int
+update_symbols(PyObject *symbols, PyObject *scope, 
+               PyObject *bound, PyObject *free, int class)
+{
+	PyObject *name, *v, *u, *w, *free_value = NULL;
+	int i, flags, pos = 0;
+
+	while (PyDict_Next(symbols, &pos, &name, &v)) {
+		assert(PyInt_Check(v));
+		flags = PyInt_AS_LONG(v);
+		w = PyDict_GetItem(scope, name);
+		assert(w && PyInt_Check(w));
+		i = PyInt_AS_LONG(w);
+		flags |= (i << SCOPE_OFF);
+		u = PyInt_FromLong(flags);
+		if (PyDict_SetItem(symbols, name, u) < 0) {
+			Py_DECREF(u);
+			return 0;
+		}
+		Py_DECREF(u);
+	}
+
+        free_value = PyInt_FromLong(FREE << SCOPE_OFF);
+        if (!free_value)
+		return 0;
+
+        /* add a free variable when it's only use is for creating a closure */
+        pos = 0;
+	while (PyDict_Next(free, &pos, &name, &v)) {
+		PyObject *o = PyDict_GetItem(symbols, name);
+
+		if (o) {
+			/* It could be a free variable in a method of
+			   the class that has the same name as a local
+			   or global in the class scope.
+			*/
+			if  (class && 
+			     PyInt_AS_LONG(o) & (DEF_BOUND | DEF_GLOBAL)) {
+				int i = PyInt_AS_LONG(o) | DEF_FREE_CLASS;
+				o = PyInt_FromLong(i);
+				if (!o) {
+					Py_DECREF(free_value);
+					return 0;
+				}
+				if (PyDict_SetItem(symbols, name, o) < 0) {
+					Py_DECREF(o);
+					Py_DECREF(free_value);
+					return 0;
+				}
+			}
+			/* else it's not free, probably a cell */
+			continue;
+		}
+		if (!PyDict_GetItem(bound, name))
+			continue;       /* it's a global */
+
+		if (PyDict_SetItem(symbols, name, free_value) < 0) {
+			Py_DECREF(free_value);
+			return 0;
+		}
+        }
+        Py_DECREF(free_value);
+	return 1;
+}   
+
+/* Make final symbol table decisions for block of ste.
+   Arguments:
+   ste -- current symtable entry (input/output)
+   bound -- set of variables bound in enclosing scopes (input)
+   free -- set of free variables in enclosed scopes (output)
+   globals -- set of declared global variables in enclosing scopes (input)
+*/
+
+static int
+analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, 
+	      PyObject *global)
+{
+	PyObject *name, *v, *local = NULL, *scope = NULL, *newbound = NULL;
+	PyObject *newglobal = NULL, *newfree = NULL;
+	int i, flags, pos = 0, success = 0;
+
+	local = PyDict_New();
+	if (!local)
+		goto error;
+	scope = PyDict_New();
+	if (!scope)
+		goto error;
+	newglobal = PyDict_New();
+	if (!newglobal)
+		goto error;
+	newfree = PyDict_New();
+	if (!newfree)
+		goto error;
+	newbound = PyDict_New();
+	if (!newbound)
+		goto error;
+
+	if (ste->ste_type == ClassBlock) {
+		/* make a copy of globals before calling analyze_name(),
+		   because global statements in the class have no effect
+		   on nested functions.
+		*/
+		if (PyDict_Update(newglobal, global) < 0)
+			goto error;
+		if (bound)
+			if (PyDict_Update(newbound, bound) < 0)
+				goto error;
+	}
+
+	assert(PySTEntry_Check(ste));
+	assert(PyDict_Check(ste->ste_symbols));
+	while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) {
+		flags = PyInt_AS_LONG(v);
+		if (!analyze_name(ste, scope, name, flags, bound, local, free,
+				  global))
+			goto error;
+	}
+
+	if (ste->ste_type != ClassBlock) {
+		if (ste->ste_type == FunctionBlock) {
+			if (PyDict_Update(newbound, local) < 0)
+				goto error;
+		}
+		if (bound) {
+			if (PyDict_Update(newbound, bound) < 0)
+				goto error;
+		}
+		if (PyDict_Update(newglobal, global) < 0)
+			goto error;
+	}
+
+	/* Recursively call analyze_block() on each child block */
+	for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) {
+		PyObject *c = PyList_GET_ITEM(ste->ste_children, i);
+		assert(c && PySTEntry_Check(c));
+		PySTEntryObject* entry = (PySTEntryObject*)c;
+		if (!analyze_block(entry, newbound, newfree, newglobal))
+			goto error;
+		if (entry->ste_free || entry->ste_child_free)
+			ste->ste_child_free = 1;
+	}
+
+	if (ste->ste_type == FunctionBlock && !analyze_cells(scope, newfree))
+		goto error;
+	if (!update_symbols(ste->ste_symbols, scope, bound, newfree,
+			    ste->ste_type == ClassBlock))
+		goto error;
+	if (!check_unoptimized(ste))
+		goto error;
+
+	if (PyDict_Update(free, newfree) < 0)
+		goto error;
+	success = 1;
+ error:
+	Py_XDECREF(local);
+	Py_XDECREF(scope);
+	Py_XDECREF(newbound);
+	Py_XDECREF(newglobal);
+	Py_XDECREF(newfree);
+	if (!success)
+		assert(PyErr_Occurred());
+	return success;
+}
+
+static int
+symtable_analyze(struct symtable *st)
+{
+	PyObject *free, *global;
+	int r;
+
+	free = PyDict_New();
+	if (!free)
+	    return 0;
+	global = PyDict_New();
+	if (!global) {
+	    Py_DECREF(global);
+	    return 0;
+	}
+	r = analyze_block(st->st_top, NULL, free, global);
+	Py_DECREF(free);
+	Py_DECREF(global);
+	return r;
+}
+
+
+static int
+symtable_warn(struct symtable *st, char *msg)
+{
+	if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, st->st_filename,
+			       st->st_cur->ste_lineno, NULL, NULL) < 0)	{
+		if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
+			PyErr_SetString(PyExc_SyntaxError, msg);
+			PyErr_SyntaxLocation(st->st_filename, 
+					     st->st_cur->ste_lineno);
+		}
+		return 0;
+	}
+	return 1;
+}
+
+/* symtable_enter_block() gets a reference via PySTEntry_New().
+   This reference is released when the block is exited, via the DECREF
+   in symtable_exit_block().
+*/
+
+static int
+symtable_exit_block(struct symtable *st, void *ast)
+{
+	int end;
+
+	Py_DECREF(st->st_cur);
+	end = PyList_GET_SIZE(st->st_stack) - 1;
+	if (end >= 0) {
+		st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack, 
+								end);
+		Py_INCREF(st->st_cur);
+		if (PySequence_DelItem(st->st_stack, end) < 0)
+			return 0;
+	}
+	return 1;
+}
+
+static int
+symtable_enter_block(struct symtable *st, identifier name, block_ty block, 
+		     void *ast, int lineno)
+{
+	PySTEntryObject *prev = NULL;
+
+	if (st->st_cur) {
+		prev = st->st_cur;
+		if (PyList_Append(st->st_stack, (PyObject *)st->st_cur) < 0) {
+			Py_DECREF(st->st_cur);
+			return 0;
+		}
+		Py_DECREF(st->st_cur);
+	}
+	st->st_cur = PySTEntry_New(st, name, block, ast, lineno);
+	if (name == GET_IDENTIFIER(top))
+		st->st_global = st->st_cur->ste_symbols;
+	if (prev) {
+		if (PyList_Append(prev->ste_children, 
+				  (PyObject *)st->st_cur) < 0) {
+			return 0;
+		}
+	}
+	return 1;
+}
+
+static int
+symtable_lookup(struct symtable *st, PyObject *name)
+{
+	PyObject *o;
+
+	o = PyDict_GetItem(st->st_cur->ste_symbols, name);
+	if (!o)
+		return 0;
+	return PyInt_AsLong(o);
+}
+
+static int
+symtable_add_def(struct symtable *st, PyObject *name, int flag) 
+{
+	PyObject *o;
+	PyObject *dict;
+	int val;
+
+	dict = st->st_cur->ste_symbols;
+	if ((o = PyDict_GetItem(dict, name))) {
+	    val = PyInt_AS_LONG(o);
+	    if ((flag & DEF_PARAM) && (val & DEF_PARAM)) {
+		    PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT,
+				 PyString_AsString(name));
+		    PyErr_SyntaxLocation(st->st_filename,
+				       st->st_cur->ste_lineno);
+		    return 0;
+	    }
+	    val |= flag;
+	} else
+	    val = flag;
+	o = PyInt_FromLong(val);
+        if (o == NULL)
+            return 0;
+	if (PyDict_SetItem(dict, name, o) < 0) {
+		Py_DECREF(o);
+		return 0;
+	}
+	Py_DECREF(o);
+
+	if (flag & DEF_PARAM) {
+		if (PyList_Append(st->st_cur->ste_varnames, name) < 0) 
+			return 0;
+	} else	if (flag & DEF_GLOBAL) {
+		/* XXX need to update DEF_GLOBAL for other flags too;
+		   perhaps only DEF_FREE_GLOBAL */
+		val = flag;
+		if ((o = PyDict_GetItem(st->st_global, name))) {
+			val |= PyInt_AS_LONG(o);
+		}
+		o = PyInt_FromLong(val);
+		if (o == NULL)
+			return 0;
+		if (PyDict_SetItem(st->st_global, name, o) < 0) {
+			Py_DECREF(o);
+			return 0;
+		}
+		Py_DECREF(o);
+	}
+	return 1;
+}
+
+/* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument.
+   They use the ASDL name to synthesize the name of the C type and the visit
+   function. 
+   
+   VISIT_SEQ_TAIL permits the start of an ASDL sequence to be skipped, which is
+   useful if the first node in the sequence requires special treatment.
+*/
+
+#define VISIT(ST, TYPE, V) \
+	if (!symtable_visit_ ## TYPE((ST), (V))) \
+		return 0; 
+						    
+#define VISIT_SEQ(ST, 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 (!symtable_visit_ ## TYPE((ST), elt)) \
+			return 0; \
+	} \
+}
+						    
+#define VISIT_SEQ_TAIL(ST, TYPE, SEQ, START) { \
+	int i; \
+	asdl_seq *seq = (SEQ); /* avoid variable capture */ \
+	for (i = (START); i < asdl_seq_LEN(seq); i++) { \
+		TYPE ## _ty elt = asdl_seq_GET(seq, i); \
+		if (!symtable_visit_ ## TYPE((ST), elt)) \
+			return 0; \
+	} \
+}
+						    
+static int
+symtable_visit_stmt(struct symtable *st, stmt_ty s)
+{
+	switch (s->kind) {
+        case FunctionDef_kind:
+		if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL))
+			return 0;
+		if (s->v.FunctionDef.args->defaults)
+			VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults);
+		if (s->v.FunctionDef.decorators)
+			VISIT_SEQ(st, expr, s->v.FunctionDef.decorators);
+		if (!symtable_enter_block(st, s->v.FunctionDef.name, 
+					  FunctionBlock, (void *)s, s->lineno))
+			return 0;
+		VISIT(st, arguments, s->v.FunctionDef.args);
+		VISIT_SEQ(st, stmt, s->v.FunctionDef.body);
+		if (!symtable_exit_block(st, s))
+			return 0;
+		break;
+        case ClassDef_kind:
+		if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL))
+			return 0;
+		VISIT_SEQ(st, expr, s->v.ClassDef.bases);
+		if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, 
+					  (void *)s, s->lineno))
+			return 0;
+		VISIT_SEQ(st, stmt, s->v.ClassDef.body);
+		if (!symtable_exit_block(st, s))
+			return 0;
+		break;
+        case Return_kind:
+		if (s->v.Return.value)
+			VISIT(st, expr, s->v.Return.value);
+		break;
+        case Delete_kind:
+		VISIT_SEQ(st, expr, s->v.Delete.targets);
+		break;
+        case Assign_kind:
+		VISIT_SEQ(st, expr, s->v.Assign.targets);
+		VISIT(st, expr, s->v.Assign.value);
+		break;
+        case AugAssign_kind:
+		VISIT(st, expr, s->v.AugAssign.target);
+		VISIT(st, expr, s->v.AugAssign.value);
+		break;
+        case Print_kind:
+		if (s->v.Print.dest)
+			VISIT(st, expr, s->v.Print.dest);
+		VISIT_SEQ(st, expr, s->v.Print.values);
+		break;
+        case For_kind:
+		VISIT(st, expr, s->v.For.target);
+		VISIT(st, expr, s->v.For.iter);
+		VISIT_SEQ(st, stmt, s->v.For.body);
+		if (s->v.For.orelse)
+			VISIT_SEQ(st, stmt, s->v.For.orelse);
+		break;
+        case While_kind:
+		VISIT(st, expr, s->v.While.test);
+		VISIT_SEQ(st, stmt, s->v.While.body);
+		if (s->v.While.orelse)
+			VISIT_SEQ(st, stmt, s->v.While.orelse);
+		break;
+        case If_kind:
+		/* XXX if 0: and lookup_yield() hacks */
+		VISIT(st, expr, s->v.If.test);
+		VISIT_SEQ(st, stmt, s->v.If.body);
+		if (s->v.If.orelse)
+			VISIT_SEQ(st, stmt, s->v.If.orelse);
+		break;
+        case Raise_kind:
+		if (s->v.Raise.type) {
+			VISIT(st, expr, s->v.Raise.type);
+			if (s->v.Raise.inst) {
+				VISIT(st, expr, s->v.Raise.inst);
+				if (s->v.Raise.tback)
+					VISIT(st, expr, s->v.Raise.tback);
+			}
+		}
+		break;
+        case TryExcept_kind:
+		VISIT_SEQ(st, stmt, s->v.TryExcept.body);
+		VISIT_SEQ(st, stmt, s->v.TryExcept.orelse);
+		VISIT_SEQ(st, excepthandler, s->v.TryExcept.handlers);
+		break;
+        case TryFinally_kind:
+		VISIT_SEQ(st, stmt, s->v.TryFinally.body);
+		VISIT_SEQ(st, stmt, s->v.TryFinally.finalbody);
+		break;
+        case Assert_kind:
+		VISIT(st, expr, s->v.Assert.test);
+		if (s->v.Assert.msg)
+			VISIT(st, expr, s->v.Assert.msg);
+		break;
+        case Import_kind:
+		VISIT_SEQ(st, alias, s->v.Import.names);
+		/* XXX Don't have the lineno available inside
+		   visit_alias */
+		if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno)
+			st->st_cur->ste_opt_lineno = s->lineno;
+		break;
+        case ImportFrom_kind:
+		VISIT_SEQ(st, alias, s->v.ImportFrom.names);
+		/* XXX Don't have the lineno available inside
+		   visit_alias */
+		if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno)
+			st->st_cur->ste_opt_lineno = s->lineno;
+		break;
+        case Exec_kind:
+		VISIT(st, expr, s->v.Exec.body);
+		if (!st->st_cur->ste_opt_lineno)
+			st->st_cur->ste_opt_lineno = s->lineno;
+		if (s->v.Exec.globals) {
+			st->st_cur->ste_unoptimized |= OPT_EXEC;
+			VISIT(st, expr, s->v.Exec.globals);
+			if (s->v.Exec.locals) 
+				VISIT(st, expr, s->v.Exec.locals);
+		} else {
+			st->st_cur->ste_unoptimized |= OPT_BARE_EXEC;
+		}
+		break;
+        case Global_kind: {
+		int i;
+		asdl_seq *seq = s->v.Global.names;
+		for (i = 0; i < asdl_seq_LEN(seq); i++) {
+			identifier name = asdl_seq_GET(seq, i);
+			char *c_name = PyString_AS_STRING(name);
+			int cur = symtable_lookup(st, name);
+			if (cur < 0)
+				return 0;
+			if (cur & (DEF_LOCAL | USE)) {
+				char buf[1000];
+				if (cur & DEF_LOCAL) 
+					PyOS_snprintf(buf, sizeof(buf),
+						      GLOBAL_AFTER_ASSIGN,
+						      c_name);
+				else
+					PyOS_snprintf(buf, sizeof(buf),
+						      GLOBAL_AFTER_USE,
+						      c_name);
+				if (!symtable_warn(st, buf))
+                                    return 0;
+			}
+			if (!symtable_add_def(st, name, DEF_GLOBAL))
+				return 0;
+			
+		}
+		
+		break;
+	}
+        case Expr_kind:
+		VISIT(st, expr, s->v.Expr.value);
+		break;
+        case Pass_kind:
+        case Break_kind:
+        case Continue_kind:
+		/* nothing to do here */
+		break;
+	}
+	return 1;
+}
+
+static int 
+symtable_visit_expr(struct symtable *st, expr_ty e)
+{
+	switch (e->kind) {
+        case BoolOp_kind:
+		VISIT_SEQ(st, expr, e->v.BoolOp.values);
+		break;
+        case BinOp_kind:
+		VISIT(st, expr, e->v.BinOp.left);
+		VISIT(st, expr, e->v.BinOp.right);
+		break;
+        case UnaryOp_kind:
+		VISIT(st, expr, e->v.UnaryOp.operand);
+		break;
+        case Lambda_kind: {
+		if (!symtable_add_def(st, GET_IDENTIFIER(lambda), DEF_LOCAL))
+			return 0;
+		if (e->v.Lambda.args->defaults)
+			VISIT_SEQ(st, expr, e->v.Lambda.args->defaults);
+		/* XXX how to get line numbers for expressions */
+		if (!symtable_enter_block(st, GET_IDENTIFIER(lambda),
+                                          FunctionBlock, (void *)e, 0))
+			return 0;
+		VISIT(st, arguments, e->v.Lambda.args);
+		VISIT(st, expr, e->v.Lambda.body);
+		if (!symtable_exit_block(st, (void *)e))
+			return 0;
+		break;
+	}
+        case Dict_kind:
+		VISIT_SEQ(st, expr, e->v.Dict.keys);
+		VISIT_SEQ(st, expr, e->v.Dict.values);
+		break;
+        case ListComp_kind: {
+		char tmpname[256];
+		identifier tmp;
+
+		PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]",
+			      ++st->st_cur->ste_tmpname);
+		tmp = PyString_FromString(tmpname);
+		if (!symtable_add_def(st, tmp, DEF_LOCAL))
+			return 0;
+		VISIT(st, expr, e->v.ListComp.elt);
+		VISIT_SEQ(st, comprehension, e->v.ListComp.generators);
+		break;
+	}
+        case GeneratorExp_kind: {
+		if (!symtable_visit_genexp(st, e)) {
+			return 0;
+		}
+		break;
+	}
+        case Yield_kind:
+		if (e->v.Yield.value)
+			VISIT(st, expr, e->v.Yield.value);
+                st->st_cur->ste_generator = 1;
+		break;
+        case Compare_kind:
+		VISIT(st, expr, e->v.Compare.left);
+		VISIT_SEQ(st, expr, e->v.Compare.comparators);
+		break;
+        case Call_kind:
+		VISIT(st, expr, e->v.Call.func);
+		VISIT_SEQ(st, expr, e->v.Call.args);
+		VISIT_SEQ(st, keyword, e->v.Call.keywords);
+		if (e->v.Call.starargs)
+			VISIT(st, expr, e->v.Call.starargs);
+		if (e->v.Call.kwargs)
+			VISIT(st, expr, e->v.Call.kwargs);
+		break;
+        case Repr_kind:
+		VISIT(st, expr, e->v.Repr.value);
+		break;
+        case Num_kind:
+        case Str_kind:
+		/* Nothing to do here. */
+		break;
+	/* The following exprs can be assignment targets. */
+        case Attribute_kind:
+		VISIT(st, expr, e->v.Attribute.value);
+		break;
+        case Subscript_kind:
+		VISIT(st, expr, e->v.Subscript.value);
+		VISIT(st, slice, e->v.Subscript.slice);
+		break;
+        case Name_kind:
+		if (!symtable_add_def(st, e->v.Name.id, 
+				      e->v.Name.ctx == Load ? USE : DEF_LOCAL))
+			return 0;
+		break;
+	/* child nodes of List and Tuple will have expr_context set */
+        case List_kind:
+		VISIT_SEQ(st, expr, e->v.List.elts);
+		break;
+        case Tuple_kind:
+		VISIT_SEQ(st, expr, e->v.Tuple.elts);
+		break;
+	}
+	return 1;
+}
+
+static int
+symtable_implicit_arg(struct symtable *st, int pos)
+{
+	PyObject *id = PyString_FromFormat(".%d", pos);
+	if (id == NULL)
+		return 0;
+	if (!symtable_add_def(st, id, DEF_PARAM)) {
+		Py_DECREF(id);
+		return 0;
+	}
+	Py_DECREF(id);
+	return 1;
+}
+
+static int 
+symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel)
+{
+	int i, complex = 0;
+	
+        /* go through all the toplevel arguments first */
+	for (i = 0; i < asdl_seq_LEN(args); i++) {
+		expr_ty arg = asdl_seq_GET(args, i);
+		if (arg->kind == Name_kind) {
+			assert(arg->v.Name.ctx == Param ||
+                               (arg->v.Name.ctx == Store && !toplevel));
+			if (!symtable_add_def(st, arg->v.Name.id, DEF_PARAM))
+				return 0;
+		}
+		else if (arg->kind == Tuple_kind) {
+			assert(arg->v.Tuple.ctx == Store);
+                        complex = 1;
+			if (toplevel) {
+				if (!symtable_implicit_arg(st, i))
+					return 0;
+			}
+		}
+		else {
+			/* syntax error */
+			fprintf(stderr, "unexpected expr in parameter list\n");
+			return 0;
+		}
+	}
+
+	if (!toplevel) {
+		if (!symtable_visit_params_nested(st, args))
+			return 0;
+	}
+
+	return 1;
+}
+
+static int
+symtable_visit_params_nested(struct symtable *st, asdl_seq *args)
+{
+	int i;
+	for (i = 0; i < asdl_seq_LEN(args); i++) {
+		expr_ty arg = asdl_seq_GET(args, i);
+		if (arg->kind == Tuple_kind &&
+		    !symtable_visit_params(st, arg->v.Tuple.elts, 0))
+			return 0;
+	}
+	
+	return 1;
+}
+
+static int 
+symtable_visit_arguments(struct symtable *st, arguments_ty a)
+{
+	/* skip default arguments inside function block
+	   XXX should ast be different?
+	*/
+	if (a->args && !symtable_visit_params(st, a->args, 1))
+		return 0;
+	if (a->vararg) {
+		if (!symtable_add_def(st, a->vararg, DEF_PARAM))
+			return 0;
+		st->st_cur->ste_varargs = 1;
+	}
+	if (a->kwarg) {
+		if (!symtable_add_def(st, a->kwarg, DEF_PARAM))
+			return 0;
+		st->st_cur->ste_varkeywords = 1;
+	}
+	if (a->args && !symtable_visit_params_nested(st, a->args))
+		return 0;
+	return 1;
+}
+
+
+static int 
+symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh)
+{
+	if (eh->type)
+		VISIT(st, expr, eh->type);
+	if (eh->name)
+		VISIT(st, expr, eh->name);
+	VISIT_SEQ(st, stmt, eh->body);
+	return 1;
+}
+
+
+static int 
+symtable_visit_alias(struct symtable *st, alias_ty a)
+{
+	/* Compute store_name, the name actually bound by the import
+	   operation.  It is diferent than a->name when a->name is a
+	   dotted package name (e.g. spam.eggs) 
+	*/
+	PyObject *store_name;
+	PyObject *name = (a->asname == NULL) ? a->name : a->asname;
+	const char *base = PyString_AS_STRING(name);
+	char *dot = strchr(base, '.');
+	if (dot)
+		store_name = PyString_FromStringAndSize(base, dot - base);
+	else {
+		store_name = name;
+		Py_INCREF(store_name);
+	}
+	if (strcmp(PyString_AS_STRING(name), "*")) {
+		int r = symtable_add_def(st, store_name, DEF_IMPORT); 
+		Py_DECREF(store_name);
+		return r;
+	}
+	else {
+            if (st->st_cur->ste_type != ModuleBlock) {
+                if (!symtable_warn(st,
+                                   "import * only allowed at module level"))
+                    return 0;
+            }
+	    st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR;
+	    return 1;
+	}
+}
+
+
+static int 
+symtable_visit_comprehension(struct symtable *st, comprehension_ty lc)
+{
+	VISIT(st, expr, lc->target);
+	VISIT(st, expr, lc->iter);
+	VISIT_SEQ(st, expr, lc->ifs);
+	return 1;
+}
+
+
+static int 
+symtable_visit_keyword(struct symtable *st, keyword_ty k)
+{
+	VISIT(st, expr, k->value);
+	return 1;
+}
+
+
+static int 
+symtable_visit_slice(struct symtable *st, slice_ty s)
+{
+	switch (s->kind) {
+	case Slice_kind:
+		if (s->v.Slice.lower)
+			VISIT(st, expr, s->v.Slice.lower)
+		if (s->v.Slice.upper)
+			VISIT(st, expr, s->v.Slice.upper)
+		if (s->v.Slice.step)
+			VISIT(st, expr, s->v.Slice.step)
+		break;
+	case ExtSlice_kind:
+		VISIT_SEQ(st, slice, s->v.ExtSlice.dims)
+		break;
+	case Index_kind:
+		VISIT(st, expr, s->v.Index.value)
+		break;
+	case Ellipsis_kind:
+		break;
+	}
+	return 1;
+}
+
+static int 
+symtable_visit_genexp(struct symtable *st, expr_ty e)
+{
+	identifier tmp;
+	comprehension_ty outermost = ((comprehension_ty)
+			 (asdl_seq_GET(e->v.GeneratorExp.generators, 0)));
+	/* Outermost iterator is evaluated in current scope */
+	VISIT(st, expr, outermost->iter);
+	/* Create generator scope for the rest */
+	tmp = PyString_FromString("<genexpr>");
+	if (!symtable_enter_block(st, tmp, FunctionBlock, (void *)e, 0)) {
+		return 0;
+	}
+	st->st_cur->ste_generator = 1;
+	/* Outermost iter is received as an argument */
+	if (!symtable_implicit_arg(st, 0)) {
+		return 0;
+	}
+	VISIT(st, expr, outermost->target);
+	VISIT_SEQ(st, expr, outermost->ifs);
+	VISIT_SEQ_TAIL(st, comprehension, e->v.GeneratorExp.generators, 1);
+	VISIT(st, expr, e->v.GeneratorExp.elt);
+	if (!symtable_exit_block(st, (void *)e))
+		return 0;
+	return 1;
+}
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 0775bb8..d9f1337 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -15,7 +15,7 @@
 */
 
 #include "Python.h"
-#include "compile.h"
+#include "code.h"
 #include "frameobject.h"
 #include "eval.h"
 
diff --git a/Python/traceback.c b/Python/traceback.c
index f40cfb4..b58e8ad 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -3,7 +3,7 @@
 
 #include "Python.h"
 
-#include "compile.h"
+#include "code.h"
 #include "frameobject.h"
 #include "structmember.h"
 #include "osdefs.h"
diff --git a/Tools/compiler/dumppyc.py b/Tools/compiler/dumppyc.py
index dd460c9..8cfe3b1 100755
--- a/Tools/compiler/dumppyc.py
+++ b/Tools/compiler/dumppyc.py
@@ -28,7 +28,7 @@
         if type(obj) == types.CodeType:
             walk(obj, match)
 
-def main(filename, codename=None):
+def load(filename, codename=None):
     co = loadCode(filename)
     walk(co, codename)
 
@@ -39,6 +39,9 @@
     else:
         filename = sys.argv[1]
         codename = None
-    if filename.endswith('.py') and os.path.exists(filename+"c"):
-        filename += "c"
-    main(filename, codename)
+    if filename.endswith('.py'):
+        buf = open(filename).read()
+        co = compile(buf, filename, "exec")
+        walk(co)
+    else:   
+        load(filename, codename)