From 882571c599751b7e79da2f5ec9ede75a90714d78 Mon Sep 17 00:00:00 2001 From: Adrian Haensler Date: Fri, 8 Jul 2022 15:44:46 -0500 Subject: [PATCH 1/4] some fixes for 3.9 --- ASTree.cpp | 106 +++++++++++++++++++++++++++++++++++-------------- CMakeLists.txt | 1 + bytecode.cpp | 3 +- 3 files changed, 80 insertions(+), 30 deletions(-) diff --git a/ASTree.cpp b/ASTree.cpp index 62bb4eb..63b1f90 100644 --- a/ASTree.cpp +++ b/ASTree.cpp @@ -54,7 +54,11 @@ static void CheckIfExpr(FastStack& stack, PycRef curblock) if (curblock->nodes().size() < 2) return; auto rit = curblock->nodes().crbegin(); - ++rit; // the last is "else" block, the one before should be "if" (could be "for", ...) + // the last is "else" block, the one before should be "if" (could be "for", ...) + if ((*rit)->type() != ASTNode::NODE_BLOCK || + (*rit).cast()->blktype() != ASTBlock::BLK_ELSE) + return; + ++rit; if ((*rit)->type() != ASTNode::NODE_BLOCK || (*rit).cast()->blktype() != ASTBlock::BLK_IF) return; @@ -87,11 +91,18 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) bool need_try = false; bool variable_annotations = false; +#define STACK_DEBUG +#define BLOCK_DEBUG while (!source.atEof()) { + curpos = pos; + bc_next(source, mod, opcode, operand, pos); + #if defined(BLOCK_DEBUG) || defined(STACK_DEBUG) fprintf(stderr, "%-7d", pos); #ifdef STACK_DEBUG fprintf(stderr, "%-5d", (unsigned int)stack_hist.size() + 1); + fprintf(stderr, "%-5d", (unsigned int)defblock->nodes().size()); + fprintf(stderr, "%-24s", Pyc::OpcodeName(opcode)); #endif #ifdef BLOCK_DEBUG for (unsigned int i = 0; i < blocks.size(); i++) @@ -101,9 +112,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) fprintf(stderr, "\n"); #endif - curpos = pos; - bc_next(source, mod, opcode, operand, pos); - if (need_try && opcode != Pyc::SETUP_EXCEPT_A) { need_try = false; @@ -120,9 +128,10 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) && opcode != Pyc::JUMP_IF_TRUE_A && opcode != Pyc::JUMP_IF_TRUE_OR_POP_A && opcode != Pyc::POP_JUMP_IF_TRUE_A - && opcode != Pyc::POP_BLOCK) { + && opcode != Pyc::POP_BLOCK + && opcode != Pyc::JUMP_IF_NOT_EXC_MATCH_A + ) { else_pop = false; - PycRef prev = curblock; while (prev->end() < pos && prev->blktype() != ASTBlock::BLK_MAIN) { @@ -149,6 +158,13 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) CheckIfExpr(stack, curblock); } + } else if (curblock->blktype() == ASTBlock::BLK_WITH + && curblock->end() == pos) { + /* end with blocks */ + PycRef with = curblock; + blocks.pop(); + curblock = blocks.top(); + curblock->append(with.cast()); } switch (opcode) { @@ -902,6 +918,11 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) break; case Pyc::FOR_ITER_A: { + int offs = operand; + if (mod->verCompare(3, 10) >= 0) + offs *= sizeof(uint16_t); // // BPO-27129 + offs += pos; + PycRef iter = stack.top(); // Iterable stack.pop(); /* Pop it? Don't pop it? */ @@ -913,7 +934,7 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) } else { comprehension = true; } - PycRef forblk = new ASTIterBlock(ASTBlock::BLK_FOR, top->end(), iter); + PycRef forblk = new ASTIterBlock(ASTBlock::BLK_FOR, offs, iter); forblk->setComprehension(comprehension); blocks.push(forblk.cast()); curblock = blocks.top(); @@ -1169,6 +1190,7 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) case Pyc::JUMP_IF_TRUE_OR_POP_A: case Pyc::POP_JUMP_IF_FALSE_A: case Pyc::POP_JUMP_IF_TRUE_A: + case Pyc::JUMP_IF_NOT_EXC_MATCH_A: { PycRef cond = stack.top(); PycRef ifblk; @@ -1179,6 +1201,10 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) /* Pop condition before the jump */ stack.pop(); popped = ASTCondBlock::PRE_POPPED; + } else if (opcode == Pyc::JUMP_IF_NOT_EXC_MATCH_A) { + stack.pop(); + stack.pop(); + popped = ASTCondBlock::PRE_POPPED; } /* Store the current stack for the else statement(s) */ @@ -1200,7 +1226,8 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) if (mod->verCompare(3, 10) >= 0) offs *= sizeof(uint16_t); // // BPO-27129 if (opcode == Pyc::JUMP_IF_FALSE_A - || opcode == Pyc::JUMP_IF_TRUE_A) { + || opcode == Pyc::JUMP_IF_TRUE_A + || opcode == Pyc::JUMP_IF_NOT_EXC_MATCH_A) { /* Offset is relative in these cases */ offs = pos + operand; } @@ -1214,7 +1241,17 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) stack_hist.pop(); } + ifblk = new ASTCondBlock(ASTBlock::BLK_EXCEPT, offs, cond.cast()->right(), false); + } else if (opcode == Pyc::JUMP_IF_NOT_EXC_MATCH_A) { + if ((curblock->blktype() == ASTBlock::BLK_EXCEPT) || (curblock->blktype() == ASTBlock::BLK_TRY)) { + /* End of previous block */ + PycRef prev = curblock; + blocks.pop(); + curblock = blocks.top(); + curblock->append(prev.cast()); + } + ifblk = new ASTCondBlock(ASTBlock::BLK_EXCEPT, offs, cond, false); } else if (curblock->blktype() == ASTBlock::BLK_ELSE && curblock->size() == 0) { /* Collapse into elif statement */ @@ -1286,18 +1323,29 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) offs *= sizeof(uint16_t); // // BPO-27129 if (offs < pos) { - if (curblock->blktype() == ASTBlock::BLK_FOR - && curblock.cast()->isComprehension()) { - PycRef top = stack.top(); + if (curblock->blktype() == ASTBlock::BLK_FOR) { + if (mod->majorVer() == 3 && mod->minorVer() >= 8) { + // in v3.8, SETUP_LOOP is deprecated and list comprehensions don't use BLK_FOR + // the following code fixes for loops, list comprehensions need more work + if (curblock->end() == pos) { + PycRef tmp = curblock; + blocks.pop(); + curblock = blocks.top(); + curblock->append(tmp.cast()); + } + } else if (curblock.cast()->isComprehension()) { + PycRef top = stack.top(); - if (top.type() == ASTNode::NODE_COMPREHENSION) { - PycRef comp = top.cast(); + if (top.type() == ASTNode::NODE_COMPREHENSION) { + PycRef comp = top.cast(); - comp->addGenerator(curblock.cast()); + comp->addGenerator(curblock.cast()); + } + + PycRef tmp = curblock; + blocks.pop(); + curblock = blocks.top(); } - - blocks.pop(); - curblock = blocks.top(); } else if (curblock->blktype() == ASTBlock::BLK_ELSE) { stack = stack_hist.top(); stack_hist.pop(); @@ -1733,6 +1781,7 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) break; case Pyc::POP_TOP: { + fprintf(stderr, "g1 %s (%d)\n", curblock->type_str(), curblock->end()); PycRef value = stack.top(); stack.pop(); if (!curblock->inited()) { @@ -1760,6 +1809,7 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) stack.push(new ASTComprehension(res)); } } + fprintf(stderr, "g2 %s (%d)\n", curblock->type_str(), curblock->end()); } break; case Pyc::PRINT_ITEM: @@ -1819,9 +1869,17 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) } break; case Pyc::RAISE_VARARGS_A: + case Pyc::RERAISE: + case Pyc::RERAISE_A: { ASTRaise::param_t paramList; - for (int i = 0; i < operand; i++) { + int argument_count; + if (opcode == Pyc::RAISE_VARARGS_A) { + argument_count = operand; + } else { + argument_count = 0; // TODO: should have one argument, maybe support syntax like "except Exception as e:" + } + for (int i = 0; i < argument_count; i++) { paramList.push_front(stack.top()); stack.pop(); } @@ -1925,6 +1983,7 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) } break; case Pyc::WITH_CLEANUP: + case Pyc::WITH_EXCEPT_START: { // Stack top should be a None. Ignore it. PycRef none = stack.top(); @@ -1934,17 +1993,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) fprintf(stderr, "Something TERRIBLE happened!\n"); break; } - - if (curblock->blktype() == ASTBlock::BLK_WITH - && curblock->end() == curpos) { - PycRef with = curblock; - blocks.pop(); - curblock = blocks.top(); - curblock->append(with.cast()); - } - else { - fprintf(stderr, "Something TERRIBLE happened! No matching with block found for WITH_CLEANUP at %d\n", curpos); - } } break; case Pyc::SETUP_EXCEPT_A: diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a3b979..f9a1b5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.1) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_BUILD_TYPE Debug) # Debug options. option(ENABLE_BLOCK_DEBUG "Enable block debugging" OFF) diff --git a/bytecode.cpp b/bytecode.cpp index 12ed098..eba8e0b 100644 --- a/bytecode.cpp +++ b/bytecode.cpp @@ -140,7 +140,8 @@ bool Pyc::IsCellArg(int opcode) bool Pyc::IsJumpArg(int opcode) { return (opcode == Pyc::POP_JUMP_IF_FALSE_A) || (opcode == Pyc::POP_JUMP_IF_TRUE_A) || - (opcode == Pyc::JUMP_IF_FALSE_OR_POP_A) || (opcode == JUMP_IF_TRUE_OR_POP_A); + (opcode == Pyc::JUMP_IF_FALSE_OR_POP_A) || (opcode == JUMP_IF_TRUE_OR_POP_A) || + (opcode == Pyc::JUMP_ABSOLUTE_A) || (opcode == Pyc::JUMP_IF_NOT_EXC_MATCH_A); } bool Pyc::IsJumpOffsetArg(int opcode) From 462260991ef01b4e760bbc3c9e9f2d8319afec57 Mon Sep 17 00:00:00 2001 From: Adrian Haensler Date: Fri, 8 Jul 2022 17:53:39 -0500 Subject: [PATCH 2/4] fix for loops in 3.8 --- ASTNode.h | 6 ++- ASTree.cpp | 116 +++++++++++++++++++++---------------------------- CMakeLists.txt | 1 - 3 files changed, 53 insertions(+), 70 deletions(-) diff --git a/ASTNode.h b/ASTNode.h index 3331467..e1a05bc 100644 --- a/ASTNode.h +++ b/ASTNode.h @@ -550,13 +550,14 @@ private: class ASTIterBlock : public ASTBlock { public: - ASTIterBlock(ASTBlock::BlkType blktype, int end, PycRef iter) - : ASTBlock(blktype, end), m_iter(std::move(iter)), m_idx(), m_comp() { } + ASTIterBlock(ASTBlock::BlkType blktype, int start, int end, PycRef iter) + : ASTBlock(blktype, end), m_iter(std::move(iter)), m_idx(), m_comp(), m_start(start) { } PycRef iter() const { return m_iter; } PycRef index() const { return m_idx; } PycRef condition() const { return m_cond; } bool isComprehension() const { return m_comp; } + int start() const { return m_start; } void setIndex(PycRef idx) { m_idx = std::move(idx); init(); } void setCondition(PycRef cond) { m_cond = std::move(cond); } @@ -567,6 +568,7 @@ private: PycRef m_idx; PycRef m_cond; bool m_comp; + int m_start; }; class ASTContainerBlock : public ASTBlock { diff --git a/ASTree.cpp b/ASTree.cpp index 63b1f90..b11c1da 100644 --- a/ASTree.cpp +++ b/ASTree.cpp @@ -91,18 +91,11 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) bool need_try = false; bool variable_annotations = false; -#define STACK_DEBUG -#define BLOCK_DEBUG while (!source.atEof()) { - curpos = pos; - bc_next(source, mod, opcode, operand, pos); - #if defined(BLOCK_DEBUG) || defined(STACK_DEBUG) fprintf(stderr, "%-7d", pos); #ifdef STACK_DEBUG fprintf(stderr, "%-5d", (unsigned int)stack_hist.size() + 1); - fprintf(stderr, "%-5d", (unsigned int)defblock->nodes().size()); - fprintf(stderr, "%-24s", Pyc::OpcodeName(opcode)); #endif #ifdef BLOCK_DEBUG for (unsigned int i = 0; i < blocks.size(); i++) @@ -112,6 +105,9 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) fprintf(stderr, "\n"); #endif + curpos = pos; + bc_next(source, mod, opcode, operand, pos); + if (need_try && opcode != Pyc::SETUP_EXCEPT_A) { need_try = false; @@ -128,10 +124,9 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) && opcode != Pyc::JUMP_IF_TRUE_A && opcode != Pyc::JUMP_IF_TRUE_OR_POP_A && opcode != Pyc::POP_JUMP_IF_TRUE_A - && opcode != Pyc::POP_BLOCK - && opcode != Pyc::JUMP_IF_NOT_EXC_MATCH_A - ) { + && opcode != Pyc::POP_BLOCK) { else_pop = false; + PycRef prev = curblock; while (prev->end() < pos && prev->blktype() != ASTBlock::BLK_MAIN) { @@ -158,13 +153,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) CheckIfExpr(stack, curblock); } - } else if (curblock->blktype() == ASTBlock::BLK_WITH - && curblock->end() == pos) { - /* end with blocks */ - PycRef with = curblock; - blocks.pop(); - curblock = blocks.top(); - curblock->append(with.cast()); } switch (opcode) { @@ -918,23 +906,33 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) break; case Pyc::FOR_ITER_A: { - int offs = operand; - if (mod->verCompare(3, 10) >= 0) - offs *= sizeof(uint16_t); // // BPO-27129 - offs += pos; - PycRef iter = stack.top(); // Iterable stack.pop(); /* Pop it? Don't pop it? */ + int end; bool comprehension = false; - PycRef top = blocks.top(); - if (top->blktype() == ASTBlock::BLK_WHILE) { - blocks.pop(); + + // before 3.8, there is a SETUP_LOOP instruction with block start and end position, + // the operand is usually a jump to a POP_BLOCK instruction + // after 3.8, block extent has to be inferred implicitly; the operand is a jump to a position after the for block + if (mod->majorVer() == 3 && mod->minorVer() >= 8) { + end = operand; + if (mod->verCompare(3, 10) >= 0) + end *= sizeof(uint16_t); // // BPO-27129 + end += pos; + comprehension = strcmp(code->name()->value(), "") == 0; } else { - comprehension = true; + PycRef top = blocks.top(); + end = top->end(); // block end position from SETUP_LOOP + if (top->blktype() == ASTBlock::BLK_WHILE) { + blocks.pop(); + } else { + comprehension = true; + } } - PycRef forblk = new ASTIterBlock(ASTBlock::BLK_FOR, offs, iter); + + PycRef forblk = new ASTIterBlock(ASTBlock::BLK_FOR, curpos, end, iter); forblk->setComprehension(comprehension); blocks.push(forblk.cast()); curblock = blocks.top(); @@ -956,7 +954,7 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) } else { comprehension = true; } - PycRef forblk = new ASTIterBlock(ASTBlock::BLK_FOR, top->end(), iter); + PycRef forblk = new ASTIterBlock(ASTBlock::BLK_FOR, curpos, top->end(), iter); forblk->setComprehension(comprehension); blocks.push(forblk.cast()); curblock = blocks.top(); @@ -978,7 +976,7 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) PycRef top = blocks.top(); if (top->blktype() == ASTBlock::BLK_WHILE) { blocks.pop(); - PycRef forblk = new ASTIterBlock(ASTBlock::BLK_ASYNCFOR, top->end(), iter); + PycRef forblk = new ASTIterBlock(ASTBlock::BLK_ASYNCFOR, curpos, top->end(), iter); blocks.push(forblk.cast()); curblock = blocks.top(); stack.push(nullptr); @@ -1190,7 +1188,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) case Pyc::JUMP_IF_TRUE_OR_POP_A: case Pyc::POP_JUMP_IF_FALSE_A: case Pyc::POP_JUMP_IF_TRUE_A: - case Pyc::JUMP_IF_NOT_EXC_MATCH_A: { PycRef cond = stack.top(); PycRef ifblk; @@ -1201,10 +1198,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) /* Pop condition before the jump */ stack.pop(); popped = ASTCondBlock::PRE_POPPED; - } else if (opcode == Pyc::JUMP_IF_NOT_EXC_MATCH_A) { - stack.pop(); - stack.pop(); - popped = ASTCondBlock::PRE_POPPED; } /* Store the current stack for the else statement(s) */ @@ -1226,8 +1219,7 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) if (mod->verCompare(3, 10) >= 0) offs *= sizeof(uint16_t); // // BPO-27129 if (opcode == Pyc::JUMP_IF_FALSE_A - || opcode == Pyc::JUMP_IF_TRUE_A - || opcode == Pyc::JUMP_IF_NOT_EXC_MATCH_A) { + || opcode == Pyc::JUMP_IF_TRUE_A) { /* Offset is relative in these cases */ offs = pos + operand; } @@ -1243,15 +1235,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) } ifblk = new ASTCondBlock(ASTBlock::BLK_EXCEPT, offs, cond.cast()->right(), false); - } else if (opcode == Pyc::JUMP_IF_NOT_EXC_MATCH_A) { - if ((curblock->blktype() == ASTBlock::BLK_EXCEPT) || (curblock->blktype() == ASTBlock::BLK_TRY)) { - /* End of previous block */ - PycRef prev = curblock; - blocks.pop(); - curblock = blocks.top(); - curblock->append(prev.cast()); - } - ifblk = new ASTCondBlock(ASTBlock::BLK_EXCEPT, offs, cond, false); } else if (curblock->blktype() == ASTBlock::BLK_ELSE && curblock->size() == 0) { /* Collapse into elif statement */ @@ -1324,16 +1307,12 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) if (offs < pos) { if (curblock->blktype() == ASTBlock::BLK_FOR) { - if (mod->majorVer() == 3 && mod->minorVer() >= 8) { - // in v3.8, SETUP_LOOP is deprecated and list comprehensions don't use BLK_FOR - // the following code fixes for loops, list comprehensions need more work - if (curblock->end() == pos) { - PycRef tmp = curblock; - blocks.pop(); - curblock = blocks.top(); - curblock->append(tmp.cast()); - } - } else if (curblock.cast()->isComprehension()) { + bool is_jump_to_start = offs == curblock.cast()->start(); + bool should_pop_for_block = curblock.cast()->isComprehension(); + // in v3.8, SETUP_LOOP is deprecated and for blocks aren't terminated by POP_BLOCK, so we add them here + bool should_add_for_block = mod->majorVer() == 3 && mod->minorVer() >= 8 && is_jump_to_start && !curblock.cast()->isComprehension(); + + if (should_pop_for_block || should_add_for_block) { PycRef top = stack.top(); if (top.type() == ASTNode::NODE_COMPREHENSION) { @@ -1345,6 +1324,9 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) PycRef tmp = curblock; blocks.pop(); curblock = blocks.top(); + if (should_add_for_block) { + curblock->append(tmp.cast()); + } } } else if (curblock->blktype() == ASTBlock::BLK_ELSE) { stack = stack_hist.top(); @@ -1781,7 +1763,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) break; case Pyc::POP_TOP: { - fprintf(stderr, "g1 %s (%d)\n", curblock->type_str(), curblock->end()); PycRef value = stack.top(); stack.pop(); if (!curblock->inited()) { @@ -1809,7 +1790,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) stack.push(new ASTComprehension(res)); } } - fprintf(stderr, "g2 %s (%d)\n", curblock->type_str(), curblock->end()); } break; case Pyc::PRINT_ITEM: @@ -1869,17 +1849,9 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) } break; case Pyc::RAISE_VARARGS_A: - case Pyc::RERAISE: - case Pyc::RERAISE_A: { ASTRaise::param_t paramList; - int argument_count; - if (opcode == Pyc::RAISE_VARARGS_A) { - argument_count = operand; - } else { - argument_count = 0; // TODO: should have one argument, maybe support syntax like "except Exception as e:" - } - for (int i = 0; i < argument_count; i++) { + for (int i = 0; i < operand; i++) { paramList.push_front(stack.top()); stack.pop(); } @@ -1983,7 +1955,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) } break; case Pyc::WITH_CLEANUP: - case Pyc::WITH_EXCEPT_START: { // Stack top should be a None. Ignore it. PycRef none = stack.top(); @@ -1993,6 +1964,17 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) fprintf(stderr, "Something TERRIBLE happened!\n"); break; } + + if (curblock->blktype() == ASTBlock::BLK_WITH + && curblock->end() == curpos) { + PycRef with = curblock; + blocks.pop(); + curblock = blocks.top(); + curblock->append(with.cast()); + } + else { + fprintf(stderr, "Something TERRIBLE happened! No matching with block found for WITH_CLEANUP at %d\n", curpos); + } } break; case Pyc::SETUP_EXCEPT_A: diff --git a/CMakeLists.txt b/CMakeLists.txt index f9a1b5b..7a3b979 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.1) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_BUILD_TYPE Debug) # Debug options. option(ENABLE_BLOCK_DEBUG "Enable block debugging" OFF) From deebbb044d02876b924deb689b7b0b7c3f889ede Mon Sep 17 00:00:00 2001 From: Adrian Haensler Date: Sat, 30 Jul 2022 00:02:47 -0500 Subject: [PATCH 3/4] add a test --- tests/compiled/test_for_loop_py3.8.3.10.pyc | Bin 0 -> 611 bytes tests/input/test_for_loop_py3.8.py | 19 +++++++++++++++++++ tests/tokenized/test_for_loop_py3.8.txt | 13 +++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 tests/compiled/test_for_loop_py3.8.3.10.pyc create mode 100644 tests/input/test_for_loop_py3.8.py create mode 100644 tests/tokenized/test_for_loop_py3.8.txt diff --git a/tests/compiled/test_for_loop_py3.8.3.10.pyc b/tests/compiled/test_for_loop_py3.8.3.10.pyc new file mode 100644 index 0000000000000000000000000000000000000000..473b3f804459f30aae4be9377886b3670410dc56 GIT binary patch literal 611 zcmY*W&2H2%5VrTHtSqh66I|!W9+E(j03n1pR7hMeKKF zJjz};z=c=ffEe#~`LQ)4fAjl|2bW91=$wA}UVP<@eT(4VGbQkv#6Kma*qSM>_~pb2 z&DG?V^8LtdfF4WiATq|Z}3LXv>T-jy1n zTf9M+M7M`pe$r6ZvfF3{O$T-iHFglw;G*7#gX|QXy%!Jb5UhWZWt%3{eUX;fX4g($ zWp*r8nc3c$?Bv;_6-cG1U8}+O)}jlkcpE?(k5DyN+Jgk^urRuXfhs{qlw$WP*>xiB zP#7#PeJaF7-S`7_dRgfLU= QYQ`4J1&>$o*{>P@4FbBkYybcN literal 0 HcmV?d00001 diff --git a/tests/input/test_for_loop_py3.8.py b/tests/input/test_for_loop_py3.8.py new file mode 100644 index 0000000..bad3ee7 --- /dev/null +++ b/tests/input/test_for_loop_py3.8.py @@ -0,0 +1,19 @@ +""" +test_for_loop_3.8.py -- source test +For-loops have changed in python 3.8. The test and PR +(https://github.com/zrax/pycdc/pull/270) add some support. +It also fixes a problem with nested if- and for blocks. + +This source is part of the decompyle test suite. + +decompyle is a Python byte-code decompiler +See http://www.goebel-consult.de/decompyle/ for download and +for further information +""" + +if 1 == 1: + print('block1') +if 1 == 1: + for a in 'foo': + print('block2') +return None diff --git a/tests/tokenized/test_for_loop_py3.8.txt b/tests/tokenized/test_for_loop_py3.8.txt new file mode 100644 index 0000000..0fd636a --- /dev/null +++ b/tests/tokenized/test_for_loop_py3.8.txt @@ -0,0 +1,13 @@ +'\ntest_for_loop_3.8.py -- source test\nFor-loops have changed in python 3.8. The test and PR\n(https://github.com/zrax/pycdc/pull/270) add some support.\nIt also fixes a problem with nested if- and for blocks.\n\nThis source is part of the decompyle test suite.\n\ndecompyle is a Python byte-code decompiler\nSee http://www.goebel-consult.de/decompyle/ for download and\nfor further information\n' +if 1 == 1 : + +print ( 'block1' ) + +if 1 == 1 : + +for a in 'foo' : + +print ( 'block2' ) + + +return None From 5758634f813455dcf17f7e5b46f281c1a89e5c1c Mon Sep 17 00:00:00 2001 From: Adrian Haensler Date: Sat, 30 Jul 2022 00:07:38 -0500 Subject: [PATCH 4/4] support three digit versions in tests --- tests/decompyle_test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/decompyle_test.sh b/tests/decompyle_test.sh index 2be87f9..09feb13 100755 --- a/tests/decompyle_test.sh +++ b/tests/decompyle_test.sh @@ -19,8 +19,8 @@ if [[ -z "$outdir" ]]; then fi shopt -s nullglob -compfiles=( "$testdir/compiled/$testname".?.?.pyc ) -xfcfiles=( "$testdir/xfail/$testname".?.?.pyc ) +compfiles=( "$testdir/compiled/$testname".?.?*.pyc ) +xfcfiles=( "$testdir/xfail/$testname".?.?*.pyc ) shopt -u nullglob if (( ${#compfiles[@]} + ${#xfcfiles[@]} == 0 )); then