2#define REDUCT_HANDLE_H 1
56#define REDUCT_HANDLE_OFFSET_NUMBER 0x0007000000000000ULL
58#define REDUCT_HANDLE_TAG_ITEM 0x0000000000000000ULL
60#define REDUCT_HANDLE_MASK_TAG 0xFFFF000000000000ULL
61#define REDUCT_HANDLE_MASK_VAL 0x0000FFFFFFFFFFFFULL
62#define REDUCT_HANDLE_MASK_PTR REDUCT_HANDLE_MASK_VAL
64#define REDUCT_HANDLE_NUMBER_WIDTH 64
72#define REDUCT_HANDLE_FROM_NUMBER(_val) \
73 ((reduct_handle_t){((union { \
78 REDUCT_HANDLE_OFFSET_NUMBER})
86#define REDUCT_HANDLE_FROM_ITEM(_ptr) \
87 ((reduct_handle_t){REDUCT_HANDLE_TAG_ITEM | ((uintptr_t)(void*)(_ptr) & REDUCT_HANDLE_MASK_PTR)})
95#define REDUCT_HANDLE_FROM_ATOM(_atom) REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_atom, reduct_item_t, atom))
103#define REDUCT_HANDLE_FROM_LIST(_list) REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_list, reduct_item_t, list))
111#define REDUCT_HANDLE_FROM_FUNCTION(_func) REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_func, reduct_item_t, function))
119#define REDUCT_HANDLE_FROM_CLOSURE(_closure) \
120 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_closure, reduct_item_t, closure))
128#define REDUCT_HANDLE_FROM_RVSDG_NODE(_node) \
129 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_node, reduct_item_t, rvsdgNode))
137#define REDUCT_HANDLE_FROM_RVSDG_EDGE(_edge) \
138 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_edge, reduct_item_t, rvsdgEdge))
146#define REDUCT_HANDLE_FROM_BOOL(_reduct, _cond) ((_cond) ? REDUCT_HANDLE_TRUE() : REDUCT_HANDLE_FALSE(_reduct))
154#define REDUCT_HANDLE_FROM_FUTURE(_future) REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_future, reduct_item_t, future))
162#define REDUCT_HANDLE_IS_NUMBER(_handle) (((_handle)._value) >= REDUCT_HANDLE_OFFSET_NUMBER)
170#define REDUCT_HANDLE_IS_NUMBER_SHAPED(_handle) \
171 (REDUCT_HANDLE_IS_NUMBER(_handle) || \
172 (REDUCT_HANDLE_IS_ATOM(_handle) && reduct_atom_is_number(REDUCT_HANDLE_TO_ATOM(_handle))))
196#define REDUCT_HANDLE_GET_TYPE_STRING(_handle) (reduct_handle_type_string(reduct_handle_get_type(_handle)))
204#define REDUCT_HANDLE_IS_NIL(_handle) (REDUCT_HANDLE_IS_LIST(_handle) && REDUCT_HANDLE_TO_LIST(_handle)->length == 0)
211#define REDUCT_HANDLE_IS_EMPTY(_handle) \
212 (REDUCT_HANDLE_IS_NIL(_handle) || (REDUCT_HANDLE_IS_ATOM(_handle) && REDUCT_HANDLE_TO_ATOM(_handle)->length == 0))
220#define REDUCT_HANDLE_IS_ITEM(_handle) ((((_handle)._value) & REDUCT_HANDLE_MASK_TAG) == REDUCT_HANDLE_TAG_ITEM)
228#define REDUCT_HANDLE_IS_ATOM(_handle) \
229 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_ATOM)
237#define REDUCT_HANDLE_IS_LIST(_handle) \
238 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_LIST)
246#define REDUCT_HANDLE_IS_FUNCTION(_handle) \
247 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_FUNCTION)
255#define REDUCT_HANDLE_IS_CLOSURE(_handle) \
256 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_CLOSURE)
264#define REDUCT_HANDLE_IS_RVSDG_NODE(_handle) \
265 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_RVSDG_NODE)
273#define REDUCT_HANDLE_IS_RVSDG_EDGE(_handle) \
274 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_RVSDG_EDGE)
281#define REDUCT_HANDLE_IS_FUTURE(_handle) \
282 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_FUTURE)
290#define REDUCT_HANDLE_IS_LAMBDA(_handle) (REDUCT_HANDLE_IS_FUNCTION(_handle) || REDUCT_HANDLE_IS_CLOSURE(_handle))
298#define REDUCT_HANDLE_IS_NATIVE(_reduct, _handle) \
299 (REDUCT_HANDLE_IS_ATOM(_handle) && reduct_atom_is_native(_reduct, REDUCT_HANDLE_TO_ATOM(_handle)))
308#define REDUCT_HANDLE_IS_INTRINSIC(_reduct, _handle) \
309 (REDUCT_HANDLE_IS_ATOM(_handle) && reduct_atom_is_intrinsic(_reduct, REDUCT_HANDLE_TO_ATOM(_handle)))
317#define REDUCT_HANDLE_IS_CALLABLE(_reduct, _handle) \
318 (REDUCT_HANDLE_IS_LAMBDA(_handle) || REDUCT_HANDLE_IS_NATIVE(_reduct, _handle))
326#define REDUCT_HANDLE_IS_ATOM_LIKE(_handle) (REDUCT_HANDLE_IS_NUMBER(_handle) || REDUCT_HANDLE_IS_ATOM(_handle))
334#define REDUCT_HANDLE_TO_NUMBER(_handle) \
338 }){.u = ((_handle)._value) - REDUCT_HANDLE_OFFSET_NUMBER}) \
347#define REDUCT_HANDLE_TO_ITEM(_handle) ((reduct_item_t*)(void*)(((_handle)._value) & REDUCT_HANDLE_MASK_PTR))
355#define REDUCT_HANDLE_TO_ATOM(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->atom)
363#define REDUCT_HANDLE_TO_LIST(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->list)
371#define REDUCT_HANDLE_TO_FUNCTION(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->function)
379#define REDUCT_HANDLE_TO_CLOSURE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->closure)
387#define REDUCT_HANDLE_TO_RVSDG_NODE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->rvsdgNode)
395#define REDUCT_HANDLE_TO_RVSDG_EDGE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->rvsdgEdge)
402#define REDUCT_HANDLE_TO_FUTURE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->future)
410#define REDUCT_HANDLE_TO_BOOL(_handle) (REDUCT_HANDLE_IS_TRUTHY(_handle) ? true : false)
418#define REDUCT_HANDLE_CREATE_LIST(_reduct, _length) REDUCT_HANDLE_FROM_LIST(reduct_list_new(_reduct, _length))
427#define REDUCT_HANDLE_CREATE_HANDLES(_reduct, _count, _handles) \
428 REDUCT_HANDLE_FROM_LIST(reduct_list_new_handles(_reduct, _count, _handles))
437#define REDUCT_HANDLE_CREATE_ALIST(_reduct, _count, ...) \
438 REDUCT_HANDLE_FROM_LIST(reduct_list_new_alist(_reduct, _count, __VA_ARGS__))
446#define REDUCT_HANDLE_CREATE_ATOM(_reduct, _len) REDUCT_HANDLE_FROM_ATOM(reduct_atom_new(_reduct, _len))
454#define REDUCT_HANDLE_CREATE_STRING(_reduct, _str) \
455 REDUCT_HANDLE_FROM_ATOM(reduct_atom_lookup(_reduct, _str, strlen(_str), REDUCT_ATOM_LOOKUP_QUOTED))
463#define REDUCT_HANDLE_CREATE_SYMBOL(_reduct, _str) \
464 REDUCT_HANDLE_FROM_ATOM(reduct_atom_lookup(_reduct, _str, strlen(_str), REDUCT_ATOM_LOOKUP_NONE))
472#define REDUCT_HANDLE_CREATE_NUMBER(_reduct, _val) REDUCT_HANDLE_FROM_ATOM(reduct_atom_new_number(_reduct, _val))
480#define REDUCT_HANDLE_CREATE_NATIVE(_reduct, _fn) REDUCT_HANDLE_FROM_ATOM(reduct_atom_new_native(_reduct, _fn))
490#define REDUCT_HANDLE_CREATE_FUTURE(_reduct, _callable, _argc, _argv) \
491 REDUCT_HANDLE_FROM_FUTURE(reduct_future_new(_reduct, _callable, _argc, _argv))
499#define REDUCT_HANDLE_FOR_EACH(_handle, _list) REDUCT_LIST_FOR_EACH(_handle, REDUCT_HANDLE_TO_LIST(_list))
508#define REDUCT_HANDLE_JOIN(_reduct, _handle) \
509 (REDUCT_HANDLE_IS_FUTURE(_handle) ? reduct_future_join(_reduct, REDUCT_HANDLE_TO_FUTURE(_handle)) : (_handle))
516#define REDUCT_HANDLE_NIL(_reduct) ((_reduct)->global->nil)
522#define REDUCT_HANDLE_FALSE(_reduct) REDUCT_HANDLE_NIL(_reduct)
524#define REDUCT_HANDLE_TRUE() REDUCT_HANDLE_FROM_NUMBER(1.0)
526#define REDUCT_HANDLE_PI() REDUCT_HANDLE_FROM_NUMBER(REDUCT_PI)
528#define REDUCT_HANDLE_E() REDUCT_HANDLE_FROM_NUMBER(REDUCT_E)
530#define REDUCT_HANDLE_INF() REDUCT_HANDLE_FROM_NUMBER(REDUCT_INF)
532#define REDUCT_HANDLE_NAN() REDUCT_HANDLE_FROM_NUMBER(REDUCT_NAN)
543#define REDUCT_HANDLE_COMPARE_FAST(_reduct, _a, _b, _op) \
544 (REDUCT_LIKELY((_a)._value >= REDUCT_HANDLE_OFFSET_NUMBER && (_b)._value >= REDUCT_HANDLE_OFFSET_NUMBER) \
545 ? (REDUCT_HANDLE_TO_NUMBER(_a) _op REDUCT_HANDLE_TO_NUMBER(_b)) \
546 : (reduct_handle_compare(_reduct, (_a), (_b)) _op 0))
557#define REDUCT_HANDLE_ARITHMETIC_FAST(_reduct, _a, _b, _c, _op) \
560 reduct_handle_t _bVal = (_b); \
561 reduct_handle_t _cVal = (_c); \
563 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
565 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
566 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
570 _bv = reduct_handle_as_number(_reduct, _bVal); \
571 _cv = reduct_handle_as_number(_reduct, _cVal); \
573 *(_a) = REDUCT_HANDLE_FROM_NUMBER(_bv _op _cv); \
584#define REDUCT_HANDLE_DIV_FAST(_reduct, _a, _b, _c) \
587 reduct_handle_t _bVal = (_b); \
588 reduct_handle_t _cVal = (_c); \
590 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
592 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
593 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
597 _bv = reduct_handle_as_number(_reduct, _bVal); \
598 _cv = reduct_handle_as_number(_reduct, _cVal); \
600 if (REDUCT_UNLIKELY(_cv == 0.0)) \
602 REDUCT_ERROR_THROW(_reduct, "division by zero"); \
604 *(_a) = REDUCT_HANDLE_FROM_NUMBER(_bv / _cv); \
615#define REDUCT_HANDLE_MOD_FAST(_reduct, _a, _b, _c) \
618 reduct_handle_t _bVal = (_b); \
619 reduct_handle_t _cVal = (_c); \
621 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
623 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
624 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
628 _bv = reduct_handle_as_number(_reduct, _bVal); \
629 _cv = reduct_handle_as_number(_reduct, _cVal); \
631 if (REDUCT_UNLIKELY(_cv == 0.0)) \
633 REDUCT_ERROR_THROW(_reduct, "division by zero"); \
635 *(_a) = REDUCT_HANDLE_FROM_NUMBER(fmod(_bv, _cv)); \
647#define REDUCT_HANDLE_BITWISE_FAST(_reduct, _a, _b, _c, _op) \
650 reduct_handle_t _bVal = (_b); \
651 reduct_handle_t _cVal = (_c); \
653 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
655 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
656 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
660 _bv = reduct_handle_as_number(_reduct, _bVal); \
661 _cv = reduct_handle_as_number(_reduct, _cVal); \
663 *(_a) = REDUCT_HANDLE_FROM_NUMBER((double)((int64_t)_bv _op(int64_t) _cv)); \
672#define REDUCT_HANDLE_IS_TRUTHY(_handle) \
673 (!REDUCT_HANDLE_IS_LIST(_handle) || REDUCT_HANDLE_TO_LIST(_handle)->length != 0)
681#define REDUCT_HANDLE_RETAIN(_reduct, _handle) \
684 reduct_handle_t _h = (_handle); \
685 if (REDUCT_HANDLE_IS_ITEM(_h)) \
687 reduct_item_retain(REDUCT_HANDLE_TO_ITEM(_h)); \
697#define REDUCT_HANDLE_RELEASE(_reduct, _handle) \
700 reduct_handle_t _h = (_handle); \
701 if (REDUCT_HANDLE_IS_ITEM(_h)) \
703 reduct_item_release(REDUCT_HANDLE_TO_ITEM(_h)); \
716#define REDUCT_HANDLE_FREE(_reduct, _handle) \
719 reduct_handle_t _h = (_handle); \
720 if (REDUCT_HANDLE_IS_ITEM(_h)) \
722 reduct_item_free((_reduct), REDUCT_HANDLE_TO_ITEM(_h)); \
Atom representation and operations.
#define REDUCT_LIKELY(_x)
#define REDUCT_UNLIKELY(_x)
#define REDUCT_ALWAYS_INLINE
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.
#define REDUCT_HANDLE_TO_NUMBER(_handle)
Get the number value of a handle.
#define REDUCT_HANDLE_IS_ITEM(_handle)
Check if a handle is an item.
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.
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.
#define REDUCT_HANDLE_TO_ITEM(_handle)
Get the item pointer of a handle.
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.
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.
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.
#define REDUCT_HANDLE_TO_ATOM(_handle)
Get the atom pointer of a handle.
#define REDUCT_HANDLE_IS_ATOM(_handle)
Check if a handle is an atom.
reduct_handle_type_t
High-level handle types.
@ REDUCT_HANDLE_TYPE_FUTURE
Handle is a reference to a future.
@ REDUCT_HANDLE_TYPE_FUNCTION
Handle is a reference to a function.
@ REDUCT_HANDLE_TYPE_NUMBER
Handle is a number or references a number shaped atom.
@ REDUCT_HANDLE_TYPE_RVSDG_NODE
Handle is a reference to an IR node.
@ REDUCT_HANDLE_TYPE_RVSDG_EDGE
Handle is a reference to an IR edge.
@ REDUCT_HANDLE_TYPE_ATOM
Handle is a reference to an atom.
@ REDUCT_HANDLE_TYPE_UNKNOWN
Handle is corrupt or otherwise invalid.
@ REDUCT_HANDLE_TYPE_NONE
Invalid type.
@ REDUCT_HANDLE_TYPE_CLOSURE
Handle is a reference to a closure.
@ REDUCT_HANDLE_TYPE_ARENA
Handle is a reference to an arena.
@ REDUCT_HANDLE_TYPE_LIST
Handle is a reference to a list.
#define REDUCT_ITEM_TYPE_ATOM
An atom.
Built-in library registration and operations.
reduct_atom_t atom
An atom.
reduct_item_type_t type
The type of the item.