Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/brandtbucher/hax

Write compiled bytecode inline with pure Python. 🤖
https://github.com/brandtbucher/hax

bytecode cpython

Last synced: 4 days ago
JSON representation

Write compiled bytecode inline with pure Python. 🤖

Awesome Lists containing this project

README

        

HAX
===

[![latest version](https://img.shields.io/github/release-pre/brandtbucher/hax.svg?style=for-the-badge&label=latest)![latest release date](https://img.shields.io/github/release-date-pre/brandtbucher/hax.svg?style=for-the-badge&label=released)](https://github.com/brandtbucher/hax/releases)[![build status](https://img.shields.io/github/actions/workflow/status/brandtbucher/hax/ci.yml.svg?style=for-the-badge&branch=master)](https://github.com/brandtbucher/hax/actions)[![issues](https://img.shields.io/github/issues-raw/brandtbucher/hax.svg?label=issues&style=for-the-badge)](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.