Merge branch 'master' into dev

This commit is contained in:
Eloïse Brocas 2026-05-26 17:16:54 +02:00
commit 6ad9d4b2cd
No known key found for this signature in database
GPG key ID: E84AA823D9885AD4
4 changed files with 130 additions and 1 deletions

View file

@ -110,6 +110,12 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
bool else_pop = false;
bool need_try = false;
bool variable_annotations = false;
std::vector<PycExceptionTableEntry> exception_entries;
size_t next_exception_entry = 0;
if (mod->verCompare(3, 11) >= 0) {
exception_entries = code->exceptionTableEntries();
}
while (!source.atEof()) {
#if defined(BLOCK_DEBUG) || defined(STACK_DEBUG)
@ -125,6 +131,84 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
fprintf(stderr, "\n");
#endif
while (next_exception_entry < exception_entries.size()
&& exception_entries[next_exception_entry].start_offset < pos) {
next_exception_entry++;
}
if (next_exception_entry < exception_entries.size()) {
const auto& entry = exception_entries[next_exception_entry];
if (entry.start_offset == pos
&& entry.stack_depth == 0
&& !entry.push_lasti) {
if (curblock->blktype() == ASTBlock::BLK_CONTAINER) {
curblock.cast<ASTContainerBlock>()->setExcept(entry.target);
} else {
PycRef<ASTBlock> next = new ASTContainerBlock(0, entry.target);
blocks.push(next.cast<ASTBlock>());
curblock = blocks.top();
}
stack_hist.push(stack);
PycRef<ASTBlock> tryblock = new ASTBlock(ASTBlock::BLK_TRY, entry.target, true);
blocks.push(tryblock.cast<ASTBlock>());
curblock = blocks.top();
next_exception_entry++;
}
}
if (curblock->blktype() == ASTBlock::BLK_TRY
&& curblock->end() == pos
&& blocks.size() > 1) {
PycRef<ASTBlock> prev = curblock;
blocks.pop();
curblock = blocks.top();
if (curblock->blktype() == ASTBlock::BLK_CONTAINER
&& curblock.cast<ASTContainerBlock>()->hasExcept()) {
if (!stack_hist.empty()) {
stack = stack_hist.top();
stack_hist.pop();
}
curblock->append(prev.cast<ASTNode>());
stack_hist.push(stack);
PycRef<ASTBlock> except = new ASTCondBlock(ASTBlock::BLK_EXCEPT, 0, NULL, false);
except->init();
blocks.push(except);
curblock = blocks.top();
} else {
blocks.push(prev);
curblock = prev;
}
}
if (curblock->blktype() == ASTBlock::BLK_EXCEPT
&& curblock->end() == pos
&& blocks.size() > 1) {
PycRef<ASTBlock> prev = curblock;
blocks.pop();
curblock = blocks.top();
if (!stack_hist.empty()) {
stack = stack_hist.top();
stack_hist.pop();
}
if (prev->size() != 0) {
curblock->append(prev.cast<ASTNode>());
}
if (curblock->blktype() == ASTBlock::BLK_CONTAINER
&& !curblock.cast<ASTContainerBlock>()->hasFinally()) {
PycRef<ASTBlock> cont = curblock;
blocks.pop();
curblock = blocks.top();
curblock->append(cont.cast<ASTNode>());
}
}
curpos = pos;
bc_next(source, mod, opcode, operand, pos);
@ -1134,8 +1218,12 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
if (cond.type() == ASTNode::NODE_COMPARE
&& cond.cast<ASTCompare>()->op() == ASTCompare::CMP_EXCEPTION) {
int except_end = offs;
if ((curblock->blktype() == ASTBlock::BLK_EXCEPT && curblock.cast<ASTExceptBlock>()->expr() == NULL)
|| (curblock->blktype() == ASTBlock::BLK_FINALLY && curblock->size() == 0)){
if (mod->verCompare(3,11) >= 0){
except_end = curblock->end();
}
blocks.pop();
curblock = blocks.top();
@ -1176,7 +1264,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
stack_hist.push(stack);
}
ifblk = new ASTExceptBlock(offs, cond.cast<ASTCompare>()->right());
ifblk = new ASTExceptBlock(except_end, cond.cast<ASTCompare>()->right());
} else if (curblock->blktype() == ASTBlock::BLK_ELSE
&& curblock->size() == 0) {
/* Collapse into elif statement */
@ -1812,6 +1900,10 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
case Pyc::RERAISE_A:
case Pyc::POP_BLOCK:
{
if (mod->verCompare(3, 11) >= 0)
{
break;
}
if (mod->verCompare(3, 9) < 0) {
if (opcode == Pyc::POP_EXCEPT) {
break;
@ -1921,6 +2013,19 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
}
}
break;
case Pyc::PUSH_EXC_INFO:
/* Python 3.11+: pushes exception info tuple. We ignore here to keep decompilation going. */
break;
case Pyc::CHECK_EXC_MATCH:
{
/* Python 3.11+: compares exception against handler type. */
PycRef<ASTNode> right = stack.top();
stack.pop();
PycRef<ASTNode> left = stack.top();
stack.pop();
stack.push(new ASTCompare(left, right, ASTCompare::CMP_EXCEPTION));
}
break;
case Pyc::END_FOR:
{
stack.pop();
@ -2166,6 +2271,9 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
curblock = blocks.top();
}
break;
case Pyc::BEFORE_WITH:
/* Python 3.11: setup for with block; ignore. */
break;
case Pyc::WITH_CLEANUP:
case Pyc::WITH_CLEANUP_START:
{

Binary file not shown.

View file

@ -0,0 +1,7 @@
def handle_specific(flag):
try:
if flag:
raise ValueError('boom')
except ValueError:
return 'value'
return 'ok'

View file

@ -0,0 +1,14 @@
def handle_specific ( flag ) : <EOL>
<INDENT>
try : <EOL>
<INDENT>
if flag : <EOL>
<INDENT>
raise ValueError ( 'boom' ) <EOL>
<OUTDENT>
<OUTDENT>
except ValueError : <EOL>
<INDENT>
return 'value' <EOL>
<OUTDENT>
return 'ok' <EOL>