Skip to content

Commit

Permalink
Merge branch 'zrax:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
merdw authored Jun 11, 2024
2 parents 8381017 + 513e03c commit 7500547
Show file tree
Hide file tree
Showing 15 changed files with 74 additions and 16 deletions.
2 changes: 1 addition & 1 deletion ASTNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void ASTNodeList::removeLast()

void ASTNodeList::removeFirst()
{
m_nodes.erase(m_nodes.cbegin());
m_nodes.erase(m_nodes.begin());
}


Expand Down
50 changes: 38 additions & 12 deletions ASTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ static bool printClassDocstring = true;
// shortcut for all top/pop calls
static PycRef<ASTNode> StackPopTop(FastStack& stack)
{
const auto node{ stack.top() };
const auto node(stack.top());
stack.pop();
return node;
}
Expand Down 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 @@ -1475,6 +1481,17 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
PycRef<ASTNode> name = stack.top();
if (name.type() != ASTNode::NODE_IMPORT) {
stack.pop();

if (mod->verCompare(3, 12) >= 0) {
if (operand & 1) {
/* Changed in version 3.12:
If the low bit of namei is set, then a NULL or self is pushed to the stack
before the attribute or unbound method respectively. */
stack.push(nullptr);
}
operand >>= 1;
}

stack.push(new ASTBinary(name, new ASTName(code->getName(operand)), ASTBinary::BIN_ATTR));
}
}
Expand Down Expand Up @@ -1509,6 +1526,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
stack.push(new ASTName(code->getCellVar(mod, operand)));
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 All @@ -1519,19 +1537,14 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
break;
case Pyc::LOAD_GLOBAL_A:
if (mod->verCompare(3, 11) >= 0) {
// Loads the global named co_names[namei>>1] onto the stack.
if (operand & 1) {
/* Changed in version 3.11:
If the low bit of "NAMEI" (operand) is set,
then a NULL is pushed to the stack before the global variable. */
stack.push(nullptr);
/*
and thats because for some reason for example 3 global functions: input, int, print.
it tries to load: 1, 3, 5
all though we have only 3 names, so thats should be: (1-1)/2 = 0, (3-1)/2 = 1, (5-1)/2 = 2
i dont know why, maybe because of the null push, but thats a FIX for now.
*/
operand = (int)((operand - 1) / 2);
}
operand >>= 1;
}
stack.push(new ASTName(code->getName(operand)));
break;
Expand Down Expand Up @@ -1886,6 +1899,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
}
break;
case Pyc::WITH_CLEANUP:
case Pyc::WITH_CLEANUP_START:
{
// Stack top should be a None. Ignore it.
PycRef<ASTNode> none = stack.top();
Expand All @@ -1908,6 +1922,9 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
}
}
break;
case Pyc::WITH_CLEANUP_FINISH:
/* Ignore this */
break;
case Pyc::SETUP_EXCEPT_A:
{
if (curblock->blktype() == ASTBlock::BLK_CONTAINER) {
Expand Down Expand Up @@ -2512,8 +2529,18 @@ static int cmp_prec(PycRef<ASTNode> parent, PycRef<ASTNode> child)
return 1; // Always parenthesize not(x)
if (child.type() == ASTNode::NODE_BINARY) {
PycRef<ASTBinary> binChild = child.cast<ASTBinary>();
if (parent.type() == ASTNode::NODE_BINARY)
return binChild->op() - parent.cast<ASTBinary>()->op();
if (parent.type() == ASTNode::NODE_BINARY) {
PycRef<ASTBinary> binParent = parent.cast<ASTBinary>();
if (binParent->right() == child) {
if (binParent->op() == ASTBinary::BIN_SUBTRACT &&
binChild->op() == ASTBinary::BIN_ADD)
return 1;
else if (binParent->op() == ASTBinary::BIN_DIVIDE &&
binChild->op() == ASTBinary::BIN_MULTIPLY)
return 1;
}
return binChild->op() - binParent->op();
}
else if (parent.type() == ASTNode::NODE_COMPARE)
return (binChild->op() == ASTBinary::BIN_LOG_AND ||
binChild->op() == ASTBinary::BIN_LOG_OR) ? 1 : -1;
Expand Down Expand Up @@ -3356,8 +3383,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
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if (ENABLE_STACK_DEBUG)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wshadow -Werror ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-error=shadow -Werror ${CMAKE_CXX_FLAGS}")
elseif(MSVC)
set(CMAKE_CXX_FLAGS "/WX ${CMAKE_CXX_FLAGS}")
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
Expand Down
5 changes: 4 additions & 1 deletion bytecode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,10 @@ void bc_disasm(std::ostream& pyc_output, PycRef<PycCode> code, PycModule* mod,
case Pyc::LOAD_METHOD_A:
case Pyc::LOAD_FROM_DICT_OR_GLOBALS_A:
try {
formatted_print(pyc_output, "%d: %s", operand, code->getName(operand)->value());
auto arg = operand;
if (opcode == Pyc::LOAD_ATTR_A && mod->verCompare(3, 12) >= 0)
arg >>= 1;
formatted_print(pyc_output, "%d: %s", operand, code->getName(arg)->value());
} catch (const std::out_of_range &) {
formatted_print(pyc_output, "%d <INVALID>", operand);
}
Expand Down
2 changes: 1 addition & 1 deletion pyc_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class PycRef {
obj.m_obj = nullptr;
}

~PycRef<_Obj>()
~PycRef()
{
if (m_obj)
m_obj->delRef();
Expand Down
Binary file added tests/compiled/load_classderef.3.4.pyc
Binary file not shown.
Binary file added tests/compiled/op_precedence.2.7.pyc
Binary file not shown.
Binary file added tests/compiled/op_precedence.3.10.pyc
Binary file not shown.
Binary file added tests/compiled/op_precedence.3.5.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
8 changes: 8 additions & 0 deletions tests/input/op_precedence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
def foo(a, b, c):
return c - (a + b)

def bar(a, b, c, d):
return a / ((b ** c) * d)

def baz(a, b, c, d):
return a - ((b ^ c) + d)
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>
11 changes: 11 additions & 0 deletions tests/tokenized/op_precedence.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
def foo ( a , b , c ) : <EOL>
<INDENT>
return c - ( a + b ) <EOL>
<OUTDENT>
def bar ( a , b , c , d ) : <EOL>
<INDENT>
return a / ( b ** c * d ) <EOL>
<OUTDENT>
def baz ( a , b , c , d ) : <EOL>
<INDENT>
return a - ( ( b ^ c ) + d ) <EOL>
Binary file added tests/xfail/test_with.3.4.pyc
Binary file not shown.
Binary file added tests/xfail/test_with.3.5.pyc
Binary file not shown.

0 comments on commit 7500547

Please sign in to comment.