Write compiled bytecode inline with standard Python syntax.

# HAX

HAX lets you write compiled bytecode inline with standard Python syntax.

## Installation

HAX supports CPython 3.6–3.9.

To install, just run:

\$ pip install hax


## Example

Consider the following function; it accepts a sequence of items, and returns a list with each item repeated twice:

from typing import List, Sequence, TypeVar

T = TypeVar("T")

def double(items: Sequence[T]) -> List[T]:
out = []
for item in items:
out += item, item
return out


For example, (0, 1, 2) becomes [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:

from hax import *

@hax
def double(items: Sequence[T]) -> List[T]:

BUILD_LIST(0)

for item in items:

DUP_TOP()
LIST_APPEND(3)
LIST_APPEND(2)

RETURN_VALUE()


If you're up to the challenge of computing jump targets, the function can be further sped up by rewriting the for-loop in bytecode, removing all temporary variables, and operating entirely on the stack:

@hax
def double(items: Sequence[T]) -> List[T]:

BUILD_LIST(0)

GET_ITER()
FOR_ITER(34)  # When done, jump forward to RETURN_VALUE().

DUP_TOP()
LIST_APPEND(3)
LIST_APPEND(2)
JUMP_ABSOLUTE(28)  # Jump back to FOR_ITER(34).

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 double'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.

## Project details

Uploaded source
Uploaded py3