This tutorial helps C++20 clients evaluate a cached program on reusable storage. You construct operations directly; this runtime does not parse text.
Before you begin
Create the CPM application from Build and link the runtime with CPM. Keep its dependency declaration and target_link_libraries call.
Build the reuse example
Replace the application's add_executable line with the example source fetched by CPM:
add_executable(client "${cel-runtime_SOURCE_DIR}/examples/getting_started.cpp")
Build the consumer:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
Run its tests:
ctest --test-dir build --output-on-failure --verbose
Confirm that client passes and prints 5 followed by 7.
Reuse the stack
The example compiles subtraction with one positional double argument. It binds the complete signature once, reserves storage around an existing bool prefix, and makes two calls. Both calls leave the prefix live.
Start the builder with a positional argument, then add a constant and an operation. The operation reads the older argument before the newer constant, so its result is input - 3.0. Freezing prevents further emission, and preparation binds the result and argument as double.
The complete compiled source is examples/getting_started.cpp:
#include <exception>
#include <iostream>
int main() try {
builder.
op2<double, double,
double>([](
double older,
double newer) {
return older - newer; });
auto program = std::move(builder).finish();
auto prepared = program.prepare<double, double>();
const auto needed = prepared.requirements().for_prefix(stack.cursor(), stack.depth());
stack.reserve(needed.bytes.size, needed.bytes.alignment);
stack.reserve_depth(needed.slots);
const auto first = prepared.call(stack, 8.0);
const auto second = prepared.call(stack, 10.0);
if (first != 5.0 || second != 7.0 || !stack.pop<bool>() || stack.depth() != 0) return 1;
std::cout << first << '\n' << second << '\n';
return 0;
} catch (const std::exception& error) {
std::cerr << error.what() << '\n';
return 2;
} catch (...) {
std::cerr << "Unexpected non-standard exception\n";
return 3;
}
Checks stack effects while constructing a move-only ordinary operation sequence. Operations consume o...
Definition dyn_segment.hpp:227
void just(value literal)
Retains a literal owner and emits an independent clone on every execution. Callable components share ...
void push_argument(std::size_t index, value_type type)
Emits a read that clones a borrowed positional input when the program executes. Repeated declarations...
void op2(F &&callback)
Consumes two operands older-first and pushes R unless R is void. Follows op's callback,...
Definition dyn_segment.hpp:465
Owns reusable canonical operand bytes and complete live-slot metadata. The owner outlives every borro...
Definition raw_stack.hpp:33
void push(const T &source)
Writes a concrete leaf or packed composite without constructing scalar value boxes....
Definition raw_stack.hpp:159
static value_type leaf()
Returns T's descriptor as an opaque, trivially copyable leaf. Rejects nontrivial T at compile time....
Definition value_type.hpp:93
static value from(const T &source)
Copies a concrete leaf or recursively nested owning vector/tuple into a runtime value....
Definition value.hpp:138
Provides values, program builders, and reusable execution for C++20 runtime clients....
The executable prints:
finish() freezes the builder. prepare<double, double>() binds a double result and one double argument; call(stack, input) borrows the input and returns its independent result. A prepared handle retains frozen code, so you can discard the builder and original compiled handle.
The reservation includes the stack's measured byte cursor and logical depth. Do not mutate the prefix between measuring it and reserving. The bool remains owned by the caller until pop<bool>() retires it.
To adapt the example, copy its source into your application's main.cpp and restore add_executable(client main.cpp). The cel::runtime target continues to supply headers, the static library, and its C++20 requirement. For raw result storage, composite boundaries, or nested calls, see Choose execution and ownership boundaries.