Skip to content

Commit

Permalink
Added support for LOAD_CLASSDEREF
Browse files Browse the repository at this point in the history
The opcode itself is exactly the same as `LOAD_DEREF`
1) The problem is when the class is a closure (e.g. defined inside a function body) then there is a `BUILD_TUPLE` after the `LOAD_BUILD_CLASS` which makes problems.
2) There is another problem which makes the `code->name()` of the class to be part of the function locals. (e.g. `func.<locals>.my_class` instead of `my_class`) which makes the check `srcString->isEqual(code->name().cast<PycObject>())` be invalid.
  • Loading branch information
TiZCrocodile committed Feb 26, 2024
1 parent 0a50980 commit 00d4b02
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 2 deletions.
10 changes: 8 additions & 2 deletions ASTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,12 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
break;
case Pyc::BUILD_TUPLE_A:
{
// if class is a closure code, ignore this tuple
PycRef<ASTNode> tos = stack.top();
if (tos->type() == ASTNode::NODE_LOADBUILDCLASS) {
break;
}

ASTTuple::value_t values;
values.resize(operand);
for (int i=0; i<operand; i++) {
Expand Down Expand Up @@ -1501,6 +1507,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
}
break;
case Pyc::LOAD_DEREF_A:
case Pyc::LOAD_CLASSDEREF_A:
stack.push(new ASTName(code->getCellVar(mod, operand)));
break;
case Pyc::LOAD_FAST_A:
Expand Down Expand Up @@ -3358,8 +3365,7 @@ void decompyle(PycRef<PycCode> code, PycModule* mod, std::ostream& pyc_output)
PycRef<ASTObject> src = store->src().cast<ASTObject>();
PycRef<PycString> srcString = src->object().try_cast<PycString>();
PycRef<ASTName> dest = store->dest().cast<ASTName>();
if (srcString != nullptr && srcString->isEqual(code->name().cast<PycObject>())
&& dest->name()->isEqual("__qualname__")) {
if (dest->name()->isEqual("__qualname__")) {
// __qualname__ = '<Class Name>'
// Automatically added by Python 3.3 and later
clean->removeFirst();
Expand Down
Binary file added tests/compiled/load_classderef.3.4.pyc
Binary file not shown.
4 changes: 4 additions & 0 deletions tests/input/load_classderef.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def func():
x = 1
class my_class:
y = x
6 changes: 6 additions & 0 deletions tests/tokenized/load_classderef.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
def func ( ) : <EOL>
<INDENT>
x = 1 <EOL>
class my_class : <EOL>
<INDENT>
y = x <EOL>

0 comments on commit 00d4b02

Please sign in to comment.