Skip to main content

GenericValue

Enum GenericValue 

Source
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>

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn type_name(&self) -> &'static str

Return a human-readable type name for error messages.

Source

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.

Source

pub fn as_str(&self) -> Option<&str>

Borrow the underlying UTF-8 contents of a static string.

Source

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.

Source

pub fn contains_dynstr(&self) -> bool

Returns true if the value is an arena-resident dynamic string or transitively contains one.

Source

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>

Source§

fn clone(&self) -> GenericValue<W, F>

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<W: Debug + Word, F: Debug + Float> Debug for GenericValue<W, F>

Source§

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

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

impl<W: Word, F: Float> PartialEq for GenericValue<W, F>

Source§

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

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto 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>
where W: Freeze, F: Freeze,

§

impl<W, F> Unpin for GenericValue<W, F>
where W: Unpin, F: Unpin,

§

impl<W, F> UnsafeUnpin for GenericValue<W, F>
where W: UnsafeUnpin, F: UnsafeUnpin,

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> ArchivePointee for T

Source§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
Source§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
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> LayoutRaw for T

Source§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Returns the layout of the type.
Source§

impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
where T: SharedNiching<N1, N2>, N1: Niching<T>, N2: Niching<T>,

Source§

unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool

Returns whether the given value has been niched. Read more
Source§

fn resolve_niched(out: Place<NichedOption<T, N1>>)

Writes data to out indicating that a T is niched.
Source§

impl<T> Pointee for T

Source§

type Metadata = ()

The metadata type for pointers and references to this type.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.