summaryrefslogtreecommitdiff
path: root/Python/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c69
1 files changed, 64 insertions, 5 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 9cce8aeb4e..0336959d3d 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -161,6 +161,11 @@ struct compiler {
int c_optimize; /* optimization level */
int c_interactive; /* true if in interactive mode */
int c_nestlevel;
+ int c_do_not_emit_bytecode; /* The compiler won't emit any bytecode
+ if this value is different from zero.
+ This can be used to temporarily visit
+ nodes without emitting bytecode to
+ check only errors. */
PyObject *c_const_cache; /* Python dict holding all constants,
including names tuple */
@@ -340,6 +345,7 @@ PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags,
c.c_flags = flags;
c.c_optimize = (optimize == -1) ? config->optimization_level : optimize;
c.c_nestlevel = 0;
+ c.c_do_not_emit_bytecode = 0;
if (!_PyAST_Optimize(mod, arena, c.c_optimize)) {
goto finally;
@@ -1152,6 +1158,9 @@ compiler_addop(struct compiler *c, int opcode)
struct instr *i;
int off;
assert(!HAS_ARG(opcode));
+ if (c->c_do_not_emit_bytecode) {
+ return 1;
+ }
off = compiler_next_instr(c, c->u->u_curblock);
if (off < 0)
return 0;
@@ -1305,6 +1314,10 @@ merge_consts_recursive(struct compiler *c, PyObject *o)
static Py_ssize_t
compiler_add_const(struct compiler *c, PyObject *o)
{
+ if (c->c_do_not_emit_bytecode) {
+ return 0;
+ }
+
PyObject *key = merge_consts_recursive(c, o);
if (key == NULL) {
return -1;
@@ -1318,6 +1331,10 @@ compiler_add_const(struct compiler *c, PyObject *o)
static int
compiler_addop_load_const(struct compiler *c, PyObject *o)
{
+ if (c->c_do_not_emit_bytecode) {
+ return 1;
+ }
+
Py_ssize_t arg = compiler_add_const(c, o);
if (arg < 0)
return 0;
@@ -1328,6 +1345,10 @@ static int
compiler_addop_o(struct compiler *c, int opcode, PyObject *dict,
PyObject *o)
{
+ if (c->c_do_not_emit_bytecode) {
+ return 1;
+ }
+
Py_ssize_t arg = compiler_add_o(c, dict, o);
if (arg < 0)
return 0;
@@ -1339,6 +1360,11 @@ compiler_addop_name(struct compiler *c, int opcode, PyObject *dict,
PyObject *o)
{
Py_ssize_t arg;
+
+ if (c->c_do_not_emit_bytecode) {
+ return 1;
+ }
+
PyObject *mangled = _Py_Mangle(c->u->u_private, o);
if (!mangled)
return 0;
@@ -1359,6 +1385,10 @@ compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg)
struct instr *i;
int off;
+ if (c->c_do_not_emit_bytecode) {
+ return 1;
+ }
+
/* oparg value is unsigned, but a signed C int is usually used to store
it in the C code (like Python/ceval.c).
@@ -1385,6 +1415,10 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
struct instr *i;
int off;
+ if (c->c_do_not_emit_bytecode) {
+ return 1;
+ }
+
assert(HAS_ARG(opcode));
assert(b != NULL);
off = compiler_next_instr(c, c->u->u_curblock);
@@ -1519,6 +1553,17 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
} \
}
+/* These macros allows to check only for errors and not emmit bytecode
+ * while visiting nodes.
+*/
+
+#define BEGIN_DO_NOT_EMIT_BYTECODE { \
+ c->c_do_not_emit_bytecode++;
+
+#define END_DO_NOT_EMIT_BYTECODE \
+ c->c_do_not_emit_bytecode--; \
+}
+
/* Search if variable annotations are present statically in a block. */
static int
@@ -2546,13 +2591,23 @@ compiler_if(struct compiler *c, stmt_ty s)
return 0;
constant = expr_constant(s->v.If.test);
- /* constant = 0: "if 0" Leave the optimizations to
- * the pephole optimizer to check for syntax errors
- * in the block.
+ /* constant = 0: "if 0"
* constant = 1: "if 1", "if 2", ...
* constant = -1: rest */
- if (constant == 1) {
+ if (constant == 0) {
+ BEGIN_DO_NOT_EMIT_BYTECODE
+ VISIT_SEQ(c, stmt, s->v.If.body);
+ END_DO_NOT_EMIT_BYTECODE
+ 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);
+ if (s->v.If.orelse) {
+ BEGIN_DO_NOT_EMIT_BYTECODE
+ VISIT_SEQ(c, stmt, s->v.If.orelse);
+ END_DO_NOT_EMIT_BYTECODE
+ }
} else {
if (asdl_seq_LEN(s->v.If.orelse)) {
next = compiler_new_block(c);
@@ -2662,8 +2717,12 @@ compiler_while(struct compiler *c, stmt_ty s)
int constant = expr_constant(s->v.While.test);
if (constant == 0) {
- if (s->v.While.orelse)
+ BEGIN_DO_NOT_EMIT_BYTECODE
+ VISIT_SEQ(c, stmt, s->v.While.body);
+ END_DO_NOT_EMIT_BYTECODE
+ if (s->v.While.orelse) {
VISIT_SEQ(c, stmt, s->v.While.orelse);
+ }
return 1;
}
loop = compiler_new_block(c);