pycdc did not reconstruct `match` statements: class patterns hit the
unhandled MATCH_CLASS opcode and bailed to "# WARNING: Decompyle incomplete",
and value patterns were mis-rendered as an if/elif chain.
This adds reconstruction of the common, statically-recognizable shapes:
* Class patterns - `case Cls(a, b):` - including positional captures and
`_` wildcard sub-patterns (`case Cls(_):`).
* Value patterns - `case 0:` / `case 'x':` - compiled as a COPY-threaded
COMPARE_OP chain rather than MATCH_CLASS.
* The `case _:` wildcard (which carries no test opcode).
A pre-scan over the code object recognizes the simple, guard-free shape of
each case and records it; the MATCH_CLASS handler and a small guarded hook in
COMPARE_OP open ASTMatchBlock/ASTCaseBlock and skip the pattern-test
machinery, and the block-close logic closes each case at its fail-target and
the match at its merge. Anything outside the recognized shape (kwarg patterns,
guards, sequence/mapping patterns) is left unregistered and still bails
honestly, so no incorrect output is produced.
New AST nodes: ASTMatchBlock (subject) and ASTCaseBlock (pattern), rendered
via the existing block-header machinery (type_str + print_src). PycBuffer
gains setPos() so the reconstructor can skip to a case body.
All hooks are guarded by per-offset match tables that are empty for code
without a match statement, so non-match input is unaffected.
Test: tests/input/match_statement.py exercises class patterns, a wildcard
sub-pattern, value patterns and `case _`. Full existing suite still passes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Modify .gitignore
* Added support for SWAP and WITH_EXCEPT_START, WITH_EXCEPT_START is simply added on top of SETUP_WITH_A so that it works properly.
* Resolve the warning about comparing size_t and int.
* Revert "Resolve the warning about comparing size_t and int."
This reverts commit 54dfe36629.
* Reapply "Resolve the warning about comparing size_t and int."
This reverts commit d21d1681ed.
* Modify decompyle_test.sh
* Modify .gitignore
* Fix the logic error by placing the assignment inside the tuple
* Re-adding test files
* Fixing redundant brackets
* Add support for swap bytecode and simple WITH_EXCEPT_START bytecode support.
* Clean up some formatting issues
---------
Co-authored-by: Michael Hansen <zrax0111@gmail.com>
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.
* fix#396 Unsupported Node type: 27
* Add test file
* Modify a little comment
* Modify the test pyc file name
* Delete redundant pyc files
* retest
* Add newline at EOF
---------
Co-authored-by: Michael Hansen <zrax0111@gmail.com>
* Apparently should be enough ?
* Add `GEN_START` test
* Add `GEN_START` test compiled
* Add `GEN_START` test tokenized
* Smaller test since only POP is needed.
* Smaller test since only POP is needed.
* Smaller test since only POP is needed.
* dos2unix
* Add `PUSH_NULL`, `PRECALL_A`, `CALL_A` support
* feat: @zrax
Co-authored-by: Michael Hansen <zrax0111@gmail.com>
* Good suggested change to make the code shorter
* Add `PUSH_NULL`, `PRECALL`, `CALL` test tokenized
* Add `PUSH_NULL`, `PRECALL`, `CALL` test
* Add `PUSH_NULL`, `PRECALL`, `CALL` test compiled
* Delete push_null-precall-call.3.11.pyc
* Delete push_null-precall-call.py
* Delete push_null-precall-call.txt
* Update README.markdown
Blank commit to re-run the tests.
* Join all no-ops/"fake"-ops together
* Update ASTree.cpp
https://github.com/zrax/pycdc/pull/324#issuecomment-1449049283
* Add compiled test for #324
---------
Co-authored-by: Michael Hansen <zrax0111@gmail.com>