Skip to main content

Crate cel_runtime

Crate cel_runtime 

Source
Expand description

cel-rs provides a stack-based runtime for developing domain specific languages, including concatenative languages to describe concurrent processes. A sequence is a list of operations (the machine instructions). Each operation is a closure that takes it’s arguments from the stack and the result is pushed back onto the stack.

Segments can be created in two ways.

  1. Using the DynSegment struct which validates the type safety of the operations at runtime as the segment is built.
  2. Using the Segment struct, which validates the type safety of the operations at compile time.

The two types of segments can be converted to each other [not yet implemented from Segment to DynSegment].

Operations are added using the form op#[r] where # is the arity of the operation and the optional r signifies that the operation returns a std::result::Result type and may fail.

§Composable canonical values

Array<T> owns actual contiguous T values. Array::into_vec and Array::from_vec transfer allocations in O(1); Array::as_slice borrows them. A nested array uses Array<Array<T>>: its vector view is Vec<Array<T>>, not Vec<Vec<T>>. Deep native conversion builds a new outer vector. Tuples use source-ordered CStackList values ending in CNil<()>, bridged to native tuples by IntoCStackList and IntoRustTuple. Source unit uses Nil, not an opaque host Leaf<()>.

ValueType records complete recursive identity/layout and optional capabilities; ArrayOf, Cons, Nil, Leaf, and FnOf witness concrete representations. Moving storage requires no clone/equality/debug bounds. OwnedValue checks arbitrary erased external values, whereas DynSegment::prepare binds a PreparedSegment once. Repeated prepared calls borrow arguments and return independent owners without comparing descriptors or downcasting. Runtime-bound hosts can instead prepare a prepared_segment::PreparedRawSegment and uphold its unsafe pointer contract. Callable binds native or prepared bodies to the same typed interface. This is interoperability with native Rust, not a macro-compiled CEL backend.

use cel_runtime::{ArrayOf, Cons, IntoCStackList, IntoRustTuple, Leaf, Nil, DynSegment};
type Row = Cons<Leaf<i32>, Cons<Leaf<bool>, Nil>>;
let mut body = DynSegment::new::<()>();
body.just(7i32); body.just(true); body.make_tuple(2, 0).unwrap();
body.make_array(1, 0).unwrap();
let mut prepared = body.prepare::<Nil, ArrayOf<Row>>().unwrap();
let row = prepared.call(&().into_c_stack_list()).unwrap().into_vec().pop().unwrap();
assert_eq!(row.into_rust_tuple(), (7, true));

§Examples

use cel_runtime::*;

// Create a segment that takes a u32 and &str as arguments
let segment = Segment::<(u32, &str)>::new()
    .op1r(|s| {
        let r = s.parse::<u32>()?;
        Ok(r)
    })
    .op2(|a, b| a + b)
    .op1(|r| r.to_string());
assert_eq!(segment.call((1u32, "2")).unwrap(), "3");

Re-exports§

pub use array::Array;
pub use callable::Callable;
pub use dyn_closure::CallDynFn;
pub use dyn_closure::DynClosure;
pub use owned_value::OwnedValue;
pub use prepared_segment::PreparedSegment;
pub use value_type::ArgumentList;
pub use value_type::ArrayOf;
pub use value_type::AssociatedType;
pub use value_type::Cons;
pub use value_type::FnOf;
pub use value_type::Leaf;
pub use value_type::Nil;
pub use value_type::ValueKind;
pub use value_type::ValueRepr;
pub use value_type::ValueType;
pub use c_stack_list::*;
pub use dyn_segment::*;
pub use list_traits::*;
pub use memory::*;
pub use raw_segment::*;
pub use raw_sequence::*;
pub use raw_stack::*;
pub use raw_vec::*;
pub use segment::*;
pub use tuple_list::*;

Modules§

array
Concrete typed ownership for homogeneous, contiguous arrays. Concrete, contiguous ownership for homogeneous CEL arrays.
c_stack_list
Compile-time stack list implementation for type-safe stack operations. A CStackList is a List with guaranteed memory layout (repr(C)). The tail is stored first, so appending items does not change the memory layout of prior items (though the required alignment may increase). CNil<T> represents the empty list where T is used to hide the tail for std::ops::RangeTo and std::ops::RangeToInclusive indexing.
callable
Signature-typed callable facade over the canonical shared carrier. Calls native and prepared bodies through one statically fixed signature.
dyn_closure
First-class callable CEL values with declared signatures. A first-class, callable CEL value: a compiled body plus its declared signature.
dyn_segment
Dynamic segment implementation with runtime type checking. Builds checked instructions for the canonical raw interpreter.
list_traits
Traits for working with type lists and type information. A collection of traits for homegenous lists (cons cells), similar to tuples.
memory
Memory management and alignment utilities for the runtime.
owned_value
Whole-value ownership with complete checked representation witnesses. Owns an erased whole value together with its frozen ownership descriptor.
prepared_segment
Prepared typed execution over the existing raw interpreter. Executes one construction-validated canonical borrowed frame.
raw_segment
Raw segment implementation without type safety.
raw_sequence
Raw sequence implementation for operation sequences.
raw_stack
Raw stack implementation for low-level stack operations.
raw_vec
Raw vector implementation for dynamic memory allocation.
segment
Type-safe segment implementation with compile-time validation.
tuple_list
Tuple list implementation for type-safe tuple operations. Implements List for tuples where () is an empty list and (H, T) is a list with a head and tail.
value_type
Complete recursive canonical metadata and sealed concrete representation witnesses. Describes complete recursive identities independently of interpreter descriptors.