Reduct  v1.0.4-3-gdaf0d70
A functional and immutable language.
Loading...
Searching...
No Matches
list_impl.h
Go to the documentation of this file.
1#ifndef REDUCT_LIST_IMPL_H
2#define REDUCT_LIST_IMPL_H 1
3
4#include "core.h"
5#include "handle.h"
6#include "item.h"
7#include "list.h"
8
9static inline reduct_list_node_t* reduct_list_node_new(struct reduct* reduct)
10{
11 reduct_item_t* item = reduct_item_new(reduct);
13 reduct_list_node_t* node = &item->node;
14 for (reduct_uint32_t i = 0; i < REDUCT_LIST_WIDTH; i++)
15 {
16 node->children[i] = REDUCT_NULL;
17 }
18 return &item->node;
19}
20
22{
24 REDUCT_MEMCPY(newNode, node, sizeof(reduct_list_node_t));
25 return newNode;
26}
27
29{
30 REDUCT_ASSERT(reduct != REDUCT_NULL);
31
32 reduct_item_t* item = reduct_item_new(reduct);
34 reduct_list_t* list = &item->list;
35 list->length = 0;
36 list->shift = 0;
37 list->root = REDUCT_NULL;
38 list->tail = REDUCT_NULL;
39 return list;
40}
41
43{
44 if (index >= tailOffset || list->root == REDUCT_NULL)
45 {
46 return list->tail;
47 }
48
49 reduct_list_node_t* node = list->root;
50 for (reduct_uint32_t level = list->shift; level > 0; level -= REDUCT_LIST_BITS)
51 {
52 node = node->children[(index >> level) & REDUCT_LIST_MASK];
53 }
54 return node;
55}
56
59{
60 reduct_list_node_t* newNode = reduct_list_node_copy(reduct, node);
61 if (shift == 0)
62 {
63 newNode->handles[index & REDUCT_LIST_MASK] = val;
64 }
65 else
66 {
67 reduct_uint32_t subIdx = (index >> shift) & REDUCT_LIST_MASK;
68 newNode->children[subIdx] =
69 reduct_list_assoc_internal(reduct, shift - REDUCT_LIST_BITS, newNode->children[subIdx], index, val);
70 }
71 return newNode;
72}
73
76{
77 REDUCT_ASSERT(reduct != REDUCT_NULL);
79
80 if (REDUCT_UNLIKELY(index >= list->length))
81 {
82 REDUCT_ERROR_RUNTIME(reduct, "index %zu out of bounds", index);
83 }
84
85 reduct_list_t* newList = reduct_list_new(reduct);
86 newList->length = list->length;
87 newList->shift = list->shift;
88
89 reduct_size_t tailOffset = REDUCT_LIST_TAIL_OFFSET(list);
90
91 if (index >= tailOffset)
92 {
93 newList->root = list->root;
94 newList->tail = reduct_list_node_copy(reduct, list->tail);
95 newList->tail->handles[index & REDUCT_LIST_MASK] = val;
96 }
97 else
98 {
99 newList->root = reduct_list_assoc_internal(reduct, list->shift, list->root, index, val);
100 newList->tail = list->tail;
101 }
102
103 return newList;
104}
105
107{
108 REDUCT_ASSERT(reduct != REDUCT_NULL);
109 REDUCT_ASSERT(list != REDUCT_NULL);
110
111 if (REDUCT_UNLIKELY(index >= list->length))
112 {
113 return list;
114 }
115
116 /// @todo There is definetly a better way to do this
117
118 reduct_list_t* newList = reduct_list_new(reduct);
119 reduct_handle_t val;
120 REDUCT_LIST_FOR_EACH(&val, list)
121 {
122 if (_iter.index - 1 != index)
123 {
124 reduct_list_append(reduct, newList, val);
125 }
126 }
127
128 return newList;
129}
130
132 reduct_size_t end)
133{
134 REDUCT_ASSERT(reduct != REDUCT_NULL);
135 REDUCT_ASSERT(list != REDUCT_NULL);
136
137 if (REDUCT_UNLIKELY(start > end || end > list->length))
138 {
139 REDUCT_ERROR_RUNTIME(reduct, "invalid slice range [%zu, %zu) for list of length %u", start, end, list->length);
140 }
141
142 reduct_list_t* newList = reduct_list_new(reduct);
143 reduct_list_iter_t iter = REDUCT_LIST_ITER_AT(list, start);
144
145 reduct_handle_t val;
146 while (iter.index < end)
147 {
148 if (REDUCT_LIKELY(reduct_list_iter_next(&iter, &val)))
149 {
150 reduct_list_append(reduct, newList, val);
151 }
152 }
153
154 return newList;
155}
156
158{
159 REDUCT_ASSERT(reduct != REDUCT_NULL);
160 REDUCT_ASSERT(list != REDUCT_NULL);
161
162 if (REDUCT_UNLIKELY(index >= list->length))
163 {
164 REDUCT_ERROR_RUNTIME(reduct, "index %zu out of bounds", index);
165 }
166
167 reduct_size_t tailOffset = REDUCT_LIST_TAIL_OFFSET(list);
168 reduct_list_node_t* node = reduct_list_find_leaf(list, index, tailOffset);
169 return node->handles[index & REDUCT_LIST_MASK];
170}
171
172REDUCT_API struct reduct_item* reduct_list_nth_item(struct reduct* reduct, reduct_list_t* list, reduct_size_t index)
173{
174 reduct_handle_t handle = reduct_list_nth(reduct, list, index);
175 reduct_handle_ensure_item(reduct, &handle);
176 return REDUCT_HANDLE_TO_ITEM(&handle);
177}
178
180 reduct_list_node_t* parent, reduct_list_node_t* tailNode)
181{
182 REDUCT_ASSERT(reduct != REDUCT_NULL);
183 REDUCT_ASSERT(tailNode != REDUCT_NULL);
184
185 if (shift == 0)
186 {
187 return tailNode;
188 }
189
190 reduct_list_node_t* newNode =
191 parent != REDUCT_NULL ? reduct_list_node_copy(reduct, parent) : reduct_list_node_new(reduct);
192 reduct_uint32_t subIdx = (index >> shift) & REDUCT_LIST_MASK;
193 newNode->children[subIdx] =
194 reduct_push_tail(reduct, shift - REDUCT_LIST_BITS, index, newNode->children[subIdx], tailNode);
195 return newNode;
196}
197
199{
200 REDUCT_ASSERT(list != REDUCT_NULL);
201
202 if (list->length > 0 && (list->length & REDUCT_LIST_MASK) == 0)
203 {
204 reduct_list_node_t* fullTail = list->tail;
205 list->tail = reduct_list_node_new(reduct);
206 list->tail->handles[0] = val;
207
208 if (list->root == REDUCT_NULL)
209 {
210 list->root = fullTail;
211 list->shift = 0;
212 }
213 else
214 {
215 if ((list->length - 1) >> (list->shift + REDUCT_LIST_BITS) > 0)
216 {
217 reduct_list_node_t* newRoot = reduct_list_node_new(reduct);
218 newRoot->children[0] = list->root;
219 newRoot->children[1] = reduct_push_tail(reduct, list->shift, list->length - 1, REDUCT_NULL, fullTail);
220 list->root = newRoot;
221 list->shift += REDUCT_LIST_BITS;
222 }
223 else
224 {
225 list->root = reduct_push_tail(reduct, list->shift, list->length - 1, list->root, fullTail);
226 }
227 }
228 }
229 else
230 {
231 if (list->tail == REDUCT_NULL)
232 {
233 list->tail = reduct_list_node_new(reduct);
234 }
235
236 list->tail->handles[list->length & REDUCT_LIST_MASK] = val;
237 }
238
239 list->length++;
240}
241
243{
244 REDUCT_ASSERT(reduct != REDUCT_NULL);
245 REDUCT_ASSERT(list != REDUCT_NULL);
246 REDUCT_ASSERT(other != REDUCT_NULL);
247
248 reduct_handle_t val;
249 REDUCT_LIST_FOR_EACH(&val, other)
250 {
251 reduct_list_append(reduct, list, val);
252 }
253}
254
256{
257 if (REDUCT_UNLIKELY(iter->index >= iter->list->length))
258 {
259 return REDUCT_FALSE;
260 }
261
262 if (iter->leaf == REDUCT_NULL || (iter->index & REDUCT_LIST_MASK) == 0)
263 {
264 iter->leaf = reduct_list_find_leaf(iter->list, iter->index, iter->tailOffset);
265 }
266
267 if (out != REDUCT_NULL)
268 {
269 *out = iter->leaf->handles[iter->index & REDUCT_LIST_MASK];
270 }
271
272 iter->index++;
273 return REDUCT_TRUE;
274}
275
276#endif
Core definitions and structures.
#define REDUCT_LIKELY(_x)
Definition defs.h:117
size_t reduct_size_t
Definition defs.h:100
#define REDUCT_UNLIKELY(_x)
Definition defs.h:118
reduct_bool_t
Boolean type.
Definition defs.h:135
@ REDUCT_FALSE
Definition defs.h:137
@ REDUCT_TRUE
Definition defs.h:136
#define REDUCT_MEMCPY(_dest, _src, _size)
Definition defs.h:33
reduct_uint64_t reduct_handle_t
Handle type.
Definition defs.h:189
uint32_t reduct_uint32_t
Definition defs.h:95
#define REDUCT_ASSERT(_cond)
Definition defs.h:25
#define REDUCT_API
Definition defs.h:7
#define REDUCT_NULL
Definition defs.h:23
#define REDUCT_ERROR_RUNTIME(_reduct,...)
Throw a runtime error using the jump buffer in the error structure.
Definition error.h:175
#define REDUCT_HANDLE_TO_ITEM(_handle)
Get the item pointer of a handle.
Definition handle.h:257
REDUCT_API void reduct_handle_ensure_item(struct reduct *reduct, reduct_handle_t *handle)
Ensure that a handle is an item handle.
#define REDUCT_ITEM_TYPE_LIST
A list.
Definition item.h:28
REDUCT_API reduct_item_t * reduct_item_new(struct reduct *reduct)
Allocate a new Reduct item.
#define REDUCT_ITEM_TYPE_LIST_NODE
A list node.
Definition item.h:31
Handle management.
Item management.
List management.
#define REDUCT_LIST_ITER_AT(_list, _start)
Create a initializer for a list iterator start at a specific index.
Definition list.h:164
#define REDUCT_LIST_BITS
Number of bits per level in the trie.
Definition list.h:27
#define REDUCT_LIST_WIDTH
The number of children per node.
Definition list.h:28
#define REDUCT_LIST_TAIL_OFFSET(_list)
Calculate the offset of the tail node.
Definition list.h:149
#define REDUCT_LIST_FOR_EACH(_handle, _list)
Macro for iterating over all elements in a list.
Definition list.h:181
#define REDUCT_LIST_MASK
Mask for the index at each level.
Definition list.h:29
static reduct_list_node_t * reduct_push_tail(reduct_t *reduct, reduct_uint32_t shift, reduct_size_t index, reduct_list_node_t *parent, reduct_list_node_t *tailNode)
Definition list_impl.h:179
static reduct_list_node_t * reduct_list_assoc_internal(reduct_t *reduct, reduct_uint32_t shift, reduct_list_node_t *node, reduct_size_t index, reduct_handle_t val)
Definition list_impl.h:57
static reduct_list_node_t * reduct_list_node_new(struct reduct *reduct)
Definition list_impl.h:9
REDUCT_API reduct_handle_t reduct_list_nth(struct reduct *reduct, reduct_list_t *list, reduct_size_t index)
Get the nth element of the list.
Definition list_impl.h:157
REDUCT_API reduct_list_t * reduct_list_dissoc(struct reduct *reduct, reduct_list_t *list, reduct_size_t index)
Create a new list with the element at the specified index removed.
Definition list_impl.h:106
REDUCT_API void reduct_list_append_list(reduct_t *reduct, reduct_list_t *list, reduct_list_t *other)
Definition list_impl.h:242
REDUCT_API reduct_list_t * reduct_list_assoc(struct reduct *reduct, reduct_list_t *list, reduct_size_t index, reduct_handle_t val)
Create a new list with an updated value at the specified index.
Definition list_impl.h:74
REDUCT_API void reduct_list_append(reduct_t *reduct, reduct_list_t *list, reduct_handle_t val)
Definition list_impl.h:198
static reduct_list_node_t * reduct_list_find_leaf(reduct_list_t *list, reduct_size_t index, reduct_size_t tailOffset)
Definition list_impl.h:42
REDUCT_API reduct_list_t * reduct_list_slice(struct reduct *reduct, reduct_list_t *list, reduct_size_t start, reduct_size_t end)
Create a new list by slicing an existing list.
Definition list_impl.h:131
static reduct_list_node_t * reduct_list_node_copy(reduct_t *reduct, reduct_list_node_t *node)
Definition list_impl.h:21
REDUCT_API reduct_bool_t reduct_list_iter_next(reduct_list_iter_t *iter, reduct_handle_t *out)
Get the next element from the iterator.
Definition list_impl.h:255
REDUCT_API reduct_list_t * reduct_list_new(reduct_t *reduct)
Definition list_impl.h:28
REDUCT_API struct reduct_item * reduct_list_nth_item(struct reduct *reduct, reduct_list_t *list, reduct_size_t index)
Get the nth element of the list as an item.
Definition list_impl.h:172
Item structure.
Definition item.h:57
reduct_list_t list
A list.
Definition item.h:67
reduct_list_node_t node
A list node.
Definition item.h:68
reduct_item_type_t type
The type of the item.
Definition item.h:61
List iterator structure.
Definition list.h:139
reduct_list_t * list
Definition list.h:140
reduct_size_t index
Definition list.h:141
reduct_size_t tailOffset
Definition list.h:143
reduct_list_node_t * leaf
Definition list.h:142
List node structure.
Definition list.h:36
reduct_handle_t handles[REDUCT_LIST_WIDTH]
Definition list.h:39
struct reduct_list_node * children[REDUCT_LIST_WIDTH]
Definition list.h:38
List structure.
Definition list.h:48
reduct_list_node_t * tail
Pointer to the tail node.
Definition list.h:52
reduct_list_node_t * root
Pointer to the trie root node.
Definition list.h:51
reduct_uint32_t shift
The amount to shift the index to compute access paths.
Definition list.h:50
reduct_uint32_t length
Total number of elements.
Definition list.h:49
State structure.
Definition core.h:61