[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;
+ }
+