Reduct  v1.0.4-3-gdaf0d70
A functional and immutable language.
Loading...
Searching...
No Matches
atom.h
Go to the documentation of this file.
1#ifndef REDUCT_ATOM_H
2#define REDUCT_ATOM_H 1
3
4#include "defs.h"
5#include "intrinsic.h"
6#include "native.h"
7
8struct reduct;
9
10/**
11 * @file atom.h
12 * @brief Atom representation and operations.
13 * @defgroup atom Atoms
14 *
15 * Atoms represent all strings within a Reduct expression, as such it also represents anything that a string can be,
16 * including integers, floats and intrinsics.
17 *
18 * ## Interning
19 *
20 * To improve performance, we "intern" all atoms. Meaning that instead of needing to use `strcmp()` or similar to
21 * compare atoms, we store all atoms in a hash map.
22 *
23 * When a new string is encountered, we look it up in the map. As such, any instance of the same string will always be
24 * represented by the same `reduct_atom_t` structure. Turning a string comparison into a pointer comparison and avoiding
25 * redundant parsing of numeric or intrinsic values.
26 *
27 * @see [Wikipedia String Interning](https://en.wikipedia.org/wiki/String_interning)
28 *
29 * @{
30 */
31
32#define REDUCT_ATOM_SMALL_MAX 15 ///< The maximum length of a small atom.
33
34/**
35 * @brief Atom lookup flags.
36 */
37typedef enum
38{
39 REDUCT_ATOM_LOOKUP_NONE = 0, ///< No flags.
40 REDUCT_ATOM_LOOKUP_QUOTED = 1 << 0 ///< Atom should be explicitly quoted.
42
43/**
44 * @brief Atom structure.
45 * @struct reduct_atom_t
46 */
47typedef struct reduct_atom
48{
49 reduct_uint32_t length; ///< The length of the string (must be first, check the `reduct_item_t` structure).
50 reduct_uint32_t hash; ///< The hash of the string.
51 char small[REDUCT_ATOM_SMALL_MAX]; ///< The small string buffer.
52 reduct_intrinsic_t intrinsic; ///< Cached intrinsic, item must have `REDUCT_ITEM_FLAG_INTRINSIC`.
53 char* string; ///< Pointer to the string.
54 union {
55 reduct_int64_t integerValue; ///< Pre-computed integer value, item must have `REDUCT_ITEM_FLAG_INT_SHAPED`.
56 reduct_float_t floatValue; ///< Pre-computed float value, item must have `REDUCT_ITEM_FLAG_FLOAT_SHAPED`.
57 reduct_native_fn native; ///< Native function, item must have `REDUCT_ITEM_FLAG_NATIVE`.
58 };
59 struct reduct_atom* next; ///< Pointer to the next atom in the hash map.
61
62#define REDUCT_FNV_PRIME 16777619U ///< FNV-1a 32-bit prime.
63#define REDUCT_FNV_OFFSET 2166136261U ///< FNV-1a 32-bit offset basis.
64
65/**
66 * @brief Hash a string.
67 *
68 * @param str The string to hash.
69 * @param len The length of the string.
70 * @return The hash of the string.
71 */
73{
75 for (reduct_size_t i = 0; i < len; i++)
76 {
77 hash ^= (unsigned char)str[i];
78 hash *= REDUCT_FNV_PRIME;
79 }
80 return hash;
81}
82
83/**
84 * @brief Initialize an atom.
85 *
86 * @param atom Pointer to the atom to initialize.
87 */
88static inline void reduct_atom_init(reduct_atom_t* atom)
89{
91 atom->length = 0;
92 atom->next = REDUCT_NULL;
93 atom->hash = 0;
94}
95
96/**
97 * @brief Deinitialize an atom.
98 *
99 * @param reduct Pointer to the Reduct structure.
100 * @param atom Pointer to the atom to deinitialize.
101 */
102REDUCT_API void reduct_atom_deinit(struct reduct* reduct, reduct_atom_t* atom);
103
104/**
105 * @brief Check if an atom is equal to a string.
106 *
107 * @param atom Pointer to the atom.
108 * @param str The string to compare.
109 * @param len The length of the string.
110 * @return `REDUCT_TRUE` if the atom is equal to the string, `REDUCT_FALSE` otherwise.
111 */
113 reduct_size_t len)
114{
115 REDUCT_ASSERT(atom != REDUCT_NULL);
117
118 if (atom->length != len)
119 {
120 return REDUCT_FALSE;
121 }
122
123 return REDUCT_MEMCMP(str, atom->string, len) == 0;
124}
125
126/**
127 * @brief Lookup an atom by integer value.
128 *
129 * Will create a new atom if it does not exist.
130 *
131 * @param reduct Pointer to the Reduct structure.
132 * @param value The integer value.
133 * @return A pointer to the atom.
134 */
136
137/**
138 * @brief Lookup an atom by float value.
139 *
140 * Will create a new atom if it does not exist.
141 *
142 * @param reduct Pointer to the Reduct structure.
143 * @param value The float value.
144 * @return A pointer to the atom.
145 */
147
148/**
149 * @brief Lookup an atom in the Reduct structure.
150 *
151 * Will create a new atom if it does not exist.
152 *
153 * @param reduct Pointer to the Reduct structure.
154 * @param str The string to lookup.
155 * @param len The length of the string.
156 * @param flags Lookup flags to alter the interning behavior.
157 * @return A pointer to the atom.
158 */
159REDUCT_API reduct_atom_t* reduct_atom_lookup(struct reduct* reduct, const char* str, reduct_size_t len,
161
162/**
163 * @brief Normalize an atom, determining its shape and parsing escape sequences.
164 *
165 * @warning Should only be called on atoms stored in a `reduct_item_t`.
166 *
167 * @param reduct Pointer to the Reduct structure.
168 * @param atom Pointer to the atom to normalize.
169 */
170REDUCT_API void reduct_atom_normalize(struct reduct* reduct, reduct_atom_t* atom);
171
172/** @} */
173
174#endif
size_t reduct_size_t
Definition defs.h:100
reduct_bool_t
Boolean type.
Definition defs.h:135
@ REDUCT_FALSE
Definition defs.h:137
#define REDUCT_MEMCMP(_s1, _s2, _size)
Definition defs.h:34
int64_t reduct_int64_t
Definition defs.h:92
uint32_t reduct_uint32_t
Definition defs.h:95
double reduct_float_t
Definition defs.h:102
#define REDUCT_ALWAYS_INLINE
Definition defs.h:120
#define REDUCT_ASSERT(_cond)
Definition defs.h:25
#define REDUCT_API
Definition defs.h:7
#define REDUCT_NULL
Definition defs.h:23
REDUCT_API reduct_atom_t * reduct_atom_lookup(struct reduct *reduct, const char *str, reduct_size_t len, reduct_atom_lookup_flags_t flags)
Lookup an atom in the Reduct structure.
reduct_atom_lookup_flags_t
Atom lookup flags.
Definition atom.h:38
static REDUCT_ALWAYS_INLINE reduct_bool_t reduct_atom_is_equal(reduct_atom_t *atom, const char *str, reduct_size_t len)
Check if an atom is equal to a string.
Definition atom.h:112
#define REDUCT_FNV_PRIME
FNV-1a 32-bit prime.
Definition atom.h:62
static void reduct_atom_init(reduct_atom_t *atom)
Initialize an atom.
Definition atom.h:88
#define REDUCT_ATOM_SMALL_MAX
The maximum length of a small atom.
Definition atom.h:32
REDUCT_API reduct_atom_t * reduct_atom_lookup_int(struct reduct *reduct, reduct_int64_t value)
Lookup an atom by integer value.
REDUCT_API void reduct_atom_deinit(struct reduct *reduct, reduct_atom_t *atom)
Deinitialize an atom.
static REDUCT_ALWAYS_INLINE reduct_uint32_t reduct_hash(const char *str, reduct_size_t len)
Hash a string.
Definition atom.h:72
REDUCT_API reduct_atom_t * reduct_atom_lookup_float(struct reduct *reduct, reduct_float_t value)
Lookup an atom by float value.
REDUCT_API void reduct_atom_normalize(struct reduct *reduct, reduct_atom_t *atom)
Normalize an atom, determining its shape and parsing escape sequences.
#define REDUCT_FNV_OFFSET
FNV-1a 32-bit offset basis.
Definition atom.h:63
@ REDUCT_ATOM_LOOKUP_NONE
No flags.
Definition atom.h:39
@ REDUCT_ATOM_LOOKUP_QUOTED
Atom should be explicitly quoted.
Definition atom.h:40
reduct_uint8_t reduct_intrinsic_t
Intrinsic types.
Definition intrinsic.h:28
reduct_handle_t(* reduct_native_fn)(struct reduct *reduct, reduct_size_t argc, reduct_handle_t *argv)
Native function pointer type.
Definition native.h:26
Intrinsic management.
Native function registration.
Atom structure.
Definition atom.h:48
reduct_native_fn native
Native function, item must have REDUCT_ITEM_FLAG_NATIVE.
Definition atom.h:57
reduct_int64_t integerValue
Pre-computed integer value, item must have REDUCT_ITEM_FLAG_INT_SHAPED.
Definition atom.h:55
reduct_uint32_t hash
The hash of the string.
Definition atom.h:50
reduct_uint32_t length
The length of the string (must be first, check the reduct_item_t structure).
Definition atom.h:49
char * string
Pointer to the string.
Definition atom.h:53
struct reduct_atom * next
Pointer to the next atom in the hash map.
Definition atom.h:59
reduct_float_t floatValue
Pre-computed float value, item must have REDUCT_ITEM_FLAG_FLOAT_SHAPED.
Definition atom.h:56
reduct_intrinsic_t intrinsic
Cached intrinsic, item must have REDUCT_ITEM_FLAG_INTRINSIC.
Definition atom.h:52