Reduct  v4.1.3-1-gd06c383
A functional and immutable language.
Loading...
Searching...
No Matches
handle.h
Go to the documentation of this file.
1#ifndef REDUCT_HANDLE_H
2#define REDUCT_HANDLE_H 1
3
4#include <reduct/atom.h>
5#include <reduct/defs.h>
6#include <reduct/error.h>
7#include <reduct/item.h>
8#include <reduct/standard.h>
9
10#include <math.h>
11
12struct reduct;
13
14/**
15 * @file handle.h
16 * @brief Handle management.
17 * @defgroup handle Handle
18 *
19 * A handle is a lightweight reference to a Reduct item, with the ability to cache a numeric value or reference
20 * an item using Tagged Pointers (NaN Boxing).
21 *
22 * ## 64-bit Handle Bit Layout
23 *
24 * The top 16 bits are used as a type tag. The remaining 48 bits represent the payload
25 * (either a 48-bit pointer or a shifted IEEE 754 double).
26 *
27 * | Tag (16 bits) | Payload (48 bits) |
28 * |-----------------|-----------------------------------|
29 * | `0x0000` | Item Pointer (`reduct_item_t*`) |
30 * | `0x0007...FFFF` | Number (Shifted IEEE 754 double) |
31 *
32 * @see [Wikipedia Tagged pointer](https://en.wikipedia.org/wiki/Tagged_pointer)
33 *
34 * @{
35 */
36
37/**
38 * @brief High-level handle types.
39 * @enum reduct_handle_type_t
40 */
41typedef enum
42{
43 REDUCT_HANDLE_TYPE_NONE = 0, ///< Invalid type.
44 REDUCT_HANDLE_TYPE_NUMBER, ///< Handle is a number or references a number shaped atom.
45 REDUCT_HANDLE_TYPE_ATOM, ///< Handle is a reference to an atom.
46 REDUCT_HANDLE_TYPE_LIST, ///< Handle is a reference to a list.
47 REDUCT_HANDLE_TYPE_FUNCTION, ///< Handle is a reference to a function.
48 REDUCT_HANDLE_TYPE_CLOSURE, ///< Handle is a reference to a closure.
49 REDUCT_HANDLE_TYPE_ARENA, ///< Handle is a reference to an arena.
50 REDUCT_HANDLE_TYPE_RVSDG_NODE, ///< Handle is a reference to an IR node.
51 REDUCT_HANDLE_TYPE_RVSDG_EDGE, ///< Handle is a reference to an IR edge.
52 REDUCT_HANDLE_TYPE_FUTURE, ///< Handle is a reference to a future.
53 REDUCT_HANDLE_TYPE_UNKNOWN ///< Handle is corrupt or otherwise invalid.
55
56#define REDUCT_HANDLE_OFFSET_NUMBER 0x0007000000000000ULL ///< Offset used for encoding doubles.
57
58#define REDUCT_HANDLE_TAG_ITEM 0x0000000000000000ULL ///< Tag for item handles.
59
60#define REDUCT_HANDLE_MASK_TAG 0xFFFF000000000000ULL ///< Mask for handle tag bits.
61#define REDUCT_HANDLE_MASK_VAL 0x0000FFFFFFFFFFFFULL ///< Mask for handle value bits.
62#define REDUCT_HANDLE_MASK_PTR REDUCT_HANDLE_MASK_VAL ///< Mask for item pointer bits.
63
64#define REDUCT_HANDLE_NUMBER_WIDTH 64 ///< The bit width used for shift operations on numbers.
65
66/**
67 * @brief Create a handle from a number.
68 *
69 * @param _val The number value.
70 * @return The handle.
71 */
72#define REDUCT_HANDLE_FROM_NUMBER(_val) \
73 ((reduct_handle_t){((union { \
74 double d; \
75 uint64_t u; \
76 }){.d = (_val)}) \
77 .u + \
78 REDUCT_HANDLE_OFFSET_NUMBER})
79
80/**
81 * @brief Create a handle from an item pointer.
82 *
83 * @param _ptr The pointer to the reduct_item_t.
84 * @return The handle.
85 */
86#define REDUCT_HANDLE_FROM_ITEM(_ptr) \
87 ((reduct_handle_t){REDUCT_HANDLE_TAG_ITEM | ((uintptr_t)(void*)(_ptr) & REDUCT_HANDLE_MASK_PTR)})
88
89/**
90 * @brief Create a handle from an atom pointer.
91 *
92 * @param _atom The pointer to the reduct_atom_t.
93 * @return The handle.
94 */
95#define REDUCT_HANDLE_FROM_ATOM(_atom) REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_atom, reduct_item_t, atom))
96
97/**
98 * @brief Create a handle from a list pointer.
99 *
100 * @param _list The pointer to the reduct_list_t.
101 * @return The handle.
102 */
103#define REDUCT_HANDLE_FROM_LIST(_list) REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_list, reduct_item_t, list))
104
105/**
106 * @brief Create a handle from a function pointer.
107 *
108 * @param _func The pointer to the reduct_function_t.
109 * @return The handle.
110 */
111#define REDUCT_HANDLE_FROM_FUNCTION(_func) REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_func, reduct_item_t, function))
112
113/**
114 * @brief Create a handle from a closure pointer.
115 *
116 * @param _closure The pointer to the reduct_closure_t.
117 * @return The handle.
118 */
119#define REDUCT_HANDLE_FROM_CLOSURE(_closure) \
120 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_closure, reduct_item_t, closure))
121
122/**
123 * @brief Create a handle from an IR node pointer.
124 *
125 * @param _node The pointer to the reduct_rvsdg_node_t.
126 * @return The handle.
127 */
128#define REDUCT_HANDLE_FROM_RVSDG_NODE(_node) \
129 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_node, reduct_item_t, rvsdgNode))
130
131/**
132 * @brief Create a handle from an IR edge pointer.
133 *
134 * @param _edge The pointer to the reduct_rvsdg_edge_t.
135 * @return The handle.
136 */
137#define REDUCT_HANDLE_FROM_RVSDG_EDGE(_edge) \
138 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_edge, reduct_item_t, rvsdgEdge))
139
140/**
141 * @brief Create a handle from an IR origin pointer.
142 *
143 * @param _origin The pointer to the reduct_rvsdg_origin_t.
144 * @return The handle.
145 */
146#define REDUCT_HANDLE_FROM_RVSDG_ORIGIN(_origin) \
147 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_origin, reduct_item_t, rvsdgOrigin))
148
149/**
150 * @brief Create a handle from an IR user pointer.
151 *
152 * @param _user The pointer to the reduct_rvsdg_user_t.
153 * @return The handle.
154 */
155#define REDUCT_HANDLE_FROM_RVSDG_USER(_user) \
156 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_user, reduct_item_t, rvsdgUser))
157
158/**
159 * @brief Create a handle from an IR region pointer.
160 *
161 * @param _region The pointer to the reduct_rvsdg_region_t.
162 * @return The handle.
163 */
164#define REDUCT_HANDLE_FROM_RVSDG_REGION(_region) \
165 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_region, reduct_item_t, rvsdgRegion))
166
167/**
168 * @brief Create a boolean handle from a C condition.
169 *
170 * @param _reduct Pointer to the Reduct structure.
171 * @param _cond The condition to evaluate.
172 */
173#define REDUCT_HANDLE_FROM_BOOL(_reduct, _cond) ((_cond) ? REDUCT_HANDLE_TRUE() : REDUCT_HANDLE_FALSE(_reduct))
174
175/**
176 * @brief Create a handle from a future pointer.
177 *
178 * @param _future The pointer to the reduct_future_t.
179 * @return The handle.
180 */
181#define REDUCT_HANDLE_FROM_FUTURE(_future) REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_future, reduct_item_t, future))
182
183/**
184 * @brief Check if a handle is a number.
185 *
186 * @param _handle Pointer to the handle.
187 * @return Non-zero if the handle is a number, zero otherwise.
188 */
189#define REDUCT_HANDLE_IS_NUMBER(_handle) (((_handle)._value) >= REDUCT_HANDLE_OFFSET_NUMBER)
190
191/**
192 * @brief Check if a handle is a number or references a number shaped item.
193 *
194 * @param _handle Pointer to the handle.
195 * @return Non-zero if the handle is number shaped, zero otherwise.
196 */
197#define REDUCT_HANDLE_IS_NUMBER_SHAPED(_handle) \
198 (REDUCT_HANDLE_IS_NUMBER(_handle) || \
199 (REDUCT_HANDLE_IS_ATOM(_handle) && reduct_atom_is_number(REDUCT_HANDLE_TO_ATOM(_handle))))
200
201/**
202 * @brief Get the high-level type of a handle.
203 *
204 * @param handle Pointer to the handle.
205 * @return The type of the handle.
206 */
208
209/**
210 * @brief Get the string name of a handle type.
211 *
212 * @param type The handle type.
213 * @return A constant string representing the type.
214 */
216
217/**
218 * @brief Get the string representation of the type of the item referenced by the handle.
219 *
220 * @param _handle Pointer to the handle.
221 * @return The string representation of the item type.
222 */
223#define REDUCT_HANDLE_GET_TYPE_STRING(_handle) (reduct_handle_type_string(reduct_handle_get_type(_handle)))
224
225/**
226 * @brief Check if a handle is nil (an empty list).
227 *
228 * @param _handle Pointer to the handle.
229 * @return Non-zero if the handle is nil, zero otherwise.
230 */
231#define REDUCT_HANDLE_IS_NIL(_handle) (REDUCT_HANDLE_IS_LIST(_handle) && REDUCT_HANDLE_TO_LIST(_handle)->length == 0)
232
233/**
234 * @brief Check if a handle is empty (nil or empty atom).
235 *
236 * @param _handle Pointer to the handle.
237 */
238#define REDUCT_HANDLE_IS_EMPTY(_handle) \
239 (REDUCT_HANDLE_IS_NIL(_handle) || (REDUCT_HANDLE_IS_ATOM(_handle) && REDUCT_HANDLE_TO_ATOM(_handle)->length == 0))
240
241/**
242 * @brief Check if a handle is an item.
243 *
244 * @param _handle Pointer to the handle.
245 * @return Non-zero if the handle is an item, zero otherwise.
246 */
247#define REDUCT_HANDLE_IS_ITEM(_handle) ((((_handle)._value) & REDUCT_HANDLE_MASK_TAG) == REDUCT_HANDLE_TAG_ITEM)
248
249/**
250 * @brief Check if a handle is an atom.
251 *
252 * @param _handle Pointer to the handle.
253 * @return Non-zero if the handle is an atom, zero otherwise.
254 */
255#define REDUCT_HANDLE_IS_ATOM(_handle) \
256 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_ATOM)
257
258/**
259 * @brief Check if a handle is a list.
260 *
261 * @param _handle Pointer to the handle.
262 * @return Non-zero if the handle is a list, zero otherwise.
263 */
264#define REDUCT_HANDLE_IS_LIST(_handle) \
265 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_LIST)
266
267/**
268 * @brief Check if a handle is a function.
269 *
270 * @param _handle Pointer to the handle.
271 * @return Non-zero if the handle is a function, zero otherwise.
272 */
273#define REDUCT_HANDLE_IS_FUNCTION(_handle) \
274 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_FUNCTION)
275
276/**
277 * @brief Check if a handle is a closure.
278 *
279 * @param _handle Pointer to the handle.
280 * @return Non-zero if the handle is a closure, zero otherwise.
281 */
282#define REDUCT_HANDLE_IS_CLOSURE(_handle) \
283 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_CLOSURE)
284
285/**
286 * @brief Check if a handle is an IR node.
287 *
288 * @param _handle Pointer to the handle.
289 * @return Non-zero if the handle is an IR node, zero otherwise.
290 */
291#define REDUCT_HANDLE_IS_RVSDG_NODE(_handle) \
292 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_RVSDG_NODE)
293
294/**
295 * @brief Check if a handle is an IR edge.
296 *
297 * @param _handle Pointer to the handle.
298 * @return Non-zero if the handle is an IR edge, zero otherwise.
299 */
300#define REDUCT_HANDLE_IS_RVSDG_EDGE(_handle) \
301 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_RVSDG_EDGE)
302
303/**
304 * @brief Check if a handle is an IR origin.
305 *
306 * @param _handle Pointer to the handle.
307 * @return Non-zero if the handle is an IR origin, zero otherwise.
308 */
309#define REDUCT_HANDLE_IS_RVSDG_ORIGIN(_handle) \
310 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_RVSDG_ORIGIN)
311
312/**
313 * @brief Check if a handle is an IR user.
314 *
315 * @param _handle Pointer to the handle.
316 * @return Non-zero if the handle is an IR user, zero otherwise.
317 */
318#define REDUCT_HANDLE_IS_RVSDG_USER(_handle) \
319 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_RVSDG_USER)
320
321/**
322 * @brief Check if a handle is a future.
323 *
324 * @param _handle Pointer to the handle.
325 */
326#define REDUCT_HANDLE_IS_FUTURE(_handle) \
327 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_FUTURE)
328
329/**
330 * @brief Check if a handle is a lambda.
331 *
332 * @param _handle Pointer to the handle.
333 * @return Non-zero if the handle is a lambda, zero otherwise.
334 */
335#define REDUCT_HANDLE_IS_LAMBDA(_handle) (REDUCT_HANDLE_IS_FUNCTION(_handle) || REDUCT_HANDLE_IS_CLOSURE(_handle))
336
337/**
338 * @brief Check if a handle is a native function.
339 *
340 * @param _handle Pointer to the handle.
341 * @return Non-zero if the handle is a native function, zero otherwise.
342 */
343#define REDUCT_HANDLE_IS_NATIVE(_reduct, _handle) \
344 (REDUCT_HANDLE_IS_ATOM(_handle) && reduct_atom_is_native(_reduct, REDUCT_HANDLE_TO_ATOM(_handle)))
345
346/**
347 * @brief Check if a handle is an intrinsic function.
348 *
349 * @param _reduct Pointer to the Reduct structure.
350 * @param _handle Pointer to the handle.
351 * @return Non-zero if the handle is an intrinsic function, zero otherwise.
352 */
353#define REDUCT_HANDLE_IS_INTRINSIC(_reduct, _handle) \
354 (REDUCT_HANDLE_IS_ATOM(_handle) && reduct_atom_is_intrinsic(_reduct, REDUCT_HANDLE_TO_ATOM(_handle)))
355
356/**
357 * @brief Check if a handle is callable.
358 *
359 * @param _handle Pointer to the handle.
360 * @return Non-zero if the handle is callable, zero otherwise.
361 */
362#define REDUCT_HANDLE_IS_CALLABLE(_reduct, _handle) \
363 (REDUCT_HANDLE_IS_LAMBDA(_handle) || REDUCT_HANDLE_IS_NATIVE(_reduct, _handle))
364
365/**
366 * @brief Check if a handle either is an atom, or could be represented by an atom item.
367 *
368 * @param _handle Pointer to the handle.
369 * @return Non-zero if the handle is atom-like, zero otherwise.
370 */
371#define REDUCT_HANDLE_IS_ATOM_LIKE(_handle) (REDUCT_HANDLE_IS_NUMBER(_handle) || REDUCT_HANDLE_IS_ATOM(_handle))
372
373/**
374 * @brief Get the number value of a handle.
375 *
376 * @param _handle Pointer to the handle.
377 * @return The number value.
378 */
379#define REDUCT_HANDLE_TO_NUMBER(_handle) \
380 (((union { \
381 uint64_t u; \
382 double d; \
383 }){.u = ((_handle)._value) - REDUCT_HANDLE_OFFSET_NUMBER}) \
384 .d)
385
386/**
387 * @brief Get the item pointer of a handle.
388 *
389 * @param _handle Pointer to the handle.
390 * @return The item pointer.
391 */
392#define REDUCT_HANDLE_TO_ITEM(_handle) ((reduct_item_t*)(void*)(((_handle)._value) & REDUCT_HANDLE_MASK_PTR))
393
394/**
395 * @brief Get the atom pointer of a handle.
396 *
397 * @param _handle Pointer to the handle.
398 * @return The atom pointer.
399 */
400#define REDUCT_HANDLE_TO_ATOM(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->atom)
401
402/**
403 * @brief Get the list pointer of a handle.
404 *
405 * @param _handle Pointer to the handle.
406 * @return The list pointer.
407 */
408#define REDUCT_HANDLE_TO_LIST(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->list)
409
410/**
411 * @brief Get the function pointer of a handle.
412 *
413 * @param _handle Pointer to the handle.
414 * @return The function pointer.
415 */
416#define REDUCT_HANDLE_TO_FUNCTION(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->function)
417
418/**
419 * @brief Get the closure pointer of a handle.
420 *
421 * @param _handle Pointer to the handle.
422 * @return The closure pointer.
423 */
424#define REDUCT_HANDLE_TO_CLOSURE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->closure)
425
426/**
427 * @brief Get the IR node pointer of a handle.
428 *
429 * @param _handle Pointer to the handle.
430 * @return The IR node pointer.
431 */
432#define REDUCT_HANDLE_TO_RVSDG_NODE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->rvsdgNode)
433
434/**
435 * @brief Get the IR edge pointer of a handle.
436 *
437 * @param _handle Pointer to the handle.
438 * @return The IR edge pointer.
439 */
440#define REDUCT_HANDLE_TO_RVSDG_EDGE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->rvsdgEdge)
441
442/**
443 * @brief Get the IR origin pointer of a handle.
444 *
445 * @param _handle Pointer to the handle.
446 * @return The IR origin pointer.
447 */
448#define REDUCT_HANDLE_TO_RVSDG_ORIGIN(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->rvsdgOrigin)
449
450/**
451 * @brief Get the IR user pointer of a handle.
452 *
453 * @param _handle Pointer to the handle.
454 * @return The IR user pointer.
455 */
456#define REDUCT_HANDLE_TO_RVSDG_USER(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->rvsdgUser)
457
458/**
459 * @brief Get the future pointer of a handle.
460 *
461 * @param _handle Pointer to the handle.
462 */
463#define REDUCT_HANDLE_TO_FUTURE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->future)
464
465/**
466 * @brief Get the boolean value of a handle.
467 *
468 * @param _handle Pointer to the handle.
469 * @return The boolean value.
470 */
471#define REDUCT_HANDLE_TO_BOOL(_handle) (REDUCT_HANDLE_IS_TRUTHY(_handle) ? true : false)
472
473/**
474 * @brief Create a list handle.
475 *
476 * @param _reduct Pointer to the Reduct structure.
477 * @param _length The length of the list.
478 */
479#define REDUCT_HANDLE_CREATE_LIST(_reduct, _length) REDUCT_HANDLE_FROM_LIST(reduct_list_new(_reduct, _length))
480
481/**
482 * @brief Create a list handle from an array of handles.
483 *
484 * @param _reduct Pointer to the Reduct structure.
485 * @param _count The number of handles.
486 * @param _handles The array of handles.
487 */
488#define REDUCT_HANDLE_CREATE_HANDLES(_reduct, _count, _handles) \
489 REDUCT_HANDLE_FROM_LIST(reduct_list_new_handles(_reduct, _count, _handles))
490
491/**
492 * @brief Create a list handle of pairs (key-value) from a variable number of pairs.
493 *
494 * @param _reduct Pointer to the Reduct structure.
495 * @param _count The number of pairs.
496 * @param ... Each pair should be provided as a `(const char*, reduct_handle_t)`.
497 */
498#define REDUCT_HANDLE_CREATE_ALIST(_reduct, _count, ...) \
499 REDUCT_HANDLE_FROM_LIST(reduct_list_new_alist(_reduct, _count, __VA_ARGS__))
500
501/**
502 * @brief Create an atom handle with a reserved size.
503 *
504 * @param _reduct Pointer to the Reduct structure.
505 * @param _len The length of the buffer.
506 */
507#define REDUCT_HANDLE_CREATE_ATOM(_reduct, _len) REDUCT_HANDLE_FROM_ATOM(reduct_atom_new(_reduct, _len))
508
509/**
510 * @brief Create an atom handle from a string.
511 *
512 * @param _reduct Pointer to the Reduct structure.
513 * @param _str The null-terminated string.
514 */
515#define REDUCT_HANDLE_CREATE_STRING(_reduct, _str) \
516 REDUCT_HANDLE_FROM_ATOM(reduct_atom_lookup(_reduct, _str, strlen(_str), REDUCT_ATOM_LOOKUP_QUOTED))
517
518/**
519 * @brief Create an interned atom handle from a string.
520 *
521 * @param _reduct Pointer to the Reduct structure.
522 * @param _str The null-terminated string.
523 */
524#define REDUCT_HANDLE_CREATE_SYMBOL(_reduct, _str) \
525 REDUCT_HANDLE_FROM_ATOM(reduct_atom_lookup(_reduct, _str, strlen(_str), REDUCT_ATOM_LOOKUP_NONE))
526
527/**
528 * @brief Create an atom handle from a number.
529 *
530 * @param _reduct Pointer to the Reduct structure.
531 * @param _val The number value.
532 */
533#define REDUCT_HANDLE_CREATE_NUMBER(_reduct, _val) REDUCT_HANDLE_FROM_ATOM(reduct_atom_new_number(_reduct, _val))
534
535/**
536 * @brief Create an atom handle from a native function.
537 *
538 * @param _reduct Pointer to the Reduct structure.
539 * @param _fn The native function pointer.
540 */
541#define REDUCT_HANDLE_CREATE_NATIVE(_reduct, _fn) REDUCT_HANDLE_FROM_ATOM(reduct_atom_new_native(_reduct, _fn))
542
543/**
544 * @brief Create a future handle.
545 *
546 * @param _reduct Pointer to the Reduct structure.
547 * @param _callable The callable handle.
548 * @param _argc The number of arguments.
549 * @param _argv Pointer to the arguments array.
550 */
551#define REDUCT_HANDLE_CREATE_FUTURE(_reduct, _callable, _argc, _argv) \
552 REDUCT_HANDLE_FROM_FUTURE(reduct_future_new(_reduct, _callable, _argc, _argv))
553
554/**
555 * @brief Macro for iterating over all elements in a list handle.
556 *
557 * @param _handle The reduct_handle_t variable to store each element.
558 * @param _list Pointer to the list handle.
559 */
560#define REDUCT_HANDLE_FOR_EACH(_handle, _list) REDUCT_LIST_FOR_EACH(_handle, REDUCT_HANDLE_TO_LIST(_list))
561
562/**
563 * @brief Get the value of the future referenced by the handle or the handle itself.
564 *
565 * @param _reduct Pointer to the Reduct structure.
566 * @param _handle The handle.
567 * @return The result of the future if the handle is a future, otherwise the handle itself.
568 */
569#define REDUCT_HANDLE_JOIN(_reduct, _handle) \
570 (REDUCT_HANDLE_IS_FUTURE(_handle) ? reduct_future_join(_reduct, REDUCT_HANDLE_TO_FUTURE(_handle)) : (_handle))
571
572/**
573 * @brief Get the constant nil handle.
574 *
575 * @param _reduct Pointer to the Reduct structure.
576 */
577#define REDUCT_HANDLE_NIL(_reduct) ((_reduct)->global->nil)
578/**
579 * @brief Get the constant false (nil) handle.
580 *
581 * @param _reduct Pointer to the Reduct structure.
582 */
583#define REDUCT_HANDLE_FALSE(_reduct) REDUCT_HANDLE_NIL(_reduct)
584
585#define REDUCT_HANDLE_TRUE() REDUCT_HANDLE_FROM_NUMBER(1.0) ///< Constant true handle.
586
587#define REDUCT_HANDLE_PI() REDUCT_HANDLE_FROM_NUMBER(REDUCT_PI) ///< Constant pi handle.
588
589#define REDUCT_HANDLE_E() REDUCT_HANDLE_FROM_NUMBER(REDUCT_E) ///< Constant e handle.
590
591#define REDUCT_HANDLE_INF() REDUCT_HANDLE_FROM_NUMBER(REDUCT_INF) ///< Constant infinity handle.
592
593#define REDUCT_HANDLE_NAN() REDUCT_HANDLE_FROM_NUMBER(REDUCT_NAN) ///< Constant not a number handle.
594
595/**
596 * @brief Compare two handles using a given operator with a fast path for numbers.
597 *
598 * @param _reduct Pointer to the Reduct structure.
599 * @param _a The first handle.
600 * @param _b The second handle.
601 * @param _op The comparison operator (e.g., <, >, <=, >=, etc.).
602 * @return The result of the comparison.
603 */
604#define REDUCT_HANDLE_COMPARE_FAST(_reduct, _a, _b, _op) \
605 (REDUCT_LIKELY((_a)._value >= REDUCT_HANDLE_OFFSET_NUMBER && (_b)._value >= REDUCT_HANDLE_OFFSET_NUMBER) \
606 ? (REDUCT_HANDLE_TO_NUMBER(_a) _op REDUCT_HANDLE_TO_NUMBER(_b)) \
607 : (reduct_handle_compare(_reduct, (_a), (_b)) _op 0))
608
609/**
610 * @brief Perform a arithmetic operation on two handles with a fast path for numbers.
611 *
612 * @param _reduct Pointer to the Reduct structure.
613 * @param _a The target handle.
614 * @param _b The first handle.
615 * @param _c The second handle.
616 * @param _op The arithmetic operator, (e.g., +, -, *, etc.)
617 */
618#define REDUCT_HANDLE_ARITHMETIC_FAST(_reduct, _a, _b, _c, _op) \
619 do \
620 { \
621 reduct_handle_t _bVal = (_b); \
622 reduct_handle_t _cVal = (_c); \
623 double _bv, _cv; \
624 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
625 { \
626 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
627 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
628 } \
629 else \
630 { \
631 _bv = reduct_handle_as_number(_reduct, _bVal); \
632 _cv = reduct_handle_as_number(_reduct, _cVal); \
633 } \
634 *(_a) = REDUCT_HANDLE_FROM_NUMBER(_bv _op _cv); \
635 } while (0)
636
637/**
638 * @brief Perform a division operation on two handles with a fast path for numbers.
639 *
640 * @param _reduct Pointer to the Reduct structure.
641 * @param _a The target handle.
642 * @param _b The first handle.
643 * @param _c The second handle.
644 */
645#define REDUCT_HANDLE_DIV_FAST(_reduct, _a, _b, _c) \
646 do \
647 { \
648 reduct_handle_t _bVal = (_b); \
649 reduct_handle_t _cVal = (_c); \
650 double _bv, _cv; \
651 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
652 { \
653 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
654 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
655 } \
656 else \
657 { \
658 _bv = reduct_handle_as_number(_reduct, _bVal); \
659 _cv = reduct_handle_as_number(_reduct, _cVal); \
660 } \
661 if (REDUCT_UNLIKELY(_cv == 0.0)) \
662 { \
663 REDUCT_ERROR_THROW(_reduct, "division by zero"); \
664 } \
665 *(_a) = REDUCT_HANDLE_FROM_NUMBER(_bv / _cv); \
666 } while (0)
667
668/**
669 * @brief Perform a modulo operation on two handles.
670 *
671 * @param _reduct Pointer to the Reduct structure.
672 * @param _a The target handle.
673 * @param _b The first handle.
674 * @param _c The second handle.
675 */
676#define REDUCT_HANDLE_MOD_FAST(_reduct, _a, _b, _c) \
677 do \
678 { \
679 reduct_handle_t _bVal = (_b); \
680 reduct_handle_t _cVal = (_c); \
681 double _bv, _cv; \
682 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
683 { \
684 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
685 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
686 } \
687 else \
688 { \
689 _bv = reduct_handle_as_number(_reduct, _bVal); \
690 _cv = reduct_handle_as_number(_reduct, _cVal); \
691 } \
692 if (REDUCT_UNLIKELY(_cv == 0.0)) \
693 { \
694 REDUCT_ERROR_THROW(_reduct, "division by zero"); \
695 } \
696 *(_a) = REDUCT_HANDLE_FROM_NUMBER(fmod(_bv, _cv)); \
697 } while (0)
698
699/**
700 * @brief Perform a bitwise operation on two handles.
701 *
702 * @param _reduct Pointer to the Reduct structure.
703 * @param _a The target handle.
704 * @param _b The first handle.
705 * @param _c The second handle
706 * @param _op The bitwise operator, (e.g., &, |, ^, etc.)
707 */
708#define REDUCT_HANDLE_BITWISE_FAST(_reduct, _a, _b, _c, _op) \
709 do \
710 { \
711 reduct_handle_t _bVal = (_b); \
712 reduct_handle_t _cVal = (_c); \
713 double _bv, _cv; \
714 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
715 { \
716 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
717 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
718 } \
719 else \
720 { \
721 _bv = reduct_handle_as_number(_reduct, _bVal); \
722 _cv = reduct_handle_as_number(_reduct, _cVal); \
723 } \
724 *(_a) = REDUCT_HANDLE_FROM_NUMBER((double)((int64_t)_bv _op(int64_t) _cv)); \
725 } while (0)
726
727/**
728 * @brief Check if a handle is truthy.
729 *
730 * @param _handle Pointer to the handle.
731 * @return `true` if the handle is truthy, `false` otherwise.
732 */
733#define REDUCT_HANDLE_IS_TRUTHY(_handle) \
734 (!REDUCT_HANDLE_IS_LIST(_handle) || REDUCT_HANDLE_TO_LIST(_handle)->length != 0)
735
736/**
737 * @brief Retain a handle, preventing its referenced item from being collected by the garbage collector.
738 *
739 * @param _reduct Pointer to the Reduct structure.
740 * @param _handle Pointer to the handle.
741 */
742#define REDUCT_HANDLE_RETAIN(_reduct, _handle) \
743 do \
744 { \
745 reduct_handle_t _h = (_handle); \
746 if (REDUCT_HANDLE_IS_ITEM(_h)) \
747 { \
748 reduct_item_retain(REDUCT_HANDLE_TO_ITEM(_h)); \
749 } \
750 } while (0)
751
752/**
753 * @brief Release a handle, allowing its referenced item to be collected by the garbage collector.
754 *
755 * @param _reduct Pointer to the Reduct structure.
756 * @param _handle The handle.
757 */
758#define REDUCT_HANDLE_RELEASE(_reduct, _handle) \
759 do \
760 { \
761 reduct_handle_t _h = (_handle); \
762 if (REDUCT_HANDLE_IS_ITEM(_h)) \
763 { \
764 reduct_item_release(REDUCT_HANDLE_TO_ITEM(_h)); \
765 } \
766 } while (0)
767
768/**
769 * @brief Free the item that a handle is referencing.
770 *
771 * Intended to be used by the GC or when it is known that a handle has no more users and its item was allocated by the
772 * current thread.
773 *
774 * @param _reduct Pointer to the Reduct structure.
775 * @param _handle The handle to the item.
776 */
777#define REDUCT_HANDLE_FREE(_reduct, _handle) \
778 do \
779 { \
780 reduct_handle_t _h = (_handle); \
781 if (REDUCT_HANDLE_IS_ITEM(_h)) \
782 { \
783 reduct_item_free((_reduct), REDUCT_HANDLE_TO_ITEM(_h)); \
784 } \
785 } while (0)
786
787/**
788 * @brief Ensure that a handle is an item handle.
789 *
790 * If the handle is a number, it will be upgraded to an item handle by looking up a corresponding atom.
791 *
792 * @param reduct Pointer to the Reduct structure.
793 * @param handle The handle to ensure.
794 */
795REDUCT_API void reduct_handle_ensure_item(struct reduct* reduct, reduct_handle_t* handle);
796
797/**
798 * @brief Ensure that a handle is an item and return the pointer.
799 *
800 * @param reduct Pointer to the Reduct structure.
801 * @param handle The handle.
802 * @return The item pointer.
803 */
804static inline REDUCT_ALWAYS_INLINE struct reduct_item* reduct_handle_as_item(struct reduct* reduct,
805 reduct_handle_t handle)
806{
808 {
809 reduct_handle_ensure_item(reduct, &handle);
810 }
811 return REDUCT_HANDLE_TO_ITEM(handle);
812}
813
814/**
815 * @brief Retrieve the integer representation of the handle.
816 *
817 * Will cast number values to integers or retrieve number values stored within an atom referenced by the handle
818 * if the handle is itself not a number.
819 *
820 * @param reduct Pointer to the Reduct structure.
821 * @param handle The handle.
822 * @return The integer value.
823 */
824static inline REDUCT_ALWAYS_INLINE int64_t reduct_handle_as_int(struct reduct* reduct, reduct_handle_t handle)
825{
827 {
828 return (int64_t)REDUCT_HANDLE_TO_NUMBER(handle);
829 }
830
831 REDUCT_ERROR_ASSERT(reduct, REDUCT_HANDLE_IS_ATOM(handle), "expected atom");
832 reduct_atom_t* atom = REDUCT_HANDLE_TO_ATOM(handle);
833 return reduct_atom_as_int(reduct, atom);
834}
835
836/**
837 * @brief Retrieve the number representation of the handle.
838 *
839 * Will retrieve number values stored within an atom referenced by the handle
840 * if the handle is itself not a number.
841 *
842 * @param reduct Pointer to the Reduct structure.
843 * @param handle The handle.
844 * @return The number value.
845 */
846static inline REDUCT_ALWAYS_INLINE double reduct_handle_as_number(struct reduct* reduct, reduct_handle_t handle)
847{
849 {
850 return REDUCT_HANDLE_TO_NUMBER(handle);
851 }
852
853 REDUCT_ERROR_ASSERT(reduct, REDUCT_HANDLE_IS_ATOM(handle), "expected atom");
854 reduct_atom_t* atom = REDUCT_HANDLE_TO_ATOM(handle);
855 return reduct_atom_as_number(reduct, atom);
856}
857
858/**
859 * @brief Retrieve the atom pointer of the handle.
860 *
861 * Will upgrade the handle to an item handle if it is a number.
862 *
863 * @param reduct Pointer to the Reduct structure.
864 * @param handle The handle.
865 * @return The atom pointer.
866 */
867static inline REDUCT_ALWAYS_INLINE reduct_atom_t* reduct_handle_as_atom(struct reduct* reduct, reduct_handle_t handle)
868{
869 reduct_item_t* item = reduct_handle_as_item(reduct, handle);
870 REDUCT_ERROR_ASSERT(reduct, item->type == REDUCT_ITEM_TYPE_ATOM, "expected atom");
871 return &item->atom;
872}
873
874/**
875 * @brief Check if two items are exactly equal string-wise or structurally.
876 *
877 * @param reduct Pointer to the Reduct structure.
878 * @param a The first handle, will be upgraded.
879 * @param b The second handle, will be upgraded.
880 * @return `true` if the items are strictly equal, `false` otherwise.
881 */
883
884/**
885 * @brief Compare two items for ordering (less than, equal, or greater than).
886 *
887 * Useful for sorting or range checks.
888 *
889 * @param reduct Pointer to the Reduct structure.
890 * @param a The first handle.
891 * @param b The second handle.
892 * @return A negative value if a < b, zero if a == b, and a positive value if a > b.
893 */
895
896/**
897 * @brief Get the string pointer and length from an atom handle.
898 *
899 * @param reduct Pointer to the Reduct structure.
900 * @param handle The handle to the atom.
901 * @param outStr Pointer to store the string pointer, not `NULL` terminated.
902 * @param outLen Pointer to store the string length.
903 */
904REDUCT_API void reduct_handle_atom_string(struct reduct* reduct, reduct_handle_t* handle, const char** outStr,
905 size_t* outLen);
906
907/**
908 * @brief Get the element at the specified index from a list or atom handle.
909 *
910 * For lists, returns the nth element. For atoms, returns the nth character as a string handle.
911 *
912 * @param reduct Pointer to the Reduct structure.
913 * @param handle The handle.
914 * @param index The index.
915 * @return The element handle.
916 */
917REDUCT_API reduct_handle_t reduct_handle_nth(struct reduct* reduct, reduct_handle_t handle, size_t index);
918
919/**
920 * @brief Get the length of a handle (list elements or atom characters).
921 *
922 * @param reduct Pointer to the Reduct structure.
923 * @param handle The handle.
924 * @return The length.
925 */
926REDUCT_API size_t reduct_handle_len(struct reduct* reduct, reduct_handle_t handle);
927
928/**
929 * @brief Check if an atom handle is equal to a string.
930 *
931 * @param reduct Pointer to the Reduct structure.
932 * @param handle The atom handle.
933 * @param str The string to compare.
934 * @return `true` if the atom is equal to the string, `false` otherwise.
935 */
936REDUCT_API bool reduct_handle_is_str(struct reduct* reduct, reduct_handle_t handle, const char* str);
937
938/** @} */
939
940#endif
Atom representation and operations.
#define REDUCT_LIKELY(_x)
Definition defs.h:58
#define REDUCT_UNLIKELY(_x)
Definition defs.h:59
#define REDUCT_ALWAYS_INLINE
Definition defs.h:61
#define REDUCT_API
Definition defs.h:24
Error handling and reporting.
REDUCT_API int64_t reduct_atom_as_int(struct reduct *reduct, reduct_atom_t *atom)
Retrieve an integer value from an atom, regardless of if it is quoted or not.
REDUCT_API double reduct_atom_as_number(struct reduct *reduct, reduct_atom_t *atom)
Retrieve a number value from an atom, regardless of if it is quoted or not.
#define REDUCT_ERROR_ASSERT(_reduct, _expr,...)
Throw a runtime error if the expression is false.
Definition error.h:225
#define REDUCT_HANDLE_TO_NUMBER(_handle)
Get the number value of a handle.
Definition handle.h:379
#define REDUCT_HANDLE_IS_ITEM(_handle)
Check if a handle is an item.
Definition handle.h:247
REDUCT_API reduct_handle_t reduct_handle_nth(struct reduct *reduct, reduct_handle_t handle, size_t index)
Get the element at the specified index from a list or atom handle.
REDUCT_API reduct_handle_type_t reduct_handle_get_type(reduct_handle_t handle)
Get the high-level type of a handle.
static REDUCT_ALWAYS_INLINE int64_t reduct_handle_as_int(struct reduct *reduct, reduct_handle_t handle)
Retrieve the integer representation of the handle.
Definition handle.h:824
REDUCT_API const char * reduct_handle_type_string(reduct_handle_type_t type)
Get the string name of a handle type.
static REDUCT_ALWAYS_INLINE double reduct_handle_as_number(struct reduct *reduct, reduct_handle_t handle)
Retrieve the number representation of the handle.
Definition handle.h:846
#define REDUCT_HANDLE_TO_ITEM(_handle)
Get the item pointer of a handle.
Definition handle.h:392
REDUCT_API bool reduct_handle_is_equal(struct reduct *reduct, reduct_handle_t a, reduct_handle_t b)
Check if two items are exactly equal string-wise or structurally.
#define REDUCT_HANDLE_IS_NUMBER(_handle)
Check if a handle is a number.
Definition handle.h:189
REDUCT_API size_t reduct_handle_len(struct reduct *reduct, reduct_handle_t handle)
Get the length of a handle (list elements or atom characters).
REDUCT_API void reduct_handle_ensure_item(struct reduct *reduct, reduct_handle_t *handle)
Ensure that a handle is an item handle.
REDUCT_API int64_t reduct_handle_compare(struct reduct *reduct, reduct_handle_t a, reduct_handle_t b)
Compare two items for ordering (less than, equal, or greater than).
REDUCT_API bool reduct_handle_is_str(struct reduct *reduct, reduct_handle_t handle, const char *str)
Check if an atom handle is equal to a string.
REDUCT_API void reduct_handle_atom_string(struct reduct *reduct, reduct_handle_t *handle, const char **outStr, size_t *outLen)
Get the string pointer and length from an atom handle.
static REDUCT_ALWAYS_INLINE reduct_atom_t * reduct_handle_as_atom(struct reduct *reduct, reduct_handle_t handle)
Retrieve the atom pointer of the handle.
Definition handle.h:867
static REDUCT_ALWAYS_INLINE struct reduct_item * reduct_handle_as_item(struct reduct *reduct, reduct_handle_t handle)
Ensure that a handle is an item and return the pointer.
Definition handle.h:804
#define REDUCT_HANDLE_TO_ATOM(_handle)
Get the atom pointer of a handle.
Definition handle.h:400
#define REDUCT_HANDLE_IS_ATOM(_handle)
Check if a handle is an atom.
Definition handle.h:255
reduct_handle_type_t
High-level handle types.
Definition handle.h:42
@ REDUCT_HANDLE_TYPE_FUTURE
Handle is a reference to a future.
Definition handle.h:52
@ REDUCT_HANDLE_TYPE_FUNCTION
Handle is a reference to a function.
Definition handle.h:47
@ REDUCT_HANDLE_TYPE_NUMBER
Handle is a number or references a number shaped atom.
Definition handle.h:44
@ REDUCT_HANDLE_TYPE_RVSDG_NODE
Handle is a reference to an IR node.
Definition handle.h:50
@ REDUCT_HANDLE_TYPE_RVSDG_EDGE
Handle is a reference to an IR edge.
Definition handle.h:51
@ REDUCT_HANDLE_TYPE_ATOM
Handle is a reference to an atom.
Definition handle.h:45
@ REDUCT_HANDLE_TYPE_UNKNOWN
Handle is corrupt or otherwise invalid.
Definition handle.h:53
@ REDUCT_HANDLE_TYPE_NONE
Invalid type.
Definition handle.h:43
@ REDUCT_HANDLE_TYPE_CLOSURE
Handle is a reference to a closure.
Definition handle.h:48
@ REDUCT_HANDLE_TYPE_ARENA
Handle is a reference to an arena.
Definition handle.h:49
@ REDUCT_HANDLE_TYPE_LIST
Handle is a reference to a list.
Definition handle.h:46
#define REDUCT_ITEM_TYPE_ATOM
An atom.
Definition item.h:31
Item management.
Built-in library registration and operations.
Atom structure.
Definition atom.h:88
Handle type.
Definition defs.h:121
Item structure.
Definition item.h:59
reduct_atom_t atom
An atom.
Definition item.h:66
reduct_item_type_t type
The type of the item.
Definition item.h:63