pub enum GenericValue<W: Word, F: Float> {
Show 14 variants
Unit,
Bool(bool),
Int(W),
Byte(u8),
Fixed(W),
Float(F),
StaticStr(String),
KStr(KString),
Tuple(TupleBody<W, F>),
Array(ArrayBody<W, F>),
Struct(StructBody<W, F>),
Enum(EnumBody<W, F>),
None,
Opaque(Arc<dyn HostOpaque>),
// some variants omitted
}Variants§
Unit
Unit value ().
Bool(bool)
Boolean.
Int(W)
Script-visible signed integer. Surface type is Word.
The bit width is determined by the W parameter and
matches the bytecode header’s word_bits_log2.
Byte(u8)
Eight-bit unsigned integer. Surface type is Byte. Arithmetic
uses wrapping u8 semantics; conversions to and from Word
go through Op::WordToByte and Op::ByteToWord.
Fixed(W)
Signed Q-format fixed-point. The wrapped W holds the
fixed-point bits; the fraction-bit count is carried by the
opcodes that produce or consume the value.
Float(F)
Script-visible floating-point number. The width is
determined by the F parameter and matches the bytecode
header’s float_bits_log2. Gated behind the floats
cargo feature alongside the rest of the floating-point
runtime surface.
StaticStr(String)
Immutable static string referenced from the rodata region. Source-level string literals compile to this variant. Permitted to flow through the dialogue type B and across hot updates subject to the host attestation for rodata pointer validity. See R31, R32, R33 and B5.
KStr(KString)
Dynamic string allocated in the host-owned arena’s top region.
Carries a crate::kstring::KString handle that becomes
keleusma_arena::Stale on access if the arena has been reset
since the handle was issued. Subject to the cross-yield
prohibition because the underlying storage does not survive a
reset. The boundary type for native callers and the host that
want bounded-memory accounting and stale-pointer detection.
Tuple(TupleBody<W, F>)
Tuple of values. The body is flat bytes for a transitively-scalar
tuple or boxed elements otherwise (B28 P2); see TupleBody.
Array(ArrayBody<W, F>)
Fixed-size array of values. The body is flat bytes for a
transitively-scalar element type or boxed elements otherwise
(B28 P2); see ArrayBody.
Struct(StructBody<W, F>)
Named struct. The body is flat bytes for a transitively-scalar
field list or boxed named fields otherwise (B28 P2); see
StructBody.
Enum(EnumBody<W, F>)
Enum variant with optional payload. The body is flat bytes for a
transitively-scalar payload or boxed otherwise (B28 P2); see
EnumBody.
None
Option::None.
Opaque(Arc<dyn HostOpaque>)
Opaque host-managed value referenced through a shared
reference-counted pointer. Produced by host-registered native
functions that operate on Rust types the script does not
introspect. The pointee implements the
crate::opaque::HostOpaque marker trait; the script-side
type is the opaque name registered through the type checker.
Lifetime is independent of the arena: opaque values may cross the yield boundary in the dialogue type, persist across arena resets, and survive hot code swaps. Equality is by pointer identity, matching the convention for host-managed references.
WCMU contribution is zero from the script side because the
allocation is host-managed. Hosts that want to bound their
own opaque heap supply a per-native attestation through
crate::vm::Vm::set_native_bounds.
Implementations§
Source§impl<W: Word, F: Float> GenericValue<W, F>
impl<W: Word, F: Float> GenericValue<W, F>
Sourcepub fn tuple(elements: Vec<Self>) -> Self
pub fn tuple(elements: Vec<Self>) -> Self
Construct a tuple value, choosing the flat byte body for a transitively-scalar tuple and the boxed body otherwise (B28 P2).
This is the common constructor used by hosts, tests, and the
runtime. It delegates to GenericValue::tuple_with_widths at
the runtime’s own scalar widths (from crate::word::Word::BITS_LOG2
and crate::float::Float::BITS_LOG2), which equal the
module-declared widths on the bundled runtime. Routing every
construction through the same flat-or-boxed decision is what lets
a given tuple type have one representation, which tuple equality
and flat access both rely on. A reference-bearing or float-
bearing tuple is not flat-eligible and stays boxed.
Sourcepub fn tuple_with_widths(
elements: Vec<Self>,
word_bytes: usize,
float_bytes: usize,
) -> Self
pub fn tuple_with_widths( elements: Vec<Self>, word_bytes: usize, float_bytes: usize, ) -> Self
Construct a tuple value, choosing the flat byte body for a transitively-scalar tuple and the boxed body otherwise, using the given scalar widths (B28 P2).
This is the single choke point for tuple construction so every
path (the VM NewTuple handler, constant materialisation, and
host marshalling) agrees on the representation for a given type.
A flat body is produced only when every element is a
flat-eligible scalar (see flat_tuple_scalar_kind) and the
packed size fits the sixteen-bit access offset; the fields are
written little-endian at packed offsets using word_bytes and
float_bytes, the same widths the compiler bakes access offsets
against.
Sourcepub fn array(elements: Vec<Self>) -> Self
pub fn array(elements: Vec<Self>) -> Self
Construct an array value at the runtime’s own scalar widths,
choosing the flat byte body for a transitively-scalar element type
and the boxed body otherwise (B28 P2). The array analogue of
GenericValue::tuple.
Sourcepub fn array_with_widths(
elements: Vec<Self>,
word_bytes: usize,
float_bytes: usize,
) -> Self
pub fn array_with_widths( elements: Vec<Self>, word_bytes: usize, float_bytes: usize, ) -> Self
Construct an array value, choosing the flat byte body for a transitively-scalar element type and the boxed body otherwise, using the given scalar widths (B28 P2).
This is the single choke point for array construction so the VM
NewArray handler, constant materialisation, and host marshalling
all agree on the representation an array type uses, which equality
relies on. The eligibility rule is the same as for a tuple field
(flat_tuple_scalar_kind): a flat body is produced only when
every element is a flat-eligible scalar and the packed size fits
the sixteen-bit access offset. Because the array is homogeneous the
elements share one kind, so the packed layout is count * size.
Sourcepub fn struct_value(type_name: String, fields: Vec<(String, Self)>) -> Self
pub fn struct_value(type_name: String, fields: Vec<(String, Self)>) -> Self
Construct a struct value at the runtime’s own scalar widths,
choosing the flat byte body for a transitively-scalar field list and
the boxed body otherwise (B28 P2). The struct analogue of
GenericValue::tuple; fields must be in declaration order.
Sourcepub fn struct_with_widths(
type_name: String,
fields: Vec<(String, Self)>,
word_bytes: usize,
float_bytes: usize,
) -> Self
pub fn struct_with_widths( type_name: String, fields: Vec<(String, Self)>, word_bytes: usize, float_bytes: usize, ) -> Self
Construct a struct value, choosing the flat byte body for a transitively-scalar field list and the boxed body otherwise, using the given scalar widths (B28 P2).
The single choke point for struct construction, so the VM
NewStruct handler, constant materialisation, and host marshalling
agree on the representation a struct type uses, which equality relies
on. fields are packed in declaration order, the same order the
compiler bakes field offsets against; the eligibility rule is the
same as for a tuple field (flat_tuple_scalar_kind). A flat body
carries no type name or field names.
Sourcepub fn enum_value(
type_name: String,
variant: String,
disc: i64,
fields: Vec<Self>,
) -> Self
pub fn enum_value( type_name: String, variant: String, disc: i64, fields: Vec<Self>, ) -> Self
Construct an enum value at the runtime’s own scalar widths, choosing
the flat byte body for a transitively-scalar payload and the boxed
body otherwise (B28 P2). disc is the variant’s discriminant value.
Sourcepub fn enum_with_widths(
type_name: String,
variant: String,
disc: i64,
fields: Vec<Self>,
min_payload: usize,
word_bytes: usize,
float_bytes: usize,
) -> Self
pub fn enum_with_widths( type_name: String, variant: String, disc: i64, fields: Vec<Self>, min_payload: usize, word_bytes: usize, float_bytes: usize, ) -> Self
Construct an enum value at the given scalar widths (B28 P2). No arena is
available here, so the no-arena path produces the boxed representation
(B28 item 2 step 6B); the owned Inline flat body is gone and every flat
body is an arena region handle. The runtime builds flat enums through the
arena-direct path, and host/const enums stay boxed, which composite
equality (field-wise) and the boxed access ops handle. disc,
min_payload, and the widths are accepted for signature compatibility
with the callers and are not needed by the boxed body, which records the
variant name from which the discriminant is recovered.
Sourcepub fn tuple_in_arena(
elements: Vec<Self>,
word_bytes: usize,
float_bytes: usize,
arena: &Arena,
) -> Result<Self, AllocError>
pub fn tuple_in_arena( elements: Vec<Self>, word_bytes: usize, float_bytes: usize, arena: &Arena, ) -> Result<Self, AllocError>
Arena-direct counterpart of GenericValue::tuple_with_widths (B28 P3
item 2, Increment 3).
Packs a flat-eligible tuple body straight into the arena through
GenericValue::pack_flat_in_arena, with no intermediate global-heap
Inline; a reference- or boxed-element tuple falls back to the boxed
body exactly as the global-heap constructor does. The host marshalling
boundary calls this so a native tuple result carries no global-heap
body. A nested composite element is still built by the global-heap
into_value and resolved-and-copied into the parent’s single arena
allocation, so the arena footprint is exactly one body (no per-child
arena allocation, hence no change to the worst-case-memory accounting);
eliminating that transient child Inline is the Increment 5 collapse.
Sourcepub fn array_in_arena(
elements: Vec<Self>,
word_bytes: usize,
float_bytes: usize,
arena: &Arena,
) -> Result<Self, AllocError>
pub fn array_in_arena( elements: Vec<Self>, word_bytes: usize, float_bytes: usize, arena: &Arena, ) -> Result<Self, AllocError>
Arena-direct counterpart of GenericValue::array_with_widths (B28 P3
item 2, Increment 3). See GenericValue::tuple_in_arena.
Sourcepub fn struct_in_arena(
type_name: String,
fields: Vec<(String, Self)>,
word_bytes: usize,
float_bytes: usize,
arena: &Arena,
) -> Result<Self, AllocError>
pub fn struct_in_arena( type_name: String, fields: Vec<(String, Self)>, word_bytes: usize, float_bytes: usize, arena: &Arena, ) -> Result<Self, AllocError>
Arena-direct counterpart of GenericValue::struct_with_widths (B28 P3
item 2, Increment 3). See GenericValue::tuple_in_arena. The field
names are retained for the boxed fallback by unzipping before the pack
and rezipping only on the not-flat-eligible path.
Sourcepub fn enum_in_arena(
type_name: String,
variant: String,
disc: i64,
min_payload: usize,
fields: Vec<Self>,
word_bytes: usize,
float_bytes: usize,
arena: &Arena,
) -> Result<Self, AllocError>
pub fn enum_in_arena( type_name: String, variant: String, disc: i64, min_payload: usize, fields: Vec<Self>, word_bytes: usize, float_bytes: usize, arena: &Arena, ) -> Result<Self, AllocError>
Arena-direct enum constructor (B28 item 2 step 6B). Packs a flat enum
body [disc word][payload] straight into the arena, matching the layout
GenericValue::enum_with_widths produced before the Inline form was
removed and what Op::IsEnum/Op::GetEnumField read. The
discriminant is the leading Word; the payload packs in declaration
order with no variant padding (min_bytes is the discriminant word
alone), which a host-built value not inlined into a fixed parent slot
permits. A reference- or float-bearing payload is not flat-eligible and
falls back to the boxed body. The built-in generic Option is kept
boxed by the caller, since its access is baked boxed.
Sourcepub fn into_arena_canonical(
self,
word_bytes: usize,
float_bytes: usize,
arena: &Arena,
) -> Result<Self, AllocError>
pub fn into_arena_canonical( self, word_bytes: usize, float_bytes: usize, arena: &Arena, ) -> Result<Self, AllocError>
Re-pack a host-built boxed composite into an arena-resident flat body so
the compiler-baked flat field-access ops can read it (B28 item 2 step
6B). The arena-less host constructors (Self::enum_with_widths and
kin, the KeleusmaType derive’s no-arena from_value) can only produce
the boxed representation, but a script reads a host-provided composite
argument through flat-baked ops (Op::GetField/Op::GetTupleField/
Op::GetEnumField) that reject a boxed body. This canonicalisation
runs at the VM entry points (call arguments and the resume value) where
the arena is available. It recurses bottom-up, so a nested boxed child
becomes flat first and lets its parent flatten.
A scalar, reference, already-flat, Unit, or None value is returned
unchanged. A composite whose payload is not flat-eligible (a reference-
or float-bearing field, or an Option) stays boxed and is read through
the boxed access ops, which tolerate it. Widths are the MODULE widths,
so a narrow-word build casts each host scalar to the module width
exactly as crate::marshall::KeleusmaType::from_value_ctx does (B36);
the cast cannot widen because the loader requires module width at most
runtime width.
Sourcepub fn write_scalar_le(
&self,
dst: &mut [u8],
offset: usize,
word_bytes: usize,
float_bytes: usize,
) -> Result<(), ScalarError>
pub fn write_scalar_le( &self, dst: &mut [u8], offset: usize, word_bytes: usize, float_bytes: usize, ) -> Result<(), ScalarError>
Write this fixed-size scalar’s little-endian bytes into dst at
offset (B28 P2). The width of an Int/Fixed is word_bytes
and of a Float is float_bytes, taken from the runtime’s
target descriptor, so the same routine serves narrow runtimes.
Unit and None write nothing.
This is the pack half of the composite construct handlers: each
field’s scalar is written at the offset the compiler baked.
Reference scalars (StaticStr, KStr, Opaque) and composites
are handled by later phases and panic here, which a correct
compiler never reaches because it routes them differently.
Sourcepub fn new_composite_boxed(
kind: CompositeKind,
type_name: String,
names: Vec<String>,
values: Vec<Self>,
) -> Self
pub fn new_composite_boxed( kind: CompositeKind, type_name: String, names: Vec<String>, values: Vec<Self>, ) -> Self
Build a boxed composite of kind from values (B28 P4). For a
struct the names are the field names (declaration order); for an
enum names[0] is the variant name and type_name the enum name; a
tuple or array ignores type_name and names. The boxed form is the
interim representation for a reference-bearing field or Option,
removed at P3.
Sourcepub fn flat_nested_field(
parent: &FlatComposite,
offset: usize,
size: usize,
variant: CompositeKind,
arena: &Arena,
) -> Result<Self, Stale>
pub fn flat_nested_field( parent: &FlatComposite, offset: usize, size: usize, variant: CompositeKind, arena: &Arena, ) -> Result<Self, Stale>
Re-wrap a nested composite’s extracted byte range as a flat
composite Value of the given kind (B28 P2 nested inlining). The
access handler slices the child body out of the parent and calls
this to materialise the field value. The bytes are copied into a
fresh body, so the result is independent of the parent.
Extract a nested child composite occupying [offset, offset + size) of
parent, as a flat composite Value of variant kind, viewing the
child in place (B28 P3 item 5 C-residual 3b). The arena parent yields a
zero-copy sub-handle into its own storage (see
crate::flat_value::FlatComposite::nested_view), so a nested access
allocates nothing. Returns keleusma_arena::Stale only if an arena
parent no longer resolves, which a correct caller never observes.
Sourcepub fn into_arena_body(self, arena: &Arena) -> Result<Self, AllocError>
pub fn into_arena_body(self, arena: &Arena) -> Result<Self, AllocError>
Migrate a flat composite value’s body to the arena’s top ephemeral
head (B28 P2 arena residence). A Flat-bodied tuple, array, struct,
or enum has its body copied to the arena and replaced with an
epoch-guarded handle; any other value (a scalar, a boxed composite,
a reference) is returned unchanged. The VM calls this on a
freshly-constructed composite so it carries no global-heap allocation
across a loop iteration’s RESET.
Sourcepub fn flat_ref_epoch(&self) -> Option<u64>
pub fn flat_ref_epoch(&self) -> Option<u64>
Materialise any arena-resident composite body in this value back to
an owned Inline body (B28 P2 arena residence). A Flat body is
copied out of the arena (its bytes are self-contained, so nested
composites come with it); a Boxed body recurses into its element
values, since those are separate values that may themselves be
arena-resident. Scalars and references are returned unchanged.
Used to bridge arena bodies across the three points that read bytes
without an arena handle: the shared construction packer (which reads
a child field’s bytes to inline them), value equality, and the
native-call boundary (where from_value has no arena).
The originating arena epoch of this value’s flat composite body, if
it has one (B28 P3 item 1). A flat Text field is decoded by
reattaching this epoch so a read after a RESET resolves Stale.
Returns None for a boxed or non-composite value, whose reference
fields (a bare KStr, an opaque index) carry their own validity.
Sourcepub fn pack_flat_in_arena(
values: &[Self],
min_bytes: usize,
word_bytes: usize,
float_bytes: usize,
arena: &Arena,
) -> Result<Option<FlatComposite>, AllocError>
pub fn pack_flat_in_arena( values: &[Self], min_bytes: usize, word_bytes: usize, float_bytes: usize, arena: &Arena, ) -> Result<Option<FlatComposite>, AllocError>
Pack values into a flat byte body built directly in the arena,
padded to at least min_bytes (B28 P3 item 5 C-residual 3b). Used by
the VM Op::NewComposite handler so a freshly constructed composite is
arena-resident with no global-heap allocation. Since B28 item 2 step 6B
this is the only flat-packing path; the owned-bytes Inline form and
its try_pack_flat packer are gone, so a no-arena caller (host
marshalling, constants) uses the boxed representation or the const pool
instead.
Returns Ok(None) when any value is not flat-eligible (a reference or
boxed field) or the packed body exceeds the sixteen-bit access offset,
in which case the caller falls back to the boxed body. Returns
Err(AllocError) when the arena top head cannot satisfy the allocation.
The fields are packed contiguously in order at running offsets (the
flat model has no inter-field padding), so the [0, packed) prefix is
written exactly once by the fields and the [packed, size) slack is
zero-filled; together they cover every byte of the uninitialised arena
allocation. A nested child is inlined by resolving its arena bytes and
copying them into the parent’s destination, never through an owned
Inline intermediate.
Sourcepub fn read_scalar_le(
src: &[u8],
offset: usize,
kind: ScalarKind,
word_bytes: usize,
float_bytes: usize,
) -> Result<Self, ScalarError>
pub fn read_scalar_le( src: &[u8], offset: usize, kind: ScalarKind, word_bytes: usize, float_bytes: usize, ) -> Result<Self, ScalarError>
Read a fixed-size scalar of kind from src at offset (B28
P2), the read half of the composite access handlers. Int and
Fixed are sign-extended from word_bytes; Float is widened
from float_bytes. kind is the value the compiler baked into
the access instruction. Panics on the reference kinds and on a
kind outside the fixed-size scalar set, which later phases
handle.
Sourcepub fn materialise_kstrings(&self, arena: &Arena) -> Self
pub fn materialise_kstrings(&self, arena: &Arena) -> Self
Walk the value recursively and replace every KStr variant
with an equivalent StaticStr whose contents come from the
supplied arena. Use this when transporting a value across a
Vm boundary: KStr handles reference the original arena
through an epoch-tagged pointer, so a value snapshotted from
one Vm and restored into a Vm backed by a different arena
would carry a stale handle. Materialising to StaticStr
breaks the arena dependency so the value is portable.
Composite variants (Tuple, Array, Struct, Enum) are
walked recursively. Scalar variants are cloned unchanged.
Opaque values are cloned by Arc increment as usual; the
HostOpaque trait makes no assumption about arena residency.
Stale KStr handles produce an empty StaticStr. A stale
handle here means the original arena was already dropped
between snapshot and materialisation, which should not happen
in the documented REPL pattern but is handled defensively.
Sourcepub fn opaque_type_name(&self) -> Option<&'static str>
pub fn opaque_type_name(&self) -> Option<&'static str>
Return the host-supplied script-side type name for an
opaque value, or None if the value is not opaque.
Sourcepub fn as_str_with_arena<'a>(
&'a self,
arena: &'a Arena,
) -> Result<Option<&'a str>, Stale>
pub fn as_str_with_arena<'a>( &'a self, arena: &'a Arena, ) -> Result<Option<&'a str>, Stale>
Borrow the underlying UTF-8 contents of any string variant,
resolving KStr through the supplied arena.
Sourcepub fn contains_dynstr(&self) -> bool
pub fn contains_dynstr(&self) -> bool
Returns true if the value is an arena-resident dynamic string or transitively contains one.
Sourcepub fn from_const_archived(
c: &ArchivedConstValue,
word_bytes: usize,
float_bytes: usize,
) -> Self
pub fn from_const_archived( c: &ArchivedConstValue, word_bytes: usize, float_bytes: usize, ) -> Self
Lift an archived constant pool entry into a runtime
GenericValue<W, F>.
The constant pool stores ConstValue entries with fixed
i64 and f64 payloads; this lift converts each constant
to the runtime’s W and F types via Word::from_i64_wrap
and Float::from_f64. The conversion truncates / rounds
when the runtime’s word or float width is narrower than
the bytecode’s; programs whose constants do not fit are
rejected at load time by the bytecode-header width check.
Trait Implementations§
Source§impl<W: Clone + Word, F: Clone + Float> Clone for GenericValue<W, F>
impl<W: Clone + Word, F: Clone + Float> Clone for GenericValue<W, F>
Source§fn clone(&self) -> GenericValue<W, F>
fn clone(&self) -> GenericValue<W, F>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl<W, F> !RefUnwindSafe for GenericValue<W, F>
impl<W, F> !Send for GenericValue<W, F>
impl<W, F> !Sync for GenericValue<W, F>
impl<W, F> !UnwindSafe for GenericValue<W, F>
impl<W, F> Freeze for GenericValue<W, F>
impl<W, F> Unpin for GenericValue<W, F>
impl<W, F> UnsafeUnpin for GenericValue<W, F>where
W: UnsafeUnpin,
F: UnsafeUnpin,
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
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,
Source§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.