Ruby 4.1.0dev (2026-09-30 revision 5f5d65517e31dc76858b4b5924392ce2ced86f58)
constant_pool.h
1#ifndef PRISM_INTERNAL_CONSTANT_POOL_H
2#define PRISM_INTERNAL_CONSTANT_POOL_H
3
5
6#include "prism/arena.h"
8
9#include <stdbool.h>
10
11/* A constant in the pool which effectively stores a string. */
13 /* A pointer to the start of the string. */
14 const uint8_t *start;
15
16 /* The length of the string. */
17 size_t length;
18};
19
20/*
21 * The type of bucket in the constant pool hash map. This determines how the
22 * bucket should be freed.
23 */
24typedef unsigned int pm_constant_pool_bucket_type_t;
25
26/* By default, each constant is a slice of the source. */
27static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_DEFAULT = 0;
28
29/* An owned constant is one for which memory has been allocated. */
30static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_OWNED = 1;
31
32/* A constant constant is known at compile time. */
33static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_CONSTANT = 2;
34
35/* A bucket in the hash map. */
36typedef struct {
37 /* The incremental ID used for indexing back into the pool. */
38 unsigned int id: 30;
39
40 /* The type of the bucket, which determines how to free it. */
41 pm_constant_pool_bucket_type_t type: 2;
42
43 /* The hash of the bucket. */
44 uint32_t hash;
45
46 /*
47 * A pointer to the start of the string, stored directly in the bucket to
48 * avoid a pointer chase to the constants array during probing.
49 */
50 const uint8_t *start;
51
52 /* The length of the string. */
53 size_t length;
55
56/* The overall constant pool, which stores constants found while parsing. */
58 /* The buckets in the hash map. */
60
61 /* The constants that are stored in the buckets. */
62 pm_constant_t *constants;
63
64 /* The number of buckets in the hash map. */
65 uint32_t size;
66
67 /* The number of buckets that have been allocated in the hash map. */
68 uint32_t capacity;
69};
70
71/*
72 * When we allocate constants into the pool, we reserve 0 to mean that the slot
73 * is not yet filled. This constant is reused in other places to indicate the
74 * lack of a constant id.
75 */
76#define PM_CONSTANT_ID_UNSET 0
77
78/* Initialize a list of constant ids with a given capacity. */
79void pm_constant_id_list_init_capacity(pm_arena_t *arena, pm_constant_id_list_t *list, size_t capacity);
80
81/* Insert a constant id into a list of constant ids at the specified index. */
82void pm_constant_id_list_insert(pm_constant_id_list_t *list, size_t index, pm_constant_id_t id);
83
84/*
85 * Mix the bits of a constant id so that ids which are close together, as
86 * sequentially assigned ids are, land in unrelated slots of a hash table.
87 */
88static PRISM_INLINE uint32_t
89pm_constant_id_hash(pm_constant_id_t id) {
90 id = ((id >> 16) ^ id) * 0x45d9f3b;
91 id = ((id >> 16) ^ id) * 0x45d9f3b;
92 id = (id >> 16) ^ id;
93 return id;
94}
95
96/*
97 * A set of constant ids, for where the parser only needs to know whether it has
98 * already seen a name, as with the variables a pattern captures or the named
99 * capture groups of a regular expression.
100 */
101typedef struct {
102 /* The number of ids in the set. */
103 size_t size;
104
105 /* The number of slots in `ids`, either zero or a power of two. */
106 size_t capacity;
107
108 /*
109 * An open-addressed table of the ids in the set, where PM_CONSTANT_ID_UNSET
110 * marks an empty slot. It is NULL until the first id is added.
111 */
112 pm_constant_id_t *ids;
114
115/*
116 * Add a constant id, which must not be PM_CONSTANT_ID_UNSET, to the set.
117 * Returns whether the set did not already contain it.
118 */
119bool pm_constant_id_set_insert(pm_arena_t *arena, pm_constant_id_set_t *set, pm_constant_id_t id);
120
121/* Initialize a new constant pool with a given capacity. */
122void pm_constant_pool_init(pm_arena_t *arena, pm_constant_pool_t *pool, uint32_t capacity);
123
124/* Return a pointer to the constant indicated by the given constant id. */
125pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id);
126
127/*
128 * Find a constant in a constant pool. Returns the id of the constant, or 0 if
129 * the constant is not found.
130 */
131pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size_t length);
132
133/*
134 * Insert a constant into a constant pool that is a slice of a source string.
135 * Returns the id of the constant, or 0 if any potential calls to resize fail.
136 */
137pm_constant_id_t pm_constant_pool_insert_shared(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length);
138
139/*
140 * Insert a constant into a constant pool from memory that is now owned by the
141 * constant pool. Returns the id of the constant, or 0 if any potential calls to
142 * resize fail.
143 */
144pm_constant_id_t pm_constant_pool_insert_owned(pm_arena_t *arena, pm_constant_pool_t *pool, uint8_t *start, size_t length);
145
146/*
147 * Insert a constant into a constant pool from memory that is constant. Returns
148 * the id of the constant, or 0 if any potential calls to resize fail.
149 */
150pm_constant_id_t pm_constant_pool_insert_constant(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length);
151
152#endif
A bump allocator for the prism parser.
A data structure that stores a set of strings.
uint32_t pm_constant_id_t
A constant id is a unique identifier for a constant in the constant pool.
#define PRISM_INLINE
Old Visual Studio versions do not support the inline keyword, so we need to define it to be __inline.
Definition inline.h:12
C99 shim for <stdbool.h>
A list of constant IDs.