rbs 3.9.2 → 4.0.0.dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/.github/workflows/windows.yml +1 -1
- data/CHANGELOG.md +0 -13
- data/Rakefile +28 -21
- data/Steepfile +1 -0
- data/config.yml +232 -62
- data/ext/rbs_extension/ast_translation.c +1149 -0
- data/ext/rbs_extension/ast_translation.h +30 -0
- data/{src/constants.c → ext/rbs_extension/class_constants.c} +15 -1
- data/{include/rbs/constants.h → ext/rbs_extension/class_constants.h} +10 -1
- data/ext/rbs_extension/extconf.rb +3 -1
- data/ext/rbs_extension/{location.c → legacy_location.c} +25 -34
- data/ext/rbs_extension/legacy_location.h +40 -0
- data/ext/rbs_extension/main.c +402 -8
- data/ext/rbs_extension/rbs_extension.h +3 -21
- data/ext/rbs_extension/rbs_string_bridging.c +9 -0
- data/ext/rbs_extension/rbs_string_bridging.h +20 -0
- data/include/rbs/ast.h +748 -0
- data/include/rbs/defines.h +60 -0
- data/{ext/rbs_extension → include/rbs}/lexer.h +40 -32
- data/include/rbs/location.h +59 -0
- data/include/rbs/parser.h +151 -0
- data/include/rbs/string.h +49 -0
- data/include/rbs/util/rbs_allocator.h +38 -0
- data/include/rbs/util/rbs_assert.h +9 -0
- data/include/rbs/util/rbs_buffer.h +83 -0
- data/include/rbs/util/rbs_constant_pool.h +3 -64
- data/include/rbs/util/rbs_encoding.h +280 -0
- data/include/rbs/util/rbs_unescape.h +23 -0
- data/include/rbs.h +1 -2
- data/lib/rbs/annotate/formatter.rb +3 -13
- data/lib/rbs/annotate/rdoc_annotator.rb +3 -1
- data/lib/rbs/annotate/rdoc_source.rb +1 -1
- data/lib/rbs/ast/ruby/annotations.rb +119 -0
- data/lib/rbs/ast/ruby/comment_block.rb +221 -0
- data/lib/rbs/ast/ruby/declarations.rb +86 -0
- data/lib/rbs/ast/ruby/helpers/constant_helper.rb +24 -0
- data/lib/rbs/ast/ruby/helpers/location_helper.rb +15 -0
- data/lib/rbs/ast/ruby/members.rb +213 -0
- data/lib/rbs/buffer.rb +104 -24
- data/lib/rbs/cli/validate.rb +39 -34
- data/lib/rbs/cli.rb +4 -5
- data/lib/rbs/definition.rb +6 -1
- data/lib/rbs/definition_builder/ancestor_builder.rb +63 -60
- data/lib/rbs/definition_builder/method_builder.rb +45 -30
- data/lib/rbs/definition_builder.rb +44 -9
- data/lib/rbs/environment/class_entry.rb +69 -0
- data/lib/rbs/environment/module_entry.rb +66 -0
- data/lib/rbs/environment.rb +185 -154
- data/lib/rbs/environment_loader.rb +2 -2
- data/lib/rbs/errors.rb +4 -3
- data/lib/rbs/inline_parser/comment_association.rb +117 -0
- data/lib/rbs/inline_parser.rb +206 -0
- data/lib/rbs/location_aux.rb +35 -3
- data/lib/rbs/parser_aux.rb +11 -1
- data/lib/rbs/prototype/runtime.rb +2 -2
- data/lib/rbs/source.rb +99 -0
- data/lib/rbs/subtractor.rb +4 -3
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs.rb +12 -0
- data/lib/rdoc/discover.rb +1 -1
- data/lib/rdoc_plugin/parser.rb +2 -2
- data/rbs.gemspec +1 -0
- data/sig/ancestor_builder.rbs +1 -1
- data/sig/annotate/formatter.rbs +2 -2
- data/sig/annotate/rdoc_annotater.rbs +1 -1
- data/sig/ast/ruby/annotations.rbs +110 -0
- data/sig/ast/ruby/comment_block.rbs +119 -0
- data/sig/ast/ruby/declarations.rbs +60 -0
- data/sig/ast/ruby/helpers/constant_helper.rbs +11 -0
- data/sig/ast/ruby/helpers/location_helper.rbs +15 -0
- data/sig/ast/ruby/members.rbs +72 -0
- data/sig/buffer.rbs +63 -5
- data/sig/definition.rbs +1 -0
- data/sig/definition_builder.rbs +1 -1
- data/sig/environment/class_entry.rbs +50 -0
- data/sig/environment/module_entry.rbs +50 -0
- data/sig/environment.rbs +22 -76
- data/sig/errors.rbs +13 -6
- data/sig/inline_parser/comment_association.rbs +71 -0
- data/sig/inline_parser.rbs +87 -0
- data/sig/location.rbs +32 -7
- data/sig/method_builder.rbs +7 -4
- data/sig/parser.rbs +16 -0
- data/sig/source.rbs +48 -0
- data/src/ast.c +1345 -0
- data/src/lexer.c +2867 -0
- data/src/lexer.re +151 -0
- data/{ext/rbs_extension → src}/lexstate.c +58 -42
- data/src/location.c +71 -0
- data/src/parser.c +3739 -0
- data/src/string.c +89 -0
- data/src/util/rbs_allocator.c +149 -0
- data/src/util/rbs_assert.c +19 -0
- data/src/util/rbs_buffer.c +54 -0
- data/src/util/rbs_constant_pool.c +13 -81
- data/src/util/rbs_encoding.c +5273 -0
- data/src/util/rbs_unescape.c +130 -0
- data/stdlib/rdoc/0/code_object.rbs +2 -2
- data/stdlib/rdoc/0/comment.rbs +2 -0
- data/stdlib/rdoc/0/options.rbs +76 -0
- data/stdlib/rdoc/0/rdoc.rbs +6 -4
- data/stdlib/rdoc/0/store.rbs +1 -1
- metadata +70 -17
- data/ext/rbs_extension/lexer.c +0 -2728
- data/ext/rbs_extension/lexer.re +0 -147
- data/ext/rbs_extension/location.h +0 -85
- data/ext/rbs_extension/parser.c +0 -2982
- data/ext/rbs_extension/parser.h +0 -18
- data/ext/rbs_extension/parserstate.c +0 -411
- data/ext/rbs_extension/parserstate.h +0 -163
- data/ext/rbs_extension/unescape.c +0 -32
- data/include/rbs/ruby_objs.h +0 -72
- data/src/ruby_objs.c +0 -799
data/src/string.c
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
#include "rbs/string.h"
|
2
|
+
|
3
|
+
#include <stdlib.h>
|
4
|
+
#include <string.h>
|
5
|
+
#include <stdio.h>
|
6
|
+
#include <ctype.h>
|
7
|
+
|
8
|
+
unsigned int rbs_utf8_string_to_codepoint(const rbs_string_t string) {
|
9
|
+
unsigned int codepoint = 0;
|
10
|
+
int remaining_bytes = 0;
|
11
|
+
|
12
|
+
const char *s = string.start;
|
13
|
+
const char *end = string.end;
|
14
|
+
|
15
|
+
if (s >= end) return 0; // End of string
|
16
|
+
|
17
|
+
if ((*s & 0x80) == 0) {
|
18
|
+
// Single byte character (0xxxxxxx)
|
19
|
+
return *s;
|
20
|
+
} else if ((*s & 0xE0) == 0xC0) {
|
21
|
+
// Two byte character (110xxxxx 10xxxxxx)
|
22
|
+
codepoint = *s & 0x1F;
|
23
|
+
remaining_bytes = 1;
|
24
|
+
} else if ((*s & 0xF0) == 0xE0) {
|
25
|
+
// Three byte character (1110xxxx 10xxxxxx 10xxxxxx)
|
26
|
+
codepoint = *s & 0x0F;
|
27
|
+
remaining_bytes = 2;
|
28
|
+
} else if ((*s & 0xF8) == 0xF0) {
|
29
|
+
// Four byte character (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)
|
30
|
+
codepoint = *s & 0x07;
|
31
|
+
remaining_bytes = 3;
|
32
|
+
} else {
|
33
|
+
// Invalid UTF-8 sequence
|
34
|
+
return 0xFFFD; // Unicode replacement character
|
35
|
+
}
|
36
|
+
|
37
|
+
s++;
|
38
|
+
while (remaining_bytes > 0 && s < end) {
|
39
|
+
if ((*s & 0xC0) != 0x80) {
|
40
|
+
// Invalid continuation byte
|
41
|
+
return 0xFFFD;
|
42
|
+
}
|
43
|
+
codepoint = (codepoint << 6) | (*s & 0x3F);
|
44
|
+
s++;
|
45
|
+
remaining_bytes--;
|
46
|
+
}
|
47
|
+
|
48
|
+
if (remaining_bytes > 0) {
|
49
|
+
// Incomplete sequence
|
50
|
+
return 0xFFFD;
|
51
|
+
}
|
52
|
+
|
53
|
+
return codepoint;
|
54
|
+
}
|
55
|
+
|
56
|
+
rbs_string_t rbs_string_new(const char *start, const char *end) {
|
57
|
+
return (rbs_string_t) {
|
58
|
+
.start = start,
|
59
|
+
.end = end,
|
60
|
+
};
|
61
|
+
}
|
62
|
+
|
63
|
+
rbs_string_t rbs_string_strip_whitespace(rbs_string_t *self) {
|
64
|
+
const char *new_start = self->start;
|
65
|
+
while (isspace(*new_start) && new_start < self->end) {
|
66
|
+
new_start++;
|
67
|
+
}
|
68
|
+
|
69
|
+
if (new_start == self->end) { // Handle empty string case
|
70
|
+
return rbs_string_new(new_start, new_start);
|
71
|
+
}
|
72
|
+
|
73
|
+
const char *new_end = self->end - 1;
|
74
|
+
while (isspace(*new_end) && new_start < new_end) {
|
75
|
+
new_end--;
|
76
|
+
}
|
77
|
+
|
78
|
+
return rbs_string_new(new_start, new_end + 1);
|
79
|
+
}
|
80
|
+
|
81
|
+
size_t rbs_string_len(const rbs_string_t self) {
|
82
|
+
return self.end - self.start;
|
83
|
+
}
|
84
|
+
|
85
|
+
bool rbs_string_equal(const rbs_string_t lhs, const rbs_string_t rhs) {
|
86
|
+
if (lhs.start == rhs.start && lhs.end == rhs.end) return true;
|
87
|
+
if (rbs_string_len(lhs) != rbs_string_len(rhs)) return false;
|
88
|
+
return strncmp(lhs.start, rhs.start, rbs_string_len(lhs)) == 0;
|
89
|
+
}
|
@@ -0,0 +1,149 @@
|
|
1
|
+
/**
|
2
|
+
* @file rbs_allocator.c
|
3
|
+
*
|
4
|
+
* A simple arena allocator that can be freed all at once.
|
5
|
+
*
|
6
|
+
* This allocator doesn't support freeing individual allocations. Only the whole arena can be freed at once at the end.
|
7
|
+
*/
|
8
|
+
|
9
|
+
#include "rbs/util/rbs_allocator.h"
|
10
|
+
#include "rbs/util/rbs_assert.h"
|
11
|
+
|
12
|
+
#include <stdlib.h>
|
13
|
+
#include <string.h> // for memset()
|
14
|
+
#include <stdint.h>
|
15
|
+
#include <inttypes.h>
|
16
|
+
|
17
|
+
#ifdef _WIN32
|
18
|
+
#include <windows.h>
|
19
|
+
#else
|
20
|
+
#include <unistd.h>
|
21
|
+
#include <sys/types.h>
|
22
|
+
#include <sys/mman.h>
|
23
|
+
#endif
|
24
|
+
|
25
|
+
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun)
|
26
|
+
#define MAP_ANONYMOUS MAP_ANON
|
27
|
+
#endif
|
28
|
+
|
29
|
+
|
30
|
+
struct rbs_allocator {
|
31
|
+
uintptr_t heap_ptr;
|
32
|
+
uintptr_t size;
|
33
|
+
};
|
34
|
+
|
35
|
+
static size_t get_system_page_size(void) {
|
36
|
+
#ifdef _WIN32
|
37
|
+
SYSTEM_INFO si;
|
38
|
+
GetSystemInfo(&si);
|
39
|
+
return si.dwPageSize;
|
40
|
+
#else
|
41
|
+
long sz = sysconf(_SC_PAGESIZE);
|
42
|
+
if (sz == -1) return 4096; // Fallback to the common 4KB page size
|
43
|
+
return (size_t) sz;
|
44
|
+
#endif
|
45
|
+
}
|
46
|
+
|
47
|
+
static void *map_memory(size_t size) {
|
48
|
+
#ifdef _WIN32
|
49
|
+
LPVOID result = VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
50
|
+
rbs_assert(result != NULL, "VirtualAlloc failed");
|
51
|
+
#else
|
52
|
+
void *result = mmap(NULL, size, PROT_READ | PROT_WRITE,
|
53
|
+
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
54
|
+
rbs_assert(result != MAP_FAILED, "mmap failed");
|
55
|
+
#endif
|
56
|
+
return result;
|
57
|
+
}
|
58
|
+
|
59
|
+
static void destroy_memory(void *memory, size_t size) {
|
60
|
+
#ifdef _WIN32
|
61
|
+
VirtualFree(memory, 0, MEM_RELEASE);
|
62
|
+
#else
|
63
|
+
munmap(memory, size);
|
64
|
+
#endif
|
65
|
+
}
|
66
|
+
|
67
|
+
static void guard_page(void *memory, size_t page_size) {
|
68
|
+
#ifdef _WIN32
|
69
|
+
DWORD old_protect_;
|
70
|
+
BOOL result = VirtualProtect(memory, page_size, PAGE_NOACCESS, &old_protect_);
|
71
|
+
rbs_assert(result != 0, "VirtualProtect failed");
|
72
|
+
#else
|
73
|
+
int result = mprotect(memory, page_size, PROT_NONE);
|
74
|
+
rbs_assert(result == 0, "mprotect failed");
|
75
|
+
#endif
|
76
|
+
}
|
77
|
+
|
78
|
+
static size_t rbs_allocator_default_mem(void) {
|
79
|
+
size_t kib = 1024;
|
80
|
+
size_t mib = kib * 1024;
|
81
|
+
size_t gib = mib * 1024;
|
82
|
+
return 4 * gib;
|
83
|
+
}
|
84
|
+
|
85
|
+
static inline bool is_power_of_two(uintptr_t value) {
|
86
|
+
return value > 0 && (value & (value - 1)) == 0;
|
87
|
+
}
|
88
|
+
|
89
|
+
// Align `val' to nearest multiple of `alignment'.
|
90
|
+
static uintptr_t align(uintptr_t size, uintptr_t alignment) {
|
91
|
+
rbs_assert(is_power_of_two(alignment), "alignment is not a power of two");
|
92
|
+
return (size + alignment - 1) & ~(alignment - 1);
|
93
|
+
}
|
94
|
+
|
95
|
+
rbs_allocator_t *rbs_allocator_init(void) {
|
96
|
+
size_t size = rbs_allocator_default_mem();
|
97
|
+
size_t page_size = get_system_page_size();
|
98
|
+
size = align(size, page_size);
|
99
|
+
void *mem = map_memory(size + page_size);
|
100
|
+
// Guard page; remove range checks in alloc fast path and hard fail if we
|
101
|
+
// consume all memory
|
102
|
+
void *last_page = (char *) mem + size;
|
103
|
+
guard_page(last_page, page_size);
|
104
|
+
uintptr_t start = (uintptr_t) mem;
|
105
|
+
rbs_allocator_t header = (rbs_allocator_t) {
|
106
|
+
.heap_ptr = start + sizeof header,
|
107
|
+
.size = size + page_size,
|
108
|
+
};
|
109
|
+
memcpy(mem, &header, sizeof header);
|
110
|
+
return (rbs_allocator_t *) mem;
|
111
|
+
}
|
112
|
+
|
113
|
+
void rbs_allocator_free(rbs_allocator_t *allocator) {
|
114
|
+
destroy_memory((void *) allocator, allocator->size);
|
115
|
+
}
|
116
|
+
|
117
|
+
// Allocates `new_size` bytes from `allocator`, aligned to an `alignment`-byte boundary.
|
118
|
+
// Copies `old_size` bytes from `ptr` to the new allocation.
|
119
|
+
// It always reallocates the memory in new space and thus wastes the old space.
|
120
|
+
void *rbs_allocator_realloc_impl(rbs_allocator_t *allocator, void *ptr, size_t old_size, size_t new_size, size_t alignment) {
|
121
|
+
void *p = rbs_allocator_malloc_impl(allocator, new_size, alignment);
|
122
|
+
memcpy(p, ptr, old_size);
|
123
|
+
return p;
|
124
|
+
}
|
125
|
+
|
126
|
+
// Allocates `size` bytes from `allocator`, aligned to an `alignment`-byte boundary.
|
127
|
+
void *rbs_allocator_malloc_impl(rbs_allocator_t *allocator, size_t size, size_t alignment) {
|
128
|
+
rbs_assert(size % alignment == 0, "size must be a multiple of the alignment. size: %zu, alignment: %zu", size, alignment);
|
129
|
+
uintptr_t aligned = align(allocator->heap_ptr, alignment);
|
130
|
+
allocator->heap_ptr = aligned + size;
|
131
|
+
return (void *) aligned;
|
132
|
+
}
|
133
|
+
|
134
|
+
// Note: This will eagerly fill with zeroes, unlike `calloc()` which can map a page in a page to be zeroed lazily.
|
135
|
+
// It's assumed that callers to this function will immediately write to the allocated memory, anyway.
|
136
|
+
void *rbs_allocator_calloc_impl(rbs_allocator_t *allocator, size_t count, size_t size, size_t alignment) {
|
137
|
+
void *p = rbs_allocator_malloc_many_impl(allocator, count, size, alignment);
|
138
|
+
#if defined(__linux__)
|
139
|
+
// mmap with MAP_ANONYMOUS gives zero-filled pages.
|
140
|
+
#else
|
141
|
+
memset(p, 0, count * size);
|
142
|
+
#endif
|
143
|
+
return p;
|
144
|
+
}
|
145
|
+
|
146
|
+
// Similar to `rbs_allocator_malloc_impl()`, but allocates `count` instances of `size` bytes, aligned to an `alignment`-byte boundary.
|
147
|
+
void *rbs_allocator_malloc_many_impl(rbs_allocator_t *allocator, size_t count, size_t size, size_t alignment) {
|
148
|
+
return rbs_allocator_malloc_impl(allocator, count * size, alignment);
|
149
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#include "rbs/util/rbs_assert.h"
|
2
|
+
|
3
|
+
#include <stdarg.h>
|
4
|
+
#include <stdio.h>
|
5
|
+
#include <stdlib.h>
|
6
|
+
#include <stdbool.h>
|
7
|
+
|
8
|
+
void rbs_assert(bool condition, const char *fmt, ...) {
|
9
|
+
if (condition) {
|
10
|
+
return;
|
11
|
+
}
|
12
|
+
|
13
|
+
va_list args;
|
14
|
+
va_start(args, fmt);
|
15
|
+
vfprintf(stderr, fmt, args);
|
16
|
+
va_end(args);
|
17
|
+
fprintf(stderr, "\n");
|
18
|
+
exit(EXIT_FAILURE);
|
19
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#include "rbs/util/rbs_buffer.h"
|
2
|
+
#include "rbs/util/rbs_assert.h"
|
3
|
+
|
4
|
+
bool rbs_buffer_init(rbs_allocator_t *allocator, rbs_buffer_t *buffer) {
|
5
|
+
size_t capacity = RBS_BUFFER_DEFAULT_CAPACITY;
|
6
|
+
|
7
|
+
buffer->length = 0;
|
8
|
+
buffer->capacity = capacity;
|
9
|
+
|
10
|
+
buffer->value = rbs_allocator_calloc(allocator, capacity, char);
|
11
|
+
return buffer->value != NULL;
|
12
|
+
}
|
13
|
+
|
14
|
+
char *rbs_buffer_value(const rbs_buffer_t *buffer) {
|
15
|
+
return buffer->value;
|
16
|
+
}
|
17
|
+
|
18
|
+
size_t rbs_buffer_length(const rbs_buffer_t *buffer) {
|
19
|
+
return buffer->length;
|
20
|
+
}
|
21
|
+
|
22
|
+
void rbs_buffer_append_string(rbs_allocator_t *allocator, rbs_buffer_t *buffer, const char *source, size_t length) {
|
23
|
+
size_t next_length = buffer->length + length;
|
24
|
+
|
25
|
+
if (next_length > buffer->capacity) {
|
26
|
+
size_t old_capacity = buffer->capacity;
|
27
|
+
|
28
|
+
rbs_assert(old_capacity != 0, "Precondition: capacity must be at least 1. Got %zu", old_capacity);
|
29
|
+
|
30
|
+
size_t new_capacity = buffer->capacity * 2;
|
31
|
+
|
32
|
+
while (next_length > new_capacity) {
|
33
|
+
new_capacity *= 2;
|
34
|
+
}
|
35
|
+
|
36
|
+
char *new_value = rbs_allocator_realloc(allocator, buffer->value, old_capacity, new_capacity, char);
|
37
|
+
rbs_assert(new_value != NULL, "Failed to append to buffer. Old capacity: %zu, new capacity: %zu", old_capacity, new_capacity);
|
38
|
+
|
39
|
+
buffer->value = new_value;
|
40
|
+
buffer->capacity = new_capacity;
|
41
|
+
}
|
42
|
+
|
43
|
+
size_t cursor = buffer->length;
|
44
|
+
buffer->length = next_length;
|
45
|
+
memcpy(buffer->value + cursor, source, length);
|
46
|
+
}
|
47
|
+
|
48
|
+
void rbs_buffer_append_cstr(rbs_allocator_t *allocator, rbs_buffer_t *buffer, const char *value) {
|
49
|
+
rbs_buffer_append_string(allocator, buffer, value, strlen(value));
|
50
|
+
}
|
51
|
+
|
52
|
+
rbs_string_t rbs_buffer_to_string(rbs_buffer_t *buffer) {
|
53
|
+
return rbs_string_new(buffer->value, buffer->value + buffer->length);
|
54
|
+
}
|
@@ -1,75 +1,5 @@
|
|
1
1
|
#include "rbs/util/rbs_constant_pool.h"
|
2
|
-
|
3
|
-
/**
|
4
|
-
* Initialize a list of constant ids.
|
5
|
-
*/
|
6
|
-
void
|
7
|
-
rbs_constant_id_list_init(rbs_constant_id_list_t *list) {
|
8
|
-
list->ids = NULL;
|
9
|
-
list->size = 0;
|
10
|
-
list->capacity = 0;
|
11
|
-
}
|
12
|
-
|
13
|
-
/**
|
14
|
-
* Initialize a list of constant ids with a given capacity.
|
15
|
-
*/
|
16
|
-
void
|
17
|
-
rbs_constant_id_list_init_capacity(rbs_constant_id_list_t *list, size_t capacity) {
|
18
|
-
list->ids = calloc(capacity, sizeof(rbs_constant_id_t));
|
19
|
-
if (list->ids == NULL) abort();
|
20
|
-
|
21
|
-
list->size = 0;
|
22
|
-
list->capacity = capacity;
|
23
|
-
}
|
24
|
-
|
25
|
-
/**
|
26
|
-
* Append a constant id to a list of constant ids. Returns false if any
|
27
|
-
* potential reallocations fail.
|
28
|
-
*/
|
29
|
-
bool
|
30
|
-
rbs_constant_id_list_append(rbs_constant_id_list_t *list, rbs_constant_id_t id) {
|
31
|
-
if (list->size >= list->capacity) {
|
32
|
-
list->capacity = list->capacity == 0 ? 8 : list->capacity * 2;
|
33
|
-
list->ids = (rbs_constant_id_t *) realloc(list->ids, sizeof(rbs_constant_id_t) * list->capacity);
|
34
|
-
if (list->ids == NULL) return false;
|
35
|
-
}
|
36
|
-
|
37
|
-
list->ids[list->size++] = id;
|
38
|
-
return true;
|
39
|
-
}
|
40
|
-
|
41
|
-
/**
|
42
|
-
* Insert a constant id into a list of constant ids at the specified index.
|
43
|
-
*/
|
44
|
-
void
|
45
|
-
rbs_constant_id_list_insert(rbs_constant_id_list_t *list, size_t index, rbs_constant_id_t id) {
|
46
|
-
assert(index < list->capacity);
|
47
|
-
assert(list->ids[index] == RBS_CONSTANT_ID_UNSET);
|
48
|
-
|
49
|
-
list->ids[index] = id;
|
50
|
-
list->size++;
|
51
|
-
}
|
52
|
-
|
53
|
-
/**
|
54
|
-
* Checks if the current constant id list includes the given constant id.
|
55
|
-
*/
|
56
|
-
bool
|
57
|
-
rbs_constant_id_list_includes(rbs_constant_id_list_t *list, rbs_constant_id_t id) {
|
58
|
-
for (size_t index = 0; index < list->size; index++) {
|
59
|
-
if (list->ids[index] == id) return true;
|
60
|
-
}
|
61
|
-
return false;
|
62
|
-
}
|
63
|
-
|
64
|
-
/**
|
65
|
-
* Free the memory associated with a list of constant ids.
|
66
|
-
*/
|
67
|
-
void
|
68
|
-
rbs_constant_id_list_free(rbs_constant_id_list_t *list) {
|
69
|
-
if (list->ids != NULL) {
|
70
|
-
free(list->ids);
|
71
|
-
}
|
72
|
-
}
|
2
|
+
#include "rbs/util/rbs_assert.h"
|
73
3
|
|
74
4
|
/**
|
75
5
|
* A relatively simple hash function (djb2) that is used to hash strings. We are
|
@@ -107,19 +37,16 @@ next_power_of_two(uint32_t v) {
|
|
107
37
|
return v;
|
108
38
|
}
|
109
39
|
|
110
|
-
|
111
|
-
static bool
|
112
|
-
is_power_of_two(uint32_t size) {
|
40
|
+
static bool is_power_of_two(uint32_t size) {
|
113
41
|
return (size & (size - 1)) == 0;
|
114
42
|
}
|
115
|
-
#endif
|
116
43
|
|
117
44
|
/**
|
118
45
|
* Resize a constant pool to a given capacity.
|
119
46
|
*/
|
120
47
|
static inline bool
|
121
48
|
rbs_constant_pool_resize(rbs_constant_pool_t *pool) {
|
122
|
-
|
49
|
+
rbs_assert(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity);
|
123
50
|
|
124
51
|
uint32_t next_capacity = pool->capacity * 2;
|
125
52
|
if (next_capacity < pool->capacity) return false;
|
@@ -169,7 +96,7 @@ rbs_constant_pool_resize(rbs_constant_pool_t *pool) {
|
|
169
96
|
}
|
170
97
|
|
171
98
|
// This storage is initialized by `Init_rbs_extension()` in `main.c`.
|
172
|
-
static rbs_constant_pool_t RBS_GLOBAL_CONSTANT_POOL_STORAGE = {
|
99
|
+
static rbs_constant_pool_t RBS_GLOBAL_CONSTANT_POOL_STORAGE = {};
|
173
100
|
rbs_constant_pool_t *RBS_GLOBAL_CONSTANT_POOL = &RBS_GLOBAL_CONSTANT_POOL_STORAGE;
|
174
101
|
|
175
102
|
/**
|
@@ -197,7 +124,7 @@ rbs_constant_pool_init(rbs_constant_pool_t *pool, uint32_t capacity) {
|
|
197
124
|
*/
|
198
125
|
rbs_constant_t *
|
199
126
|
rbs_constant_pool_id_to_constant(const rbs_constant_pool_t *pool, rbs_constant_id_t constant_id) {
|
200
|
-
|
127
|
+
rbs_assert(constant_id != RBS_CONSTANT_ID_UNSET && constant_id <= pool->size, "constant_id is not valid. Got %i, pool->size: %i", constant_id, pool->size);
|
201
128
|
return &pool->constants[constant_id - 1];
|
202
129
|
}
|
203
130
|
|
@@ -207,7 +134,7 @@ rbs_constant_pool_id_to_constant(const rbs_constant_pool_t *pool, rbs_constant_i
|
|
207
134
|
*/
|
208
135
|
rbs_constant_id_t
|
209
136
|
rbs_constant_pool_find(const rbs_constant_pool_t *pool, const uint8_t *start, size_t length) {
|
210
|
-
|
137
|
+
rbs_assert(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity);
|
211
138
|
const uint32_t mask = pool->capacity - 1;
|
212
139
|
|
213
140
|
uint32_t hash = rbs_constant_pool_hash(start, length);
|
@@ -235,7 +162,7 @@ rbs_constant_pool_insert(rbs_constant_pool_t *pool, const uint8_t *start, size_t
|
|
235
162
|
if (!rbs_constant_pool_resize(pool)) return RBS_CONSTANT_ID_UNSET;
|
236
163
|
}
|
237
164
|
|
238
|
-
|
165
|
+
rbs_assert(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity);
|
239
166
|
const uint32_t mask = pool->capacity - 1;
|
240
167
|
|
241
168
|
uint32_t hash = rbs_constant_pool_hash(start, length);
|
@@ -276,7 +203,7 @@ rbs_constant_pool_insert(rbs_constant_pool_t *pool, const uint8_t *start, size_t
|
|
276
203
|
// IDs are allocated starting at 1, since the value 0 denotes a non-existent
|
277
204
|
// constant.
|
278
205
|
uint32_t id = ++pool->size;
|
279
|
-
|
206
|
+
rbs_assert(pool->size < ((uint32_t) (1 << 30)), "pool->size is too large. Got %i", pool->size);
|
280
207
|
|
281
208
|
*bucket = (rbs_constant_pool_bucket_t) {
|
282
209
|
.id = (unsigned int) (id & 0x3fffffff),
|
@@ -301,6 +228,11 @@ rbs_constant_pool_insert_shared(rbs_constant_pool_t *pool, const uint8_t *start,
|
|
301
228
|
return rbs_constant_pool_insert(pool, start, length, RBS_CONSTANT_POOL_BUCKET_DEFAULT);
|
302
229
|
}
|
303
230
|
|
231
|
+
rbs_constant_id_t
|
232
|
+
rbs_constant_pool_insert_shared_with_encoding(rbs_constant_pool_t *pool, const uint8_t *start, size_t length, const rbs_encoding_t *encoding) {
|
233
|
+
return rbs_constant_pool_insert_shared(pool, start, length);
|
234
|
+
}
|
235
|
+
|
304
236
|
/**
|
305
237
|
* Insert a constant into a constant pool from memory that is now owned by the
|
306
238
|
* constant pool. Returns the id of the constant, or RBS_CONSTANT_ID_UNSET if any
|