state->try_depth++;
INCR_TRY_DEPTH(state);
generate_stmt(Stmt * stmt, State * state){    for (; stmt; stmt = stmt->next) {	switch (stmt->kind) {	case STMT_COND:	    {		Opcode if_op = OP_IF;		int end_label = -1;		Cond_Arm *arms;		for (arms = stmt->s.cond.arms; arms; arms = arms->next) {		    int else_label;		    generate_expr(arms->condition, state);		    emit_byte(if_op, state);		    else_label = add_label(state);		    pop_stack(1, state);		    generate_stmt(arms->stmt, state);		    emit_byte(OP_JUMP, state);		    end_label = add_linked_label(end_label, state);		    define_label(else_label, state);		    if_op = OP_EIF;		}		if (stmt->s.cond.otherwise)		    generate_stmt(stmt->s.cond.otherwise, state);		define_label(end_label, state);	    }	    break;	case STMT_LIST:	    {		Fixup loop_top;		int end_label;		generate_expr(stmt->s.list.expr, state);		emit_byte(OPTIM_NUM_TO_OPCODE(1), state);	/* loop list index */		push_stack(1, state);		loop_top = capture_label(state);		emit_byte(OP_FOR_LIST, state);		add_var_ref(stmt->s.list.id, state);		end_label = add_label(state);		enter_loop(stmt->s.list.id, loop_top, state->cur_stack,			   end_label, state->cur_stack - 2, state);		generate_stmt(stmt->s.list.body, state);		end_label = exit_loop(state);		emit_byte(OP_JUMP, state);		add_known_label(loop_top, state);		define_label(end_label, state);		pop_stack(2, state);	    }	    break;	case STMT_RANGE:	    {		Fixup loop_top;		int end_label;		generate_expr(stmt->s.range.from, state);		generate_expr(stmt->s.range.to, state);		loop_top = capture_label(state);		emit_byte(OP_FOR_RANGE, state);		add_var_ref(stmt->s.range.id, state);		end_label = add_label(state);		enter_loop(stmt->s.range.id, loop_top, state->cur_stack,			   end_label, state->cur_stack - 2, state);		generate_stmt(stmt->s.range.body, state);		end_label = exit_loop(state);		emit_byte(OP_JUMP, state);		add_known_label(loop_top, state);		define_label(end_label, state);		pop_stack(2, state);	    }	    break;	case STMT_WHILE:	    {		Fixup loop_top;		int end_label;		loop_top = capture_label(state);		generate_expr(stmt->s.loop.condition, state);		if (stmt->s.loop.id == -1)		    emit_byte(OP_WHILE, state);		else {		    emit_extended_byte(EOP_WHILE_ID, state);		    add_var_ref(stmt->s.loop.id, state);		}		end_label = add_label(state);		pop_stack(1, state);		enter_loop(stmt->s.loop.id, loop_top, state->cur_stack,			   end_label, state->cur_stack, state);		generate_stmt(stmt->s.loop.body, state);		end_label = exit_loop(state);		emit_byte(OP_JUMP, state);		add_known_label(loop_top, state);		define_label(end_label, state);	    }	    break;	case STMT_FORK:	    generate_expr(stmt->s.fork.time, state);	    if (stmt->s.fork.id >= 0)		emit_byte(OP_FORK_WITH_ID, state);	    else		emit_byte(OP_FORK, state);	    add_fork(stmt_to_code(stmt->s.fork.body, state->gstate), state);	    if (stmt->s.fork.id >= 0)		add_var_ref(stmt->s.fork.id, state);	    pop_stack(1, state);	    break;	case STMT_EXPR:	    generate_expr(stmt->s.expr, state);	    emit_byte(OP_POP, state);	    pop_stack(1, state);	    break;	case STMT_RETURN:	    if (stmt->s.expr) {		generate_expr(stmt->s.expr, state);		emit_ending_op(OP_RETURN, state);		pop_stack(1, state);	    } else		emit_ending_op(OP_RETURN0, state);	    break;	case STMT_TRY_EXCEPT:	    {		int end_label, arm_count = 0;		Except_Arm *ex;		for (ex = stmt->s.catch.excepts; ex; ex = ex->next) {		    generate_codes(ex->codes, state);		    emit_extended_byte(EOP_PUSH_LABEL, state);		    ex->label = add_label(state);		    push_stack(1, state);		    arm_count++;		}		emit_extended_byte(EOP_TRY_EXCEPT, state);		emit_byte(arm_count, state);		push_stack(1, state);		state->try_depth++;		generate_stmt(stmt->s.catch.body, state);		state->try_depth--;		emit_extended_byte(EOP_END_EXCEPT, state);		end_label = add_label(state);		pop_stack(2 * arm_count + 1, state);	/* 2(codes,pc) + catch */		for (ex = stmt->s.catch.excepts; ex; ex = ex->next) {		    define_label(ex->label, state);		    push_stack(1, state);	/* exception tuple */		    if (ex->id >= 0)			emit_var_op(OP_PUT, ex->id, state);		    emit_byte(OP_POP, state);		    pop_stack(1, state);		    generate_stmt(ex->stmt, state);		    if (ex->next) {			emit_byte(OP_JUMP, state);			end_label = add_linked_label(end_label, state);		    }		}		define_label(end_label, state);	    }	    break;	case STMT_TRY_FINALLY:	    {		int handler_label;		emit_extended_byte(EOP_TRY_FINALLY, state);		handler_label = add_label(state);		push_stack(1, state);		state->try_depth++;		generate_stmt(stmt->s.finally.body, state);		state->try_depth--;		emit_extended_byte(EOP_END_FINALLY, state);		pop_stack(1, state);	/* FINALLY marker */		define_label(handler_label, state);		push_stack(2, state);	/* continuation value, reason */		generate_stmt(stmt->s.finally.handler, state);		emit_extended_byte(EOP_CONTINUE, state);		pop_stack(2, state);	    }	    break;	case STMT_BREAK:	case STMT_CONTINUE:	    {		int i;		Loop *loop = 0;	/* silence warnings */		if (stmt->s.exit == -1) {		    emit_extended_byte(EOP_EXIT, state);		    if (state->num_loops == 0)			panic("No loop to exit, in CODE_GEN!");		    loop = &(state->loops[state->num_loops - 1]);		} else {		    emit_extended_byte(EOP_EXIT_ID, state);		    add_var_ref(stmt->s.exit, state);		    for (i = state->num_loops - 1; i >= 0; i--)			if (state->loops[i].id == stmt->s.exit) {			    loop = &(state->loops[i]);			    break;			}		    if (i < 0)			panic("Can't find loop in CONTINUE_LOOP!");		}		if (stmt->kind == STMT_CONTINUE) {		    add_stack_ref(loop->top_stack, state);		    add_known_label(loop->top_label, state);		} else {		    add_stack_ref(loop->bottom_stack, state);		    loop->bottom_label = add_linked_label(loop->bottom_label,							  state);		}	    }	    break;	default:	    panic("Can't happen in GENERATE_STMT()");	}    }}