lib/python/src/code/op.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 //! The package's virtual machine has 39 operations, each of which takes its inputs from one stack
2 //! of values and pushes its result back onto it. Each operation has to be small enough for the
3 //! virtual machine to run with one switch, and together they have to express every statement and
4 //! expression that the package accepts from Python 3.14, including `and` and `or`, chained
5 //! comparisons, loops with `else` blocks, and calls.
6 //!
7 //! Instructions run in order from one list, so every `if`, loop, `and` and `or` has to become jumps
8 //! within that list. Python evaluates `a < b < c` with `b` computed once and stops at the first
9 //! false comparison, so the middle operand has to stay available while its first comparison runs.
10 //!
11 //! The package keeps the stack-machine design of [CPython](https://github.com/python/cpython):
12 //! values move through one stack, and each operation pops its inputs and pushes its result.
13 //!
14 //! Each tag takes at most one integer operand, which the instruction stores. Each tag's doc below
15 //! says what the operation pops, what it pushes and what its operand means. A jump names an
16 //! absolute position in the chunk's list of instructions. `jump_if_false` leaves the tested value
17 //! on the stack, so `and` and `or` can return the operand that decided them. The compiler emits a
18 //! `pop` on each path that no longer needs the tested value. A chained comparison uses `dup`,
19 //! `rotate_three` and `swap` to keep each middle operand for the comparison after it. A function
20 //! body ends with `return_value`. The top level ends with `ret`, which returns the value that
21 //! `save` last recorded from a top-level expression statement.
22 /// The operations of the package's bytecode, one tag each. The compiler picks one tag per
23 /// instruction, and the virtual machine's run loop switches on it. An instruction carries the tag
24 /// with one integer operand, and each tag's doc says what the operand means. The virtual machine
25 /// checks the stack depth before each operation that pops, and fails with `StackUnderflow` when too
26 /// few values are there.
27 pub const Op = enum {
28 /// Pushes the constant at the operand's position in the current chunk's constant table.
29 constant,
30 /// Pushes the value of the name at the operand's position in the current chunk's name table.
31 /// The lookup tries the current call's local variables, then the global variables, then the
32 /// builtin functions. The lookup fails with `UndefinedName` when none of the three holds the
33 /// name.
34 load,
35 /// Pops a value and binds it to the name at the operand's position. At top level the binding is
36 /// a global variable, and inside a call it is a local variable of that call.
37 store,
38 /// Removes the binding of the name at the operand's position: a global variable at top level,
39 /// and a local variable of the call inside a function. The operation fails with `UndefinedName`
40 /// when the name has no binding there. The operation leaves the stack as it was. The compiler
41 /// emits it for `del name`.
42 delete,
43 /// Pops the top value and discards it. The compiler emits it after an expression statement
44 /// inside a function, after each condition test, and to drop the iterators of loops that
45 /// `break` or `return` leaves.
46 pop,
47 /// Pops the top value and records it in the current frame. `ret` later returns the recorded
48 /// value. The compiler emits it after each expression statement at top level, so a program's
49 /// value is the value of its last top-level expression statement.
50 save,
51 /// Pushes a second copy of the top value. The compiler emits it in a chained comparison to keep
52 /// a middle operand.
53 dup,
54 /// Exchanges the top two values. When a chained comparison stops early, the compiler emits it
55 /// to bring the kept middle operand above the false result, and a `pop` then drops that
56 /// operand.
57 swap,
58 /// Moves the top value below the two values under it, so the stack `a b c`, with `c` on top,
59 /// becomes `c a b`. In a chained comparison, the operation moves the copy of the middle operand
60 /// below the two values being compared.
61 rotate_three,
62 /// Continues at the instruction whose position is the operand. The operation leaves the stack
63 /// as it was.
64 jump,
65 /// Continues at the operand's position when the top value is false by Python's truth rules, and
66 /// at the next instruction otherwise. The operation leaves the tested value on the stack on
67 /// both paths. The compiler follows it with `pop` on each path that no longer needs the value,
68 /// so `and` and `or` return the operand that decided them.
69 jump_if_false,
70 /// Pops two values, with the right operand on top, and pushes their sum. Integers and booleans
71 /// add as integers, and two lists, two tuples or two strings join into a new object on the
72 /// heap. The operation fails with `IntegerOverflow` when the sum leaves the signed 128-bit
73 /// range, and with `TypeError` for any other pair of types.
74 add,
75 /// Pops two integers or booleans and pushes the left minus the right. The operation fails with
76 /// `IntegerOverflow` when the result leaves the signed 128-bit range, and with `TypeError` for
77 /// any other type.
78 sub,
79 /// Pops two values and pushes their product. Integers and booleans multiply as integers, and a
80 /// list, tuple or string on either side of an integer or boolean repeats into a new object on
81 /// the heap. A count of zero or less gives an empty sequence. The operation fails with
82 /// `IntegerOverflow` when the product or the repeated length overflows, and with `TypeError`
83 /// for any other pair of types.
84 mul,
85 /// Pops an integer or boolean and pushes its negation as an integer. The operation fails with
86 /// `IntegerOverflow` for the smallest signed 128-bit integer, and with `TypeError` for any
87 /// other type.
88 neg,
89 /// Pops a value and pushes `True` when the value is false by Python's truth rules, and `False`
90 /// otherwise.
91 not,
92 /// Pops two values and pushes whether they are equal, as `Value.eql` decides. Values of
93 /// unrelated types compare unequal, and the comparison returns no error.
94 equal,
95 /// Pops two values and pushes whether they are unequal, the negation of `equal`.
96 not_equal,
97 /// Pops two values and pushes whether the left is less than the right. Integers and booleans
98 /// compare as numbers, strings compare by their UTF-8 bytes, and lists and tuples compare item
99 /// by item. When one list or tuple is a prefix of the other, the shorter one is less. The
100 /// operation fails with `TypeError` for any other pair of types, including a list against a
101 /// tuple.
102 less,
103 /// Pops two values and pushes whether the left is less than or equal to the right, under the
104 /// ordering that `less` uses. The operation fails with `TypeError` for the pairs of types that
105 /// `less` rejects.
106 less_equal,
107 /// Pops two values and pushes whether the left is greater than the right, under the ordering
108 /// that `less` uses. The operation fails with `TypeError` for the pairs of types that `less`
109 /// rejects.
110 greater,
111 /// Pops two values and pushes whether the left is greater than or equal to the right, under the
112 /// ordering that `less` uses. The operation fails with `TypeError` for the pairs of types that
113 /// `less` rejects.
114 greater_equal,
115 /// Pops a container from the top, then an item, and pushes whether the item is in the
116 /// container, so `x in xs` pushes `x` first. A list or tuple matches an item that is the same
117 /// object or equal. A dictionary or its keys view tests its keys, a values view tests its
118 /// values, and an items view tests a two-item tuple against a key and its value. A range tests
119 /// membership from its start, stop and step, in constant time. A string tests for a substring.
120 /// An iterator takes items until one matches, so the items it passed are gone. The operation
121 /// fails with `TypeError` for an unhashable item tested against a dictionary or its keys, for
122 /// an item other than a string tested against a string, and for a container of any other type.
123 contains,
124 /// Pops a container from the top, then an item, and pushes whether the item is absent from the
125 /// container, under the rules of `contains`.
126 not_contains,
127 /// Pops two values and pushes whether they are the same object. `None`, booleans and integers
128 /// are the same when their values are. A boolean is never the same as an integer, although
129 /// `True == 1` holds. Two strings are the same when they start at the same address and have the
130 /// same length. Functions and builtins compare their positions and tags, and objects on the
131 /// heap compare their addresses.
132 identical,
133 /// Pops two values and pushes whether they are different objects, the negation of `identical`.
134 not_identical,
135 /// The operand is the number of arguments, which sit on top of the stack in order, with the
136 /// called value below them. A Python function takes the called value and the arguments off the
137 /// stack, binds each argument to its parameter in a new call frame, and runs the body, whose
138 /// `return_value` pushes the result. A builtin function or bound method runs at once and
139 /// replaces the called value and the arguments with its result. The operation fails with
140 /// `StackUnderflow` when the stack holds fewer values than the arguments and the called value,
141 /// with `ArityMismatch` when the number of arguments does not fit, with `InvalidFunction` when
142 /// a function value names no function, and with `TypeError` when the value cannot be called.
143 call,
144 /// Pops a list or dictionary and pushes its method, bound to that object and named by the
145 /// operand's position in the name table. Lists offer `append`, `clear`, `copy` and `pop`, and
146 /// dictionaries offer `clear`, `copy`, `get`, `items`, `keys`, `pop`, `popitem`, `setdefault`,
147 /// `update` and `values`. Each read creates a new bound method on the heap. The operation fails
148 /// with `AttributeError` for any other name and for any other type.
149 attribute,
150 /// Pops as many values as the operand says and pushes a new list of them, in the order they
151 /// were pushed. The operation fails with `StackUnderflow` when the stack holds fewer values.
152 build_list,
153 /// Pops as many values as the operand says and pushes a new tuple of them, in the order they
154 /// were pushed. The operation fails with `StackUnderflow` when the stack holds fewer values.
155 build_tuple,
156 /// The operand is the number of key and value pairs, and the stack holds each key followed by
157 /// its value. The operation pops all of them and pushes a new dictionary with the pairs in
158 /// stack order. A repeated key keeps its first position and takes the last value. The operation
159 /// fails with `TypeError` for an unhashable key, and with `IntegerOverflow` when twice the
160 /// operand overflows.
161 build_dict,
162 /// Pops a value and pushes an iterator over it. A list, tuple, range, string, dictionary or
163 /// dictionary view gets a new iterator on the heap, and a dictionary's iterator yields its
164 /// keys. An iterator goes back on the stack as it is. The operation fails with `TypeError` for
165 /// any other type.
166 iter,
167 /// The operand is the position of the first instruction after the loop body. The instruction
168 /// reads the iterator on top of the stack and pushes its next item above it. When the iterator
169 /// is exhausted, the operation pops it and continues at the operand's position. The operation
170 /// fails with `TypeError` when the top value is other than an iterator.
171 for_next,
172 /// Pops an index from the top, then a container, and pushes the item. A list or tuple takes an
173 /// integer or boolean index, counts a negative index from the end, and fails with `IndexError`
174 /// outside the sequence. A dictionary looks the key up and fails with `KeyError` when the key
175 /// is absent. The operation fails with `TypeError` for a sequence index other than an integer
176 /// or boolean, for an unhashable key, and for any other container, strings and ranges included.
177 subscript,
178 /// Pops the step, the stop and the start, then a container, and pushes the slice. The compiler
179 /// pushes `None` for each part the source leaves out. A list, tuple or string gives a new value
180 /// of the same type, and a range gives a new range. Strings are sliced by codepoint. A string
181 /// slice with step 1 points into the original bytes, and every other string slice is a copy on
182 /// the heap. The operation fails with `ValueError` for a step of zero or a string with invalid
183 /// UTF-8, and with `TypeError` for a bound other than an integer, boolean or `None`, and for
184 /// any other container.
185 slice,
186 /// Pops a value, an index and a container, and stores the value in the container at that index.
187 /// A list replaces the item at an integer or boolean index, counts a negative index from the
188 /// end, and fails with `IndexError` outside the list. A dictionary inserts the key or replaces
189 /// its value, and fails with `TypeError` when the key is unhashable. The operation fails with
190 /// `TypeError` for any other container, tuples included. The instruction pushes nothing.
191 store_subscript,
192 /// Pops an index from the top, then a container, and removes that item. A list removes the item
193 /// at the index and shifts the later items down, with the index rules and errors of
194 /// `subscript`. A dictionary removes the key, and fails with `KeyError` when the key is absent
195 /// and with `TypeError` when it is unhashable. The operation fails with `TypeError` for any
196 /// other container.
197 delete_subscript,
198 /// Pops the return value, ends the current call and pushes the value for the caller. In the
199 /// top-level frame, the operation ends the run with that value. The compiler emits it for
200 /// `return` and at the end of every function body. Before a `return` inside loops, the compiler
201 /// pops the iterators of those loops.
202 return_value,
203 /// Ends the current frame with the value that `save` last recorded, or with `None` when no
204 /// expression statement ran. The compiler emits it once, at the end of the top-level chunk.
205 ret,
206 };