Skip to documentation
SLOP

tiny.python.code.op

Reference tiny.python code op

Defined in code.

The package's virtual machine has 39 operations, each of which takes its inputs from one stack of values and pushes its result back onto it.

API (1)

Types and contracts

Public types and contracts.

No direct callersNo direct callscodeop
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: lib/python/src/code/op.zig

zig
//! The package's virtual machine has 39 operations, each of which takes its inputs from one stack//! of values and pushes its result back onto it. Each operation has to be small enough for the//! virtual machine to run with one switch, and together they have to express every statement and//! expression that the package accepts from Python 3.14, including `and` and `or`, chained//! comparisons, loops with `else` blocks, and calls.//!//! Instructions run in order from one list, so every `if`, loop, `and` and `or` has to become jumps//! within that list. Python evaluates `a < b < c` with `b` computed once and stops at the first//! false comparison, so the middle operand has to stay available while its first comparison runs.//!//! The package keeps the stack-machine design of [CPython](https://github.com/python/cpython)://! values move through one stack, and each operation pops its inputs and pushes its result.//!//! Each tag takes at most one integer operand, which the instruction stores. Each tag's doc below//! says what the operation pops, what it pushes and what its operand means. A jump names an//! absolute position in the chunk's list of instructions. `jump_if_false` leaves the tested value//! on the stack, so `and` and `or` can return the operand that decided them. The compiler emits a//! `pop` on each path that no longer needs the tested value. A chained comparison uses `dup`,//! `rotate_three` and `swap` to keep each middle operand for the comparison after it. A function//! body ends with `return_value`. The top level ends with `ret`, which returns the value that//! `save` last recorded from a top-level expression statement./// The operations of the package's bytecode, one tag each. The compiler picks one tag per/// instruction, and the virtual machine's run loop switches on it. An instruction carries the tag/// with one integer operand, and each tag's doc says what the operand means. The virtual machine/// checks the stack depth before each operation that pops, and fails with `StackUnderflow` when too/// few values are there.pub const Op = enum {    /// Pushes the constant at the operand's position in the current chunk's constant table.    constant,    /// Pushes the value of the name at the operand's position in the current chunk's name table.    /// The lookup tries the current call's local variables, then the global variables, then the    /// builtin functions. The lookup fails with `UndefinedName` when none of the three holds the    /// name.    load,    /// Pops a value and binds it to the name at the operand's position. At top level the binding is    /// a global variable, and inside a call it is a local variable of that call.    store,    /// Removes the binding of the name at the operand's position: a global variable at top level,    /// and a local variable of the call inside a function. The operation fails with `UndefinedName`    /// when the name has no binding there. The operation leaves the stack as it was. The compiler    /// emits it for `del name`.    delete,    /// Pops the top value and discards it. The compiler emits it after an expression statement    /// inside a function, after each condition test, and to drop the iterators of loops that    /// `break` or `return` leaves.    pop,    /// Pops the top value and records it in the current frame. `ret` later returns the recorded    /// value. The compiler emits it after each expression statement at top level, so a program's    /// value is the value of its last top-level expression statement.    save,    /// Pushes a second copy of the top value. The compiler emits it in a chained comparison to keep    /// a middle operand.    dup,    /// Exchanges the top two values. When a chained comparison stops early, the compiler emits it    /// to bring the kept middle operand above the false result, and a `pop` then drops that    /// operand.    swap,    /// Moves the top value below the two values under it, so the stack `a b c`, with `c` on top,    /// becomes `c a b`. In a chained comparison, the operation moves the copy of the middle operand    /// below the two values being compared.    rotate_three,    /// Continues at the instruction whose position is the operand. The operation leaves the stack    /// as it was.    jump,    /// Continues at the operand's position when the top value is false by Python's truth rules, and    /// at the next instruction otherwise. The operation leaves the tested value on the stack on    /// both paths. The compiler follows it with `pop` on each path that no longer needs the value,    /// so `and` and `or` return the operand that decided them.    jump_if_false,    /// Pops two values, with the right operand on top, and pushes their sum. Integers and booleans    /// add as integers, and two lists, two tuples or two strings join into a new object on the    /// heap. The operation fails with `IntegerOverflow` when the sum leaves the signed 128-bit    /// range, and with `TypeError` for any other pair of types.    add,    /// Pops two integers or booleans and pushes the left minus the right. The operation fails with    /// `IntegerOverflow` when the result leaves the signed 128-bit range, and with `TypeError` for    /// any other type.    sub,    /// Pops two values and pushes their product. Integers and booleans multiply as integers, and a    /// list, tuple or string on either side of an integer or boolean repeats into a new object on    /// the heap. A count of zero or less gives an empty sequence. The operation fails with    /// `IntegerOverflow` when the product or the repeated length overflows, and with `TypeError`    /// for any other pair of types.    mul,    /// Pops an integer or boolean and pushes its negation as an integer. The operation fails with    /// `IntegerOverflow` for the smallest signed 128-bit integer, and with `TypeError` for any    /// other type.    neg,    /// Pops a value and pushes `True` when the value is false by Python's truth rules, and `False`    /// otherwise.    not,    /// Pops two values and pushes whether they are equal, as `Value.eql` decides. Values of    /// unrelated types compare unequal, and the comparison returns no error.    equal,    /// Pops two values and pushes whether they are unequal, the negation of `equal`.    not_equal,    /// Pops two values and pushes whether the left is less than the right. Integers and booleans    /// compare as numbers, strings compare by their UTF-8 bytes, and lists and tuples compare item    /// by item. When one list or tuple is a prefix of the other, the shorter one is less. The    /// operation fails with `TypeError` for any other pair of types, including a list against a    /// tuple.    less,    /// Pops two values and pushes whether the left is less than or equal to the right, under the    /// ordering that `less` uses. The operation fails with `TypeError` for the pairs of types that    /// `less` rejects.    less_equal,    /// Pops two values and pushes whether the left is greater than the right, under the ordering    /// that `less` uses. The operation fails with `TypeError` for the pairs of types that `less`    /// rejects.    greater,    /// Pops two values and pushes whether the left is greater than or equal to the right, under the    /// ordering that `less` uses. The operation fails with `TypeError` for the pairs of types that    /// `less` rejects.    greater_equal,    /// Pops a container from the top, then an item, and pushes whether the item is in the    /// container, so `x in xs` pushes `x` first. A list or tuple matches an item that is the same    /// object or equal. A dictionary or its keys view tests its keys, a values view tests its    /// values, and an items view tests a two-item tuple against a key and its value. A range tests    /// membership from its start, stop and step, in constant time. A string tests for a substring.    /// An iterator takes items until one matches, so the items it passed are gone. The operation    /// fails with `TypeError` for an unhashable item tested against a dictionary or its keys, for    /// an item other than a string tested against a string, and for a container of any other type.    contains,    /// Pops a container from the top, then an item, and pushes whether the item is absent from the    /// container, under the rules of `contains`.    not_contains,    /// Pops two values and pushes whether they are the same object. `None`, booleans and integers    /// are the same when their values are. A boolean is never the same as an integer, although    /// `True == 1` holds. Two strings are the same when they start at the same address and have the    /// same length. Functions and builtins compare their positions and tags, and objects on the    /// heap compare their addresses.    identical,    /// Pops two values and pushes whether they are different objects, the negation of `identical`.    not_identical,    /// The operand is the number of arguments, which sit on top of the stack in order, with the    /// called value below them. A Python function takes the called value and the arguments off the    /// stack, binds each argument to its parameter in a new call frame, and runs the body, whose    /// `return_value` pushes the result. A builtin function or bound method runs at once and    /// replaces the called value and the arguments with its result. The operation fails with    /// `StackUnderflow` when the stack holds fewer values than the arguments and the called value,    /// with `ArityMismatch` when the number of arguments does not fit, with `InvalidFunction` when    /// a function value names no function, and with `TypeError` when the value cannot be called.    call,    /// Pops a list or dictionary and pushes its method, bound to that object and named by the    /// operand's position in the name table. Lists offer `append`, `clear`, `copy` and `pop`, and    /// dictionaries offer `clear`, `copy`, `get`, `items`, `keys`, `pop`, `popitem`, `setdefault`,    /// `update` and `values`. Each read creates a new bound method on the heap. The operation fails    /// with `AttributeError` for any other name and for any other type.    attribute,    /// Pops as many values as the operand says and pushes a new list of them, in the order they    /// were pushed. The operation fails with `StackUnderflow` when the stack holds fewer values.    build_list,    /// Pops as many values as the operand says and pushes a new tuple of them, in the order they    /// were pushed. The operation fails with `StackUnderflow` when the stack holds fewer values.    build_tuple,    /// The operand is the number of key and value pairs, and the stack holds each key followed by    /// its value. The operation pops all of them and pushes a new dictionary with the pairs in    /// stack order. A repeated key keeps its first position and takes the last value. The operation    /// fails with `TypeError` for an unhashable key, and with `IntegerOverflow` when twice the    /// operand overflows.    build_dict,    /// Pops a value and pushes an iterator over it. A list, tuple, range, string, dictionary or    /// dictionary view gets a new iterator on the heap, and a dictionary's iterator yields its    /// keys. An iterator goes back on the stack as it is. The operation fails with `TypeError` for    /// any other type.    iter,    /// The operand is the position of the first instruction after the loop body. The instruction    /// reads the iterator on top of the stack and pushes its next item above it. When the iterator    /// is exhausted, the operation pops it and continues at the operand's position. The operation    /// fails with `TypeError` when the top value is other than an iterator.    for_next,    /// Pops an index from the top, then a container, and pushes the item. A list or tuple takes an    /// integer or boolean index, counts a negative index from the end, and fails with `IndexError`    /// outside the sequence. A dictionary looks the key up and fails with `KeyError` when the key    /// is absent. The operation fails with `TypeError` for a sequence index other than an integer    /// or boolean, for an unhashable key, and for any other container, strings and ranges included.    subscript,    /// Pops the step, the stop and the start, then a container, and pushes the slice. The compiler    /// pushes `None` for each part the source leaves out. A list, tuple or string gives a new value    /// of the same type, and a range gives a new range. Strings are sliced by codepoint. A string    /// slice with step 1 points into the original bytes, and every other string slice is a copy on    /// the heap. The operation fails with `ValueError` for a step of zero or a string with invalid    /// UTF-8, and with `TypeError` for a bound other than an integer, boolean or `None`, and for    /// any other container.    slice,    /// Pops a value, an index and a container, and stores the value in the container at that index.    /// A list replaces the item at an integer or boolean index, counts a negative index from the    /// end, and fails with `IndexError` outside the list. A dictionary inserts the key or replaces    /// its value, and fails with `TypeError` when the key is unhashable. The operation fails with    /// `TypeError` for any other container, tuples included. The instruction pushes nothing.    store_subscript,    /// Pops an index from the top, then a container, and removes that item. A list removes the item    /// at the index and shifts the later items down, with the index rules and errors of    /// `subscript`. A dictionary removes the key, and fails with `KeyError` when the key is absent    /// and with `TypeError` when it is unhashable. The operation fails with `TypeError` for any    /// other container.    delete_subscript,    /// Pops the return value, ends the current call and pushes the value for the caller. In the    /// top-level frame, the operation ends the run with that value. The compiler emits it for    /// `return` and at the end of every function body. Before a `return` inside loops, the compiler    /// pops the iterators of those loops.    return_value,    /// Ends the current frame with the value that `save` last recorded, or with `None` when no    /// expression statement ran. The compiler emits it once, at the end of the top-level chunk.    ret,};

Source: lib/python/src/code/root.zig:10

zig
pub const op = @import("op.zig");

Audit

Definitions2
Public names3
Members39
Version26.7.0
Revisiondaab053ee433