pub enum Op {
Show 107 variants
LoadConst {
dst: u16,
idx: u32,
},
Move {
dst: u16,
src: u16,
},
EnsureOwned {
reg: u16,
},
Add {
dst: u16,
lhs: u16,
rhs: u16,
},
AddAssign {
dst: u16,
src: u16,
},
Sub {
dst: u16,
lhs: u16,
rhs: u16,
},
Mul {
dst: u16,
lhs: u16,
rhs: u16,
},
Div {
dst: u16,
lhs: u16,
rhs: u16,
},
ExactDiv {
dst: u16,
lhs: u16,
rhs: u16,
},
FloorDiv {
dst: u16,
lhs: u16,
rhs: u16,
},
Mod {
dst: u16,
lhs: u16,
rhs: u16,
},
DivPow2 {
dst: u16,
lhs: u16,
k: u8,
},
MagicDivU {
dst: u16,
lhs: u16,
magic: u64,
more: u8,
mul_back: i64,
},
Lt {
dst: u16,
lhs: u16,
rhs: u16,
},
Gt {
dst: u16,
lhs: u16,
rhs: u16,
},
LtEq {
dst: u16,
lhs: u16,
rhs: u16,
},
GtEq {
dst: u16,
lhs: u16,
rhs: u16,
},
Eq {
dst: u16,
lhs: u16,
rhs: u16,
},
ApproxEq {
dst: u16,
lhs: u16,
rhs: u16,
},
NotEq {
dst: u16,
lhs: u16,
rhs: u16,
},
Not {
dst: u16,
src: u16,
},
Concat {
dst: u16,
lhs: u16,
rhs: u16,
},
SeqConcat {
dst: u16,
lhs: u16,
rhs: u16,
},
Pow {
dst: u16,
lhs: u16,
rhs: u16,
},
BitXor {
dst: u16,
lhs: u16,
rhs: u16,
},
BitAnd {
dst: u16,
lhs: u16,
rhs: u16,
},
BitOr {
dst: u16,
lhs: u16,
rhs: u16,
},
Shl {
dst: u16,
lhs: u16,
rhs: u16,
},
Shr {
dst: u16,
lhs: u16,
rhs: u16,
},
Jump {
target: usize,
},
JumpIfFalse {
cond: u16,
target: usize,
},
JumpIfTrue {
cond: u16,
target: usize,
},
Call {
dst: u16,
func: u16,
args_start: u16,
arg_count: u16,
},
CallBuiltin {
dst: u16,
builtin: BuiltinId,
args_start: u16,
arg_count: u16,
},
CallValue {
dst: u16,
callee: u16,
args_start: u16,
arg_count: u16,
name_for_err: u32,
},
MakeClosure {
dst: u16,
func: u16,
locals_start: u16,
},
CheckPolicy {
subject: u16,
predicate: Symbol,
is_capability: bool,
object: u16,
source_text: u32,
},
ListPushField {
obj: u16,
field: u32,
src: u16,
},
GlobalGet {
dst: u16,
idx: u16,
},
GlobalSet {
idx: u16,
src: u16,
},
Return {
src: u16,
},
ReturnNothing,
NewList {
dst: u16,
start: u16,
count: u16,
},
NewEmptyList {
dst: u16,
},
NewEmptyListI32 {
dst: u16,
},
NewEmptySet {
dst: u16,
},
NewEmptyMap {
dst: u16,
},
NewRange {
dst: u16,
start: u16,
end: u16,
},
ListPush {
list: u16,
value: u16,
},
SetAdd {
set: u16,
value: u16,
},
RemoveFrom {
collection: u16,
value: u16,
},
SetIndex {
collection: u16,
index: u16,
value: u16,
},
SetIndexUnchecked {
collection: u16,
index: u16,
value: u16,
},
Index {
dst: u16,
collection: u16,
index: u16,
},
IndexUnchecked {
dst: u16,
collection: u16,
index: u16,
},
RegionBoundsGuard {
array: u16,
bound: u16,
iv: u16,
add_max: i32,
add_min: i32,
},
Length {
dst: u16,
collection: u16,
},
Contains {
dst: u16,
collection: u16,
value: u16,
},
FormatValue {
dst: u16,
src: u16,
spec: u32,
debug_prefix: u32,
},
SliceOp {
dst: u16,
collection: u16,
start: u16,
end: u16,
},
DeepClone {
dst: u16,
src: u16,
},
NewTuple {
dst: u16,
start: u16,
count: u16,
},
UnionOp {
dst: u16,
lhs: u16,
rhs: u16,
},
IntersectOp {
dst: u16,
lhs: u16,
rhs: u16,
},
LoadToday {
dst: u16,
},
LoadNow {
dst: u16,
},
NewStruct {
dst: u16,
type_name: u32,
},
StructInsert {
obj: u16,
field: u32,
value: u16,
},
GetField {
dst: u16,
obj: u16,
field: u32,
},
NewInductive {
dst: u16,
type_name: u32,
ctor: u32,
args_start: u16,
count: u16,
},
TestArm {
dst: u16,
target: u16,
variant: u32,
},
BindArm {
dst: u16,
target: u16,
field: u32,
index: u16,
},
CrdtBump {
obj: u16,
field: u32,
amount: u16,
negate: bool,
},
CrdtMerge {
target: u16,
source: u16,
},
NewCrdt {
dst: u16,
kind: u8,
},
CrdtAppend {
seq: u16,
value: u16,
},
CrdtResolve {
obj: u16,
field: u32,
value: u16,
},
IterPrepare {
iterable: u16,
},
IterNext {
dst: u16,
exit: usize,
},
IterPop,
ListPop {
list: u16,
dst: u16,
},
Sleep {
duration: u16,
},
DestructureTuple {
src: u16,
start: u16,
count: u16,
},
Show {
src: u16,
},
Args {
dst: u16,
},
ChanNew {
dst: u16,
cap: i32,
elem: ChanElem,
},
ChanSend {
chan: u16,
val: u16,
},
ChanRecv {
dst: u16,
chan: u16,
},
ChanTrySend {
dst: u16,
chan: u16,
val: u16,
},
ChanTryRecv {
dst: u16,
chan: u16,
},
ChanClose {
chan: u16,
},
Spawn {
func: u16,
args_start: u16,
arg_count: u16,
},
SpawnHandle {
dst: u16,
func: u16,
args_start: u16,
arg_count: u16,
},
TaskAwait {
dst: u16,
handle: u16,
},
TaskAbort {
handle: u16,
},
SelectArmRecv {
chan: u16,
var: u16,
},
SelectArmTimeout {
ticks: u16,
},
SelectWait {
dst_arm: u16,
},
NetConnect {
url: u16,
},
NetListen {
topic: u16,
},
NetSend {
to: u16,
msg: u16,
},
NetStream {
to: u16,
values: u16,
},
NetAwait {
dst: u16,
from: u16,
stream: bool,
},
NetMakePeer {
dst: u16,
addr: u16,
},
NetSync {
dst: u16,
topic: u16,
},
FailWith {
msg: u32,
},
Halt,
}Variants§
LoadConst
R[dst] = constants[idx]
Move
R[dst] = R[src] (shallow clone)
EnsureOwned
Copy-on-write barrier: if R[reg]’s collection is shared (Rc strong > 1),
deep-clone it in place so R[reg] becomes the sole owner. Emitted before an
argument is passed to a function whose corresponding parameter is an inferred
MUTABLE BORROW (mutated in place and returned): the callee’s element writes
then land on a buffer no OTHER live handle can observe, so an aliasing caller
(Let y be arr; Set arr to f(arr)) still sees value semantics. A no-op when
already uniquely owned (the common Set x to f(x) consume-reassign), so the
hot path pays only a strong-count check. Mirrors the AOT’s call-site .cow().
Add
AddAssign
R[dst] = R[dst] + R[src] — the Set x to x + … shape. Semantically
identical to Add { dst, lhs: dst, rhs: src }; the dedicated form lets
the VM append in place when R[dst] is a sole-owner Text (turning the
O(n²) build-a-string-by-concatenation loop into amortized O(n)).
Sub
Mul
Div
ExactDiv
EXACT division (7 / 2 → 7/2, a Rational), the type-directed sibling of
Op::Div — emitted for BinaryOpKind::ExactDivide.
FloorDiv
FLOOR division (-7 // 2 → -4, toward negative infinity) — emitted for
BinaryOpKind::FloorDivide, distinct from the truncating Op::Div.
Mod
DivPow2
dst = lhs / 2^k (signed, round toward zero) — emitted only when the
divisor is a literal power of two AND the Oracle proved lhs is Int.
A single op (the JIT lowers it to the side-exit-free divpow2 shift
stencil) so it fires for loop-invariant divisors the in-region JIT
detector misses, without the scratch-register pressure of an expansion.
MagicDivU
dst = lhs / c (mul_back == 0) or dst = lhs % c (mul_back == c),
where c is a compile-time-constant divisor that is NOT a power of two
(W5/DivPow2 handles powers of two), computed by the Granlund–Montgomery
/ libdivide UNSIGNED magic-reciprocal sequence (a mul-high + shift,
~3 cycles) instead of idiv (~25 cycles). magic/more are the
precomputed constants (the exact logicaffeine_data::LogosDivU64
encoding — low 6 bits of more are the shift, 0x40 is the 65-bit
add-marker path). Emitted ONLY when the Oracle proves lhs is Int and
NON-NEGATIVE: the unsigned magic equals the signed truncating //%
only for a non-negative dividend (for x < 0 the signs disagree, exactly
as for the % 2^k → & rewrite). The remainder is derived as
lhs - q*c (wrapping), bit-exact with the kernel’s wrapping_rem for
non-negative lhs.
Lt
Gt
LtEq
GtEq
Eq
ApproxEq
Tolerant float comparison (a is approximately b) — the shared
isclose semantics (logicaffeine_data::ops::logos_approx_eq);
==/Eq stays IEEE bit-exact.
NotEq
Not
Concat
SeqConcat
a followed by b — merge two sequences into one.
Pow
a ** b — exponentiation. Integer power is exact (promotes to BigInt on
overflow); a Float operand uses powf; a negative Int exponent errors.
BitXor
BitAnd
a & b — bitwise AND on Int, logical on Bool, intersection on Sets.
BitOr
a | b (see BitAnd) — union on Sets.
Shl
Shr
Jump
Unconditional jump to absolute instruction index.
JumpIfFalse
Jump if R[cond] is falsey.
JumpIfTrue
Jump if R[cond] is truthy.
Call
Call a user function. The caller has placed arg_count arguments in
consecutive registers starting at args_start (relative to the caller’s
frame base). The result is written to R[dst]. Uses register windowing.
CallBuiltin
Call a kernel builtin with already-evaluated arguments (arity was validated at compile time, mirroring the tree-walker’s arity-before-evaluation rule).
CallValue
Call the closure value in R[callee]. name_for_err is the function
name when this came from a by-name call (Unknown function: f when the
value is not callable) or u32::MAX for a call-by-expression
(Cannot call value of type T).
MakeClosure
Build a closure over program.functions[func]: its captures list is
snapshotted — local captures deep-cloned from the register window at
locals_start, global captures from the globals table (skipped when
still undefined; the body then falls through to the live global).
CheckPolicy
Check subject can/is predicate (of object) — kernel policy check.
object == Reg::MAX means no object.
ListPushField
Push value to obj's field — kernel push into a struct’s List field.
field is a Text constant (the resolved field name).
GlobalGet
R[dst] = globals[idx], error “Undefined variable: {name}” when unset.
GlobalSet
globals[idx] = R[src] (defines or overwrites).
Return
Return R[src] from the current function.
ReturnNothing
Return nothing from the current function.
NewList
R[dst] = [R[start], …, R[start+count-1]] (a new list).
NewEmptyList
NewEmptyListI32
R[dst] = a new half-width (Vec) Int sequence — emitted (behind
LOGOS_NARROW_VM) for a new Seq of Int declaration the narrowing
proof certified fits i32. Observably identical to NewEmptyList; only
the storage width differs (see crate::interpreter::ListRepr::IntsI32).
NewEmptySet
NewEmptyMap
NewRange
R[dst] = [R[start]..=R[end]] (inclusive integer range as a list).
ListPush
Append R[value] to the list in R[list] (mutates in place).
SetAdd
Add R[value] to the set in R[set] (no-op if already present).
RemoveFrom
Remove R[value] from the set/map in R[collection].
SetIndex
R[collection][R[index]] = R[value] (1-based list set, or map insert).
SetIndexUnchecked
Like SetIndex but the Oracle PROVED the index in [1, length]
(range analysis, M9) — bounds-check elimination for the STORE. The
interpreter still checks (free defense-in-depth); the JIT lowers it to
an UNCHECKED array store (no bounds branch). Only listy collections
with a stable length earn this, via index_provably_in_bounds.
Index
R[dst] = R[collection][R[index]] (1-based for ordered collections).
IndexUnchecked
Like Index but the Oracle (range analysis, M9) PROVED the index
in [1, length] at this point — bounds-check elimination, the V8/LLVM
way. The bytecode interpreter still checks (a sound proof makes the
check never fire; keeping it is free defense-in-depth), but the JIT
lowers it to an UNCHECKED array load (no bounds branch, no deopt).
Only listy collections with a stable length earn this; the compiler
emits it solely behind index_provably_in_bounds.
RegionBoundsGuard
REGION-ENTRY bounds-check hoist (V8 TurboFan loop bound-check
elimination). For a loop while iv </<= bound reading/writing
R[array] at affine indices, this asserts ONCE — at native region
entry — that the array is long enough for the whole loop:
length(R[array]) >= R[bound] + add_max and R[iv] + add_min >= 1.
If it holds, the region runs every covered access UNCHECKED; if not,
the VM declines the region and replays on bytecode (where the accesses
are checked). A pure no-op in the interpreter and the function tier —
speculation is region-only, made safe solely by this entry guard.
Length
R[dst] = length of R[collection].
Contains
R[dst] = R[collection] contains R[value].
FormatValue
R[dst] = Text(debug_prefix? + format(R[src], spec?)) — one
interpolated-string segment. u32::MAX = no spec / no prefix.
SliceOp
R[dst] = R[collection][R[start]..=R[end]] (1-indexed inclusive).
DeepClone
R[dst] = deep clone of R[src].
NewTuple
R[dst] = (R[start], …, R[start+count-1]) (immutable tuple).
UnionOp
IntersectOp
LoadToday
R[dst] = today (Date; honors the test fixed-clock).
LoadNow
R[dst] = now (Moment; honors the test fixed-clock).
NewStruct
R[dst] = Struct { type_name: constants[type_name], fields: {} }.
StructInsert
Insert R[value] under field constants[field] into the struct in
R[obj] (construction and SetField — structs have VALUE semantics, so
in-place mutation of the register equals the tree-walker’s
clone-mutate-reassign).
GetField
R[dst] = R[obj].field — “Field ‘{f}’ not found” / “Cannot access
field on {type}”.
NewInductive
R[dst] = Inductive { type, constructor, args: R[args_start..+count] }.
TestArm
R[dst] = Bool(struct type-name or inductive constructor == constants[variant]);
false for any other value.
BindArm
Inspect-arm binding: a Struct target binds fields[constants[field]],
an Inductive target binds args[index]. A missing field/index leaves
R[dst] unwritten (the tree-walker skips the bind — unreachable for
parsed programs, whose fields always exist after default-fill).
CrdtBump
GCounter/PNCounter bump of R[obj].field by R[amount] (negated for
Decrease — also selects the tree-walker’s increment/decrement wording).
CrdtMerge
GCounter merge: fold every field of R[source] into R[target].
NewCrdt
R[dst] = a fresh, empty rich CRDT — kind 0 = SharedSet (OR-Set),
1 = SharedSequence (RGA), 2 = Divergent (MV-register). Used to default-fill a
Shared struct’s CRDT fields, mirroring the tree-walker’s new-struct init.
CrdtAppend
RGA append: push R[value] onto the replicated sequence in R[seq] (mutates the
shared CRDT in place, so a field access propagates).
CrdtResolve
Resolve R[obj].field to R[value]: a real MV-register resolves in place, a plain
field is overwritten — the same fallback the tree-walker’s Resolve takes.
IterPrepare
Snapshot R[iterable] (List/Set items, Text chars, Map (k,v) tuples)
and push it onto the iterator stack.
IterNext
Load the next snapshot element into R[dst] and advance; jump to
exit when exhausted (the iterator stays pushed — IterPop at the
exit point drops it).
IterPop
Drop the top iterator.
ListPop
R[dst] = R[list].pop() — Nothing when empty (not an error).
Sleep
Sleep for R[nanos] (Duration nanos, or Int milliseconds).
DestructureTuple
Tuple-pattern binding: R[start..start+count] = tuple elements with
zip semantics (stops at the shorter side, like the tree-walker).
Errors when R[src] is not a Tuple.
Show
Emit R[src].to_display_string() to the output stream.
Args
R[dst] = the program argument vector as a Seq of Text (the
interpreter’s args() system native, mirroring the compiled binary’s
env::args(): index 0 is the program name). Outside the JIT integer
subset, so the adapters bail on it and it always runs in the VM.
ChanNew
R[dst] = a new channel; cap < 0 ⇒ the scheduler’s default capacity. elem is the
declared Pipe of T element type (a hint for a typed-queue consumer; the scheduler ignores it).
ChanSend
Send R[val] into channel R[chan] (blocks if the channel is full).
ChanRecv
R[dst] = receive from channel R[chan] (blocks if the channel is empty).
ChanTrySend
R[dst] = bool — non-blocking send of R[val] into R[chan].
ChanTryRecv
R[dst] = received value, or Nothing — non-blocking receive from R[chan].
ChanClose
Close channel R[chan].
Spawn
Spawn functions[func] with args in R[args_start..+arg_count] (fire-and-forget).
SpawnHandle
R[dst] = task handle of a spawned functions[func] (same arg convention).
TaskAwait
R[dst] = result of awaiting task R[handle] (Nothing if it was aborted).
TaskAbort
Abort task R[handle].
SelectArmRecv
Register a Receive var from chan arm for the next SelectWait.
SelectArmTimeout
Register an After ticks timeout arm for the next SelectWait.
SelectWait
Block on the registered select arms; R[dst_arm] = the winning arm index
(a recv arm’s received value is already in its var register).
NetConnect
Dial the relay at R[url] (async); resume when connected.
NetListen
Subscribe this node’s inbox to R[topic] (async); resume when subscribed.
NetSend
Encode R[msg] and publish it to peer R[to].
NetStream
Batch-stream the list R[values] to peer R[to].
NetAwait
R[dst] = await a message (or a batch stream, if stream) from peer R[from]`` (blocks).
NetMakePeer
R[dst] = a PeerAgent handle for address R[addr]`` (its canonical relay topic). Pure.
NetSync
CRDT sync point on topic R[topic]: publish R[dst]’s counter, merge what has arrived,
and write the merged value back to R[dst].
FailWith
Fail with the Text constant at msg — used for constructs whose
tree-walker semantics are “error WHEN EXECUTED” (an unbound Set, an
unsupported statement). Never fails at compile time: dead branches must
stay free.
Halt
Stop execution.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Op
impl<'de> Deserialize<'de> for Op
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Copy for Op
Auto Trait Implementations§
impl Freeze for Op
impl RefUnwindSafe for Op
impl Send for Op
impl Sync for Op
impl Unpin for Op
impl UnsafeUnpin for Op
impl UnwindSafe for Op
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.