ArkScript
A small, lisp-inspired, functional scripting language
ScopeView.hpp
Go to the documentation of this file.
1/**
2 * @file ScopeView.hpp
3 * @author Lexy Plateau (lexplt.dev@gmail.com)
4 * @brief The virtual machine scope system
5 * @date 2020-10-27
6 *
7 * @copyright Copyright (c) 2020-2026
8 *
9 */
10
11#ifndef ARK_VM_SCOPE_HPP
12#define ARK_VM_SCOPE_HPP
13
14#include <cinttypes>
15
16#include <Ark/Constants.hpp>
19
20namespace Ark::internal
21{
22 /**
23 * @brief A class to handle the VM scope more efficiently
24 *
25 */
27 {
28 public:
29 using pair_t = std::pair<uint16_t, Value>;
30
31 /**
32 * @brief Deleted constructor to avoid creating ScopeViews pointing to nothing. Helps catch bugs at compile time
33 */
34 ScopeView() = delete;
35
36 /**
37 * @brief Create a new ScopeView
38 *
39 * @param storage pointer to the shared scope storage
40 * @param start first free starting position
41 */
42 ARK_ALWAYS_INLINE ScopeView(pair_t* storage, const std::size_t start) noexcept :
43 m_storage(storage), m_start(start), m_size(0), m_min_id(MaxValue16Bits), m_max_id(0)
44 {}
45
46 /**
47 * @brief Put a value in the scope
48 *
49 * @param id The symbol id of the variable
50 * @param val The value linked to the symbol
51 */
52 ARK_ALWAYS_INLINE void pushBack(uint16_t id, Value&& val) noexcept
53 {
54 if (id < m_min_id)
55 m_min_id = id;
56 if (id > m_max_id)
57 m_max_id = id;
58
59 m_storage[m_start + m_size] = std::make_pair(id, std::move(val));
60 ++m_size;
61 }
62
63 /**
64 * @brief Put a value in the scope
65 *
66 * @param id The symbol id of the variable
67 * @param val The value linked to the symbol
68 */
69 ARK_ALWAYS_INLINE void pushBack(uint16_t id, const Value& val) noexcept
70 {
71 if (id < m_min_id)
72 m_min_id = id;
73 if (id > m_max_id)
74 m_max_id = id;
75
76 m_storage[m_start + m_size] = std::make_pair(id, val);
77 ++m_size;
78 }
79
80 /**
81 * @brief Insert one or more pairs at the beginning of the scope
82 * @details This can ONLY be called on the last known scope, otherwise it will override the data of the next scope!
83 *
84 * @param values
85 */
86 void insertFront(const std::vector<pair_t>& values) noexcept;
87
88 /**
89 * @brief Check if the scope maybe holds a specific symbol in memory
90 *
91 * @param id The id of the symbol
92 * @return true On success
93 * @return false Otherwise
94 */
95 [[nodiscard]] ARK_ALWAYS_INLINE bool maybeHas(const uint16_t id) const noexcept
96 {
97 return m_min_id <= id && id <= m_max_id;
98 }
99
100 /**
101 * @brief Get a value from its symbol id
102 *
103 * @param id_to_look_for
104 * @return Value* Returns nullptr if the value can not be found
105 */
106 [[nodiscard]] ARK_ALWAYS_INLINE Value* operator[](const uint16_t id_to_look_for) noexcept
107 {
108 if (!maybeHas(id_to_look_for))
109 return nullptr;
110
111 for (std::size_t i = m_start; i < m_start + m_size; ++i)
112 {
113 auto& [id, value] = m_storage[i];
114 if (id == id_to_look_for)
115 return &value;
116 }
117 return nullptr;
118 }
119
120 /**
121 * @brief Get a value from its symbol id
122 *
123 * @param id_to_look_for
124 * @return const Value* Returns nullptr if the value can not be found
125 */
126 [[nodiscard]] ARK_ALWAYS_INLINE const Value* operator[](const uint16_t id_to_look_for) const noexcept
127 {
128 if (!maybeHas(id_to_look_for))
129 return nullptr;
130
131 for (std::size_t i = m_start; i < m_start + m_size; ++i)
132 {
133 auto& [id, value] = m_storage[i];
134 if (id == id_to_look_for)
135 return &value;
136 }
137 return nullptr;
138 }
139
140 /**
141 * @brief Get the id of a variable based on its value ; used for debug only
142 *
143 * @param val
144 * @return uint16_t
145 */
146 [[nodiscard]] uint16_t idFromValue(const Value& val) const noexcept;
147
148 /**
149 * @brief Return the element at index in scope
150 *
151 * @return const pair_t&
152 */
153 [[nodiscard]] ARK_ALWAYS_INLINE const pair_t& atPos(const std::size_t i) const noexcept
154 {
155 return m_storage[m_start + i];
156 }
157
158 /**
159 * @brief Return the element at index, starting from the end
160 *
161 * @return const pair_t&
162 */
163 [[nodiscard]] ARK_ALWAYS_INLINE pair_t& atPosReverse(const std::size_t i) const noexcept
164 {
165 return m_storage[m_start + m_size - 1 - i];
166 }
167
168 /**
169 * @brief Reset size, min and max id for the scope, to signify it's empty
170 */
171 ARK_ALWAYS_INLINE void reset() noexcept
172 {
173 m_size = 0;
174 m_min_id = MaxValue16Bits;
175 m_max_id = 0;
176 }
177
178 /**
179 * @brief Return the size of the scope
180 *
181 * @return const std::size_t
182 */
183 [[nodiscard]] ARK_ALWAYS_INLINE std::size_t size() const noexcept
184 {
185 return m_size;
186 }
187
188 /**
189 * @brief Compute the position of the first free slot in the shared storage, after this scope
190 *
191 * @return std::size_t
192 */
193 [[nodiscard]] ARK_ALWAYS_INLINE std::size_t storageEnd() const noexcept
194 {
195 return m_start + m_size;
196 }
197
198 friend ARK_API bool operator==(const ScopeView& A, const ScopeView& B) noexcept;
199
200 friend class Ark::VM;
201
202 private:
204 std::size_t m_start;
205 std::size_t m_size;
206 uint16_t m_min_id; ///< Minimum stored ID, used for a basic bloom filter
207 uint16_t m_max_id; ///< Maximum stored ID, used for a basic bloom filter
208 };
209}
210
211#endif
Constants used by ArkScript.
#define ARK_API
Definition Module.hpp:22
ArkScript configuration macros.
Default value type handled by the virtual machine.
The ArkScript virtual machine, executing ArkScript bytecode.
Definition VM.hpp:40
A class to handle the VM scope more efficiently.
Definition ScopeView.hpp:27
ARK_ALWAYS_INLINE bool maybeHas(const uint16_t id) const noexcept
Check if the scope maybe holds a specific symbol in memory.
Definition ScopeView.hpp:95
ARK_ALWAYS_INLINE void reset() noexcept
Reset size, min and max id for the scope, to signify it's empty.
ScopeView()=delete
Deleted constructor to avoid creating ScopeViews pointing to nothing. Helps catch bugs at compile tim...
ARK_ALWAYS_INLINE const pair_t & atPos(const std::size_t i) const noexcept
Return the element at index in scope.
uint16_t m_max_id
Maximum stored ID, used for a basic bloom filter.
ARK_ALWAYS_INLINE void pushBack(uint16_t id, const Value &val) noexcept
Put a value in the scope.
Definition ScopeView.hpp:69
ARK_ALWAYS_INLINE pair_t & atPosReverse(const std::size_t i) const noexcept
Return the element at index, starting from the end.
std::pair< uint16_t, Value > pair_t
Definition ScopeView.hpp:29
ARK_ALWAYS_INLINE void pushBack(uint16_t id, Value &&val) noexcept
Put a value in the scope.
Definition ScopeView.hpp:52
ARK_ALWAYS_INLINE Value * operator[](const uint16_t id_to_look_for) noexcept
Get a value from its symbol id.
ARK_ALWAYS_INLINE std::size_t storageEnd() const noexcept
Compute the position of the first free slot in the shared storage, after this scope.
ARK_ALWAYS_INLINE ScopeView(pair_t *storage, const std::size_t start) noexcept
Create a new ScopeView.
Definition ScopeView.hpp:42
ARK_ALWAYS_INLINE std::size_t size() const noexcept
Return the size of the scope.
ARK_ALWAYS_INLINE const Value * operator[](const uint16_t id_to_look_for) const noexcept
Get a value from its symbol id.
uint16_t m_min_id
Minimum stored ID, used for a basic bloom filter.
bool operator==(const Namespace &A, const Namespace &B)
Definition Namespace.hpp:21
constexpr uint16_t MaxValue16Bits
Definition Constants.hpp:81