|
runtime 1.0.0
Checked CEL programs, owned values, and reusable execution stacks
|
Owns a reference-semantic handle to frozen code and its complete declared signature. Copies share code, explicit callback references, and the same-carrier entry guard. There is no implicit lexical environment or shared invocation argument/result table. Exclusive access is required; recursive entry into the same carrier throws logic_error. Distinct carriers can nest on the caller's stack. Callback references stay caller-owned. Moves between distinct handles leave the source without code; assign a live handle before using source's borrowed accessors. Borrowed signatures and requirements remain valid while an unchanged live handle retains their code. Last ownership retires runtime-managed executable graphs without allocation or recursive descent, including callable literals and lazy bodies. Client destructors retain their costs. More...
#include <cel/runtime/callable.hpp>
Public Member Functions | |
| callable (compiled_segment body, std::span< const value_type > parameters) | |
| Binds independent one-result code and every explicit source-order parameter. Precondition: body has not been moved from. Retains code and copies parameter descriptors; the span need not outlive construction. Unused declarations remain parameters. Parameters admit bool/double and their composites; results admit every complete owned type, including client leaves and installed callables. Throws invalid_argument for dependent origin, undeclared/wrong reads, or invalid types. Complexity: O(parameters + compared metadata) time and frozen binding space. Example: callable fn(std::move(b).finish(), std::array{value_type::leaf<double>()});. | |
| callable (const callable &) noexcept=default | |
| Shares the reference-semantic code handle, not an independent callback-state copy. Example: auto alias = fn;. | |
| callable (callable &&) noexcept=default | |
| Transfers the code handle. Example: auto moved = std::move(fn);. | |
| callable & | operator= (const callable &) noexcept=default |
| Shares the handle and releases the previous code on last ownership. Leaves the source unchanged; self-copy is unchanged. Complexity: O(last-owned captures and binding metadata). Example: alias = fn;. | |
| callable & | operator= (callable &&) noexcept=default |
| Transfers the handle and releases previous last-owned code. Leaves a distinct source without code; self-move is unchanged. Complexity: O(last-owned captures and binding metadata). Example: alias = std::move(fn);. | |
| ~callable () | |
| Releases last-owned frozen code and signature metadata. Complexity: O(last-owned captures and binding metadata). | |
| const value_type & | type () const noexcept |
| Borrows the full installed signature, including unused parameters. Precondition: this handle is live. Example: auto arity = fn.type().parameters().size();. | |
| const stack_requirements & | requirements () const noexcept |
| Borrows known body storage requirements; external callback costs are not inferred. Precondition: this handle is live. Example: auto r = fn.requirements().for_prefix(stack.cursor(), stack.depth());. | |
| value | call (raw_stack &stack, std::span< const value > arguments) const |
| Validates arity and every declared complete parameter before any body effect. Returns one independent result owner; arguments are borrowed and not consumed. Throws std::invalid_argument on any signature mismatch and std::logic_error for a moved-from handle, same-carrier entry, or stack access during a canonical ownership phase. Same-carrier exclusion covers validation, storage acquisition, body work, and result extraction. Exceptions preserve their context and retire only the execution suffix. Callbacks must not mutate aliases of arguments while this call borrows them. Returned aggregates own independent payloads; callable components share code. Complexity: O(parameters + compared metadata + executed payload work) time; allocates an invocation table and result outer storage, not per-scalar argument boxes. Example: auto result = fn.call(stack, std::array{value::from(2.0)});. | |
| value | to_value () const |
| Creates an owning value carrier sharing this explicitly reference-semantic code. Throws logic_error for a moved-from handle. Complexity: O(1) allocations for carrier and canonical outer storage. Example: auto carrier = fn.to_value();. | |
Static Public Member Functions | |
| static callable | from_value (const value &source) |
| Returns a shared handle to the installed callable stored in source. Throws std::invalid_argument if source is not a callable with runtime-installed ownership. The returned handle shares the value's reference-semantic code and entry guard. Leaves source unchanged and retains code independently of source's lifetime. Performs no payload clone or recursive signature comparison. Example: auto fn = callable::from_value(factory.call(stack, {}));. | |
Friends | |
| struct | detail::callable_access |
| class | detail::callable_invocation |
Owns a reference-semantic handle to frozen code and its complete declared signature. Copies share code, explicit callback references, and the same-carrier entry guard. There is no implicit lexical environment or shared invocation argument/result table. Exclusive access is required; recursive entry into the same carrier throws logic_error. Distinct carriers can nest on the caller's stack. Callback references stay caller-owned. Moves between distinct handles leave the source without code; assign a live handle before using source's borrowed accessors. Borrowed signatures and requirements remain valid while an unchanged live handle retains their code. Last ownership retires runtime-managed executable graphs without allocation or recursive descent, including callable literals and lazy bodies. Client destructors retain their costs.
Bind a declared parameter and call through a shared handle: