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_RVSDG_ORIGIN(_origin) \
147 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_origin, reduct_item_t, rvsdgOrigin))
155#define REDUCT_HANDLE_FROM_RVSDG_USER(_user) \
156 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_user, reduct_item_t, rvsdgUser))
164#define REDUCT_HANDLE_FROM_RVSDG_REGION(_region) \
165 REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_region, reduct_item_t, rvsdgRegion))
173#define REDUCT_HANDLE_FROM_BOOL(_reduct, _cond) ((_cond) ? REDUCT_HANDLE_TRUE() : REDUCT_HANDLE_FALSE(_reduct))
181#define REDUCT_HANDLE_FROM_FUTURE(_future) REDUCT_HANDLE_FROM_ITEM(REDUCT_CONTAINER_OF(_future, reduct_item_t, future))
189#define REDUCT_HANDLE_IS_NUMBER(_handle) (((_handle)._value) >= REDUCT_HANDLE_OFFSET_NUMBER)
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))))
223#define REDUCT_HANDLE_GET_TYPE_STRING(_handle) (reduct_handle_type_string(reduct_handle_get_type(_handle)))
231#define REDUCT_HANDLE_IS_NIL(_handle) (REDUCT_HANDLE_IS_LIST(_handle) && REDUCT_HANDLE_TO_LIST(_handle)->length == 0)
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))
247#define REDUCT_HANDLE_IS_ITEM(_handle) ((((_handle)._value) & REDUCT_HANDLE_MASK_TAG) == REDUCT_HANDLE_TAG_ITEM)
255#define REDUCT_HANDLE_IS_ATOM(_handle) \
256 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_ATOM)
264#define REDUCT_HANDLE_IS_LIST(_handle) \
265 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_LIST)
273#define REDUCT_HANDLE_IS_FUNCTION(_handle) \
274 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_FUNCTION)
282#define REDUCT_HANDLE_IS_CLOSURE(_handle) \
283 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_CLOSURE)
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)
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)
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)
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)
326#define REDUCT_HANDLE_IS_FUTURE(_handle) \
327 (REDUCT_HANDLE_IS_ITEM(_handle) && REDUCT_HANDLE_TO_ITEM(_handle)->type == REDUCT_ITEM_TYPE_FUTURE)
335#define REDUCT_HANDLE_IS_LAMBDA(_handle) (REDUCT_HANDLE_IS_FUNCTION(_handle) || REDUCT_HANDLE_IS_CLOSURE(_handle))
343#define REDUCT_HANDLE_IS_NATIVE(_reduct, _handle) \
344 (REDUCT_HANDLE_IS_ATOM(_handle) && reduct_atom_is_native(_reduct, REDUCT_HANDLE_TO_ATOM(_handle)))
353#define REDUCT_HANDLE_IS_INTRINSIC(_reduct, _handle) \
354 (REDUCT_HANDLE_IS_ATOM(_handle) && reduct_atom_is_intrinsic(_reduct, REDUCT_HANDLE_TO_ATOM(_handle)))
362#define REDUCT_HANDLE_IS_CALLABLE(_reduct, _handle) \
363 (REDUCT_HANDLE_IS_LAMBDA(_handle) || REDUCT_HANDLE_IS_NATIVE(_reduct, _handle))
371#define REDUCT_HANDLE_IS_ATOM_LIKE(_handle) (REDUCT_HANDLE_IS_NUMBER(_handle) || REDUCT_HANDLE_IS_ATOM(_handle))
379#define REDUCT_HANDLE_TO_NUMBER(_handle) \
383 }){.u = ((_handle)._value) - REDUCT_HANDLE_OFFSET_NUMBER}) \
392#define REDUCT_HANDLE_TO_ITEM(_handle) ((reduct_item_t*)(void*)(((_handle)._value) & REDUCT_HANDLE_MASK_PTR))
400#define REDUCT_HANDLE_TO_ATOM(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->atom)
408#define REDUCT_HANDLE_TO_LIST(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->list)
416#define REDUCT_HANDLE_TO_FUNCTION(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->function)
424#define REDUCT_HANDLE_TO_CLOSURE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->closure)
432#define REDUCT_HANDLE_TO_RVSDG_NODE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->rvsdgNode)
440#define REDUCT_HANDLE_TO_RVSDG_EDGE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->rvsdgEdge)
448#define REDUCT_HANDLE_TO_RVSDG_ORIGIN(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->rvsdgOrigin)
456#define REDUCT_HANDLE_TO_RVSDG_USER(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->rvsdgUser)
463#define REDUCT_HANDLE_TO_FUTURE(_handle) (&REDUCT_HANDLE_TO_ITEM(_handle)->future)
471#define REDUCT_HANDLE_TO_BOOL(_handle) (REDUCT_HANDLE_IS_TRUTHY(_handle) ? true : false)
479#define REDUCT_HANDLE_CREATE_LIST(_reduct, _length) REDUCT_HANDLE_FROM_LIST(reduct_list_new(_reduct, _length))
488#define REDUCT_HANDLE_CREATE_HANDLES(_reduct, _count, _handles) \
489 REDUCT_HANDLE_FROM_LIST(reduct_list_new_handles(_reduct, _count, _handles))
498#define REDUCT_HANDLE_CREATE_ALIST(_reduct, _count, ...) \
499 REDUCT_HANDLE_FROM_LIST(reduct_list_new_alist(_reduct, _count, __VA_ARGS__))
507#define REDUCT_HANDLE_CREATE_ATOM(_reduct, _len) REDUCT_HANDLE_FROM_ATOM(reduct_atom_new(_reduct, _len))
515#define REDUCT_HANDLE_CREATE_STRING(_reduct, _str) \
516 REDUCT_HANDLE_FROM_ATOM(reduct_atom_lookup(_reduct, _str, strlen(_str), REDUCT_ATOM_LOOKUP_QUOTED))
524#define REDUCT_HANDLE_CREATE_SYMBOL(_reduct, _str) \
525 REDUCT_HANDLE_FROM_ATOM(reduct_atom_lookup(_reduct, _str, strlen(_str), REDUCT_ATOM_LOOKUP_NONE))
533#define REDUCT_HANDLE_CREATE_NUMBER(_reduct, _val) REDUCT_HANDLE_FROM_ATOM(reduct_atom_new_number(_reduct, _val))
541#define REDUCT_HANDLE_CREATE_NATIVE(_reduct, _fn) REDUCT_HANDLE_FROM_ATOM(reduct_atom_new_native(_reduct, _fn))
551#define REDUCT_HANDLE_CREATE_FUTURE(_reduct, _callable, _argc, _argv) \
552 REDUCT_HANDLE_FROM_FUTURE(reduct_future_new(_reduct, _callable, _argc, _argv))
560#define REDUCT_HANDLE_FOR_EACH(_handle, _list) REDUCT_LIST_FOR_EACH(_handle, REDUCT_HANDLE_TO_LIST(_list))
569#define REDUCT_HANDLE_JOIN(_reduct, _handle) \
570 (REDUCT_HANDLE_IS_FUTURE(_handle) ? reduct_future_join(_reduct, REDUCT_HANDLE_TO_FUTURE(_handle)) : (_handle))
577#define REDUCT_HANDLE_NIL(_reduct) ((_reduct)->global->nil)
583#define REDUCT_HANDLE_FALSE(_reduct) REDUCT_HANDLE_NIL(_reduct)
585#define REDUCT_HANDLE_TRUE() REDUCT_HANDLE_FROM_NUMBER(1.0)
587#define REDUCT_HANDLE_PI() REDUCT_HANDLE_FROM_NUMBER(REDUCT_PI)
589#define REDUCT_HANDLE_E() REDUCT_HANDLE_FROM_NUMBER(REDUCT_E)
591#define REDUCT_HANDLE_INF() REDUCT_HANDLE_FROM_NUMBER(REDUCT_INF)
593#define REDUCT_HANDLE_NAN() REDUCT_HANDLE_FROM_NUMBER(REDUCT_NAN)
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))
618#define REDUCT_HANDLE_ARITHMETIC_FAST(_reduct, _a, _b, _c, _op) \
621 reduct_handle_t _bVal = (_b); \
622 reduct_handle_t _cVal = (_c); \
624 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
626 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
627 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
631 _bv = reduct_handle_as_number(_reduct, _bVal); \
632 _cv = reduct_handle_as_number(_reduct, _cVal); \
634 *(_a) = REDUCT_HANDLE_FROM_NUMBER(_bv _op _cv); \
645#define REDUCT_HANDLE_DIV_FAST(_reduct, _a, _b, _c) \
648 reduct_handle_t _bVal = (_b); \
649 reduct_handle_t _cVal = (_c); \
651 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
653 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
654 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
658 _bv = reduct_handle_as_number(_reduct, _bVal); \
659 _cv = reduct_handle_as_number(_reduct, _cVal); \
661 if (REDUCT_UNLIKELY(_cv == 0.0)) \
663 REDUCT_ERROR_THROW(_reduct, "division by zero"); \
665 *(_a) = REDUCT_HANDLE_FROM_NUMBER(_bv / _cv); \
676#define REDUCT_HANDLE_MOD_FAST(_reduct, _a, _b, _c) \
679 reduct_handle_t _bVal = (_b); \
680 reduct_handle_t _cVal = (_c); \
682 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
684 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
685 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
689 _bv = reduct_handle_as_number(_reduct, _bVal); \
690 _cv = reduct_handle_as_number(_reduct, _cVal); \
692 if (REDUCT_UNLIKELY(_cv == 0.0)) \
694 REDUCT_ERROR_THROW(_reduct, "division by zero"); \
696 *(_a) = REDUCT_HANDLE_FROM_NUMBER(fmod(_bv, _cv)); \
708#define REDUCT_HANDLE_BITWISE_FAST(_reduct, _a, _b, _c, _op) \
711 reduct_handle_t _bVal = (_b); \
712 reduct_handle_t _cVal = (_c); \
714 if (REDUCT_LIKELY(REDUCT_HANDLE_IS_NUMBER(_bVal) && REDUCT_HANDLE_IS_NUMBER(_cVal))) \
716 _bv = REDUCT_HANDLE_TO_NUMBER(_bVal); \
717 _cv = REDUCT_HANDLE_TO_NUMBER(_cVal); \
721 _bv = reduct_handle_as_number(_reduct, _bVal); \
722 _cv = reduct_handle_as_number(_reduct, _cVal); \
724 *(_a) = REDUCT_HANDLE_FROM_NUMBER((double)((int64_t)_bv _op(int64_t) _cv)); \
733#define REDUCT_HANDLE_IS_TRUTHY(_handle) \
734 (!REDUCT_HANDLE_IS_LIST(_handle) || REDUCT_HANDLE_TO_LIST(_handle)->length != 0)
742#define REDUCT_HANDLE_RETAIN(_reduct, _handle) \
745 reduct_handle_t _h = (_handle); \
746 if (REDUCT_HANDLE_IS_ITEM(_h)) \
748 reduct_item_retain(REDUCT_HANDLE_TO_ITEM(_h)); \
758#define REDUCT_HANDLE_RELEASE(_reduct, _handle) \
761 reduct_handle_t _h = (_handle); \
762 if (REDUCT_HANDLE_IS_ITEM(_h)) \
764 reduct_item_release(REDUCT_HANDLE_TO_ITEM(_h)); \
777#define REDUCT_HANDLE_FREE(_reduct, _handle) \
780 reduct_handle_t _h = (_handle); \
781 if (REDUCT_HANDLE_IS_ITEM(_h)) \
783 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.