[Python-checkins] python/dist/src/Python compile.c,2.247,2.247.2.1 future.c,2.12,2.12.2.1 symtable.c,2.10,2.10.8.1

jhylton@users.sourceforge.net jhylton@users.sourceforge.net
Sun, 07 Jul 2002 10:47:44 -0700


Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv579/Python

Modified Files:
      Tag: ast-branch
	compile.c future.c symtable.c 
Log Message:
checkin of partial progress:
Revise symtable to use AST.

Move the code to symtable.c in the process.
Haven't yet nuked the old code in compile.c.

Note that this code doesn't even compile.


Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.247
retrieving revision 2.247.2.1
diff -C2 -d -r2.247 -r2.247.2.1
*** compile.c	20 Jun 2002 22:23:14 -0000	2.247
--- compile.c	7 Jul 2002 17:47:42 -0000	2.247.2.1
***************
*** 12,15 ****
--- 12,16 ----
  #include "Python.h"
  
+ #include "Python-ast.h"
  #include "node.h"
  #include "token.h"
***************
*** 1012,1016 ****
  	switch (reftype) {
  	case LOCAL:
! 		if (c->c_symtable->st_cur->ste_type == TYPE_FUNCTION)
  			scope = NAME_LOCAL;
  		break;
--- 1013,1017 ----
  	switch (reftype) {
  	case LOCAL:
! 		if (c->c_symtable->st_cur->ste_type == FunctionScope)
  			scope = NAME_LOCAL;
  		break;
***************
*** 4096,4099 ****
--- 4097,4107 ----
  
  PyCodeObject *
+ PyAST_Compile(mod_ty mod, char *filename, PyCompilerFlags *flags)
+ {
+ 	/* XXX */
+ 	return NULL;
+ }
+ 
+ PyCodeObject *
  PyNode_Compile(node *n, char *filename)
  {
***************
*** 4110,4113 ****
--- 4118,4123 ----
  PyNode_CompileSymtable(node *n, char *filename)
  {
+ 	return NULL;
+ /* XXX
  	struct symtable *st;
  	PyFutureFeatures *ff;
***************
*** 4136,4139 ****
--- 4146,4150 ----
  	PySymtable_Free(st);
  	return NULL;
+ */
  }
  
***************
*** 4157,4161 ****
  		/* 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;
--- 4168,4172 ----
  		/* c_symtable still points to parent's symbols */
  		if (base->c_nested 
! 		    || (sc.c_symtable->st_cur->ste_type == FunctionScope))
  			sc.c_nested = 1;
  		sc.c_flags |= base->c_flags & PyCF_MASK;
***************
*** 4295,4299 ****
  
  static int
! issue_warning(char *msg, char *filename, int lineno)
  {
  	if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, filename,
--- 4306,4310 ----
  
  static int
! issue_warning(char *msg, const char *filename, int lineno)
  {
  	if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, filename,
***************
*** 4321,4343 ****
  
  static int
- symtable_build(struct compiling *c, node *n)
- {
- 	if ((c->c_symtable = symtable_init()) == NULL)
- 		return -1;
- 	c->c_symtable->st_future = c->c_future;
- 	c->c_symtable->st_filename = c->c_filename;
- 	symtable_enter_scope(c->c_symtable, TOP, TYPE(n), n->n_lineno);
- 	if (c->c_symtable->st_errors > 0)
- 		return -1;
- 	symtable_node(c->c_symtable, n);
- 	if (c->c_symtable->st_errors > 0)
- 		return -1;
- 	/* reset for second pass */
- 	c->c_symtable->st_nscopes = 1;
- 	c->c_symtable->st_pass = 2;
- 	return 0;
- }
- 
- static int
  symtable_init_compiling_symbols(struct compiling *c)
  {
--- 4332,4335 ----
***************
*** 4394,4398 ****
  	   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)))
--- 4386,4390 ----
  	   method and a free variable with the same name.
  	*/
! 	if (c->c_symtable->st_cur->ste_type == FunctionScope) {
  		/* If it isn't declared locally, it can't be a cell. */
  		if (!(flags & (DEF_LOCAL | DEF_PARAM)))
***************
*** 4585,4591 ****
  	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)
--- 4577,4583 ----
  	if (ste->ste_generator)
  		c->c_flags |= CO_GENERATOR;
! 	if (ste->ste_type != ModuleScope)
  		c->c_flags |= CO_NEWLOCALS;
! 	if (ste->ste_type == FunctionScope) {
  		c->c_nlocals = si->si_nlocals;
  		if (ste->ste_optimized == 0)
***************
*** 4677,4681 ****
  				goto fail;
  			Py_DECREF(v);
! 			if (ste->ste_type != TYPE_CLASS) 
  				if (PyList_Append(c->c_varnames, name) < 0)
  					goto fail;
--- 4669,4673 ----
  				goto fail;
  			Py_DECREF(v);
! 			if (ste->ste_type != ClassScope) 
  				if (PyList_Append(c->c_varnames, name) < 0)
  					goto fail;
***************
*** 4775,4779 ****
  	PySymtableEntryObject *child, *ste = st->st_cur;
  
! 	if (ste->ste_type == TYPE_CLASS)
  		def = DEF_FREE_CLASS;
  	else
--- 4767,4771 ----
  	PySymtableEntryObject *child, *ste = st->st_cur;
  
! 	if (ste->ste_type == ClassScope)
  		def = DEF_FREE_CLASS;
  	else
***************
*** 4814,4818 ****
  			   nested scopes.
  			*/
! 			if (v && (ste->ste_type != TYPE_CLASS)) {
  				int flags = PyInt_AS_LONG(v); 
  				if (flags & DEF_GLOBAL) {
--- 4806,4810 ----
  			   nested scopes.
  			*/
! 			if (v && (ste->ste_type != ClassScope)) {
  				int flags = PyInt_AS_LONG(v); 
  				if (flags & DEF_GLOBAL) {
***************
*** 4854,4858 ****
  	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);
--- 4846,4850 ----
  	PySymtableEntryObject *ste = st->st_cur;
  			
! 	if (ste->ste_type == ClassScope)
  		return symtable_undo_free(st, child, name);
  	o = PyDict_GetItem(ste->ste_symbols, name);
***************
*** 4904,4953 ****
  }
  
- /* 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) {
- 			Py_DECREF(st->st_cur);
- 			st->st_errors++;
- 			return;
- 		}
- 	}
- 	st->st_cur = (PySymtableEntryObject *)
- 		PySymtableEntry_New(st, name, type, lineno);
- 	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)
--- 4896,4899 ----
***************
*** 5455,5459 ****
  		}
  		if (TYPE(CHILD(n, 3)) == STAR) {
! 			if (st->st_cur->ste_type != TYPE_MODULE) {
  				if (symtable_warn(st,
  				  "import * only allowed at module level") < 0)
--- 5401,5405 ----
  		}
  		if (TYPE(CHILD(n, 3)) == STAR) {
! 			if (st->st_cur->ste_type != ModuleScope) {
  				if (symtable_warn(st,
  				  "import * only allowed at module level") < 0)

Index: future.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/future.c,v
retrieving revision 2.12
retrieving revision 2.12.2.1
diff -C2 -d -r2.12 -r2.12.2.1
*** future.c	12 Apr 2002 01:20:10 -0000	2.12
--- future.c	7 Jul 2002 17:47:42 -0000	2.12.2.1
***************
*** 1,3 ****
--- 1,4 ----
  #include "Python.h"
+ #include "Python-ast.h"
  #include "node.h"
  #include "token.h"

Index: symtable.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/symtable.c,v
retrieving revision 2.10
retrieving revision 2.10.8.1
diff -C2 -d -r2.10 -r2.10.8.1
*** symtable.c	10 Dec 2001 00:53:18 -0000	2.10
--- symtable.c	7 Jul 2002 17:47:42 -0000	2.10.8.1
***************
*** 1,36 ****
  #include "Python.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.  
! 
!    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.
! */
! 
! 
! PyObject *
! PySymtableEntry_New(struct symtable *st, char *name, int type, int lineno)
  {
  	PySymtableEntryObject *ste = NULL;
  	PyObject *k, *v;
  
! 	k = PyInt_FromLong(st->st_nscopes++);
  	if (k == NULL)
  		goto fail;
  	v = PyDict_GetItem(st->st_symbols, k);
  	if (v) {
  		Py_DECREF(k);
  		Py_INCREF(v);
! 		return v;
  	}
  	
--- 1,24 ----
  #include "Python.h"
+ #include "Python-ast.h"
  #include "compile.h"
  #include "symtable.h"
  #include "structmember.h"
  
! PySymtableEntryObject *
! PySymtableEntry_New(struct symtable *st, identifier name, scope_ty scope,
! 		    void *key, int lineno)
  {
  	PySymtableEntryObject *ste = NULL;
  	PyObject *k, *v;
  
! 	k = PyLong_FromVoidPtr(key);
  	if (k == NULL)
  		goto fail;
  	v = PyDict_GetItem(st->st_symbols, k);
  	if (v) {
+ 		assert(PySymtableEntry_Check(v));
  		Py_DECREF(k);
  		Py_INCREF(v);
! 		return (PySymtableEntryObject *)v;
  	}
  	
***************
*** 40,47 ****
  	ste->ste_id = k;
  
! 	v = PyString_FromString(name);
! 	if (v == NULL)
! 		goto fail;
! 	ste->ste_name = v;
  	
  	v = PyDict_New();
--- 28,33 ----
  	ste->ste_id = k;
  
! 	ste->ste_name = name;
! 	Py_INCREF(name);
  	
  	v = PyDict_New();
***************
*** 60,85 ****
  	ste->ste_children = v;
  
  	ste->ste_optimized = 0;
  	ste->ste_opt_lineno = 0;
  	ste->ste_lineno = lineno;
- 	switch (type) {
- 	case funcdef:
- 	case lambdef:
- 		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)
  		ste->ste_nested = 1;
  	else
--- 46,58 ----
  	ste->ste_children = v;
  
+ 	ste->ste_type = scope;
  	ste->ste_optimized = 0;
  	ste->ste_opt_lineno = 0;
  	ste->ste_lineno = lineno;
  
  	if (st->st_cur == NULL)
  		ste->ste_nested = 0;
  	else if (st->st_cur->ste_nested 
! 		 || st->st_cur->ste_type == FunctionScope)
  		ste->ste_nested = 1;
  	else
***************
*** 91,95 ****
  	    goto fail;
  	
! 	return (PyObject *)ste;
   fail:
  	Py_XDECREF(ste);
--- 64,68 ----
  	    goto fail;
  	
! 	return ste;
   fail:
  	Py_XDECREF(ste);
***************
*** 178,179 ****
--- 151,523 ----
  	0,					/* tp_new */
  };
+ 
+ static int symtable_enter_scope(struct symtable *st, identifier name, 
+ 				scope_ty scope, void *ast, int lineno);
+ static int symtable_exit_scope(struct symtable *st, void *ast);
+ static int symtable_visit_stmt(struct symtable *st, stmt_ty s);
+ static int symtable_visit_stmts(struct symtable *st, asdl_seq *seq);
+ static int symtable_visit_expr(struct symtable *st, expr_ty s);
+ static int symtable_visit_exprs(struct symtable *st, asdl_seq *seq); 
+ 
+ static identifier top = NULL, lambda = NULL;
+ 
+ #define GET_IDENTIFIER(VAR) \
+ 	((VAR) ? (VAR) : ((VAR) = PyString_InternFromString(# VAR)))
+ 
+ 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_errors = 0;
+ 	st->st_tmpname = 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);
+ 	PyMem_Free((void *)st);
+ }
+ 
+ struct symtable *
+ PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
+ {
+ 	struct symtable *st = symtable_new();
+ 
+ 	if (st == NULL)
+ 		return st;
+ 	st->st_filename = filename;
+ 	st->st_future = future;
+ 	/* XXX not a stmt_ty */
+ 	symtable_enter_scope(st, GET_IDENTIFIER(top),
+ 			     ModuleScope, (void *)mod, 0);
+ 	/* Any other top-level initialization? */
+ 	if (mod->kind == Module_kind)
+ 		symtable_visit_stmts(st, mod->v.Module.body);
+ 	/* XXX not a stmt_ty */
+ 	symtable_exit_scope(st, (void *)mod);
+ 	return st;
+ }
+ 
+ 
+ /* 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, void *ast)
+ {
+ 	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 int
+ symtable_enter_scope(struct symtable *st, identifier name, scope_ty scope, 
+ 		     void *ast, int lineno)
+ {
+ 	PySymtableEntryObject *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);
+ 			st->st_errors++;
+ 			return 0;
+ 		}
+ 	}
+ 	st->st_cur = PySymtableEntry_New(st, name, scope, ast, lineno);
+ 	if (name == GET_IDENTIFIER(top))
+ 		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++;
+ 			return 0;
+ 		}
+ 	}
+ 	return 1;
+ }
+ 
+ /* macros to help visit expressions that result in def or use 
+    will return 0 from current function on error.
+ */
+ #define V_EXPR(ST, E) { \
+ 	if (!symtable_visit_expr((ST), (E))) \
+ 		return 0; \
+ }
+ 						    
+ #define V_EXPRS(ST, LE) { \
+ 	if (!symtable_visit_exprs((ST), (LE))) \
+ 		return 0; \
+ }
+ 
+ #define V_STMTS(ST, LS) { \
+ 	if (!symtable_visit_stmts((ST), (LS))) \
+ 		return 0; \
+ }
+ 						    
+ static int
+ symtable_visit_stmts(struct symtable *st, asdl_seq *seq)
+ {
+ 	int i;
+ 	for (i = 0; i < asdl_seq_LEN(seq); i++) {
+ 		stmt_ty s = asdl_seq_get(seq, i);
+ 		if (!symtable_visit_stmt(st, s))
+ 			return 0;
+ 	}
+ 	return 1;
+ }
+ 
+ static int
+ symtable_visit_stmt(struct symtable *st, stmt_ty s)
+ {
+ 	switch (s->kind) {
+         case FunctionDef_kind:
+ 		symtable_add_def_o(st, s->v.FunctionDef.name, DEF_LOCAL);
+ 		if (!symtable_visit_arguments(st, s->v.FunctionDef.args))
+ 			return 0;
+ 		symtable_enter_scope(st, s->v.FunctionDef.name, FunctionScope,
+ 				     (void *)s, s->lineno);
+ 		V_STMTS(st, s->v.FunctionDef.body);
+ 		symtable_exit_scope(st, s);
+ 		break;
+         case ClassDef_kind:
+ 		symtable_add_def_o(st, s->v.ClassDef.name, DEF_LOCAL);
+ 		V_EXPRS(st, s->v.ClassDef.bases);
+ 		symtable_enter_scope(st, s->v.ClassDef.name, ClassScope, 
+ 				     (void *)s, s->lineno);
+ 		V_STMTS(st, s->v.ClassDef.body);
+ 		symtable_exit_scope(st, s);
+ 		break;
+         case Return_kind:
+ 		if (s->v.Return.value)
+ 			V_EXPR(st, s->v.Return.value);
+ 		break;
+         case Yield_kind:
+ 		V_EXPR(st, s->v.Yield.value);
+ 		break;
+         case Delete_kind:
+ 		V_EXPRS(st, s->v.Delete.targets);
+ 		break;
+         case Assign_kind:
+ 		V_EXPRS(st, s->v.Assign.targets);
+ 		V_EXPR(st, s->v.Assign.value);
+ 		break;
+         case AugAssign_kind:
+ 		V_EXPR(st, s->v.AugAssign.target);
+ 		V_EXPR(st, s->v.AugAssign.value);
+ 		break;
+         case Print_kind:
+ 		if (s->v.Print.dest)
+ 			V_EXPR(st, s->v.Print.dest);
+ 		V_EXPRS(st, s->v.Print.value);
+ 		break;
+         case For_kind:
+ 		V_EXPR(st, s->v.For.target);
+ 		V_EXPR(st, s->v.For.iter);
+ 		V_STMTS(st, s->v.For.body);
+ 		if (s->v.For.orelse)
+ 			V_STMTS(st, s->v.For.orelse);
+ 		break;
+         case While_kind:
+ 		V_EXPR(st, s->v.While.test);
+ 		V_STMTS(st, s->v.While.body);
+ 		if (s->v.While.orelse)
+ 			V_STMTS(st, s->v.While.orelse);
+ 		break;
+         case If_kind:
+ 		V_EXPR(st, s->v.If.test);
+ 		V_STMTS(st, s->v.If.body);
+ 		if (s->v.If.orelse)
+ 			V_STMTS(st, s->v.If.orelse);
+ 		break;
+         case Raise_kind:
+ 		if (s->v.Raise.type) {
+ 			V_EXPR(st, s->v.Raise.type);
+ 			if (s->v.Raise.inst) {
+ 				V_EXPR(st, s->v.Raise.inst);
+ 				if (s->v.Raise.tback)
+ 					V_EXPR(st, s->v.Raise.tback);
+ 			}
+ 		}
+ 		break;
+         case TryExcept_kind:
+ 		V_STMTS(st, s->v.TryExcept.body);
+ 		V_STMTS(st, s->v.TryExcept.orelse);
+ 		if (!symtable_visit_excepthandles(st, s->v.TryExcept.handlers))
+ 			return 0;
+ 		break;
+         case TryFinally_kind:
+ 		V_STMTS(st, s->v.TryFinally.body);
+ 		V_STMTS(st, s->v.TryFinally.finalbody);
+ 		break;
+         case Assert_kind:
+ 		V_EXPR(st, s->v.Assert.test);
+ 		if (s->v.Assert.msg)
+ 			V_EXPR(st, s->v.Assert.msg);
+ 		break;
+         case Import_kind:
+ 		if (!symtable_visit_aliases(st, s->v.Import.names))
+ 			return 0;
+ 		break;
+         case ImportFrom_kind:
+ 		if (!symtable_visit_aliases(st, s->v.ImportFrom.names))
+ 			return 0;
+ 		break;
+         case Exec_kind:
+ 		V_EXPR(st, s->v.Exec.body);
+ 		if (s->v.Exec.globals) {
+ 			V_EXPR(st, s->v.Exec.globals);
+ 			if (s->v.Exec.locals) 
+ 				V_EXPR(st, s->v.Exec.locals);
+ 		}
+ 		break;
+         case Global_kind: {
+ 		int i;
+ 		asdl_seq *seq = s->v.Global.names;
+ 		for (i = 0; i < asdl_seq_SIZE(seq); i++)
+ 			symtable_add_def_o(st, asdl_seq_get(seq, i),
+ 					   DEF_GLOBAL);
+ 		
+ 		break;
+ 	}
+         case Expr_kind:
+ 		V_EXPR(st, s->v.Expr.value);
+ 		break;
+         case Pass_kind:
+         case Break_kind:
+         case Continue_kind:
+ 		/* nothing to do here */
+ 		break;
+ 	default:
+ 		PyErr_Format(PyExc_AssertionError,
+ 			     "invalid statement kind: %d\n", s->kind);
+ 		return 0;
+ 	}
+ 	return 1;
+ }
+ 
+ static int
+ symtable_visit_exprs(struct symtable *st, asdl_seq *seq)
+ {
+ 	int i;
+ 	for (i = 0; i < asdl_seq_LEN(seq); i++) {
+ 		stmt_ty s = asdl_seq_get(seq, i);
+ 		if (!symtable_visit_expr(st, s))
+ 			return 0;
+ 	}
+ 	return 1;
+ }
+ 
+ static int 
+ symtable_visit_expr(struct symtable *st, expr_ty e)
+ {
+ 	switch (e->kind) {
+         case BoolOp_kind:
+ 		V_EXPRS(st, e->v.BoolOp.values);
+ 		break;
+         case BinOp_kind:
+ 		V_EXPR(st, e->v.BinOp.left);
+ 		V_EXPR(st, e->v.BinOp.right);
+ 		break;
+         case UnaryOp_kind:
+ 		V_EXPR(st, e->v.UnaryOp.operand);
+ 		break;
+         case Lambda_kind:
+ 		symtable_add_def_o(st, GET_IDENTIFIER(lambda), DEF_LOCAL);
+ 		if (!symtable_visit_arguments(st, e->v.Lambda.args))
+ 			return 0;
+ 		/* XXX need to make name an identifier
+ 		   XXX how to get line numbers for expressions
+ 		*/
+ 		symtable_enter_scope(st, GET_IDENTIFIER(lambda),
+ 				     FunctionScope, (void *)e, 0);
+ 		V_STMTS(st, e->v.Lambda.body);
+ 		symtable_exit_scope(st, (void *)e);
+ 		break;
+         case Dict_kind:
+ 		V_EXPRS(st, e->v.Dict.keys);
+ 		V_EXPRS(st, e->v.Dict.values);
+ 		break;
+         case ListComp_kind:
+ 		V_EXPR(st, e->v.ListComp.target);
+ 		if (!symtable_visit_listcomp(e->v.ListComp.generators))
+ 			return 0;
+ 		break;
+         case Compare_kind:
+ 		V_EXPR(st, e->v.Compare.left);
+ 		V_EXPRS(st, e->v.Compare.comparators);
+ 		break;
+         case Call_kind:
+ 		V_EXPR(st, e->v.Call.func);
+ 		V_EXPRS(st, e->v.Call.args);
+ 		if (!symtable_visit_keyword(st, e->v.Call.keywords))
+ 			return 0;
+ 		if (e->v.Call.starargs)
+ 			V_EXPR(st, e->v.Call.starargs);
+ 		if (e->v.Call.kwargs)
+ 			V_EXPR(st, e->v.Call.kwargs);
+ 		break;
+         case Repr_kind:
+ 		V_EXPR(st, 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:
+ 		V_EXPR(st, e->v.Attribute.value);
+ 		break;
+         case Subscript_kind:
+ 		V_EXPR(st, e->v.Subscript.value);
+ 		if (!symtable_visit_slice(st, e->v.Subscript.slice))
+ 			return 0;
+ 		break;
+         case Name_kind:
+ 		symtable_add_def_o(st, e->v.Name.id, 
+ 				   e->v.Name.ctx == Load ? USE : DEF_LOCAL);
+ 		break;
+ 	/* child nodes of List and Tuple will have expr_context set */
+         case List_kind:
+ 		V_EXPRS(st, e->v.List.elts);
+ 		break;
+         case Tuple_kind:
+ 		V_EXPRS(st, e->v.Tuple.elts);
+ 		break;
+ 	default:
+ 		PyErr_Format(PyExc_AssertionError,
+ 			     "invalid expression kind: %d\n", e->kind);
+ 		return 0;
+ 	}
+ 	return 1;
+ }
+