runtime 1.0.0
Checked CEL programs, owned values, and reusable execution stacks
Loading...
Searching...
No Matches
frame.hpp
1// SPDX-License-Identifier: BSL-1.0
2#ifndef CEL_RUNTIME_DETAIL_FRAME_HPP
3#define CEL_RUNTIME_DETAIL_FRAME_HPP
4#include <cel/runtime/raw_stack.hpp>
5
6namespace cel::detail {
20struct borrowed_value {
21 const value_type& type;
22 const std::byte* data;
23private:
26 void require_type(const value_type& expected) const;
27
28public:
34 template <class T>
35 T as() const {
36 const auto expected = detail::concrete_adapter<T>::type();
37 require_type(expected);
38 return detail::concrete_adapter<T>::read(type, data);
39 }
40};
41
51class frame {
52 raw_stack* _stack;
53 frame* _parent;
54 std::size_t _checkpoint;
55 std::span<const value> _arguments;
56 std::span<const borrowed_value> _canonical_arguments;
57 const void* _context;
58 friend class raw_segment;
59 friend class raw_stack;
60 friend struct detail::frame_access;
61
63 void require_active() const;
66 void reset() noexcept;
70 template <class T>
71 T read_operand(std::size_t from_top, const value_type& expected) const {
72 return detail::concrete_adapter<T>::read(
73 expected, _stack->borrow_trusted(_checkpoint, from_top, expected));
74 }
79 template <class... T, std::size_t... I>
80 std::tuple<T...> acquire_operands(const std::array<value_type, sizeof...(T)>& types,
81 std::index_sequence<I...>) const {
82 require_active();
83 raw_stack::phase_guard phase(*_stack);
84 return {read_operand<T>(sizeof...(T) - 1 - I, types[I])...};
85 }
89 void discard(std::size_t count);
93 template <class T>
94 void push_result(const value_type& type, const T& source) {
95 require_active();
96 _stack->push_written(
97 type, &source, [](const void* input, const value_type& shape, std::byte* destination) {
98 detail::concrete_adapter<T>::write(*static_cast<const T*>(input), shape,
99 destination);
100 });
101 }
102
103public:
108 explicit frame(raw_stack& stack,
109 std::span<const value> arguments = {},
110 const void* context = nullptr);
118 frame(raw_stack& stack,
119 std::span<const borrowed_value> arguments,
120 const void* context = nullptr);
124 ~frame();
126 frame(const frame&) = delete;
128 frame& operator=(const frame&) = delete;
130 frame(frame&&) = delete;
132 frame& operator=(frame&&) = delete;
135 std::size_t depth() const noexcept;
139 raw_stack& stack() const noexcept { return *_stack; }
143 std::span<const value> arguments() const noexcept { return _arguments; }
147 std::span<const borrowed_value> canonical_arguments() const noexcept {
148 return _canonical_arguments;
149 }
154 borrowed_value argument(std::size_t index) const;
157 const void* context() const noexcept { return _context; }
164 void push_argument(std::size_t index);
169 template <class T>
170 void push(const T& source) {
171 push_result(detail::concrete_adapter<T>::type(), source);
172 }
178 template <class T>
179 T pop() {
180 require_active();
181 auto result = _stack->read_value<T>(_checkpoint);
182 discard(1);
183 return result;
184 }
190 void push_clone(const value& source);
195 void push_take(value& source);
201 value pop_value();
202};
203} // namespace cel::detail
204#endif