asmpython
Compile Python source to native x86-64 executables — no VM, no interpreter, no runtime dependencies.
asmpython is a single-pass ahead-of-time compiler. It reads idiomatic Python, runs it through a lex → parse → sema → codegen pipeline, emits NASM assembly, and hands it to nasm and gcc to produce a standalone native binary with zero Python runtime overhead.
Supported output targets:
- Windows (PE64) —
.exelinked against msvcrt - Linux (ELF64) — ELF binary linked against libc
- Freestanding (Multiboot1) — bare-metal kernel that boots in QEMU
- Freestanding 16-bit — BIOS-bootable disk image (16-bit boot sector → 64-bit long mode)
Installation #
From source
shellgit clone https://github.com/deltathedumb/asmpython cd asmpython pip install .
Dependencies
| Tool | Required for | Notes |
|---|---|---|
nasm ≥ 2.15 | All targets | Must be on PATH |
gcc (MinGW on Windows) | Windows, Linux | Not needed for freestanding targets |
windres | Windows + --icon | Bundled with MinGW |
qemu-system-x86_64 | Freestanding testing | Optional |
_download-deps.bat --nasm --gcc to fetch w64devkit (nasm + gcc) automatically.Quick start #
python# hello.py print("Hello, world!") for i in range(5): print(i)
shellpython -m asmpython hello.py # produces hello.exe / hello ./hello
Freestanding kernel
shellpython -m asmpython kernel.py --target freestanding -o kernel.bin qemu-system-x86_64 -kernel kernel.bin -serial stdio -display none
CLI reference #
shellpython -m asmpython <source.py> [options]
| Option | Description |
|---|---|
-o <path> | Output path (default: source stem + platform extension) |
--target <t> | windows | linux | freestanding | freestanding16 (auto-detected) |
--emit-asm | Write .asm only — skip assemble/link |
--keep | Keep intermediate .obj/.o files |
--check | Front-end only (lex/parse/sema), no codegen |
--json | Machine-readable JSON diagnostics on stderr |
--explain <CODE> | Describe an error code and exit (e.g. --explain E014) |
--use-runtime-lib | Link pre-built libasmpython_rt (~50% smaller .asm output) |
--onefile | Single statically-linked binary (default) |
--onedir | Bundle directory: exe + shared runtime library (implies --use-runtime-lib) |
--type executable | Produce an executable (default) |
--type library | Produce a shared library (.dll / .so) |
--icon <path> | Embed .ico or .png as Windows icon resource (Windows only; PNG auto-converted via Pillow or a fallback minimal ICO wrapper) |
--nasm <path> | Override nasm executable path |
--gcc <path> | Override gcc executable path |
Diagnostics
outputbroken.py:3:5: semantic error: [E002] undefined function 'greet' greet("world") ^
All errors go to stderr with a non-zero exit code. Use --explain E002 for a full description of any error code. With --check --json the output is machine-readable for editor integration.
Types #
| Type | Representation | Notes |
|---|---|---|
int | 64-bit signed | No bignum. Hex 0x, binary 0b, octal 0o, underscores. // and % floor toward −∞ (Python semantics). Division by zero raises ZeroDivisionError. |
float | IEEE-754 double (xmm reg) | Auto-promoted in mixed arithmetic. 1/2 == 0.5. Whole-number floats print with .0. -0.0, inf, nan supported. Division by 0.0 raises ZeroDivisionError. |
str | NUL-terminated UTF-8 | Immutable. Negative indexing, slicing with step, rich methods. See Strings. |
bool | Alias for int (1/0) | True/False. type(x) → <class 'bool'>. |
None | Alias for 0 | Renders as None. type(None) → <class 'NoneType'>. |
list[T] | Heap-allocated dynamic array | Homogeneous element type. Nested: list[list[T]], list[dict[K,V]], list[tuple[...]]. |
dict[K,V] | Open-addressed hash table | String keys. Insertion-ordered (CPython 3.7+). FNV-1a hashing. |
set | Hash-backed set | String elements. Shares implementation with dict. |
tuple[T,...] | Fixed-size, heterogeneous | Element types known at compile time. Used for multi-return and unpack. |
Strings #
Literals
Single-quoted, double-quoted, triple-quoted ("""...""" / '''...'''). Escapes: \n \t \r \0 \\ \' \". Raw strings: r"...".
F-strings
Full format-spec mini-language: f"{x:.2f}", f"{n:05d}", f"{n:x}", f"{n:b}", f"{n:#010b}", f"{n:,}", f"{n:015,}" (zero-pad + grouping), f"{name:>10}", f"{name:*^11}", f"{name:.5}" (string truncation). Conversions: f"{x!r}", f"{x!s}", f"{x!a}".
str.format()
Positional {}/{0}, named {name}, {{/}} escapes. Same format-spec and conversion support as f-strings.
Printf-style %
"%s is %d years old" % (name, age). Supports %s %r %d %i %u %o %x %X %e %E %f %F %g %G %% with flags/width/precision (%05d, %-10s, %.2f).
Operators
| Op | Example |
|---|---|
| Concatenation | s1 + s2 |
| Repetition | "-" * 40 |
| Equality / ordering | s == t, s < t, s >= t |
| Membership | "sub" in s, "sub" not in s |
| Indexing | s[i] — negative indices supported |
| Slicing | s[i:j], s[::2], s[::-1] |
| Iteration | for ch in s: — yields 1-char strings |
Methods
| Method | Description |
|---|---|
upper() / lower() / casefold() | Case conversion |
capitalize() / swapcase() / title() | Word capitalization |
strip() / lstrip() / rstrip() | Whitespace trimming |
startswith(p) / endswith(s) | Prefix / suffix check |
removeprefix(p) / removesuffix(s) | Strip if present (Python 3.9+) |
find(s) / rfind(s) | First / last index, or −1 |
index(s) / rindex(s) | Like find but raises ValueError |
count(s) | Non-overlapping occurrences |
replace(old, new) | All occurrences replaced |
split(sep?, maxsplit?) / rsplit() | Split on separator |
splitlines() | Split on newlines |
join(iterable) | ", ".join(items) |
partition(sep) / rpartition(sep) | (before, sep, after) tuple |
isdigit() / isalpha() / isspace() / isalnum() | Character-class predicates |
isupper() / islower() | Case predicates |
zfill(width) | Left-pad with '0' |
ljust(w, fill) / rjust(w, fill) / center(w, fill) | Alignment padding |
encode(encoding) | Returns bytes-like string |
Collections #
Lists
pythonxs: list[int] = [1, 2, 3] xs.append(99) last = xs.pop() xs[0] = 10 del xs[1] # removes element at index 1 xs.sort(key=lambda x: x, reverse=True) print(xs[-1], xs[1:3], xs[::-1]) # negative index, slice, reverse rows: list[list[str]] = [["a"], ["b"]]
Methods: append, pop, insert, remove, index, count, extend, clear, copy, sort (key=, reverse=), reverse. del xs[i] removes at index. len(xs), x in xs, xs + ys, xs * n. sorted(), min(), max() accept key= and reverse=.
Dicts
pythond: dict[str, int] = {"a": 1, "b": 2} d["c"] = 3 val = d.get("x", -1) del d["a"] for k, v in d.items(): print(k, v) merged = d | {"d": 4} # PEP 584 dict union d |= {"e": 5} combo = {**d, "f": 6, **d2} # PEP 448 spread
Insertion-ordered (CPython 3.7+). Methods: get, keys(), values(), items(), update(), pop(key, default), popitem(), clear(), copy(), setdefault(). Dict comprehensions supported.
Sets
pythons = {"a", "b", "c"} s.add("d") s.discard("a") print("b" in s) fs = frozenset(s)
String elements. Methods: add, discard, remove, pop, copy, union, intersection, difference, update, clear. Set comprehensions supported.
Tuples & unpacking
pythona, b = 1, 2 # tuple unpack a, b = b, a # swap (no temp) first, *rest = xs # PEP 3132 starred unpack *init, last = xs a, (b, c) = 1, (2, 3) # nested unpack for i, x in enumerate(xs): print(i, x) for a, b in zip(xs, ys): print(a, b)
Targets may be plain names, subscripts, or attributes. *rest may appear anywhere. RHS fully evaluated before LHS stores.
Control flow #
python# if / elif / else if x > 0: print("positive") elif x == 0: print("zero") else: print("negative") # while / break / continue / else while i < n: if i == 5: break if i % 2 == 0: continue i += 1 else: print("no break") # for (range, list, dict, str; break/continue/else) for i in range(2, 20, 2): ... for x in my_list: ... for k in my_dict: ... for ch in my_str: ... # ternary, walrus, assert label = "even" if n % 2 == 0 else "odd" if (n := len(data)) > 10: print(n) # PEP 572 assert x > 0, "must be positive"
Pattern matching #
Full PEP 634 match/case. Lowered to if/elif chains in sema — zero runtime overhead. match is a soft keyword.
python# Literal, or-pattern, wildcard match status: case 200: print("ok") case 404 | 410: print("not found") case _: print("other") # Capture + guard match cmd: case x if x.startswith("--"): print("flag", x) case s: print("cmd:", s) # Sequence + starred match lst: case []: print("empty") case [x]: print("one", x) case [first, *rest]: print("head", first, "tail", rest) # Class pattern with __match_args__ class Point: __match_args__ = ("x", "y") def __init__(self, x: int, y: int): ... match shape: case Point(x=0, y=0): print("origin") case Point(px, py): print("point", px, py) # As-pattern match val: case [x, y] as pair: print("pair", pair)
Supported: Literal, Capture, Wildcard (_), Or-pattern (|), Sequence ([p0, p1]), Starred (*rest), Class (Cls(kw=p)), As-pattern (p as name), Guards (if expr). Mapping patterns ({"key": v}) are not supported.
Functions #
pythondef greet(name: str, times: int = 1) -> str: return (name + " ") * times # *args variadic def variadic(*args: str) -> None: for a in args: print(a) # **kwargs def kw_func(**kwargs) -> None: for k in kwargs: print(k, kwargs[k]) # First-class; closures; lambda f: int = lambda x: x * 2 xs.sort(key=lambda x: x.lower()) # *expr unpack at call site (statically-known tuple) t = (1, 2, 3) my_func(*t) # Decorators @staticmethod def util() -> int: ...
Default arguments: int, str, float, bool, None literals. Type annotations parsed and used for type inference (not enforced at runtime). Unannotated parameters infer type from call-site arguments. Closures capture free variables; nested functions can be passed and called.
int.Generators #
Generator functions use yield inside while or for loops (including nested if branches). The generator transform rewrites the function into a state machine that resumes on next() calls.
pythondef counter(n: int): i: int = 0 while i < n: yield i i += 1 def evens(xs: list[int]): for x in xs: if x % 2 == 0: yield x for i in counter(5): print(i) g = counter(3) print(next(g), next(g))
Generators are iterable via for and next(). StopIteration is raised when exhausted. Generator expressions (x for x in xs) are eagerly materialized into lists.
Classes #
pythonclass Shape: def __init__(self, name: str) -> None: self.name = name def area(self) -> int: return 0 def __str__(self) -> str: return self.name class Square(Shape): def __init__(self, side: int) -> None: super().__init__("square") self.side = side def area(self) -> int: return self.side ** 2 sq = Square(5) print(sq.area()) # 25 (virtual dispatch) print(isinstance(sq, Shape)) # True
Static methods & class variables
pythonclass Config: version: int = 5 # class variable @staticmethod def banner(title: str) -> str: return f"== {title} ==" @classmethod def bump(cls) -> None: cls.version += 1 Config.version += 1 print(Config.banner("hi"))
Properties
pythonclass Circle: def __init__(self, r: float) -> None: self._r = r @property def radius(self) -> float: return self._r @radius.setter def radius(self, v: float) -> None: if v < 0: raise ValueError("negative") self._r = v
Dunders
__init__, __str__, __repr__, __len__, __getitem__, __setitem__, __contains__, __iter__, __next__, __add__, __sub__, __mul__, __truediv__, __floordiv__, __mod__, __pow__, __neg__, __pos__, __abs__, __invert__, __eq__, __lt__, __le__, __gt__, __ge__, __hash__, __bool__, __enter__/__exit__, __match_args__. All binary dunder operators try reflected form on failure.
Exceptions #
pythontry: x = int("bad") except ValueError as e: print("caught:", e) except (TypeError, KeyError): print("other") else: print("no exception") finally: print("cleanup") raise # re-raise raise ValueError("bad input") class AppError(Exception): def __init__(self, msg: str) -> None: self.msg = msg def __str__(self) -> str: return self.msg
Built-in exceptions: Exception, ValueError, TypeError, KeyError, IndexError, AttributeError, RuntimeError, NotImplementedError, StopIteration, OverflowError, ZeroDivisionError, OSError/IOError, FileNotFoundError, PermissionError, NameError, RecursionError. Dotted exception types (module.ExcClass) supported. Subclass hierarchy respected.
Context managers #
pythonwith open("file.txt") as f: data = f.read() # Multiple managers on one line with open("a") as a, open("b") as b: ... # Custom context manager class Lock: def __enter__(self): return self def __exit__(self, t, v, tb): return False
with rewrites to try/finally in sema. __exit__ is always called as __exit__(None, None, None). contextlib.suppress and contextlib.nullcontext available.
Comprehensions #
python# List comprehension squares = [x * x for x in range(10)] even_sq = [x * x for x in range(10) if x % 2 == 0] pairs = [(x, y) for x in xs for y in ys] # Dict comprehension inv = {v: k for k, v in d.items()} # Set comprehension uniq = {x.lower() for x in words} # Generator expression (eager; same as list comp) total = sum(x * x for x in xs)
Comprehension loop variables are scoped to the comprehension (Python 3 semantics). Multiple for clauses and if filters supported.
Imports & modules #
pythonimport math from os import getcwd, path from . import utils # relative from .utils import helper
Two import modes:
- Source stdlib — modules like
re,json,collectionsare compiled whole-program alongside your code. All top-level definitions become globally visible. - FFI stdlib —
math,os,sys,timeuse direct C runtime bindings.
User modules: import utils finds utils.py in the same directory and merges into the compilation unit. Whole-program compilation ensures zero linking overhead for user modules.
Standard library overview #
All modules listed below are fully implemented. Source stdlib modules are compiled into your binary; FFI modules bind to C runtime symbols.
Data & text
Collections & algorithms
File system & OS
Date, time & math
Crypto & encoding
Networking
Diagnostics & system
math #
pythonimport math print(math.sqrt(2.0)) # 1.4142135623730951 print(math.floor(3.7)) # 3 (int) print(math.log(math.e)) # 1.0
Constants: math.pi, math.e, math.tau, math.inf, math.nan.
Functions: sqrt, floor, ceil, trunc, round, abs, pow, log, log2, log10, log1p, exp, exp2, expm1, sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh, asinh, acosh, atanh, degrees, radians, hypot, gcd, lcm, factorial, isfinite, isinf, isnan, copysign, fabs, fmod, remainder, fdim, fmax, fmin, modf, ldexp, frexp, comb, perm, nearbyint. floor/ceil/trunc return int.
os / sys / pathlib #
pythonimport os, sys from pathlib import Path print(os.getcwd()) os.chdir("/tmp") os.makedirs("a/b/c", exist_ok=True) files = os.listdir(".") env = os.getenv("HOME", "") os.rename("a", "b") os.remove("file") print(sys.argv, sys.platform) sys.exit(0) p = Path("src/main.py") print(p.name, p.stem, p.suffix, p.parent)
os: getcwd, chdir, listdir, makedirs, remove, rename, stat, path.*, getenv, environ, system, getpid, getppid, cpu_count, urandom, fflush, ftell, fseek, rewind, feof.
sys: argv, exit, platform, version, stdin/stdout/stderr, path, maxsize, byteorder.
pathlib.Path: .name, .stem, .suffix, .parent, .exists(), .is_file(), .is_dir(), .read_text(), .write_text(), .mkdir(), .unlink(), __truediv__ (Path("a") / "b").
re #
pythonimport re m = re.match(r"\d+", "123abc") if m: print(m.group(0)) # "123" print(m.start(), m.end(), m.span()) re.search(r"\w+", "hello world") re.findall(r"\d+", "1 22 333") # ["1", "22", "333"] re.sub(r"\d", "#", "a1b2") # "a#b#" re.split(r",\s*", "a, b, c") re.finditer(r"\d+", "1 22") # list of Match objects re.fullmatch(r"\d+", "123") re.subn(r"\d", "#", "a1b2") re.escape("a.b*c") # "a\\.b\\*c" pat = re.compile(r"(\w+)") # returns pattern string
Patterns: . * + ? | ^ $ [...] [^...] \d\w\s and uppercase negations, (?:...) non-capturing, (...) groups. Flags: re.IGNORECASE, re.MULTILINE, re.DOTALL. Match object: .group(n), .start(), .end(), .span().
json / csv / io #
json
pythonimport json data = json.loads('{"name":"alice","age":30}') out: str = json.dumps({"x": 1}, indent=2)
csv
pythonimport csv lines: list[str] = ["name,age", "alice,30"] rows: list[list[str]] = csv.reader(lines) line: str = csv.writer_row(["alice", "30"]) dr = csv.DictReader(lines) print(dr.get(dr.rows[0], "name"))
io
pythonimport io buf = io.StringIO() buf.write("hello") val = buf.getvalue() buf.seek(0) with io.StringIO() as b: b.write("x")
io.StringIO and io.BytesIO support write, read, getvalue, seek, tell, readable(), writable(), seekable(), context manager protocol.
datetime / time #
pythonfrom datetime import datetime, date, timedelta import time now = datetime.now() d = date.today() delta = timedelta(days=7) future = now + delta print(now.strftime("%Y-%m-%d %H:%M:%S")) t = time.time() # float seconds time.sleep(0.1) print(time.strftime("%H:%M:%S"))
collections / itertools #
pythonfrom collections import deque, Counter, defaultdict, OrderedDict import itertools dq = deque([1, 2, 3]) dq.appendleft(0); dq.popleft() c = Counter(["a", "b", "a"]) print(c.most_common(2)) # [("a",2),("b",1)] c1 + c2; c1 - c2; c1 & c2; c1 | c2 # Counter arithmetic dd = defaultdict(list) dd["key"].append(1) od = OrderedDict() od.move_to_end("key") od.popitem() for pair in itertools.combinations([1,2,3], 2): ... list(itertools.chain([1], [2], [3]))
fractions: Fraction(n, d) with full arithmetic (+, -, *, /, **, abs, comparisons).
base64: b64encode/decode, urlsafe_*, b32encode/decode, b16encode/decode.
uuid: UUID(hex_str), uuid4(), .hex, str(u).
hashlib: md5/sha1/sha256/sha512(data) with .hexdigest().
string / textwrap / others #
pythonimport string, textwrap print(string.ascii_letters) print(string.digits) print(string.punctuation) lines = textwrap.wrap("long text", width=40) print(textwrap.fill("long text", width=40))
Also available: keyword, numbers, abc, types, typing, configparser, pprint, traceback, warnings, inspect, gc, atexit, signal, getpass, locale, threading, queue, weakref.
asmlib.hardware #
Bare-metal and hardware access. Inline NASM on freestanding; stub-returns on hosted targets.
pythonfrom asmlib import hardware # Port I/O hardware.out_byte(0x60, 0xAE) byte = hardware.in_byte(0x60) # CPU hardware.halt() hardware.disable_interrupts(); hardware.enable_interrupts() tsc = hardware.rdtsc() rand = hardware.rdrand() info = hardware.cpuid(0) # Control registers, MSR cr0 = hardware.read_cr0() hardware.write_cr3(pml4_addr) msr = hardware.read_msr(0xC0000080) # VGA console (freestanding) hardware.console_clear() hardware.console_write("Hello!") hardware.console_set_color(0x0F)
asmlib.network #
pythonfrom asmlib import network fd = network.socket(network.AF_INET, network.SOCK_STREAM) network.bind(fd, "127.0.0.1", 8080) network.listen(fd, 5) client = network.accept(fd) data = network.recv(client, 1024) network.send_all(client, "HTTP/1.1 200 OK\r\n\r\n") network.close(client)
BSD socket API: socket, bind, connect, listen, accept, close, send, recv, send_all, byte-order helpers, address helpers, constants (AF_INET, SOCK_STREAM, etc.).
asmlib.gui #
pythonfrom asmlib import gui gui.init() win = gui.create_window("Demo", 800, 600) ren = gui.create_renderer(win) gui.set_window_icon(win, gui.load_bmp("icon.bmp")) while True: if gui.poll_quit(): break gui.set_draw_color(ren, 255, 0, 0, 255) gui.fill_rect(ren, 10, 10, 100, 50) gui.present(ren) gui.quit()
SDL2 bindings: window/renderer management, drawing (draw_line, fill_rect, draw_rect), event pump, timing. Icon loading with load_bmp/set_window_icon/free_surface.
Inline assembly #
pythonfrom asmpython._compiler.ast_nodes import AsmBlock def rdtsc() -> int: asm { rdtsc shl rdx, 32 or rax, rdx }
Raw NASM inserted verbatim into the function body. The enclosing function's prologue/epilogue is still emitted; the asm block appears between them. Useful for instructions without Python-level wrappers.
Inline FFI #
pythonfrom asmpython._ffi import include, link, extern include("windows.h") link("kernel32") @extern def GetTickCount() -> int: ... @extern def MessageBoxA(hwnd: int, text: str, cap: str, utype: int) -> int: ...
@extern declares a foreign function; the compiler emits an extern NASM directive and routes calls through the platform ABI. include() and link() add #include and -l flags to the compile step.
Windows (PE64) #
Default target when running on Windows. Produces a .exe linked against msvcrt.dll. Uses the x64 Windows ABI (RCX/RDX/R8/R9 with 32-byte shadow space). The entry point is main(int argc, char** argv).
shellpython -m asmpython prog.py # auto-detects Windows python -m asmpython prog.py --target windows -o prog.exe python -m asmpython prog.py --icon app.png # embed PNG icon
If networking is used (asmlib.network) the compiler automatically links -lws2_32.
Linux (ELF64) #
ELF64 binary linked against glibc using the SysV ABI (RDI/RSI/RDX/RCX/R8/R9). Linked with -no-pie (the code uses absolute relocations).
shellpython -m asmpython prog.py --target linux -o prog
Freestanding (Multiboot1) #
Bare-metal x86-64 kernel conforming to the Multiboot 1 specification. Boots under QEMU (-kernel), GRUB, and other Multiboot-compliant loaders. No OS; no libc.
- VGA text-mode output + COM1 serial mirroring
- Bump allocator (256 KB heap)
- 64 KB stack
- 32→64-bit long-mode setup with identity-mapped page tables (first 16 MB, 2 MB huge pages)
- Unhandled exceptions show a flashing red screen and warm-reboot after 5 s
shellpython -m asmpython kernel.py --target freestanding -o kernel.bin qemu-system-x86_64 -kernel kernel.bin -serial stdio -display none
--onedir / --use-runtime-lib to keep the binary smaller. The runtime library bundles all helper code into libasmpython_rt.a.16-bit boot sector #
Generates a BIOS-bootable raw disk image. Boots in real mode via INT 13h, transitions through 32-bit protected mode, then enters 64-bit long mode before running your code.
shellpython -m asmpython boot.py --target freestanding16 -o boot.img qemu-system-x86_64 -drive format=raw,file=boot.img -display none -serial stdio
Built-in functions #
| Function | Description |
|---|---|
print(*args, sep, end, file) | Prints to stdout (or file). Bool/None render as Python strings. Containers render Python-style. |
len(x) | Length of str, list, dict, set, tuple |
range(stop) / range(start, stop, step) | Integer range (1/2/3-arg, negative step); first-class value |
enumerate(iter, start=0) | Yields (index, value) tuples |
zip(*iters) | Yields tuples from parallel iterables |
int(x) / float(x) / str(x) / bool(x) | Type conversion |
abs(x) | Absolute value; dispatches __abs__ |
round(x, n) | Round to n decimal places |
min(iter, key=) / max(iter, key=) | Min/max with optional key function |
sum(iter, start=0) | Sum of iterable |
sorted(iter, key=, reverse=) | Returns sorted list |
reversed(seq) | Returns reversed list |
list(iter) / dict(iter) / set(iter) | Convert iterables to container |
tuple(iter) | Convert to tuple |
isinstance(obj, cls) | Runtime type check (respects inheritance) |
hasattr(obj, name) / getattr(obj, name, default) / setattr(obj, name, val) | Attribute access |
type(x) | Returns <class 'T'> string |
repr(x) | Calls __repr__/__str__ |
hash(x) | Calls __hash__; str uses FNV-1a |
id(x) | Heap address as int |
ord(c) / chr(n) | Char ↔ integer |
hex(n) / oct(n) / bin(n) | Integer to string |
divmod(a, b) | (a // b, a % b) with floor semantics |
pow(base, exp, mod?) | Power; optional modulus |
all(iter) / any(iter) | Boolean reduction |
next(iter) | Next value from generator |
iter(x) | Get iterator from iterable |
open(path, mode) | File object with read/write/close/seek |
input(prompt?) | Read line from stdin |
frozenset(s) | Immutable set |
vars(obj) | Instance attributes as dict |
super() | Parent class proxy for method resolution |
Architecture #
asmpython compiles through four sequential passes:
- Lex — tokenizes source; handles all Python literal types, f-strings, indentation blocks
- Parse — recursive-descent parser builds an AST; inlines closures via free-variable lifting; resolves generators into state machines
- Sema — type inference and semantic analysis; resolves method overloads, propagates element types, desugars match/case, with statements, properties, and comprehensions
- Codegen — direct AST → NASM x86-64 emission; no IR; target-specific ABI handling
Whole-program compilation: All source files (including stdlib modules) are merged into a single compilation unit before sema. The first definition of any name wins (allows stdlib to be overridden by user code).
Type system: Structural, not nominal. Types flow from annotations and literals. Unannotated parameters are inferred from call sites. Class inheritance tracked for virtual dispatch and isinstance.
Runtime: A small set of C helper functions (_runtime_*) handle dynamic dispatch, string operations, allocation, and exception propagation. These can be inlined (--onefile) or linked from a pre-built archive (--use-runtime-lib).
Error codes #
Use --explain E0XX for full descriptions. Selected codes:
| Code | Message |
|---|---|
| E001 | Syntax error |
| E002 | Undefined function |
| E003 | Undefined variable |
| E004 | Wrong number of arguments |
| E005 | Type mismatch in assignment |
| E006 | Method not found on type |
| E007 | Attribute not found on class |
| E008 | Mixed list element types |
| E009 | Return type mismatch |
| E010 | Unsupported operation |
| E014 | Feature not supported in this target |
Limitations #
- No bignum — integers are 64-bit signed; overflow wraps
- Homogeneous lists —
list[T]requires all elements to be the same type;list(bare) allows any - String keys only — dict and set elements must be strings (runtime limitation)
- Single inheritance — multiple inheritance is not supported
- No metaclasses —
type()and__class__are read-only - No dynamic attribute creation — all instance attributes must be assigned in
__init__ - No mapping patterns in
match/case - Generator expressions are eager —
(x for x in xs)materializes immediately *exprunpacking at call sites requires a statically-known tuple (literal or named variable)- No async/await
- No runtime introspection beyond
isinstance,hasattr,getattr,type
examples/ for demonstrations.