[Python-checkins] python/dist/src/Python symtable.c,2.10.8.1,2.10.8.2

jhylton@users.sourceforge.net jhylton@users.sourceforge.net
Sun, 07 Jul 2002 13:50:12 -0700


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

Modified Files:
      Tag: ast-branch
	symtable.c 
Log Message:
Change the macros used for visitor and finish symtable visitor.

This code seems to be a clear improvement over the old compile.c
version.  It was wriiten in about a quarter of the time.  It is
shorter (350 lines vs. 510 lines).  It's independent of Grammar.  And
it in't filled with magic constants.

XXX A uture revision should extract out the navigation part of the
code and make it generic.


Index: symtable.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/symtable.c,v
retrieving revision 2.10.8.1
retrieving revision 2.10.8.2
diff -C2 -d -r2.10.8.1 -r2.10.8.2
*** symtable.c	7 Jul 2002 17:47:42 -0000	2.10.8.1
--- symtable.c	7 Jul 2002 20:50:10 -0000	2.10.8.2
***************
*** 156,162 ****
  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;
--- 156,166 ----
  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_expr(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_listcomp(struct symtable *st, listcomp_ty);
! static int symtable_visit_keyword(struct symtable *st, keyword_ty);
! static int symtable_visit_slice(struct symtable *st, slice_ty);
  
  static identifier top = NULL, lambda = NULL;
***************
*** 165,168 ****
--- 169,175 ----
  	((VAR) ? (VAR) : ((VAR) = PyString_InternFromString(# VAR)))
  
+ #define DUPLICATE_ARGUMENT \
+ "duplicate argument '%s' in function definition"
+ 
  static struct symtable *
  symtable_new(void)
***************
*** 207,217 ****
  	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;
--- 214,229 ----
  	st->st_filename = filename;
  	st->st_future = future;
! 	symtable_enter_scope(st, GET_IDENTIFIER(top), ModuleScope, 
! 			     (void *)mod, 0);
  	/* Any other top-level initialization? */
! 	if (mod->kind == Module_kind) {
! 		int i;
! 		asdl_seq *seq = mod->v.Module.body;
! 		for (i = 0; i < asdl_seq_LEN(seq); i++)
! 			if (!symtable_visit_stmt(st, asdl_seq_get(seq, i))) {
! 				PySymtable_Free(st);
! 				return NULL;
! 			}
! 	}
  	symtable_exit_scope(st, (void *)mod);
  	return st;
***************
*** 267,300 ****
  }
  
- /* 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)
--- 279,350 ----
  }
  
  static int
! symtable_add_def(struct symtable *st, PyObject *name, int flag) 
  {
! 	PyObject *o;
! 	PyObject *dict;
! 	int val;
! 
! 	/* XXX must always be called with mangled names. */
! 
! 	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 -1;
! 	    }
! 	    val |= flag;
! 	} else
! 	    val = flag;
! 	o = PyInt_FromLong(val);
! 	if (PyDict_SetItem(dict, name, o) < 0) {
! 		Py_DECREF(o);
! 		return -1;
  	}
! 	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 (PyDict_SetItem(st->st_global, name, o) < 0) {
! 			Py_DECREF(o);
! 			return -1;
! 		}
! 		Py_DECREF(o);
! 	}
! 	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(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; \
+ 	} \
+ }
+ 						    
  static int
  symtable_visit_stmt(struct symtable *st, stmt_ty s)
***************
*** 302,402 ****
  	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;
--- 352,451 ----
  	switch (s->kind) {
          case FunctionDef_kind:
! 		symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL);
! 		if (s->v.FunctionDef.args->defaults)
! 			VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults);
  		symtable_enter_scope(st, s->v.FunctionDef.name, FunctionScope,
  				     (void *)s, s->lineno);
! 		VISIT(st, arguments, s->v.FunctionDef.args);
! 		VISIT_SEQ(st, stmt, s->v.FunctionDef.body);
  		symtable_exit_scope(st, s);
  		break;
          case ClassDef_kind:
! 		symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL);
! 		VISIT_SEQ(st, expr, s->v.ClassDef.bases);
  		symtable_enter_scope(st, s->v.ClassDef.name, ClassScope, 
  				     (void *)s, s->lineno);
! 		VISIT_SEQ(st, stmt, s->v.ClassDef.body);
  		symtable_exit_scope(st, s);
  		break;
          case Return_kind:
  		if (s->v.Return.value)
! 			VISIT(st, expr, s->v.Return.value);
  		break;
          case Yield_kind:
! 		VISIT(st, expr, s->v.Yield.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.value);
  		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);
  		break;
          case ImportFrom_kind:
! 		VISIT_SEQ(st, alias, s->v.ImportFrom.names);
  		break;
          case Exec_kind:
! 		VISIT(st, expr, s->v.Exec.body);
  		if (s->v.Exec.globals) {
! 			VISIT(st, expr, s->v.Exec.globals);
  			if (s->v.Exec.locals) 
! 				VISIT(st, expr, s->v.Exec.locals);
  		}
  		break;
***************
*** 404,415 ****
  		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:
--- 453,463 ----
  		int i;
  		asdl_seq *seq = s->v.Global.names;
! 		for (i = 0; i < asdl_seq_LEN(seq); i++)
! 			symtable_add_def(st, asdl_seq_get(seq, i), DEF_GLOBAL);
  		
  		break;
  	}
          case Expr_kind:
! 		VISIT(st, expr, s->v.Expr.value);
  		break;
          case Pass_kind:
***************
*** 426,441 ****
  }
  
- 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)
--- 474,477 ----
***************
*** 443,492 ****
  	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:
--- 479,523 ----
  	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:
! 		symtable_add_def(st, GET_IDENTIFIER(lambda), DEF_LOCAL);
! 		VISIT(st, arguments, e->v.Lambda.args);
! 		/* XXX how to get line numbers for expressions */
  		symtable_enter_scope(st, GET_IDENTIFIER(lambda),
  				     FunctionScope, (void *)e, 0);
! 		VISIT(st, expr, e->v.Lambda.body);
  		symtable_exit_scope(st, (void *)e);
  		break;
          case Dict_kind:
! 		VISIT_SEQ(st, expr, e->v.Dict.keys);
! 		VISIT_SEQ(st, expr, e->v.Dict.values);
  		break;
          case ListComp_kind:
! 		VISIT(st, expr, e->v.ListComp.target);
! 		VISIT_SEQ(st, listcomp, e->v.ListComp.generators);
  		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:
***************
*** 496,516 ****
  	/* 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:
--- 527,546 ----
  	/* 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:
! 		symtable_add_def(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:
! 		VISIT_SEQ(st, expr, e->v.List.elts);
  		break;
          case Tuple_kind:
! 		VISIT_SEQ(st, expr, e->v.Tuple.elts);
  		break;
  	default:
***************
*** 521,523 ****
--- 551,684 ----
  	return 1;
  }
+ 
+ static int
+ symtable_implicit_arg(struct symtable *st, int pos)
+ {
+ 	PyObject *id = PyString_FromFormat(".%d", pos);
+ 	if (id == NULL)
+ 		return 0;
+ 	/* XXX intern id? */
+ 	symtable_add_def(st, id, DEF_PARAM);
+ 	Py_DECREF(id);
+ 	return 1;
+ }
+ 
+ static int 
+ symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel)
+ {
+ 	int i;
+ 	
+ 	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 == Load);
+ 			if (!symtable_add_def(st, arg->v.Name.id, DEF_PARAM))
+ 				return 0;
+ 		}
+ 		else if (arg->kind == Tuple_kind) {
+ 			assert(arg->v.Tuple.ctx == Load);
+ 			if (toplevel) {
+ 				if (!symtable_implicit_arg(st, i))
+ 					return 0;
+ 			}
+ 			if (!symtable_visit_params(st, arg->v.Tuple.elts, 0))
+ 				return 0;
+ 		}
+ 		else {
+ 			/* syntax error */
+ 			return 0;
+ 		}
+ 	}	
+ 	
+ 	return 1;
+ }
+ 
+ static int 
+ symtable_visit_arguments(struct symtable *st, arguments_ty a)
+ {
+ 	/* skip default arguments inside function scope
+ 	   XXX should ast be different?
+ 	*/
+ 	if (!symtable_visit_params(st, a->args, 1))
+ 		return 0;
+ 
+ 	if (a->vararg)
+ 		if (!symtable_add_def(st, a->vararg, DEF_PARAM))
+ 			return 0;
+ 	if (a->kwarg)
+ 		if (!symtable_add_def(st, a->kwarg, DEF_PARAM))
+ 			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)
+ {
+ 	if (a->asname) {
+ 		if (!symtable_add_def(st, a->asname, DEF_IMPORT))
+ 			return 0;
+ 	}
+ 	else if (!symtable_add_def(st, a->name, DEF_IMPORT))
+ 		return 0;
+ 
+ 	return 1;
+ }
+ 
+ 
+ static int 
+ symtable_visit_listcomp(struct symtable *st, listcomp_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;
+ }
+