Skip to content

ast/interpreter: Use match statements#15737

Open
dcbaker wants to merge 1 commit intomesonbuild:masterfrom
dcbaker:submit/start-using-match
Open

ast/interpreter: Use match statements#15737
dcbaker wants to merge 1 commit intomesonbuild:masterfrom
dcbaker:submit/start-using-match

Conversation

@dcbaker
Copy link
Copy Markdown
Member

@dcbaker dcbaker commented Apr 23, 2026

The slightly increases the lines of code (adding the match statement itself), but generally makes the code easier to follow (and potentially faster), since we can replace things like if struct.attribute == x: with case x: and isinstance(struct, Foo) with case Foo().

I have not converted every if/elif tree into match statements, but have tried to be a bit conservative of only converting the big ones. This also doesn't make use of any super powerful match features, like unpacking.

@dcbaker dcbaker requested a review from mensinda as a code owner April 23, 2026 21:02
@bonzini bonzini added the refactoring No behavior changes label Apr 23, 2026
The slightly increases the lines of code (adding the `match` statement
itself), but generally makes the code easier to follow (and potentially
faster), since we can replace things like `if struct.attribute == x:`
with `case x:` and `isinstance(struct, Foo)` with `case Foo()`.

I have not converted every if/elif tree into match statements, but have
tried to be a bit conservative of only converting the big ones. This
also doesn't make use of any super powerful match features, like
unpacking.
@dcbaker dcbaker force-pushed the submit/start-using-match branch from 417b87d to 55a7e90 Compare April 23, 2026 21:36
@bonzini
Copy link
Copy Markdown
Contributor

bonzini commented Apr 24, 2026

Bytecode-wise I see

293           COPY                     1
              LOAD_GLOBAL             10 (str)
              LOAD_CONST               0 (())
              MATCH_CLASS              0
              COPY                     1
              POP_JUMP_IF_NONE        53 (to L4)
              NOT_TAKEN
              UNPACK_SEQUENCE          0
294           POP_TOP

instead of

292           LOAD_GLOBAL              7 (isinstance + NULL)
              LOAD_FAST_BORROW         1 (obj)
              LOAD_GLOBAL             10 (str)
              CALL                     2
              TO_BOOL
              POP_JUMP_IF_FALSE       52 (to L4)
              NOT_TAKEN

where MATCH_CLASS is (see _PyEval_MatchClass in cpython

    assert(PyTuple_CheckExact(kwargs));
    // First, an isinstance check:
    if (PyObject_IsInstance(subject, type) <= 0) {
        return NULL;
    }
    // Short circuit if there aren't any arguments:
    Py_ssize_t nkwargs = PyTuple_GET_SIZE(kwargs);
    Py_ssize_t nattrs = nargs + nkwargs;
    if (!nattrs) {
        return PyTuple_New(0);
    }

So there is no call (though in the end you pay anyway the overhead of ABCMeta.__instancecheck__) but there are a few more bytecodes to be executed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoring No behavior changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants