Skip to content

xraywidgets v0.1, and the disassembler widget - #68

Merged
tamnd merged 1 commit into
mainfrom
xraywidgets-disassembler
Aug 29, 2026
Merged

xraywidgets v0.1, and the disassembler widget#68
tamnd merged 1 commit into
mainfrom
xraywidgets-disassembler

Conversation

@tamnd

@tamnd tamnd commented Aug 29, 2026

Copy link
Copy Markdown
Owner

The first of the interactive components on #14, and the one the pilot lesson needs before it can be written.

What it does

from xraywidgets import Disassembler

Disassembler("total = sum(values)")            # a picture
Disassembler("total = sum(values)").live()     # the same picture, clickable

dis.dis prints a good table and stops. The four things a reader keeps needing next are not in it, and each one is a toggle here, off by default because a first disassembly with all four on is a wall:

Toggle What it adds
Specialized opcodes The rewritten forms the interpreter installs once it has watched an instruction run a few times
Inline caches The cache entries between the instructions, which take up real bytes and are why offsets appear to skip
Stack depth How tall the value stack is before and after each instruction
Exception table Where a try went, since there have been no SETUP_FINALLY instructions to look at since 3.11

Why the front end decides nothing

Python computes the rows and renders the markup. The JavaScript puts that markup on the page, listens for a click on a toggle and a keystroke in the source box, and hands both back. It contains no opcode names, no cache arithmetic, and no idea what an exception table is.

That is not tidiness. If the browser worked out which opcodes were specialized there would be two answers to that question in this repository, and the one written in JavaScript is the one nobody tests. It would drift in the direction of looking right, and the person who noticed would be a reader who trusted the widget over dis and came away with the wrong idea about CPython. test_the_front_end_module_works_out_no_bytecode_of_its_own greps the module for names in dis.opmap and fails if it finds any.

It is also what makes the static rendering real rather than a promise. There is no code path where a widget is only correct once a browser is involved, so the version on GitHub, in an nbconvert render, in a PDF export, and in the seconds before Pyodide has started has the right numbers in it.

Two rules that are code rather than review comments

parts.chip raises if you give it a badge with no words in it, so colour is never the only signal. The specialized badge says the word "specialized", which is what a reader with any of the common kinds of colour blindness needs, and also what survives a printed handout or a screenshot with the saturation eaten by compression.

style.py reads the palette out of pyxray.theme and writes it as CSS custom properties, and a test greps the sheet for hand written hex colours. There is exactly one place the project decides what blue means, and the widgets cannot fork away from the diagrams sitting next to them.

The toggles are real <button> elements with aria-pressed, so they are reachable by tab and operable by space bar with no JavaScript involved, and a screen reader can say whether one is on. The static rendering marks them disabled, because a button that looks live and does nothing is worse than one that admits it.

Also in here

pyxray.bytecode.exception_table, with a Handler dataclass and a covers() method. The exception toggle needed it and nothing exposed it before. It is checked against dis._parse_exception_table directly rather than against a frozen listing, and there is a test that the protected range of the first handler really does contain the call that can raise.

CI installs the live extra in the test job. Without it the interactive half of every widget would be run only on the machine of whoever happened to have anywidget installed, and the static half is the half that is easy to keep working by accident.

Checks

just check is green: 1067 passed and 2 skipped, up from 970, 352 citations resolved, and lint, format, blueprints, diagrams, lessons, notebooks and animations all clean.

Refs #14.

The first of the interactive components issue #14 lists. Type Python, see the
bytecode, and turn on the four things dis leaves out: the specialized opcodes the
interpreter installed, the inline cache entries sitting between the instructions,
the stack depth either side of each one, and the exception table.

Every widget renders twice from one piece of code. With nothing installed it draws
plain HTML with the real numbers in it and the buttons switched off, which is what
a reader gets on GitHub, in an nbconvert render, in a PDF, and while Pyodide is
still starting. With anywidget installed it draws the same picture with the buttons
working. The front end holds no bytecode logic at all: Python computes the rows and
renders the markup, the JavaScript puts it on the page and hands clicks back. So
the two pictures cannot disagree, and there is a test that greps the module for
opcode names to keep it that way.

Two rules are enforced rather than remembered. parts.chip will not build a coloured
badge without words in it, so colour is never the only signal, and style.py reads
the palette out of pyxray.theme with a test that fails on a hand written hex
colour, so the widgets cannot fork away from the diagrams beside them.

Also adds pyxray.bytecode.exception_table, which the exception toggle needs and
which nothing exposed before, and installs the live extra in the CI test job so the
interactive half is exercised on every pull request.
@tamnd tamnd added kind/tooling pyxray, bpc, the widgets and the checkers area/frontend Tokenizer, PEG parser, AST, symbol table, codegen, code objects labels Aug 29, 2026
@tamnd
tamnd merged commit c254935 into main Aug 29, 2026
8 checks passed
@tamnd
tamnd deleted the xraywidgets-disassembler branch August 29, 2026 01:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/frontend Tokenizer, PEG parser, AST, symbol table, codegen, code objects kind/tooling pyxray, bpc, the widgets and the checkers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant