pub trait Kernel:
Send
+ Sync
+ KernelInternals {
Show 46 methods
// Required methods
fn engine(&self) -> Engine;
fn set_inputs(&mut self, coords: &[u64]);
fn set_input(&mut self, name: &str, value: Value) -> Result<(), WriteError>;
fn set_cursor(
&mut self,
name: &str,
partition: &Partition,
) -> Result<(), WriteError>;
fn eval(&mut self);
fn pull(&mut self, name: &str) -> Value;
fn input_names(&self) -> Vec<String>;
fn output_names(&self) -> Vec<String>;
fn output_type(&self, name: &str) -> Option<PortType>;
fn externs(&self) -> Vec<(String, PortType)>;
fn cursor_schemas(&self) -> &[SourceSchema];
fn plan(&self) -> EnginePlan;
fn input_value(&self, name: &str) -> Option<Value>;
fn const_inits(&self) -> &[ConstInit];
fn init_input_at(
&mut self,
index: usize,
value: Value,
) -> Result<(), WriteError>;
fn traversals(&self) -> &[Traversal];
fn traverse(&mut self, index: usize) -> Result<TraversalStream, String>;
fn invalidate_all(&mut self);
fn shared_cells(&self) -> Vec<SharedCellEntry>;
fn attach_shared_cell(
&mut self,
name: &str,
cell: SharedCell,
) -> Result<(), String>;
fn into_program(self: Box<Self>) -> Arc<dyn KernelProgram> ⓘ;
fn ledger(&self) -> &Arc<CompileLedger> ⓘ;
fn coord_count(&self) -> usize;
fn input_value_at(&self, index: usize) -> Option<Value>;
fn input_default_at(&self, index: usize) -> Option<Value>;
fn input_is_cell_bound(&self, index: usize) -> bool;
fn reset_inputs(&mut self);
fn fork(&self) -> Box<dyn Kernel>;
fn publish_broadcasts(&mut self);
fn commit_write_throughs(&mut self) -> Result<(), String>;
fn input_type_origin(&self, name: &str) -> Option<TypeOrigin>;
fn program_id(&self) -> ProgramId;
// Provided methods
fn input_index(&self, name: &str) -> Option<usize> { ... }
fn set_input_at(
&mut self,
index: usize,
value: Value,
) -> Result<(), WriteError> { ... }
fn output_index(&self, name: &str) -> Option<usize> { ... }
fn pull_at(&mut self, index: usize) -> Value { ... }
fn init(&mut self) -> Result<(), KernelError> { ... }
fn traverse_all(&mut self) -> Result<Vec<TraversalStream>, String> { ... }
fn output_cell(&self, _name: &str) -> Option<SharedCell> { ... }
fn output_modifier(&self, _name: &str) -> BindingModifier { ... }
fn cells_in_scope(&self) -> Vec<SharedCellEntry> { ... }
fn set_transit_cells(&mut self, _cells: Vec<SharedCellEntry>) { ... }
fn scope_coordinates(&self) -> &[ScopeCoord] { ... }
fn extend_scope_coordinates(&mut self, _outer: &[ScopeCoord]) { ... }
fn input_port_type(&self, _name: &str) -> Option<PortType> { ... }
fn bind_input_cell(&mut self, _name: &str, _cell: SharedCell) -> bool { ... }
}Expand description
A kernel on any engine: the interpreter, the closure tier, the hybrid kernel, or pure native code. Every engine accepts every program the interpreter accepts, or refuses it at construction with a reason, and computes the same values for the same inputs; the choice of engine changes how fast a program runs and nothing else. This trait is the surface a host drives an engine through without knowing which one it has.
The interpreter kernel and the compiled kernels also keep their
inherent methods (raw slot readers, eval(&[u64]), engine_counts)
as engine-specific extras; where a name is shared, the inherent
method is the one a call on the concrete type reaches, and the
trait’s is reached through dyn Kernel or Kernel::pull(&mut k, …).
Required Methods§
Sourcefn set_inputs(&mut self, coords: &[u64])
fn set_inputs(&mut self, coords: &[u64])
Set the coordinate inputs for the next evaluation.
Sourcefn set_input(&mut self, name: &str, value: Value) -> Result<(), WriteError>
fn set_input(&mut self, name: &str, value: Value) -> Result<(), WriteError>
Set an extern by name. One rule on every engine: the value must
satisfy the declared port type (a carrier’s bit-stuffed forms
included) or be None, which clears the extern; a value of
another type is refused at the write, never healed. A coordinate
is set with Self::set_inputs, not here. An unknown name is
an error naming the known ones.
Sourcefn set_cursor(
&mut self,
name: &str,
partition: &Partition,
) -> Result<(), WriteError>
fn set_cursor( &mut self, name: &str, partition: &Partition, ) -> Result<(), WriteError>
Narrow a cursor to one partition: its Ext slot and its six
scalar projections are set.
Sourcefn pull(&mut self, name: &str) -> Value
fn pull(&mut self, name: &str) -> Value
The named output for the inputs set so far, evaluating what it
needs and no more: the output’s cone, on the interpreter, the
closure tier, and the hybrid kernel alike (pure native code,
being one function, evaluates the program). A side channel in
the cone fires when the output is pulled; a failing node fails
when pulled, with the same attributed message on every engine:
the node’s name, the outputs it feeds, the program’s context,
and its inputs. The value is owned; a handle is never returned to
the host, and a slot that holds None reads as None.
Sourcefn input_names(&self) -> Vec<String>
fn input_names(&self) -> Vec<String>
Every input by name, the coordinates first.
Sourcefn output_names(&self) -> Vec<String>
fn output_names(&self) -> Vec<String>
Every named output.
Sourcefn output_type(&self, name: &str) -> Option<PortType>
fn output_type(&self, name: &str) -> Option<PortType>
The declared port type of a named output.
Sourcefn cursor_schemas(&self) -> &[SourceSchema]
fn cursor_schemas(&self) -> &[SourceSchema]
The cursors the program declares, with the partitions the compiler resolved where it could.
Sourcefn plan(&self) -> EnginePlan
fn plan(&self) -> EnginePlan
What this kernel’s engine decided for the program: how much of it runs as native segments, as closure steps, and on the interpreter. The one planning detail a kernel exposes.
Sourcefn input_value(&self, name: &str) -> Option<Value>
fn input_value(&self, name: &str) -> Option<Value>
The value of a named input as the kernel holds it now, an extern
or a coordinate; None for a name that is not an input.
Sourcefn const_inits(&self) -> &[ConstInit]
fn const_inits(&self) -> &[ConstInit]
The const bindings this kernel initializes, in the order
Self::init evaluates them: a const that reads another comes
after it.
Sourcefn init_input_at(
&mut self,
index: usize,
value: Value,
) -> Result<(), WriteError>
fn init_input_at( &mut self, index: usize, value: Value, ) -> Result<(), WriteError>
Write an input as part of initialization. It is
Self::set_input_at except that a const’s slot is accepted,
which is how Self::init stores each const’s value.
Sourcefn traversals(&self) -> &[Traversal]
fn traversals(&self) -> &[Traversal]
The traversals the program declares, in document order.
Sourcefn traverse(&mut self, index: usize) -> Result<TraversalStream, String>
fn traverse(&mut self, index: usize) -> Result<TraversalStream, String>
Open the traversal at index against this kernel’s current
values (SRD 113 §3.6): the comprehension’s sources see the wires
they reference as this kernel holds them now, and the cascaded
wires are snapshotted into every activation. On every engine
(engine parity, step 8).
Sourcefn invalidate_all(&mut self)
fn invalidate_all(&mut self)
Begin the next cycle with nothing current, so every step, a side
channel included, runs again when pulled. The runtime model makes
a cycle whose inputs did not move cost nothing; this is how a
host runs such a cycle anyway, as the polydat binary does when
every input is fixed.
The cells this kernel’s shared bindings are bound to (scope
model §6): one register per binding, which every kernel holding
the cell reads and writes.
Bind the shared binding name to cell, so this kernel and
every other holder of the cell read and write one register:
a write on any of them is what the others read next, and a
dependent output is recomputed. A name that is not a shared
binding is an error naming the ones that are.
Sourcefn into_program(self: Box<Self>) -> Arc<dyn KernelProgram> ⓘ
fn into_program(self: Box<Self>) -> Arc<dyn KernelProgram> ⓘ
The program this kernel runs, shareable across threads: each
thread creates its own kernel from it with
KernelProgram::create_kernel.
What this kernel was set to does not travel with it. A
kernel created from the program starts at the program: every
extern at its declared default and every shared binding with
a cell of its own, whatever this kernel had been written to
before it became one. That holds on every engine.
The reason is that an extern is per-kernel state, in the same
family as the coordinates: both are writes into declared slots
of a running kernel, and neither is part of the compiled
program. A host that wants a value fixed for the program
fixes it before compiling, with
transform::assign_values
or an extern default in the source; a host that wants every
thread to see one register attaches a cell with
Self::attach_shared_cell.
Sourcefn ledger(&self) -> &Arc<CompileLedger> ⓘ
fn ledger(&self) -> &Arc<CompileLedger> ⓘ
The compile ledger of the program tree this kernel belongs to: what compiling it and everything opened from it has built.
Sourcefn coord_count(&self) -> usize
fn coord_count(&self) -> usize
How many of the inputs are coordinates: they come first in
input_names, and set_inputs writes them.
Sourcefn input_value_at(&self, index: usize) -> Option<Value>
fn input_value_at(&self, index: usize) -> Option<Value>
The value input index holds now: a coordinate’s pending or
current value, an extern’s current value. None past the end.
Sourcefn input_default_at(&self, index: usize) -> Option<Value>
fn input_default_at(&self, index: usize) -> Option<Value>
The value input index starts with: an extern’s declared
default, U64(0) for a coordinate. None past the end.
Sourcefn input_is_cell_bound(&self, index: usize) -> bool
fn input_is_cell_bound(&self, index: usize) -> bool
Whether input index is bound to a shared cell, so that its
value is the cell’s and a reset leaves it alone.
Sourcefn reset_inputs(&mut self)
fn reset_inputs(&mut self)
Every input that is not a coordinate and not bound to a cell back at its default, and whatever depends on a changed one not current. What a host does at a boundary where values written for the last stretch must not leak into the next.
Sourcefn fork(&self) -> Box<dyn Kernel>
fn fork(&self) -> Box<dyn Kernel>
A new kernel over the same program with this kernel’s state: its inputs, its current outputs, and its cells, which stay shared (a cell is the scope’s register, not a value it holds), transit cells included. Callable concurrently on a kernel shared across threads (native_scope_trees.md §4).
Sourcefn publish_broadcasts(&mut self)
fn publish_broadcasts(&mut self)
Pull every output a descendant bound to by cell, so the descendant reads the current value. Nothing happens on a kernel nothing is bound under. A failing output is left for the pull that needs it to report.
Sourcefn commit_write_throughs(&mut self) -> Result<(), String>
fn commit_write_throughs(&mut self) -> Result<(), String>
Commit the Rule 2 write-throughs: pull each synthetic
__write_<name> output and write it through the cell of the
shared binding it exports to. No-op for a kernel without them.
Sourcefn input_type_origin(&self, name: &str) -> Option<TypeOrigin>
fn input_type_origin(&self, name: &str) -> Option<TypeOrigin>
How input name’s type was established: written by the author,
or inferred by the compiler and so open to
CompileOptions::input_variance (input_variance.md §3). A host
that compiles many scopes at Info reports each open input once
from here rather than from every compile’s log.
Sourcefn program_id(&self) -> ProgramId
fn program_id(&self) -> ProgramId
The identity of this kernel’s program: equal for kernels created from one program and for forks, different for any two programs, the same program compiled twice included. What a host seals a plan of pre-resolved indices against.
Provided Methods§
Sourcefn input_index(&self, name: &str) -> Option<usize>
fn input_index(&self, name: &str) -> Option<usize>
The index of a named input among Self::input_names, the
coordinates first: what Self::set_input_at takes.
Sourcefn set_input_at(&mut self, index: usize, value: Value) -> Result<(), WriteError>
fn set_input_at(&mut self, index: usize, value: Value) -> Result<(), WriteError>
Self::set_input by index, for a host that binds the same
inputs every cycle: the name is resolved once, with
Self::input_index, and no lookup runs per write.
Sourcefn output_index(&self, name: &str) -> Option<usize>
fn output_index(&self, name: &str) -> Option<usize>
The index of a named output among Self::output_names: what
Self::pull_at takes.
Sourcefn pull_at(&mut self, index: usize) -> Value
fn pull_at(&mut self, index: usize) -> Value
Self::pull by index, for a host that reads the same outputs
every cycle: the name is resolved once, with
Self::output_index, and no lookup runs per pull.
Sourcefn init(&mut self) -> Result<(), KernelError>
fn init(&mut self) -> Result<(), KernelError>
Initialize the kernel: evaluate every const binding once, in
dependency order, and store its value for the rest of the
kernel’s life.
Every way a kernel comes into existence initializes it: a build, a kernel created from a shared program, a child bound under a parent (after the parent’s values are bound), and a traversal activation (after its tuple is bound). A host calls it again when it wants the consts recomputed from the inputs as they are now, for example after setting externs a const reads. Inputs keep their values; only the consts change.
A const whose expression yields None takes the value the binder
copied from the enclosing scope, so the outer binding stays
visible. A const whose expression fails makes initialization
fail, naming the const; a slow one makes initialization slow.
Sourcefn traverse_all(&mut self) -> Result<Vec<TraversalStream>, String>
fn traverse_all(&mut self) -> Result<Vec<TraversalStream>, String>
Open every traversal, in document order.
Sourcefn output_cell(&self, _name: &str) -> Option<SharedCell>
fn output_cell(&self, _name: &str) -> Option<SharedCell>
The broadcast cell for a computed output, created on the first ask: a descendant that binds its matching input slot to this cell reads the value each of this kernel’s pulls publishes through it, rather than a copy taken once when the descendant was built (cross_fiber_invalidation.md §3.1).
None when the name is not an output of this kernel, and on an
engine that has no broadcast cells at all. The interpreter seeds
one per output at construction; the closure tier and the hybrid
make them on demand, so a program with no descendant bound to it
allocates none.
Sourcefn output_modifier(&self, _name: &str) -> BindingModifier
fn output_modifier(&self, _name: &str) -> BindingModifier
The binding modifier a named output was declared with — const,
shared, final, or none. A binder reads it to decide how a
descendant takes the output: a const is effectively fixed for
the scope’s life and is value-copied, where a computed output is
bound to its broadcast cell (scope_model.md §4).
NONE for a name this kernel does not declare.
Sourcefn cells_in_scope(&self) -> Vec<SharedCellEntry>
fn cells_in_scope(&self) -> Vec<SharedCellEntry>
Every cell a descendant of this kernel could bind to: the ones
its own shared slots hold, plus the ones it carries forward
for a descendant without holding a slot for them itself. The
second kind is why an ancestral shared reaches a grandchild
whose parent’s program never names it.
Self::shared_cells is the first kind alone.
Sourcefn set_transit_cells(&mut self, _cells: Vec<SharedCellEntry>)
fn set_transit_cells(&mut self, _cells: Vec<SharedCellEntry>)
Carry cells forward for this kernel’s descendants. The binder
writes what the parent had and this kernel holds no slot for.
Sourcefn scope_coordinates(&self) -> &[ScopeCoord]
fn scope_coordinates(&self) -> &[ScopeCoord]
This kernel’s place in the comprehension nest its scope was built under, outermost last: a child’s path is its own followed by its parent’s. Empty for a root, which is every kernel a host compiles rather than binds, so the compiled engines answer empty until one is bound under a parent.
Sourcefn extend_scope_coordinates(&mut self, _outer: &[ScopeCoord])
fn extend_scope_coordinates(&mut self, _outer: &[ScopeCoord])
Append outer to this kernel’s own scope-coordinate path, which
the binder does once the child’s inputs are in. A no-op on an
engine that keeps no path.
Sourcefn input_port_type(&self, _name: &str) -> Option<PortType>
fn input_port_type(&self, _name: &str) -> Option<PortType>
The declared type of a named input slot, coordinates included. The binder reads it to adapt a value the parent supplies into the type the child’s slot declares.
Sourcefn bind_input_cell(&mut self, _name: &str, _cell: SharedCell) -> bool
fn bind_input_cell(&mut self, _name: &str, _cell: SharedCell) -> bool
Bind the named input slot to cell, whether or not the slot was
built as a shared register, and answer whether it was bound.
This is what a parent does to a child, not what a host does to
two kernels. A child declares its imports extern; it is the
parent binding it that decides one of them reads a register
rather than a copied value. Self::attach_shared_cell is the
host’s operation and refuses a slot that is not already a
register on both sides, which is the right answer for joining
two kernels and the wrong one for building a child.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".