runtime 1.0.0
Checked CEL programs, owned values, and reusable execution stacks
Loading...
Searching...
No Matches
raw_stack.hpp
1// SPDX-License-Identifier: BSL-1.0
2#ifndef CEL_RUNTIME_RAW_STACK_HPP
3#define CEL_RUNTIME_RAW_STACK_HPP
4
5#include <array>
6#include <cel/runtime/value.hpp>
7#include <cstddef>
8#include <memory>
9#include <span>
10#include <tuple>
11#include <utility>
12
13namespace cel {
16
17namespace detail {
18class frame;
19class raw_segment;
20struct stack_state;
21struct frame_access;
22} // namespace detail
23
31// [knowledge] Transfer only internal canonical carriers bytewise, never public facades.
32// [knowledge] Keep the ownership-phase gate nonallocating and release it before ordinary callbacks.
33class raw_stack {
34 std::unique_ptr<detail::stack_state> _state;
35 friend class detail::frame;
36 friend struct detail::frame_access;
37
40 class phase_guard {
41 detail::stack_state* _state;
42
43 public:
45 explicit phase_guard(raw_stack& stack) noexcept;
47 ~phase_guard() noexcept;
49 phase_guard(const phase_guard&) = delete;
51 phase_guard& operator=(const phase_guard&) = delete;
52 };
54 detail::stack_state& state();
56 void require_idle() const;
58 void require_access(const detail::frame* owner) const;
62 template <class T>
63 T read_value(std::size_t floor) {
64 if (depth() <= floor) throw std::out_of_range("operand underflow");
65 phase_guard phase(*this);
66 const auto type = detail::concrete_adapter<T>::type();
67 return detail::concrete_adapter<T>::read(type, borrow(floor, 0, type));
68 }
71 std::size_t prepare(const value_type& type);
73 void publish(const value_type& type, std::size_t offset) noexcept;
77 void push_written(const value_type& type,
78 const void* source,
79 void (*write)(const void*, const value_type&, std::byte*));
82 void clone(const value& source);
85 void take(value& source);
89 const std::byte* borrow(std::size_t floor,
90 std::size_t from_top,
91 const value_type& expected) const;
95 const std::byte* borrow_trusted(std::size_t floor,
96 std::size_t from_top,
97 const value_type& expected) const;
101 void truncate(std::size_t floor) noexcept;
105 value extract(std::size_t floor);
111 void release(std::size_t floor, const value_type& expected, std::byte* destination);
112
113public:
121 raw_stack(const raw_stack&) = delete;
123 raw_stack& operator=(const raw_stack&) = delete;
137 void reserve(std::size_t bytes, std::size_t alignment);
142 void reserve_depth(std::size_t count);
147 void clear();
150 std::size_t depth() const noexcept;
153 std::size_t cursor() const noexcept;
158 template <class T>
159 void push(const T& source) {
160 require_access(nullptr);
161 push_written(detail::concrete_adapter<T>::type(), &source,
162 [](const void* input, const value_type& type, std::byte* destination) {
163 detail::concrete_adapter<T>::write(*static_cast<const T*>(input), type,
164 destination);
165 });
166 }
167
172 template <class T>
173 T pop() {
174 require_access(nullptr);
175 auto result = read_value<T>(0);
176 truncate(depth() - 1);
177 return result;
178 }
179
184 void push_clone(const value& source);
189 void push_take(value& source);
196};
197
199} // namespace cel
200#endif
raw_stack()
Creates an empty reusable stack.
~raw_stack()
Retires all live payloads and releases reserved storage. Precondition: no frame referring to this sta...
void reserve_depth(std::size_t count)
Reserves bookkeeping for count simultaneously live operands, including zero-byte units....
std::size_t depth() const noexcept
Returns the number of live operands, excluding spare initialized bytes. Example: raw_stack{}...
raw_stack & operator=(const raw_stack &)=delete
Disallows copied assignment.
void push(const T &source)
Writes a concrete leaf or packed composite without constructing scalar value boxes....
Definition raw_stack.hpp:159
raw_stack(raw_stack &&other)
Transfers storage and live slots; leaves other empty and reusable. Throws logic_error if other has an...
T pop()
Returns an independent concrete top value, retiring its canonical owner. Throws out_of_range on under...
Definition raw_stack.hpp:173
void push_take(value &source)
Transfers canonical ownership, leaving source unit after success. Throws logic_error if a frame is ac...
void push_clone(const value &source)
Clones a public owner into canonical stack storage. Leaves source unchanged, preserving value's refer...
value pop_value()
Removes the top operand and transfers its canonical ownership to the returned value....
void clear()
Destroys every live payload while retaining reusable storage. Throws logic_error if a frame is active...
raw_stack & operator=(raw_stack &&other)
Releases prior payloads and transfers other; self-assignment is unchanged. Throws logic_error if eith...
void reserve(std::size_t bytes, std::size_t alignment)
Reserves bytes, alignment, and at least bytes live slots without changing the cursor....
raw_stack(const raw_stack &)=delete
Disallows duplicated mutable ownership.
std::size_t cursor() const noexcept
Returns the active byte cursor, including padding preceding live operands. Example: raw_stack{}...
Shares an immutable, complete semantic type and canonical byte layout. Leaf identity is concrete C++ ...
Definition value_type.hpp:55
Owns a complete runtime value; copies own independent mutable payloads. Installed callables are expli...
Definition value.hpp:58
Provides byte extents for stack reservation and type descriptors.
Definition callable.hpp:6