https://github.com/brandtbucher/hax
Write compiled bytecode inline with pure Python. 🤖
https://github.com/brandtbucher/hax
bytecode cpython
Last synced: 9 months ago
JSON representation
Write compiled bytecode inline with pure Python. 🤖
- Host: GitHub
- URL: https://github.com/brandtbucher/hax
- Owner: brandtbucher
- License: other
- Created: 2019-10-16T08:03:15.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2024-09-03T21:35:12.000Z (over 1 year ago)
- Last Synced: 2025-02-23T23:12:08.696Z (over 1 year ago)
- Topics: bytecode, cpython
- Language: Python
- Homepage:
- Size: 83 KB
- Stars: 75
- Watchers: 2
- Forks: 5
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
HAX
===
[](https://github.com/brandtbucher/hax/releases)[](https://github.com/brandtbucher/hax/actions)[](https://github.com/brandtbucher/hax/issues)
HAX lets you write compiled bytecode inline with pure Python. It was originally
built for exploring new improvements to CPython's compiler and peephole
optimizer.
Installation
------------
HAX supports CPython 3.7-3.10 on all platforms.
To install, just run:
```sh
$ pip install hax
```
Example
-------
Consider the following function; it accepts a sequence of items, and returns a
list with each item repeated twice:
```py
def doubled(items):
out = []
for item in items:
out += item, item
return out
```
For example, `doubled((0, 1, 2))` returns `[0, 0, 1, 1, 2, 2]`.
We can make this function faster by keeping `out` on the stack (instead of in a
local variable) and using the `LIST_APPEND` op to build it. HAX makes it
simple to inline these instructions:
```py
from hax import *
@hax
def doubled(items):
BUILD_LIST(0)
for item in items:
LOAD_FAST("item")
DUP_TOP()
LIST_APPEND(3)
LIST_APPEND(2)
RETURN_VALUE()
```
With the help of labeled jump targets (`HAX_LABEL`), the function can be further
sped up by rewriting the for-loop in bytecode, removing _all_ temporary
variables, and operating **entirely on the stack**:
```py
from hax import *
@hax
def doubled(items):
BUILD_LIST(0)
LOAD_FAST("items")
GET_ITER()
HAX_LABEL("loop")
FOR_ITER("return")
DUP_TOP()
LIST_APPEND(3)
LIST_APPEND(2)
JUMP_ABSOLUTE("loop")
HAX_LABEL("return")
RETURN_VALUE()
```
It's important to realize that the functions HAX provides (`BUILD_LIST`,
`LOAD_FAST`, ...) aren't just "emulating" their respective bytecode
instructions; the `@hax` decorator detects them, and completely recompiles
`doubled`'s code to use the _actual_ ops that we've specified here!
These performance improvements are impossible to get from CPython's compiler and
optimizer alone.