} co = assemble(c, 1); compiler_exit_scope(c); if (co == NULL) return 0; compiler_make_closure(c, co, asdl_seq_LEN(args->defaults)); Py_DECREF(co); for (i = 0; i < asdl_seq_LEN(decos); i++) { ADDOP_I(c, CALL_FUNCTION, 1); } return compiler_nameop(c, s->v.FunctionDef.name, Store);} static intcompiler_class(struct compiler *c, stmt_ty s){ int n; PyCodeObject *co; PyObject *str; /* push class name on stack, needed by BUILD_CLASS */ ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts); /* push the tuple of base classes on the stack */ n = asdl_seq_LEN(s->v.ClassDef.bases); if (n > 0) VISIT_SEQ(c, expr, s->v.ClassDef.bases); ADDOP_I(c, BUILD_TUPLE, n); if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, s->lineno)) return 0; c->u->u_private = s->v.ClassDef.name; Py_INCREF(c->u->u_private); str = PyString_InternFromString("__name__"); if (!str || !compiler_nameop(c, str, Load)) { Py_XDECREF(str); compiler_exit_scope(c); return 0; } Py_DECREF(str); str = PyString_InternFromString("__module__"); if (!str || !compiler_nameop(c, str, Store)) { Py_XDECREF(str); compiler_exit_scope(c); return 0; } Py_DECREF(str); if (!compiler_body(c, s->v.ClassDef.body)) { compiler_exit_scope(c); return 0; } ADDOP_IN_SCOPE(c, LOAD_LOCALS); ADDOP_IN_SCOPE(c, RETURN_VALUE); co = assemble(c, 1); compiler_exit_scope(c); if (co == NULL) return 0; compiler_make_closure(c, co, 0); Py_DECREF(co); ADDOP_I(c, CALL_FUNCTION, 0); ADDOP(c, BUILD_CLASS); if (!compiler_nameop(c, s->v.ClassDef.name, Store)) return 0; return 1;} static intcompiler_ifexp(struct compiler *c, expr_ty e){ basicblock *end, *next; assert(e->kind == IfExp_kind); end = compiler_new_block(c); if (end == NULL) return 0; next = compiler_new_block(c); if (next == NULL) return 0; VISIT(c, expr, e->v.IfExp.test); ADDOP_JREL(c, JUMP_IF_FALSE, next); ADDOP(c, POP_TOP); VISIT(c, expr, e->v.IfExp.body); ADDOP_JREL(c, JUMP_FORWARD, end); compiler_use_next_block(c, next); ADDOP(c, POP_TOP); VISIT(c, expr, e->v.IfExp.orelse); compiler_use_next_block(c, end); return 1;} static intcompiler_lambda(struct compiler *c, expr_ty e){ PyCodeObject *co; static identifier name; arguments_ty args = e->v.Lambda.args; assert(e->kind == Lambda_kind); if (!name) { name = PyString_InternFromString("<lambda>"); if (!name) return 0; } if (args->defaults) VISIT_SEQ(c, expr, args->defaults); if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) return 0; /* unpack nested arguments */ compiler_arguments(c, args); c->u->u_argcount = asdl_seq_LEN(args->args); VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); ADDOP_IN_SCOPE(c, RETURN_VALUE); co = assemble(c, 1); compiler_exit_scope(c); if (co == NULL) return 0; compiler_make_closure(c, co, asdl_seq_LEN(args->defaults)); Py_DECREF(co); return 1;} static intcompiler_print(struct compiler *c, stmt_ty s){ int i, n; bool dest; assert(s->kind == Print_kind); n = asdl_seq_LEN(s->v.Print.values); dest = false; if (s->v.Print.dest) { VISIT(c, expr, s->v.Print.dest); dest = true; } for (i = 0; i < n; i++) { expr_ty e = (expr_ty)asdl_seq_GET(s->v.Print.values, i); if (dest) { ADDOP(c, DUP_TOP); VISIT(c, expr, e); ADDOP(c, ROT_TWO); ADDOP(c, PRINT_ITEM_TO); } else { VISIT(c, expr, e); ADDOP(c, PRINT_ITEM); } } if (s->v.Print.nl) { if (dest) ADDOP(c, PRINT_NEWLINE_TO) else ADDOP(c, PRINT_NEWLINE) } else if (dest) ADDOP(c, POP_TOP); return 1;} static intcompiler_if(struct compiler *c, stmt_ty s){ basicblock *end, *next; int constant; assert(s->kind == If_kind); end = compiler_new_block(c); if (end == NULL) return 0; next = compiler_new_block(c); if (next == NULL) return 0; constant = expr_constant(s->v.If.test); /* constant = 0: "if 0" * constant = 1: "if 1", "if 2", ... * constant = -1: rest */ if (constant == 0) { if (s->v.If.orelse) VISIT_SEQ(c, stmt, s->v.If.orelse); } else if (constant == 1) { VISIT_SEQ(c, stmt, s->v.If.body); } else { VISIT(c, expr, s->v.If.test); ADDOP_JREL(c, JUMP_IF_FALSE, next); ADDOP(c, POP_TOP); VISIT_SEQ(c, stmt, s->v.If.body); ADDOP_JREL(c, JUMP_FORWARD, end); compiler_use_next_block(c, next); ADDOP(c, POP_TOP); if (s->v.If.orelse) VISIT_SEQ(c, stmt, s->v.If.orelse); } compiler_use_next_block(c, end); return 1;} static intcompiler_for(struct compiler *c, stmt_ty s){ basicblock *start, *cleanup, *end; start = compiler_new_block(c); cleanup = compiler_new_block(c); end = compiler_new_block(c); if (start == NULL || end == NULL || cleanup == NULL) return 0; ADDOP_JREL(c, SETUP_LOOP, end); if (!compiler_push_fblock(c, LOOP, start)) return 0; VISIT(c, expr, s->v.For.iter); ADDOP(c, GET_ITER); compiler_use_next_block(c, start); /* XXX(nnorwitz): is there a better way to handle this? for loops are special, we want to be able to trace them each time around, so we need to set an extra line number. */ c->u->u_lineno_set = false; ADDOP_JREL(c, FOR_ITER, cleanup); VISIT(c, expr, s->v.For.target); VISIT_SEQ(c, stmt, s->v.For.body); ADDOP_JABS(c, JUMP_ABSOLUTE, start); compiler_use_next_block(c, cleanup); ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, LOOP, start); VISIT_SEQ(c, stmt, s->v.For.orelse); compiler_use_next_block(c, end); return 1;} static intcompiler_while(struct compiler *c, stmt_ty s){ basicblock *loop, *orelse, *end, *anchor = NULL; int constant = expr_constant(s->v.While.test); if (constant == 0) return 1; loop = compiler_new_block(c); end = compiler_new_block(c); if (constant == -1) { anchor = compiler_new_block(c); if (anchor == NULL) return 0; } if (loop == NULL || end == NULL) return 0; if (s->v.While.orelse) { orelse = compiler_new_block(c); if (orelse == NULL) return 0; } else orelse = NULL; ADDOP_JREL(c, SETUP_LOOP, end); compiler_use_next_block(c, loop); if (!compiler_push_fblock(c, LOOP, loop)) return 0; if (constant == -1) { VISIT(c, expr, s->v.While.test); ADDOP_JREL(c, JUMP_IF_FALSE, anchor); ADDOP(c, POP_TOP); } VISIT_SEQ(c, stmt, s->v.While.body); ADDOP_JABS(c, JUMP_ABSOLUTE, loop); /* XXX should the two POP instructions be in a separate block if there is no else clause ? */ if (constant == -1) { compiler_use_next_block(c, anchor); ADDOP(c, POP_TOP); ADDOP(c, POP_BLOCK); } compiler_pop_fblock(c, LOOP, loop); if (orelse != NULL) /* what if orelse is just pass? */ VISIT_SEQ(c, stmt, s->v.While.orelse); compiler_use_next_block(c, end); return 1;} static intcompiler_continue(struct compiler *c){ static const char LOOP_ERROR_MSG[] = "'continue' not properly in loop"; static const char IN_FINALLY_ERROR_MSG[] = "'continue' not supported inside 'finally' clause"; int i; if (!c->u->u_nfblocks) return compiler_error(c, LOOP_ERROR_MSG); i = c->u->u_nfblocks - 1; switch (c->u->u_fblock[i].fb_type) { case LOOP: ADDOP_JABS(c, JUMP_ABSOLUTE, c->u->u_fblock[i].fb_block); break; case EXCEPT: case FINALLY_TRY: while (--i >= 0 && c->u->u_fblock[i].fb_type != LOOP) { /* Prevent try: ... finally: try: continue ... or try: ... except: continue */ if (c->u->u_fblock[i].fb_type == FINALLY_END) return compiler_error(c, IN_FINALLY_ERROR_MSG); } if (i == -1) return compiler_error(c, LOOP_ERROR_MSG); ADDOP_JABS(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block); break; case FINALLY_END: return compiler_error(c, IN_FINALLY_ERROR_MSG); } return 1;} /* Code generated for "try: <body> finally: <finalbody>" is as follows: SETUP_FINALLY L <code for body> POP_BLOCK LOAD_CONST <None> L: <code for finalbody> END_FINALLY The special instructions use the block stack. Each block stack entry contains the instruction that created it (here SETUP_FINALLY), the level of the value stack at the time the block stack entry was created, and a label (here L). SETUP_FINALLY: Pushes the current value stack level and the label onto the block stack. POP_BLOCK: Pops en entry from the block stack, and pops the value stack until its level is the same as indicated on the block stack. (The label is ignored.) END_FINALLY: Pops a variable number of entries from the *value* stack and re-raises the exception they specify. The number of entries popped depends on the (pseudo) exception type. The block stack is unwound when an exception is raised: when a SETUP_FINALLY entry is found, the exception is pushed onto the value stack (and the exception condition is cleared), and the interpreter jumps to the label gotten from the block stack.*/ static intcompiler_try_finally(struct compiler *c, stmt_ty s){ basicblock *body, *end; body = compiler_new_block(c); end = compiler_new_block(c); if (body == NULL || end == NULL) return 0; ADDOP_JREL(c, SETUP_FINALLY, end); compiler_use_next_block(c, body); if (!compiler_push_fblock(c, FINALLY_TRY, body)) return 0; VISIT_SEQ(c, stmt, s->v.TryFinally.body); ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, FINALLY_TRY, body); ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_use_next_block(c, end); if (!compiler_push_fblock(c, FINALLY_END, end)) return 0; VISIT_SEQ(c, stmt, s->v.TryFinally.finalbody); ADDOP(c, END_FINALLY); compiler_pop_fblock(c, FINALLY_END, end); return 1;} /* Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...": (The contents of the value stack is shown in [], with the top at the right; 'tb' is trace-back info, 'val' the exception's associated value, and 'exc' the exception.) Value stack Label Instruction Argument [] SETUP_EXCEPT L1 [] <code for S> [] POP_BLOCK [] JUMP_FORWARD L0 [tb, val, exc] L1: DUP ) [tb, val, exc, exc] <evaluate E1> ) [tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1 [tb, val, exc, 1-or-0] JUMP_IF_FALSE L2 ) [tb, val, exc, 1] POP ) [tb, val, exc] POP [tb, val] <assign to V1> (or POP if no V1) [tb] POP [] <code for S1> JUMP_FORWARD L0 [tb, val, exc, 0] L2: POP [tb, val, exc] DUP .............................etc....................... [tb, val, exc, 0] Ln+1: POP [tb, val, exc] END_FINALLY # re-raise exception [] L0: <next statement> Of course, parts are not generated if Vi or Ei is not present.*/static intcompiler_try_except(struct compiler *c, stmt_ty s){ basicblock *body, *orelse, *except, *end; int i, n; body = compiler_new_block(c); except = compiler_new_block(c); orelse = compiler_new_block(c); end = compiler_new_block(c); if (body == NULL || except == NULL || orelse == NULL || end == NULL) return 0; ADDOP_JREL(c, SETUP_EXCEPT, except); compiler_use_next_block(c, body); if (!compiler_push_fblock(c, EXCEPT, body)) return 0; VISIT_SEQ(c, stmt, s->v.TryExcept.body); ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, EXCEPT, body); ADDOP_JREL(c, JUMP_FORWARD, orelse); n = asdl_seq_LEN(s->v.TryExcept.handlers); compiler_use_next_block(c, except); for (i = 0; i < n; i++) { excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( s->v.TryExcept.handlers, i); if (!handler->type && i < n-1) return compiler_error(c, "default 'except:' must be last"); c->u->u_lineno_set = false; c->u->u_lineno = handler->lineno; except = compiler_new_block(c); if (except == NULL) return 0; if (handler->type) { ADDOP(c, DUP_TOP); VISIT(c, expr, handler->type); ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH); ADDOP_JREL(c, JUMP_IF_FALSE, except); ADDOP(c, POP_TOP); } ADDOP(c, POP_TOP); if (handler->name) { VISIT(c, expr, handler->name); } else { ADDOP(c, POP_TOP); } ADDOP(c, POP_TOP); VISIT_SEQ(c, stmt, handler->body); ADDOP_JREL(c, JUMP_FORWARD, end); compiler_use_next_block(c, except); if (handler->type) ADDOP(c, POP_TOP); } ADDOP(c, END_FINALLY); compiler_use_next_block(c, orelse); VISIT_SEQ(c, stmt, s->v.TryExcept.orelse); compiler_use_next_block(c, end); return 1;} static intcompiler_import_as(struct compiler *c, identifier name, identifier asname){ /* The IMPORT_NAME opcode was already generated. This function merely needs to bind the result to a name. If there is a dot in name, we need to split it and emit a LOAD_ATTR for each name. */ const char *src = PyString_AS_STRING(name); const char *dot = strchr(src, '.'); if (dot) { /* Consume the base module name to get the first attribute */ src = dot + 1; while (dot) { /* NB src is only defined when dot != NULL */ PyObject *attr; dot = strchr(src, '.');Lines 2001–2500 of 4570. Previous lines Load more
} co = assemble(c, 1); compiler_exit_scope(c); if (co == NULL) return 0; compiler_make_closure(c, co, asdl_seq_LEN(args->defaults)); Py_DECREF(co); for (i = 0; i < asdl_seq_LEN(decos); i++) { ADDOP_I(c, CALL_FUNCTION, 1); } return compiler_nameop(c, s->v.FunctionDef.name, Store); } static int compiler_class(struct compiler *c, stmt_ty s) { int n; PyCodeObject *co; PyObject *str; /* push class name on stack, needed by BUILD_CLASS */ ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts); /* push the tuple of base classes on the stack */ n = asdl_seq_LEN(s->v.ClassDef.bases); if (n > 0) VISIT_SEQ(c, expr, s->v.ClassDef.bases); ADDOP_I(c, BUILD_TUPLE, n); if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, s->lineno)) return 0; c->u->u_private = s->v.ClassDef.name; Py_INCREF(c->u->u_private); str = PyString_InternFromString("__name__"); if (!str || !compiler_nameop(c, str, Load)) { Py_XDECREF(str); compiler_exit_scope(c); return 0; } Py_DECREF(str); str = PyString_InternFromString("__module__"); if (!str || !compiler_nameop(c, str, Store)) { Py_XDECREF(str); compiler_exit_scope(c); return 0; } Py_DECREF(str); if (!compiler_body(c, s->v.ClassDef.body)) { compiler_exit_scope(c); return 0; } ADDOP_IN_SCOPE(c, LOAD_LOCALS); ADDOP_IN_SCOPE(c, RETURN_VALUE); co = assemble(c, 1); compiler_exit_scope(c); if (co == NULL) return 0; compiler_make_closure(c, co, 0); Py_DECREF(co); ADDOP_I(c, CALL_FUNCTION, 0); ADDOP(c, BUILD_CLASS); if (!compiler_nameop(c, s->v.ClassDef.name, Store)) return 0; return 1; } static int compiler_ifexp(struct compiler *c, expr_ty e) { basicblock *end, *next; assert(e->kind == IfExp_kind); end = compiler_new_block(c); if (end == NULL) return 0; next = compiler_new_block(c); if (next == NULL) return 0; VISIT(c, expr, e->v.IfExp.test); ADDOP_JREL(c, JUMP_IF_FALSE, next); ADDOP(c, POP_TOP); VISIT(c, expr, e->v.IfExp.body); ADDOP_JREL(c, JUMP_FORWARD, end); compiler_use_next_block(c, next); ADDOP(c, POP_TOP); VISIT(c, expr, e->v.IfExp.orelse); compiler_use_next_block(c, end); return 1; } static int compiler_lambda(struct compiler *c, expr_ty e) { PyCodeObject *co; static identifier name; arguments_ty args = e->v.Lambda.args; assert(e->kind == Lambda_kind); if (!name) { name = PyString_InternFromString("<lambda>"); if (!name) return 0; } if (args->defaults) VISIT_SEQ(c, expr, args->defaults); if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) return 0; /* unpack nested arguments */ compiler_arguments(c, args); c->u->u_argcount = asdl_seq_LEN(args->args); VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); ADDOP_IN_SCOPE(c, RETURN_VALUE); co = assemble(c, 1); compiler_exit_scope(c); if (co == NULL) return 0; compiler_make_closure(c, co, asdl_seq_LEN(args->defaults)); Py_DECREF(co); return 1; } static int compiler_print(struct compiler *c, stmt_ty s) { int i, n; bool dest; assert(s->kind == Print_kind); n = asdl_seq_LEN(s->v.Print.values); dest = false; if (s->v.Print.dest) { VISIT(c, expr, s->v.Print.dest); dest = true; } for (i = 0; i < n; i++) { expr_ty e = (expr_ty)asdl_seq_GET(s->v.Print.values, i); if (dest) { ADDOP(c, DUP_TOP); VISIT(c, expr, e); ADDOP(c, ROT_TWO); ADDOP(c, PRINT_ITEM_TO); } else { VISIT(c, expr, e); ADDOP(c, PRINT_ITEM); } } if (s->v.Print.nl) { if (dest) ADDOP(c, PRINT_NEWLINE_TO) else ADDOP(c, PRINT_NEWLINE) } else if (dest) ADDOP(c, POP_TOP); return 1; } static int compiler_if(struct compiler *c, stmt_ty s) { basicblock *end, *next; int constant; assert(s->kind == If_kind); end = compiler_new_block(c); if (end == NULL) return 0; next = compiler_new_block(c); if (next == NULL) return 0; constant = expr_constant(s->v.If.test); /* constant = 0: "if 0" * constant = 1: "if 1", "if 2", ... * constant = -1: rest */ if (constant == 0) { if (s->v.If.orelse) VISIT_SEQ(c, stmt, s->v.If.orelse); } else if (constant == 1) { VISIT_SEQ(c, stmt, s->v.If.body); } else { VISIT(c, expr, s->v.If.test); ADDOP_JREL(c, JUMP_IF_FALSE, next); ADDOP(c, POP_TOP); VISIT_SEQ(c, stmt, s->v.If.body); ADDOP_JREL(c, JUMP_FORWARD, end); compiler_use_next_block(c, next); ADDOP(c, POP_TOP); if (s->v.If.orelse) VISIT_SEQ(c, stmt, s->v.If.orelse); } compiler_use_next_block(c, end); return 1; } static int compiler_for(struct compiler *c, stmt_ty s) { basicblock *start, *cleanup, *end; start = compiler_new_block(c); cleanup = compiler_new_block(c); end = compiler_new_block(c); if (start == NULL || end == NULL || cleanup == NULL) return 0; ADDOP_JREL(c, SETUP_LOOP, end); if (!compiler_push_fblock(c, LOOP, start)) return 0; VISIT(c, expr, s->v.For.iter); ADDOP(c, GET_ITER); compiler_use_next_block(c, start); /* XXX(nnorwitz): is there a better way to handle this? for loops are special, we want to be able to trace them each time around, so we need to set an extra line number. */ c->u->u_lineno_set = false; ADDOP_JREL(c, FOR_ITER, cleanup); VISIT(c, expr, s->v.For.target); VISIT_SEQ(c, stmt, s->v.For.body); ADDOP_JABS(c, JUMP_ABSOLUTE, start); compiler_use_next_block(c, cleanup); ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, LOOP, start); VISIT_SEQ(c, stmt, s->v.For.orelse); compiler_use_next_block(c, end); return 1; } static int compiler_while(struct compiler *c, stmt_ty s) { basicblock *loop, *orelse, *end, *anchor = NULL; int constant = expr_constant(s->v.While.test); if (constant == 0) return 1; loop = compiler_new_block(c); end = compiler_new_block(c); if (constant == -1) { anchor = compiler_new_block(c); if (anchor == NULL) return 0; } if (loop == NULL || end == NULL) return 0; if (s->v.While.orelse) { orelse = compiler_new_block(c); if (orelse == NULL) return 0; } else orelse = NULL; ADDOP_JREL(c, SETUP_LOOP, end); compiler_use_next_block(c, loop); if (!compiler_push_fblock(c, LOOP, loop)) return 0; if (constant == -1) { VISIT(c, expr, s->v.While.test); ADDOP_JREL(c, JUMP_IF_FALSE, anchor); ADDOP(c, POP_TOP); } VISIT_SEQ(c, stmt, s->v.While.body); ADDOP_JABS(c, JUMP_ABSOLUTE, loop); /* XXX should the two POP instructions be in a separate block if there is no else clause ? */ if (constant == -1) { compiler_use_next_block(c, anchor); ADDOP(c, POP_TOP); ADDOP(c, POP_BLOCK); } compiler_pop_fblock(c, LOOP, loop); if (orelse != NULL) /* what if orelse is just pass? */ VISIT_SEQ(c, stmt, s->v.While.orelse); compiler_use_next_block(c, end); return 1; } static int compiler_continue(struct compiler *c) { static const char LOOP_ERROR_MSG[] = "'continue' not properly in loop"; static const char IN_FINALLY_ERROR_MSG[] = "'continue' not supported inside 'finally' clause"; int i; if (!c->u->u_nfblocks) return compiler_error(c, LOOP_ERROR_MSG); i = c->u->u_nfblocks - 1; switch (c->u->u_fblock[i].fb_type) { case LOOP: ADDOP_JABS(c, JUMP_ABSOLUTE, c->u->u_fblock[i].fb_block); break; case EXCEPT: case FINALLY_TRY: while (--i >= 0 && c->u->u_fblock[i].fb_type != LOOP) { /* Prevent try: ... finally: try: continue ... or try: ... except: continue */ if (c->u->u_fblock[i].fb_type == FINALLY_END) return compiler_error(c, IN_FINALLY_ERROR_MSG); } if (i == -1) return compiler_error(c, LOOP_ERROR_MSG); ADDOP_JABS(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block); break; case FINALLY_END: return compiler_error(c, IN_FINALLY_ERROR_MSG); } return 1; } /* Code generated for "try: <body> finally: <finalbody>" is as follows: SETUP_FINALLY L <code for body> POP_BLOCK LOAD_CONST <None> L: <code for finalbody> END_FINALLY The special instructions use the block stack. Each block stack entry contains the instruction that created it (here SETUP_FINALLY), the level of the value stack at the time the block stack entry was created, and a label (here L). SETUP_FINALLY: Pushes the current value stack level and the label onto the block stack. POP_BLOCK: Pops en entry from the block stack, and pops the value stack until its level is the same as indicated on the block stack. (The label is ignored.) END_FINALLY: Pops a variable number of entries from the *value* stack and re-raises the exception they specify. The number of entries popped depends on the (pseudo) exception type. The block stack is unwound when an exception is raised: when a SETUP_FINALLY entry is found, the exception is pushed onto the value stack (and the exception condition is cleared), and the interpreter jumps to the label gotten from the block stack. */ static int compiler_try_finally(struct compiler *c, stmt_ty s) { basicblock *body, *end; body = compiler_new_block(c); end = compiler_new_block(c); if (body == NULL || end == NULL) return 0; ADDOP_JREL(c, SETUP_FINALLY, end); compiler_use_next_block(c, body); if (!compiler_push_fblock(c, FINALLY_TRY, body)) return 0; VISIT_SEQ(c, stmt, s->v.TryFinally.body); ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, FINALLY_TRY, body); ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_use_next_block(c, end); if (!compiler_push_fblock(c, FINALLY_END, end)) return 0; VISIT_SEQ(c, stmt, s->v.TryFinally.finalbody); ADDOP(c, END_FINALLY); compiler_pop_fblock(c, FINALLY_END, end); return 1; } /* Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...": (The contents of the value stack is shown in [], with the top at the right; 'tb' is trace-back info, 'val' the exception's associated value, and 'exc' the exception.) Value stack Label Instruction Argument [] SETUP_EXCEPT L1 [] <code for S> [] POP_BLOCK [] JUMP_FORWARD L0 [tb, val, exc] L1: DUP ) [tb, val, exc, exc] <evaluate E1> ) [tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1 [tb, val, exc, 1-or-0] JUMP_IF_FALSE L2 ) [tb, val, exc, 1] POP ) [tb, val, exc] POP [tb, val] <assign to V1> (or POP if no V1) [tb] POP [] <code for S1> JUMP_FORWARD L0 [tb, val, exc, 0] L2: POP [tb, val, exc] DUP .............................etc....................... [tb, val, exc, 0] Ln+1: POP [tb, val, exc] END_FINALLY # re-raise exception [] L0: <next statement> Of course, parts are not generated if Vi or Ei is not present. */ static int compiler_try_except(struct compiler *c, stmt_ty s) { basicblock *body, *orelse, *except, *end; int i, n; body = compiler_new_block(c); except = compiler_new_block(c); orelse = compiler_new_block(c); end = compiler_new_block(c); if (body == NULL || except == NULL || orelse == NULL || end == NULL) return 0; ADDOP_JREL(c, SETUP_EXCEPT, except); compiler_use_next_block(c, body); if (!compiler_push_fblock(c, EXCEPT, body)) return 0; VISIT_SEQ(c, stmt, s->v.TryExcept.body); ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, EXCEPT, body); ADDOP_JREL(c, JUMP_FORWARD, orelse); n = asdl_seq_LEN(s->v.TryExcept.handlers); compiler_use_next_block(c, except); for (i = 0; i < n; i++) { excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( s->v.TryExcept.handlers, i); if (!handler->type && i < n-1) return compiler_error(c, "default 'except:' must be last"); c->u->u_lineno_set = false; c->u->u_lineno = handler->lineno; except = compiler_new_block(c); if (except == NULL) return 0; if (handler->type) { ADDOP(c, DUP_TOP); VISIT(c, expr, handler->type); ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH); ADDOP_JREL(c, JUMP_IF_FALSE, except); ADDOP(c, POP_TOP); } ADDOP(c, POP_TOP); if (handler->name) { VISIT(c, expr, handler->name); } else { ADDOP(c, POP_TOP); } ADDOP(c, POP_TOP); VISIT_SEQ(c, stmt, handler->body); ADDOP_JREL(c, JUMP_FORWARD, end); compiler_use_next_block(c, except); if (handler->type) ADDOP(c, POP_TOP); } ADDOP(c, END_FINALLY); compiler_use_next_block(c, orelse); VISIT_SEQ(c, stmt, s->v.TryExcept.orelse); compiler_use_next_block(c, end); return 1; } static int compiler_import_as(struct compiler *c, identifier name, identifier asname) { /* The IMPORT_NAME opcode was already generated. This function merely needs to bind the result to a name. If there is a dot in name, we need to split it and emit a LOAD_ATTR for each name. */ const char *src = PyString_AS_STRING(name); const char *dot = strchr(src, '.'); if (dot) { /* Consume the base module name to get the first attribute */ src = dot + 1; while (dot) { /* NB src is only defined when dot != NULL */ PyObject *attr; dot = strchr(src, '.');