tiny.python
Overview · API · Code relationships · Verification · Audit
Overview
A Zig program hands this package the text of a small Python program and gets back the value that program computed. That value is the value of the last expression statement run at the program's top level, or Python's None when none ran. The package itself reads, compiles and runs the program, all in Zig. The package calls no outside Python runtime and links none. Every byte the run uses comes from the allocator the caller passes. The run touches no file, clock, process or network.
An embedding program needs the answer as an ordinary Zig value that it can switch on. The embedding program also needs to know how long that value stays valid and which call frees the memory behind it. The embedding program needs to know which part of Python the package accepts, and how a program outside that part fails.
Python programs build lists, dictionaries and strings while they run. The value a program returns can point into that storage, so the storage has to outlive the run. Python marks where a block begins and ends by indentation alone, so reading the text means tracking how deeply each line is indented. A chained comparison such as a < b < c tests each neighboring pair and evaluates each operand once. Python's integers grow without bound, and an integer of fixed width needs a rule for results past its range.
The Python 3.14 language reference defines the language, and the package follows it for the part it supports. From the reference the package takes the way indentation opens and closes blocks, the order of operator precedence, and the meaning of chained comparisons. CPython, the reference implementation, compiles a program to bytecode and runs it on a stack machine. The package keeps that shape: a compiler emits a flat list of instructions, and a virtual machine runs them with a stack of values and one call frame per function call.
The package splits the work into four stages, one namespace each. The first stage, source, turns the text into tokens. Each token records its kind and the byte range it covers in the text. The second stage, syntax, builds a syntax tree from the tokens. The third stage, compile, turns the tree into bytecode. The compiler hands the virtual machine its bytecode in one shared format, code. That format holds the instructions and the tables of constants, names and functions that the instructions refer to by index. The fourth stage, runtime, runs the bytecode on a virtual machine. One set of types, object, describes every value a program computes. object also defines the heap that owns the larger values. A namespace of constants, spec, records the addresses of the language and library references and the targeted version, 3.14.0. One call, execute, runs all four stages in order. The package root re-exports execute with the value type (Value) and the result type (Result).
The statements of the subset are expression statements, assignment to a name or to one subscripted item, del of a name or of one subscripted item, if with elif and else, while and for with else, break, continue, pass, def and return. The expressions of the subset are integers, strings, True, False, None, names, +, - and *, unary minus, the comparisons ==, !=, <, <=, >, >=, in, not in, is and is not, then and, or and not, calls, attribute access, list, tuple and dictionary displays, indexing and slicing. The built-in functions are dict, enumerate, iter, len, list, next, range, reversed and tuple. Lists carry the methods append, clear, copy and pop. Dictionaries carry the methods clear, copy, get, items, keys, pop, popitem, setdefault, update and values.
A def inside a function fails to compile, so every function is defined at the top level. A return outside a function fails to compile. A break or continue outside a loop fails to compile. Integers are signed 128-bit numbers. An integer literal past that range fails to parse. Arithmetic past that range fails with IntegerOverflow. Indentation is spaces only, and a tab in a line's indentation fails. A string literal sits on one line between single or double quotes. A string literal's value is the bytes between its quotes as written, backslashes included.
A failure comes back as a Zig error from the stage that found it. Six of the virtual machine's eleven errors carry the names of Python exceptions: AttributeError, IndexError, KeyError, StopIteration, TypeError and ValueError. An error carries no line or column of the source text.
execute frees the tokens, the tree and the bytecode before it returns. execute returns a Result that holds the program's value and a heap. That heap, Result.heap, holds the lists, tuples, dictionaries, ranges, iterators and strings the program builds while it runs. A returned value that points into memory borrows that heap. A string taken from a string literal borrows the caller's source text, so that text has to outlive the value too. The caller frees the heap with Result.deinit, which invalidates every value that points into it. None, booleans and integers hold no pointer, so a copy of one stays valid after Result.deinit.
This example runs a three-line program whose last expression statement is y:
const python = @import("python");var result = try python.execute(allocator, \\x = 40 \\y = x + 2 \\y);defer result.deinit();try testing.expectEqual(python.Value{ .integer = 42 }, result.value);Definitions
Actions
Public operations.
execute: Tokenizes, parses, compiles and runs the source text, then returns the program's value together with the heap that owns the value's objects.
Types and contracts
Public types and contracts.
Result: A finished run's value together with the heap that owns every object the value can point to.Value: One Python value, as a tagged union of thirteen kinds.
Namespaces
Public namespaces.
code: The package's compiled form of a program: a list of instructions for a stack machine, with tables of the constants, names and function bodies the instructions refer to.compile: The package's third stage turns a program's syntax tree into bytecode for the package's stack machine.object: The package's runtime values: one tagged union that covers each kind of Python value the package supports, and a heap that owns the objects those values point to.runtime: The package's last stage runs a compiled program and hands its value back to the caller.source: The first stage of the package turns the text of a Python program into a list of tokens.spec: The constants below name the one Python version whose subset the package implements and link to its documentation.syntax: The second stage of the package reads the token list and builds the program's syntax tree: a list of statements, whose expressions are trees of operators and operands.
Code relationships
Direct static dependencies extracted from parsed source by semantic graph analysis.
Uses: tiny.bench, tiny.coz, tiny.hypothesis, tiny.sys
Used by: tiny.pluck, tiny.preserves
Verification
No verification records are cataloged for this module in this build.
Audit
| Evidence | Value |
|---|---|
| Source | lib/python/src/root.zig |
| Definitions | 10 of 10 documented |
| Members | 0 of 0 documented |
| Public names | 10 API, 222 indexed |
| Version | 26.7.0 |
| Revision | daab053ee433 |