Skip to main content

Opcode

Enum Opcode 

Source
pub enum Opcode {
Show 163 variants PushInt(i32), PushFloat(f32), PushBool(bool), PushString(u16), PushList(u16), PushDivertTarget(DefinitionId), PushNull, Pop, Duplicate, Add, Subtract, Multiply, Divide, Modulo, Negate, Equal, NotEqual, Greater, GreaterOrEqual, Less, LessOrEqual, Not, And, Or, GetGlobal(DefinitionId), SetGlobal(DefinitionId), DeclareTemp(u16), GetTemp(u16), SetTemp(u16), GetTempRaw(u16), PushVarPointer(DefinitionId), PushTempPointer(u16), Jump(i32), JumpIfFalse(i32), Goto(DefinitionId), GotoIf(DefinitionId), GotoVariable, EnterContainer(DefinitionId), ExitContainer, Call(DefinitionId), Return, TunnelCall(DefinitionId), TunnelReturn, TunnelCallVariable, CallVariable(u8), ThreadCall(DefinitionId), ThreadStart, ThreadDone, EmitLine(u16, u8), EmitValue, EmitNewline, EmitLineNl(u16, u8), BinaryImm(BinaryKind, i32), BinaryJumpIfFalse(BinaryKind, i32), BinaryImmJumpIfFalse(BinaryKind, i32, i32), GetTempBinaryImm(u16, BinaryKind, i32), GetTempBinaryImmJumpIfFalse(u16, BinaryKind, i32, i32), DuplicateBinaryImmJumpIfFalse(BinaryKind, i32, i32), Spring, Glue, BeginTag, EndTag, EvalLine(u16, u8), BeginFragment, EndFragment, AttachElement, EndElementRun, BeginChoice(ChoiceFlags, DefinitionId), EndChoice, Sequence(SequenceKind, u8), SequenceBranch(i32), VisitCount, CurrentVisitCount, TouchVisit, ShuffleIndexOf, TurnsSince, TurnIndex, ChoiceCount, Random, SeedRandom, CastToInt, CastToFloat, Floor, Ceiling, Pow, Min, Max, CallExternal(DefinitionId, u8), ListContains, ListNotContains, ListIntersect, ListAll, ListInvert, ListCount, ListMin, ListMax, ListValue, ListRange, ListFromInt, ListRandom, ArrayNew(u32), MapNew(u32), IndexGet, IndexSet, CollectionLen, MapGet, MapInsert, MapRemove, MapContains, CollectionKeys, CollectionValues, PushLiteral(u32), TakeGlobal(DefinitionId), TakeTemp(u16), RecordNew(u32), RecordGetDyn(u16), RecordSetDyn(u16), RecordGet(u16), RecordSet(u16), ConvertInt, ConvertFloat, ConvertString, PushFnRef(DefinitionId), MakeClosure { target: DefinitionId, bound_count: u8, }, CallValue(u8), BindValue(u8), MakeProjection { root: DefinitionId, segment_count: u8, }, ProjRead, ProjWrite, CharAt, PushNone, MakeSome, StrFind, SeqIndexOf, SeqMin, SeqMax, SeqFirst, SeqLast, SeqPop, MapGetOpt, MapContainsValue, MapClear, CoalesceSome(i32), OptionBind(u16), SeqRemoveAt, RandFloat, RandChance, RandPick, RandShuffle, RangeMakeExcl, RangeMakeIncl, RangeNonEmpty, SeqSorted, SeqSortedBy, Tower(TowerOp), Collect(CollectOp), SeqVerb(SeqVerbOp), Done, Yield, End, Nop, BeginStringEval, EndStringEval,
}
Expand description

A single VM instruction with its operands.

Variants§

§

PushInt(i32)

§

PushFloat(f32)

§

PushBool(bool)

§

PushString(u16)

§

PushList(u16)

§

PushDivertTarget(DefinitionId)

§

PushNull

§

Pop

§

Duplicate

§

Add

§

Subtract

§

Multiply

§

Divide

§

Modulo

§

Negate

§

Equal

§

NotEqual

§

Greater

§

GreaterOrEqual

§

Less

§

LessOrEqual

§

Not

§

And

§

Or

§

GetGlobal(DefinitionId)

§

SetGlobal(DefinitionId)

§

DeclareTemp(u16)

§

GetTemp(u16)

§

SetTemp(u16)

§

GetTempRaw(u16)

Get a temp’s raw value without auto-dereference (for passing a ref onward).

§

PushVarPointer(DefinitionId)

Push a pointer to a global variable onto the eval stack.

§

PushTempPointer(u16)

Push a pointer to a temp variable onto the eval stack.

§

Jump(i32)

§

JumpIfFalse(i32)

§

Goto(DefinitionId)

§

GotoIf(DefinitionId)

§

GotoVariable

§

EnterContainer(DefinitionId)

§

ExitContainer

§

Call(DefinitionId)

§

Return

§

TunnelCall(DefinitionId)

§

TunnelReturn

§

TunnelCallVariable

§

CallVariable(u8)

Call through a variable holding either a divert target (classic ink function-via-variable) or a function value (T1c-2 direct-call form f(args…)) — both share this dispatch site. argc is the exact number of args codegen pushed before the callee at this call site (never derived from the resolved target’s arity at runtime — issue #721: doing so made a gradual-mode direct-call arity mismatch leave a stray value on the stack instead of faulting). The divert-target arm ignores argc (unchanged oracle-verified behavior); the function-value arm pops exactly argc supplied args.

§

ThreadCall(DefinitionId)

§

ThreadStart

§

ThreadDone

§

EmitLine(u16, u8)

§

EmitValue

§

EmitNewline

§

EmitLineNl(u16, u8)

EmitLine(idx, slots) immediately followed by EmitNewline, as one instruction — the optimizer’s fusion of the single most common instruction pair in real stories (docs/optimizer-peephole.md). Its effect is exactly the two in sequence; the runtime shares their bodies. Never emitted by codegen.

§

BinaryImm(BinaryKind, i32)

PushInt(imm) followed by the binary operator kind, as one instruction: pops the left operand, applies kind with imm as the right operand, pushes the result. Optimizer-only (docs/optimizer-peephole.md §1); never emitted by codegen.

§

BinaryJumpIfFalse(BinaryKind, i32)

The binary operator kind followed by JumpIfFalse(rel), as one instruction: pops both operands, and jumps by rel (relative to the end of this instruction, as every relative jump is) when the result is not truthy. The result is not left on the stack. Optimizer-only.

§

BinaryImmJumpIfFalse(BinaryKind, i32, i32)

PushInt(imm), the binary operator kind, then JumpIfFalse(rel), as one instruction — the shape of every if x <= 1 and { x == 3: } in real stories. Operands are (kind, imm, rel). Optimizer-only.

§

GetTempBinaryImm(u16, BinaryKind, i32)

GetTemp(slot); PushInt(imm); op as one instruction: reads the temp exactly as GetTemp does (pointer auto-dereference, the #3354 unwritten-slot default and warning) and pushes left op imm. Operands are (slot, kind, imm). Optimizer-only.

§

GetTempBinaryImmJumpIfFalse(u16, BinaryKind, i32, i32)

GetTemp(slot); PushInt(imm); op; JumpIfFalse(rel) as one instruction — every if n <= 1 over a local. Operands are (slot, kind, imm, rel). Optimizer-only.

§

DuplicateBinaryImmJumpIfFalse(BinaryKind, i32, i32)

Duplicate; PushInt(imm); op; JumpIfFalse(rel) as one instruction: compares the top of the stack against imm without popping it and branches — the arm test of a switch-style { x: - 1: … - 2: … }. Operands are (kind, imm, rel). Optimizer-only.

§

Spring

Word break — renders as a single space between content parts.

§

Glue

§

BeginTag

§

EndTag

§

EvalLine(u16, u8)

§

BeginFragment

Begin capturing output into a fragment (structural preservation).

§

EndFragment

End fragment capture — store parts and push Value::FragmentRef.

§

AttachElement

An attach = StructName convention handler’s claimed line (issue #2108) — see brink_ir::hir::Stmt::AttachElement’s doc. Pops the call’s result off the value stack; when it is a Value::Record matching a known StructShapes entry, merges its fields (converted via the same stringify display path as string()/interpolation) into the VM’s per-block attachment state — no output, no Step::Line.

§

EndElementRun

Closes the run an AttachElement opened — see brink_ir::hir::Stmt::EndElementRun’s doc. Clears the VM’s accumulated attachment data and starts a fresh block.

§

BeginChoice(ChoiceFlags, DefinitionId)

§

EndChoice

§

Sequence(SequenceKind, u8)

§

SequenceBranch(i32)

§

VisitCount

Pop a DivertTarget from the stack, push its visit count.

§

CurrentVisitCount

Push the visit count of the current container (no stack input).

§

TouchVisit

#3273 (line-variant groups): pop a DivertTarget, increment that container’s visit count, and push the pre-increment count as an Int — the 0-based “how many times has this alternative been viewed” index a shared inline alternative’s branch selection is computed from. The increment is the point: the container is never entered (its text lives in the enumerated line-variant table, not in its body), so this is the one place its view is recorded. A non-DivertTarget operand pushes 0 and records nothing, mirroring Opcode::VisitCount’s malformed-input tolerance.

§

ShuffleIndexOf

#3273 (line-variant groups): pop a DivertTarget, then num_elements, then seq_count (both Int), and push the shuffle branch index for THAT container — the same partial-Fisher–Yates selection Opcode::Sequence(Shuffle) performs, but seeded by the named container’s path_hash instead of the current one’s. Two shared shuffles on one line must not share a seed, or their permutations correlate; the current container (the line’s scope) is the same for both, so the current-container form cannot serve.

§

TurnsSince

§

TurnIndex

§

ChoiceCount

§

Random

§

SeedRandom

§

CastToInt

§

CastToFloat

§

Floor

§

Ceiling

§

Pow

§

Min

§

Max

§

CallExternal(DefinitionId, u8)

§

ListContains

§

ListNotContains

§

ListIntersect

§

ListAll

§

ListInvert

§

ListCount

§

ListMin

§

ListMax

§

ListValue

§

ListRange

§

ListFromInt

§

ListRandom

§

ArrayNew(u32)

[elem_0, …, elem_{n-1}]Array([elem_0, …, elem_{n-1}]).

§

MapNew(u32)

[k_0, v_0, …, k_{n-1}, v_{n-1}]Map({k_0: v_0, …}) (insertion order = argument order; a repeated key keeps its first position and takes the last value, matching OrderedMap::insert).

§

IndexGet

[container, index] → element/value. Turn-terminating fault on out-of-bounds array index or missing map key (value-model-spec §6).

§

IndexSet

[container, index, value] → updated container (take → make_mut → write-back). Turn-terminating fault on out-of-bounds array index or missing map key — no silent growth on write-past-end (spec §6).

§

CollectionLen

[container]Int(len). Array or map.

§

MapGet

[map, key] → value. Turn-terminating fault on missing key.

§

MapInsert

[map, key, value] → updated map (insert-or-overwrite; unlike IndexSet, a missing key is not a fault — this is the stdlib insert() mutator’s primitive).

§

MapRemove

[map, key] → updated map with key removed (no-op if absent — the stdlib remove() mutator’s primitive). Map-only as of issue #1484: a non-map container is a turn-terminating fault (NotIndexable). The array-index leg this op used to generalize over is SeqRemoveAt.

§

MapContains

[map, key]Bool.

§

CollectionKeys

[map]Array of keys in insertion order.

§

CollectionValues

[map]Array of values in insertion order.

§

PushLiteral(u32)

LiteralPool[idx] → cloned value (an Arc bump for collections).

§

TakeGlobal(DefinitionId)

Move a global’s current value out, leaving Value::Null behind — the take-half of the take → make_mut → write-back RMW discipline (value-model-spec §5). No stack input; pushes the taken value. Unlike GetGlobal, never auto-dereferences (globals can’t hold ref-param pointers — those live in temps).

§

TakeTemp(u16)

Move a temp’s current value out, leaving Value::Null behind — mirrors TakeGlobal for temp slots. Auto-dereferences like GetTemp: if the temp holds a VariablePointer/TempPointer, the pointed-to location is taken (and left Null), not the pointer value itself, which stays in this slot untouched.

§

RecordNew(u32)

[field_0, …, field_{n-1}]Record (n = the shape’s declared field count, looked up from StructShapes; fields popped/assigned in shape declaration order). The u32 operand is the ShapeId.

§

RecordGetDyn(u16)

[record] → field value, looked up by name (NameId operand) in the record’s own shape. Turn-terminating fault if the shape has no field by that name (value-model-spec §11c).

§

RecordSetDyn(u16)

[record, value] → updated record (take → make_mut → write-back), field selected by name (NameId operand). Turn-terminating fault if the shape has no field by that name.

§

RecordGet(u16)

[record] → field value, looked up by flat offset into the record’s own field vector (TM-4c, docs/typed-mode-spec.md §6 static-offset payoff). Emitted only when the record’s shape is compile-time known (types = strict); turn-terminating fault if the offset is out of range for the popped record’s field count — no shape re-check.

§

RecordSet(u16)

[record, value] → updated record (take → make_mut → write-back), field selected by flat offset (TM-4c). Turn-terminating fault if the offset is out of range.

§

ConvertInt

[x]Int. The int(x) pure conversion intrinsic: Int (identity), Float (truncate toward zero, matching vanilla ink’s INT()), Bool (true → 1, false → 0), String (parse). Turn-terminating fault on a string that fails to parse, or on any value outside this permissive numeric+bool domain (divert targets, LIST values, arrays, maps, records) — value-model-spec §11c.

§

ConvertFloat

[x]Float. The float(x) pure conversion intrinsic: Float (identity), Int (widen), Bool (true → 1.0, false → 0.0), String (parse). Same fault domain as ConvertInt.

§

ConvertString

[x]String. The string(x) pure conversion intrinsic: display form, identical to interpolation ({x}) — total over every Value, never faults (typed-mode-spec §4: “display is universal, not a coercion”).

§

PushFnRef(DefinitionId)

[]FnRef. Push a zero-bound function value for the target DefinitionId (#fn(name) where the target has no ref params).

§

MakeClosure

[bound_0, …, bound_{n-1}]Closure. Pop the n = bound_count bound args (in declared order) and pair each with its param name/mode read from the target container’s own [ContainerDef::params] table (the bound prefix params[0..n]) to build a Closure. A ref bound arg is a VariablePointer (a captured durable cell); a val bound arg is a snapshot. The names/modes are read from the signature (not baked into the opcode) so there is one source of truth the rehydration check compares against.

Fields

§bound_count: u8
§

CallValue(u8)

[arg_0, …, arg_{argc-1}, callee] → return value. Pop the callee function value then the argc supplied (val-only) args, splice the closure’s bound prefix ahead of them, and enter the target. Faults (turn-terminating, docs/t1c-spec.md §3): callee is not a function value; bound + argc ≠ the target’s declared arity; a rehydrated env entry’s name/mode no longer matches the current signature; the callee ref-binds a #@local and is invoked from a non-creating flow.

§

BindValue(u8)

[arg_0, …, arg_{argc-1}, callee] → new function value. The bind(f, args…) stdlib intrinsic (T1c-3, docs/t1c-spec.md §3): pop the callee function value then the argc supplied (val-only) args, append them to the callee’s bound-arg row (val-only currying, consuming the head of the remaining param row), and push the new function value. The appended entries take their param name/mode from the target’s signature (always val). Faults (turn-terminating): callee is not a function value; bound + argc exceeds the target’s declared arity.

§

MakeProjection

[seg_0, …, seg_{n-1}]Projection (n = segment_count, pushed by codegen in source order; the VM’s LIFO pop-then-reverse restores it). Each popped value is classified IntProjSegment::Index, else → ProjSegment::Key and paired with the static root cell to build a Value::Projection (docs/format-v4-rfc.md §1). Emitted at every real path-projection ref-argument creation site (ref npc.inventory[3]) — the T1e-1 E099 lowering fence this replaces.

Fields

§segment_count: u8
§

ProjRead

[projection] → value. Root-cell RMW read: take the root cell’s current value, walk the segment chain, push the result. Faults ProjectionInvalidated (turn-terminating) if the path no longer resolves (spec §1(2)).

§

ProjWrite

[projection, value] → (assigns, pushes nothing). Root-cell RMW write: take root → walk → make_mut spine → write the final segment → store back (spec §3). Faults ProjectionInvalidated on an unresolved path, same domain as ProjRead.

§

CharAt

[s, i] → single-character String. The char_at(s, i) stdlib pure function: i indexes Unicode scalar values (“chars”), not UTF-8 bytes. Turn-terminating fault (value-model-spec §11c) on a non-Int i, a non-String s, or i outside [0, char_count).

§

PushNone

[]none. Push the Option[T] absence value.

§

MakeSome

[x]some(x). Wrap the top of stack — total over every value.

§

StrFind

[s, sub]Option[int]: index of sub’s first occurrence in s, counted in Unicode scalar values (chars, not bytes — the §3 indexing unit char_at already uses); absent → none. Turn-terminating fault on non-string arguments.

§

SeqIndexOf

[a, x]Option[int]: index of the first element structurally equal to x; absent → none. Fault on a non-array container.

§

SeqMin

[a]Option[T]: least element (empty → none). Orders int/float (numeric promotion, NaN per the §4b pinned prod order), bool, string; anything else faults (unorderable — wave A4 grows the roster). Ties keep the first occurrence.

§

SeqMax

[a]Option[T]: greatest element — see SeqMin.

§

SeqFirst

[a]Option[T]: first element (empty → none).

§

SeqLast

[a]Option[T]: last element (empty → none).

§

SeqPop

[a] → pushes Option[T] (the removed last element, or none on empty), then the shrunk array on top of it. Codegen brackets this TakeGlobal/TakeTempSetGlobal/SetTemp so the array writes back to its root cell and the Option remains as the expression’s value. Fault on a non-array.

§

MapGetOpt

[m, k]Option[V]: the non-faulting map read (get(m, k), §5 — martyr #3 redeemed). Missing key → none; a key outside the int/string/bool key domain is a turn-terminating fault (malformed question), as is a non-map container. The faulting m[k] (MapGet) stays the “I expect it there” read.

§

MapContainsValue

[m, v]Bool: content-equality scan over the map’s values (§5 — honest O(n)). Fault on a non-map.

§

MapClear

[m] → empty map. The clear(m) statement-only mutator’s primitive; in-place-ness comes from the RMW write-back, exactly like MapInsert/MapRemove. Fault on a non-map.

§

CoalesceSome(i32)

Pops lhs (must be an OptionVal). some(v) pushes the unwrapped v and jumps rel bytes forward (the same relative-offset convention as Jump/JumpIfFalse); none pushes nothing and falls through to the next instruction, which evaluates rhs. That fall-through is the short-circuit: rhs’s bytecode is only ever reached when lhs is nonex or expensive() runs expensive() exactly once, and only on none (RULED, issue #1471, flipping the eager evaluation PR #1469/#1460 landed and flagged as unruled). Native-surface only: reachable exclusively through InfixOp::Coalesce, which the native lowering path alone produces (InfixOp::Or, ink’s boolean ||, is untouched and oracle-frozen).

The jump target is where the two branches join: the some(v) branch has already unwrapped to v, and the none branch pushed rhs as-is. Codegen emits a MakeSome right at that target exactly when the step’s recorded typing says rhs is itself Option[U] (the two-Option form, (Option[T],Option[T]) -> Option[U], preserving optionality for chaining), so both branches agree on shape at the join; for the collapse form ((Option[T],T)->T) no MakeSome is emitted and v stands unwrapped. The retired binary opcode decided that from rhs’s runtime value; short-circuiting rules that out (rhs may never run by the time the answer is needed), so the decision is made at lowering time from the analyzer’s recorded types — see below.

§Where the collapse-vs-preserve answer comes from

RULED (maintainer, 2026-07-26, issue #1492 — docs/decision-log.md “Lowering consumes analyzer types”): typing verdicts belong to brink-analyzer, which records each or step’s operand/result types for LIR lowering (brink_analyzer::coalesce_types, threaded to lowering as brink_ir::lir::CoalesceLookup). Lowering consumes that verdict; it never re-derives it from syntax. Under types = strict an ill-typed chain never reaches codegen at all — E066 rejects it during analysis — so this op only ever executes a chain analysis either accepted or could not statically pin.

§The runtime check is the semantics for an unpinned lhs

That second case is the gradual-mode posture, and it is deliberate: when the left-hand type is unknown (brink dialect, types = gradual — the un-overridden native default), the check this op performs is the operator’s semantics, not a fallback for a missing one. An OptionVal coalesces; a plain value raises the TypeError fault (brink_runtime::value_ops::coalesce_unwrap_some) — the same class as every other gradual runtime check. Strict/native never reaches this path with an unpinned lhs, and the analyzer records exactly this case as CoalesceShape::RuntimeCheck, on which codegen emits no MakeSome: with rhs possibly never evaluated there is no value to read a shape off, so the unwrapped collapse form is the one shape that stays sound for the (Option[T],T)->T reading the check admits.

§

OptionBind(u16)

[opt][bool] — the as binding’s fused test-and-bind (if EXPR as name { … }, while EXPR as name { … }, {if EXPR as name: … else: …}). opt must be an OptionVal: some(v) stores the unwrapped v in temp slot and pushes true; none leaves slot untouched and pushes false. A non-OptionVal operand faults (RuntimeError::AsBindingNotOption — the gradual-mode residual of the checker’s E147).

The slot is always freshly allocated by the binding itself, so — unlike SetTemp — the write needs no pointer/projection write-through: an as binding can never land on a ref parameter’s cell. Native-surface only.

§

SeqRemoveAt

[a, i] → updated array with the element at i removed (shifts later elements left) — the stdlib remove_at() mutator’s primitive, the array-index leg MapRemove generalized over before this PR. Array-only: a non-array a is a turn-terminating fault (NotIndexable). i must be an Int in [0, len) — strictly less than len, matching IndexGet/IndexSet (there is no element to remove at len, unlike MapInsert’s append-friendly <=).

§

RandFloat

[]Float uniform in [0,1). One draw. The value is built from the draw’s top 24 bits (draw >> 7) divided by 2²⁴, so every result is exactly representable in the f32 payload and 1.0 is unreachable — part of the pinned-algorithm stability contract (see brink-runtime::rand_ops).

§

RandChance

[p]Bool: one uniform [0,1) draw u, result u < p with p clamped to [0,1] and NaN → false (F3, ruled 2026-07-19: interpretation, not fabrication — total over the numeric domain). Always consumes exactly one draw, NaN included. Fault on a non-numeric p (malformed question).

§

RandPick

[coll]Option[T]: uniform draw of one element from an array (→ some(elem)) or a flags subset (→ some(single-item list), mirroring the frozen ListRandom selection). Empty → none without consuming a draw. Fault on any other collection type.

§

RandShuffle

[a][a']: Fisher-Yates shuffle of an array, len-1 draws (none for len < 2), each advancing the RNG cell. One op serves both surfaces: shuffle(a) (statement-only, RMW write-back) and shuffled(a) (functional). Fault on a non-array.

§

RangeMakeExcl

[start, end]Range (NS-A5, F7): construct an exclusive (start..end) range value from two int bounds. Fault on non-int bounds (malformed question — the T1b stdlib doctrine; no numeric coercion, range bounds are ints by ruling).

§

RangeMakeIncl

[start, end]Range (NS-A5, F7): construct an inclusive (start..=end) range value from two int bounds. Same fault contract as RangeMakeExcl.

§

RangeNonEmpty

[r]Option[Range] (NS-A5, the non_empty(r) validator — S2 ruled 2026-07-19): some(r) when the range denotes at least one element, none when it is empty. The Option tax sits once at the boundary where dynamic bounds enter; the checker types the some payload as the inhabited-range refinement. Pure — no draw, no write. Fault on a non-range operand.

§

SeqSorted

[a][a']: the array sorted ascending by the §4b ordering doctrine — int/float (numeric promotion), bool (false < true), string (USV-lexicographic), arrays lexicographic element-wise (recursively). Stable (equal elements keep their input order). Float NaN is mode-dependent: DEV mode faults on any NaN comparand (UnorderedComparand — the upstream bug surfaces at its first ordering consumption); PROD mode places it by the pinned non-fabricating total order (-0 == +0 ties, NaN greatest, NaN-vs-NaN ties). One op serves both surfaces: sort(a) (statement-only, RMW write-back) and sorted(a) (functional) — the RandShuffle precedent. Fault on a non-array or unorderable elements (structs/enums without a registered compare, maps, flags subsets, divert targets — malformed question, all modes).

§

SeqSortedBy

[a, cmp][a']: the array sorted ascending by a user comparator — cmp is a function value (FnRef/Closure) of shape fn(T, T): int (negative = less, zero = tie, positive = greater; F0 ruled 2026-07-19). Stable. The comparator runs under the pure·silent contract (checker-enforced where provable); the VM evaluates it re-entrantly with output isolated and faults if it yields, presents choices, calls an external, or returns a non-int. No NaN check here — F14: sort_by does not inherit F:float; the comparator owns the element semantics. One op serves sort_by(a, cmp) (statement-only, RMW write-back) and sorted_by(a, cmp) (functional). Fault on a non-array or non-function comparator.

§

Tower(TowerOp)

One opcode, thirteen operations: the TowerOp immediate selects the constructor or verb (see its per-kind docs for stack shapes). All pure; wrong-operand-type is a turn-terminating fault (a malformed question, per the ruled fault-vs-absence doctrine). The tower’s operator family (+/-/*, mat*vec, quat*quat, quat*vec) rides the frozen arithmetic opcodes instead — see value_ops::binary_op.

§

Collect(CollectOp)

One opcode, five operations: the CollectOp immediate selects Weighted[T] construction, the rand::roll draw, or one of the heap verbs (see its per-kind docs for stack shapes). RandRoll writes the RNG cell; HeapPush carries the §4b dev/prod NaN entry-check; everything else is pure over its operands.

§

SeqVerb(SeqVerbOp)

One opcode, one operation per SeqVerbOp kind: the pure trio map/filter/fold. Every kind pops a callback function value (FnRef/Closure) and evaluates it re-entrantly per element with output isolated — the SeqSortedBy machinery, one callback contract. See the per-kind docs for stack shapes.

§

Done

§

Yield

Pause for choice presentation. Like Done but does NOT set did_safe_exit — if no choices are pending, the story ran out of content rather than reaching an explicit -> DONE.

§

End

§

Nop

§

BeginStringEval

§

EndStringEval

Implementations§

Source§

impl Opcode

Source

pub const TARGET_OPERAND_LEN: usize = 8

The width of a static-target operand: one DefinitionId.

Source

pub fn encode(&self, buf: &mut Vec<u8>)

Encode this instruction into the byte buffer.

Source

pub fn peek_static(buf: &[u8], offset: usize) -> Option<StaticSite>

Classify the instruction at buf[offset] as one whose only DefinitionId operand is static — a jump/call address or a global variable — and locate that operand, without decoding it.

This is an encoding fact about the instruction stream, offered to the runtime’s linker: it resolves each such operand once and, in its own linked copy of the code, replaces the id bytes with a resolved form of its choosing. Opcode::decode is not defined over that copy (a replaced operand is no longer a valid DefinitionId), which is why the runtime keeps the symbolic bytecode for every decoder besides its own dispatch. Returns None for any other instruction, and for a truncated buffer.

Source

pub fn peek_target(buf: &[u8], offset: usize) -> Option<TargetSite>

Self::peek_static restricted to the jump/call targets.

Source

pub fn decode(buf: &[u8], offset: &mut usize) -> Result<Self, DecodeError>

Decode a single instruction from buf starting at *offset.

On success, *offset is advanced past the consumed bytes.

Trait Implementations§

Source§

impl Clone for Opcode

Source§

fn clone(&self) -> Opcode

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Opcode

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Opcode

Source§

fn eq(&self, other: &Opcode) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Opcode

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.