示例#1
0
void BytecodeTranslatorVisitor::visitBinaryOpNode(BinaryOpNode * node) {
    onVisitNode(node);

    TokenKind op = node->kind();
    if (op == tOR || op == tAND) {
        processLazyLogic(node);
        return;
    }

    VISIT(node->right()); ensureTopIsNumeric();
    VISIT(node->left());  ensureTopIsNumeric();

    if (tEQ <= op && op <= tLE)
        processComparison(node->kind());
    else if (tADD <= op && op <= tDIV)
        processNumericOperation(node->kind());
    else if (op == tMOD || op == tAXOR || op == tAOR || op == tAAND) {
        popType(VT_INT);
        ensureTopType(VT_INT);
        EMIT(op == tAXOR ? BC_IAXOR :
             op == tMOD  ? BC_IMOD  :
             op == tAOR  ? BC_IAOR  :
                           BC_IAAND);

    } else ERROR("Unknown binary op");
}
示例#2
0
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;
}
示例#3
0
void BytecodeTranslatorVisitor::visitForNode(ForNode* node) {
    onVisitNode(node);

    const AstVar* i = node->var();
    if (i->type() != VT_INT)
        ERROR("Non-iterable type in for loop");

    const BinaryOpNode* expr = node->inExpr()->asBinaryOpNode();
    if (expr == NULL || expr->kind() != tRANGE)
        ERROR("Invalid range in for loop");

    CONTEXT(function(), locals(), node->body()->scope(), typeStack());

    beforeProcessBlock();

    bool needTempVar = !expr->right()->isIntLiteralNode();
    AstVar* temp = NULL;
    if (needTempVar) {
        if (!scope()->declareVariable("<tempForEnd>", VT_INT))
            ERROR("internal error: temp name is unavailable");
        temp = scope()->lookupVariable("<tempForEnd>", false);
    }

    Label L_Begin(bytecode());
    Label L_End(bytecode());

    VISIT(expr->left());
    EMIT_STORE(i);

    if (needTempVar) {
        VISIT(expr->right());
        EMIT_STORE(temp);
        popType(VT_INT);
    }

    popType(VT_INT);
    EMIT_BIND(L_Begin);
    if (needTempVar)
        EMIT_LOAD(temp);
    else
        VISIT(expr->right());
    EMIT_LOAD(i);
    EMIT_BRANCH(BC_IFICMPG, L_End);

    processBlockNode(node->body());
    afterProcessBlock();

    /* i += 1 */
    EMIT_LOAD(i);
    EMIT(BC_ILOAD1);
    EMIT(BC_IADD);
    EMIT_STORE(i);

    EMIT_BRANCH(BC_JA, L_Begin);
    EMIT_BIND(L_End);

    pushType(VT_VOID);
}
示例#4
0
static int
symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh)
{
    if (eh->v.ExceptHandler.type)
        VISIT(st, expr, eh->v.ExceptHandler.type);
    if (eh->v.ExceptHandler.name)
        VISIT(st, expr, eh->v.ExceptHandler.name);
    VISIT_SEQ(st, stmt, eh->v.ExceptHandler.body);
    return 1;
}
示例#5
0
static int
Writer_traverse(WriterObj *self, visitproc visit, void *arg)
{
	int err;
#define VISIT(SLOT) \
	if (SLOT) { \
		err = visit((PyObject *)(SLOT), arg); \
		if (err) \
			return err; \
	}
	VISIT(self->dialect);
	VISIT(self->writeline);
	return 0;
}
示例#6
0
static int
bomb_traverse(PyBombObject *bomb, visitproc visit, void *arg)
{
	int err;

#define VISIT(o) if (o) {if ((err = visit((PyObject *)(o), arg))) return err;}

	VISIT(bomb->curexc_type);
	VISIT(bomb->curexc_value);
	VISIT(bomb->curexc_traceback);

#undef VISIT
	return 0;
}
示例#7
0
static int
cframe_traverse(PyCFrameObject *cf, visitproc visit, void *arg)
{
	int err;

#define VISIT(o) if (o) {if ((err = visit((PyObject *)(o), arg))) return err;}

	VISIT(cf->f_back);
	VISIT(cf->ob1);
	VISIT(cf->ob2);
	VISIT(cf->ob3);
#undef VISIT
	return 0;
}
示例#8
0
static int
Reader_traverse(ReaderObj *self, visitproc visit, void *arg)
{
	int err;
#define VISIT(SLOT) \
	if (SLOT) { \
		err = visit((PyObject *)(SLOT), arg); \
		if (err) \
			return err; \
	}
	VISIT(self->dialect);
	VISIT(self->input_iter);
	VISIT(self->fields);
	return 0;
}
示例#9
0
void BytecodeTranslatorVisitor::visitUnaryOpNode(UnaryOpNode* node) {
    onVisitNode(node);

    VISIT(node->operand());

    switch (node->kind()) {
    case tNOT: {
        ensureTopType(VT_INT); /* if (!3.14) should fail */
        Label L_True(bytecode());
        Label L_End(bytecode());
        EMIT(BC_ILOAD0);
        EMIT_BRANCH(BC_IFICMPE, L_True);
        EMIT(BC_ILOAD0);
        EMIT_BRANCH(BC_JA, L_End);
        EMIT_BIND(L_True);
        EMIT(BC_ILOAD1);
        EMIT_BIND(L_End);
        break;
    }
    case tSUB:
        ensureTopIsNumeric();
        EMIT(TYPED(NEG));
        break;
    default:
        ERROR("Unknown unary op");
    }
}
示例#10
0
static int 
symtable_visit_genexp(struct symtable *st, expr_ty e)
{
	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 */
	if (!GET_IDENTIFIER(genexpr) ||
	    !symtable_enter_block(st, genexpr, 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)) {
		symtable_exit_block(st, (void *)e);
		return 0;
	}
	VISIT_IN_BLOCK(st, expr, outermost->target, (void*)e);
	VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e);
	VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension,
				e->v.GeneratorExp.generators, 1, (void*)e);
	VISIT_IN_BLOCK(st, expr, e->v.GeneratorExp.elt, (void*)e);
	return symtable_exit_block(st, (void *)e);
}
示例#11
0
void BytecodeTranslatorVisitor::visitIfNode(IfNode* node) {
    onVisitNode(node);

    Label L_End(bytecode());

    if (!node->elseBlock()) {
        falseJump(node->ifExpr(), L_End);
        VISIT(node->thenBlock());
        EMIT_BIND(L_End);
    } else {
        Label L_Else(bytecode());
        falseJump(node->ifExpr(), L_Else);
        visitTyped(node->thenBlock(), VT_VOID);
        EMIT_BRANCH(BC_JA, L_End);
        EMIT_BIND(L_Else);
        VISIT(node->elseBlock());
        EMIT_BIND(L_End);
    }
}
示例#12
0
static int
Per_traverse(cPersistentObject *self, visitproc visit, void *arg)
{
    int err;

#define VISIT(SLOT)                             \
    if (SLOT) {                                   \
        err = visit((PyObject *)(SLOT), arg);       \
        if (err)                                    \
        return err;                               \
    }

    VISIT(self->jar);
    VISIT(self->oid);
    VISIT(self->cache);

#undef VISIT
    return 0;
}
示例#13
0
void BytecodeTranslatorVisitor::processLazyLogic(BinaryOpNode* node) {
    Label L_Lazy(bytecode());
    Label L_End(bytecode());

    bool isOr = node->kind() == tOR;

    VISIT(node->left());
    popType(VT_INT);

    EMIT(BC_ILOAD0);
    EMIT_BRANCH(isOr ? BC_IFICMPNE : BC_IFICMPE, L_Lazy);

    VISIT(node->right());
    ensureTopType(VT_INT);

    EMIT_BRANCH(BC_JA, L_End);
    EMIT_BIND(L_Lazy);
    EMIT(isOr ? BC_ILOAD1 : BC_ILOAD0);
    EMIT_BIND(L_End);
}
示例#14
0
文件: share.c 项目: p-push/pycurl
PYCURL_INTERNAL int
do_share_traverse(CurlShareObject *self, visitproc visit, void *arg)
{
    int err;
#undef VISIT
#define VISIT(v)    if ((v) != NULL && ((err = visit(v, arg)) != 0)) return err

    VISIT(self->dict);

    return 0;
#undef VISIT
}
示例#15
0
void BytecodeTranslatorVisitor::visitWhileNode(WhileNode* node) {
    onVisitNode(node);

    Label L_Begin(bytecode());
    Label L_End(bytecode());

    EMIT_BIND(L_Begin);
    falseJump(node->whileExpr(), L_End);
    VISIT(node->loopBlock());
    EMIT_BRANCH(BC_JA, L_Begin);
    EMIT_BIND(L_End);
}
示例#16
0
void BytecodeTranslatorVisitor::falseJump(AstNode* node, Label& label) {
    bool isComparison = false;
    if (node->isBinaryOpNode()) {
        TokenKind kind = node->asBinaryOpNode()->kind();
        if (tEQ <= kind && kind <= tLE)
            isComparison = true;
    }
    if (!isComparison) {
        visitTyped(node, VT_INT);
        EMIT(BC_ILOAD0);
        EMIT_BRANCH(BC_IFICMPE, label);
    } else {
        /* Premature optimization is the root of all evil */
        VISIT(node->asBinaryOpNode()->right()); ensureTopIsNumeric();
        VISIT(node->asBinaryOpNode()->left());  ensureTopIsNumeric();
        TokenKind kind = node->asBinaryOpNode()->kind();

        castTopsToCommonType();

        Instruction cmp = TYPED(CMP);
        bool hack = topType() == VT_INT;
        popType();
        popType();

        if (!hack) {
            EMIT(cmp);
            EMIT(BC_ILOAD0);
        }

        switch (kind) {
        case tEQ:  EMIT_BRANCH(BC_IFICMPNE, label); break;
        case tNEQ: EMIT_BRANCH(BC_IFICMPE,  label); break;
        case tGT:  EMIT_BRANCH(hack ? BC_IFICMPLE : BC_IFICMPGE, label); break;
        case tGE:  EMIT_BRANCH(hack ? BC_IFICMPL  : BC_IFICMPG,  label); break;
        case tLT:  EMIT_BRANCH(hack ? BC_IFICMPGE : BC_IFICMPLE, label); break;
        default:   EMIT_BRANCH(hack ? BC_IFICMPG  : BC_IFICMPL,  label); break;
        }
    }
}
示例#17
0
void BytecodeTranslatorVisitor::processBlockNode(BlockNode* node) {
    for (uint32_t i = 0; i < node->nodes(); i++) {
        AstNode* ith = node->nodeAt(i);

        warningIf(isUnused(ith), "unused result of statement");

        VISIT(ith);
        VarType result = popType();

        if (result != VT_VOID && !ith->isReturnNode())
            EMIT(BC_POP);
    }
}
static PyObject *m_deepin_lunar_traverse(DeepinLunarObject *self, 
                                         visitproc visit, 
                                         void *args) 
{
    int err;
#undef VISIT
#define VISIT(v)    if ((v) != NULL && ((err = visit(v, args)) != 0)) return err

    VISIT(self->dict);

    return 0;
#undef VISIT
}
示例#19
0
static int
channel_traverse(PyChannelObject *ch, visitproc visit, void *arg)
{
	int err;
	PyTaskletObject *p;

#define VISIT(o) if (o) {if ((err = visit((PyObject *)(o), arg))) return err;}
	for (p = ch->head; p != (PyTaskletObject *) ch; p = p->next) {
		VISIT(p);
	}
#undef VISIT
	return 0;
}
示例#20
0
文件: visitor.c 项目: sutiam/luna
void
luna_visit(luna_visitor_t *self, luna_node_t *node) {
  switch (node->type) {
    case LUNA_NODE_BLOCK: VISIT(block);
    case LUNA_NODE_ID: VISIT(id);
    case LUNA_NODE_INT: VISIT(int);
    case LUNA_NODE_FLOAT: VISIT(float);
    case LUNA_NODE_STRING: VISIT(string);
    case LUNA_NODE_SLOT: VISIT(slot);
    case LUNA_NODE_CALL: VISIT(call);
    case LUNA_NODE_IF: VISIT(if);
    case LUNA_NODE_WHILE: VISIT(while);
    case LUNA_NODE_UNARY_OP: VISIT(unary_op);
    case LUNA_NODE_BINARY_OP: VISIT(binary_op);
    case LUNA_NODE_FUNCTION: VISIT(function);
    case LUNA_NODE_ARRAY: VISIT(array);
    case LUNA_NODE_RETURN: VISIT(return);
  }
}
示例#21
0
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;
}
示例#22
0
void BytecodeTranslatorVisitor::visitPrintNode(PrintNode * node) {
    onVisitNode(node);

    for (uint32_t i = 0; i < node->operands(); ++i) {
        VISIT(node->operandAt(i));

        switch (topType()) {
        case VT_INT:    EMIT(BC_IPRINT); break;
        case VT_DOUBLE: EMIT(BC_DPRINT); break;
        case VT_STRING: EMIT(BC_SPRINT); break;
        default: ERROR("Unprintable parameter");
        }

        popType();
    }

    pushType(VT_VOID);
}
示例#23
0
static inline int VisitSegment (short nSegment, int bAutomap)
{
if (nSegment < 0)
	return 0;
if (bAutomap) {
	if (automap.m_bDisplay) {
		if (!(automap.m_bFull || automap.m_visible [nSegment]))
			return 0;
		if (!gameOpts->render.automap.bSkybox && (SEGMENTS [nSegment].m_nType == SEGMENT_IS_SKYBOX))
			return 0;
		}
	else
		automap.m_visited [0][nSegment] = gameData.render.mine.bSetAutomapVisited;
	}
if (VISITED (nSegment))
	return 0;
VISIT (nSegment);
return 1;
}
示例#24
0
static int
symtable_handle_comprehension(struct symtable *st, expr_ty e,
                              identifier scope_name, asdl_seq *generators,
                              expr_ty elt, expr_ty value)
{
    int is_generator = (e->kind == GeneratorExp_kind);
    int needs_tmp = !is_generator;
    comprehension_ty outermost = ((comprehension_ty)
                                    asdl_seq_GET(generators, 0));
    /* Outermost iterator is evaluated in current scope */
    VISIT(st, expr, outermost->iter);
    /* Create comprehension scope for the rest */
    if (!scope_name ||
        !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, 0)) {
        return 0;
    }
    st->st_cur->ste_generator = is_generator;
    /* Outermost iter is received as an argument */
    if (!symtable_implicit_arg(st, 0)) {
        symtable_exit_block(st, (void *)e);
        return 0;
    }
    /* Allocate temporary name if needed */
    if (needs_tmp && !symtable_new_tmpname(st)) {
        symtable_exit_block(st, (void *)e);
        return 0;
    }
    VISIT_IN_BLOCK(st, expr, outermost->target, (void*)e);
    VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e);
    VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension,
                            generators, 1, (void*)e);
    if (value)
        VISIT_IN_BLOCK(st, expr, value, (void*)e);
    VISIT_IN_BLOCK(st, expr, elt, (void*)e);
    return symtable_exit_block(st, (void *)e);
}
示例#25
0
int
rootstate_traverse(NyHeapTraverse *ta)
{
    visitproc visit = ta->visit;
    NyHeapViewObject *hv = (void *)ta->hv;
    void *arg = ta->arg;
    PyThreadState *ts, *bts = PyThreadState_GET();
    PyInterpreterState *is;
    int err;

    for (is = PyInterpreterState_Head(); is; is = PyInterpreterState_Next(is)) {
	if (hv->is_hiding_calling_interpreter && is == bts->interp)
	  continue;
	VISIT(is->modules);
	VISIT(is->sysdict);
	VISIT(is->builtins);
	
#if PY_VERSION_HEX >= 0x020303f0
	VISIT(is->codec_search_path);
	VISIT(is->codec_search_cache);
	VISIT(is->codec_error_registry);
#endif	
	
	for (ts = is->tstate_head; ts; ts = ts->next) {
	    if (ts == bts && hv->limitframe) {
		VISIT(hv->limitframe);
	    } else if (!hv->limitframe) {
		VISIT(ts->frame);
	    }
	    VISIT(ts->c_profileobj);
	    VISIT(ts->c_traceobj);
	    VISIT(ts->curexc_type);
	    VISIT(ts->curexc_value);
	    VISIT(ts->curexc_traceback);
	    VISIT(ts->exc_type);
	    VISIT(ts->exc_value);
	    VISIT(ts->exc_traceback);
	    
	    VISIT(ts->dict);

#if PY_VERSION_HEX >= 0x020303f0
	    VISIT(ts->async_exc);
#endif	    

	      
	}
    }
    return 0;
}
示例#26
0
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 (!GET_IDENTIFIER(lambda))
            return 0;
        if (e->v.Lambda.args->defaults)
            VISIT_SEQ(st, expr, e->v.Lambda.args->defaults);
        if (!symtable_enter_block(st, lambda,
                                  FunctionBlock, (void *)e, e->lineno))
            return 0;
        VISIT_IN_BLOCK(st, arguments, e->v.Lambda.args, (void*)e);
        VISIT_IN_BLOCK(st, expr, e->v.Lambda.body, (void*)e);
        if (!symtable_exit_block(st, (void *)e))
            return 0;
        break;
    }
    case IfExp_kind:
        VISIT(st, expr, e->v.IfExp.test);
        VISIT(st, expr, e->v.IfExp.body);
        VISIT(st, expr, e->v.IfExp.orelse);
        break;
    case Dict_kind:
        VISIT_SEQ(st, expr, e->v.Dict.keys);
        VISIT_SEQ(st, expr, e->v.Dict.values);
        break;
    case Set_kind:
        VISIT_SEQ(st, expr, e->v.Set.elts);
        break;
    case ListComp_kind:
        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 SetComp_kind:
        if (!symtable_visit_setcomp(st, e))
            return 0;
        break;
    case DictComp_kind:
        if (!symtable_visit_dictcomp(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;
        if (st->st_cur->ste_returns_value) {
            PyErr_SetString(PyExc_SyntaxError,
                RETURN_VAL_IN_GENERATOR);
            PyErr_SyntaxLocation(st->st_filename,
                         e->lineno);
            return 0;
        }
        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;
}
示例#27
0
static int
symtable_visit_keyword(struct symtable *st, keyword_ty k)
{
    VISIT(st, expr, k->value);
    return 1;
}
示例#28
0
void BytecodeTranslatorVisitor::visitTyped(AstNode* node, VarType type) {
    VISIT(node);
    tryCast(type);
    popType(type);
}
示例#29
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.decorator_list)
            VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list);
        if (!symtable_enter_block(st, s->v.FunctionDef.name,
                                  FunctionBlock, (void *)s, s->lineno))
            return 0;
        VISIT_IN_BLOCK(st, arguments, s->v.FunctionDef.args, s);
        VISIT_SEQ_IN_BLOCK(st, stmt, s->v.FunctionDef.body, s);
        if (!symtable_exit_block(st, s))
            return 0;
        break;
    case ClassDef_kind: {
        PyObject *tmp;
        if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL))
            return 0;
        VISIT_SEQ(st, expr, s->v.ClassDef.bases);
        if (s->v.ClassDef.decorator_list)
            VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list);
        if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
                                  (void *)s, s->lineno))
            return 0;
        tmp = st->st_private;
        st->st_private = s->v.ClassDef.name;
        VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s);
        st->st_private = tmp;
        if (!symtable_exit_block(st, s))
            return 0;
        break;
    }
    case Return_kind:
        if (s->v.Return.value) {
            VISIT(st, expr, s->v.Return.value);
            st->st_cur->ste_returns_value = 1;
            if (st->st_cur->ste_generator) {
                PyErr_SetString(PyExc_SyntaxError,
                    RETURN_VAL_IN_GENERATOR);
                PyErr_SyntaxLocation(st->st_filename,
                             s->lineno);
                return 0;
            }
        }
        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 = (identifier)asdl_seq_GET(seq, i);
            char *c_name = PyString_AS_STRING(name);
            long cur = symtable_lookup(st, name);
            if (cur < 0)
                return 0;
            if (cur & (DEF_LOCAL | USE)) {
                char buf[256];
                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, s->lineno))
                    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;
    case With_kind:
        VISIT(st, expr, s->v.With.context_expr);
        if (s->v.With.optional_vars) {
            VISIT(st, expr, s->v.With.optional_vars);
        }
        VISIT_SEQ(st, stmt, s->v.With.body);
        break;
    }
    return 1;
}