rbs 3.9.4 → 4.1.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.
Files changed (348) hide show
  1. checksums.yaml +4 -4
  2. data/.clang-format +75 -0
  3. data/.clangd +2 -0
  4. data/.dockerignore +37 -0
  5. data/.github/dependabot.yml +16 -14
  6. data/.github/workflows/bundle-update.yml +63 -0
  7. data/.github/workflows/c-check.yml +66 -0
  8. data/.github/workflows/comments.yml +5 -3
  9. data/.github/workflows/dependabot.yml +2 -2
  10. data/.github/workflows/jruby.yml +79 -0
  11. data/.github/workflows/release-gems.yml +164 -0
  12. data/.github/workflows/ruby.yml +84 -30
  13. data/.github/workflows/rust.yml +186 -0
  14. data/.github/workflows/truffleruby.yml +54 -0
  15. data/.github/workflows/typecheck.yml +5 -2
  16. data/.github/workflows/wasm.yml +55 -0
  17. data/.github/workflows/windows.yml +9 -3
  18. data/.gitignore +16 -0
  19. data/.rubocop.yml +2 -2
  20. data/CHANGELOG.md +430 -0
  21. data/Dockerfile.jruby +53 -0
  22. data/README.md +41 -4
  23. data/Rakefile +777 -60
  24. data/Steepfile +11 -0
  25. data/config.yml +660 -62
  26. data/core/array.rbs +541 -398
  27. data/core/basic_object.rbs +9 -8
  28. data/core/binding.rbs +0 -2
  29. data/core/builtin.rbs +9 -8
  30. data/core/class.rbs +11 -8
  31. data/core/comparable.rbs +55 -34
  32. data/core/complex.rbs +104 -78
  33. data/core/dir.rbs +61 -49
  34. data/core/encoding.rbs +12 -15
  35. data/core/enumerable.rbs +297 -196
  36. data/core/enumerator/arithmetic_sequence.rbs +70 -0
  37. data/core/enumerator/product.rbs +5 -5
  38. data/core/enumerator.rbs +91 -28
  39. data/core/errno.rbs +11 -2
  40. data/core/errors.rbs +58 -29
  41. data/core/exception.rbs +13 -13
  42. data/core/fiber.rbs +74 -54
  43. data/core/file.rbs +260 -1151
  44. data/core/file_constants.rbs +463 -0
  45. data/core/file_stat.rbs +534 -0
  46. data/core/file_test.rbs +3 -3
  47. data/core/float.rbs +257 -116
  48. data/core/gc.rbs +425 -281
  49. data/core/hash.rbs +1151 -829
  50. data/core/integer.rbs +156 -195
  51. data/core/io/buffer.rbs +53 -42
  52. data/core/io/wait.rbs +13 -35
  53. data/core/io.rbs +220 -154
  54. data/core/kernel.rbs +239 -163
  55. data/core/marshal.rbs +4 -4
  56. data/core/match_data.rbs +16 -14
  57. data/core/math.rbs +107 -66
  58. data/core/method.rbs +69 -33
  59. data/core/module.rbs +302 -150
  60. data/core/nil_class.rbs +7 -6
  61. data/core/numeric.rbs +77 -63
  62. data/core/object.rbs +9 -11
  63. data/core/object_space/weak_key_map.rbs +7 -7
  64. data/core/object_space.rbs +30 -23
  65. data/core/pathname.rbs +1312 -0
  66. data/core/proc.rbs +95 -58
  67. data/core/process.rbs +222 -202
  68. data/core/ractor.rbs +364 -518
  69. data/core/random.rbs +21 -3
  70. data/core/range.rbs +181 -79
  71. data/core/rational.rbs +60 -89
  72. data/core/rbs/ops.rbs +154 -0
  73. data/core/rbs/unnamed/argf.rbs +63 -56
  74. data/core/rbs/unnamed/env_class.rbs +19 -14
  75. data/core/rbs/unnamed/main_class.rbs +123 -0
  76. data/core/rbs/unnamed/random.rbs +11 -118
  77. data/core/regexp.rbs +258 -214
  78. data/core/ruby.rbs +53 -0
  79. data/core/ruby_vm.rbs +78 -34
  80. data/core/rubygems/config_file.rbs +5 -5
  81. data/core/rubygems/errors.rbs +6 -70
  82. data/core/rubygems/requirement.rbs +5 -15
  83. data/core/rubygems/rubygems.rbs +18 -81
  84. data/core/rubygems/specification.rbs +8 -0
  85. data/core/rubygems/version.rbs +2 -163
  86. data/core/set.rbs +493 -363
  87. data/core/signal.rbs +26 -16
  88. data/core/string.rbs +3234 -1285
  89. data/core/struct.rbs +43 -42
  90. data/core/symbol.rbs +41 -34
  91. data/core/thread.rbs +139 -83
  92. data/core/time.rbs +81 -50
  93. data/core/trace_point.rbs +41 -35
  94. data/core/true_class.rbs +2 -2
  95. data/core/unbound_method.rbs +24 -16
  96. data/core/warning.rbs +7 -7
  97. data/docs/CONTRIBUTING.md +2 -1
  98. data/docs/aliases.md +79 -0
  99. data/docs/collection.md +3 -3
  100. data/docs/config.md +171 -0
  101. data/docs/encoding.md +56 -0
  102. data/docs/gem.md +0 -1
  103. data/docs/inline.md +634 -0
  104. data/docs/rbs_by_example.md +20 -20
  105. data/docs/release.md +151 -0
  106. data/docs/rust.md +96 -0
  107. data/docs/sigs.md +3 -3
  108. data/docs/syntax.md +48 -18
  109. data/docs/type_fingerprint.md +21 -0
  110. data/docs/wasm_serialization.md +80 -0
  111. data/exe/rbs +1 -1
  112. data/ext/rbs_extension/ast_translation.c +1855 -0
  113. data/ext/rbs_extension/ast_translation.h +41 -0
  114. data/ext/rbs_extension/class_constants.c +187 -0
  115. data/{include/rbs/constants.h → ext/rbs_extension/class_constants.h} +23 -1
  116. data/ext/rbs_extension/compat.h +10 -0
  117. data/ext/rbs_extension/extconf.rb +26 -1
  118. data/ext/rbs_extension/legacy_location.c +299 -0
  119. data/ext/rbs_extension/legacy_location.h +82 -0
  120. data/ext/rbs_extension/main.c +603 -23
  121. data/ext/rbs_extension/rbs_extension.h +6 -21
  122. data/ext/rbs_extension/rbs_string_bridging.c +9 -0
  123. data/ext/rbs_extension/rbs_string_bridging.h +24 -0
  124. data/include/rbs/ast.h +1047 -0
  125. data/include/rbs/defines.h +99 -0
  126. data/include/rbs/lexer.h +207 -0
  127. data/include/rbs/location.h +40 -0
  128. data/include/rbs/parser.h +153 -0
  129. data/include/rbs/serialize.h +39 -0
  130. data/include/rbs/string.h +47 -0
  131. data/include/rbs/util/rbs_allocator.h +59 -0
  132. data/include/rbs/util/rbs_assert.h +20 -0
  133. data/include/rbs/util/rbs_buffer.h +83 -0
  134. data/include/rbs/util/rbs_constant_pool.h +6 -70
  135. data/include/rbs/util/rbs_encoding.h +282 -0
  136. data/include/rbs/util/rbs_unescape.h +24 -0
  137. data/include/rbs.h +9 -2
  138. data/lib/rbs/annotate/formatter.rb +3 -13
  139. data/lib/rbs/annotate/rdoc_annotator.rb +30 -32
  140. data/lib/rbs/annotate/rdoc_source.rb +1 -1
  141. data/lib/rbs/ast/annotation.rb +1 -1
  142. data/lib/rbs/ast/comment.rb +1 -1
  143. data/lib/rbs/ast/declarations.rb +10 -10
  144. data/lib/rbs/ast/members.rb +14 -14
  145. data/lib/rbs/ast/ruby/annotations.rb +451 -0
  146. data/lib/rbs/ast/ruby/comment_block.rb +247 -0
  147. data/lib/rbs/ast/ruby/declarations.rb +291 -0
  148. data/lib/rbs/ast/ruby/helpers/constant_helper.rb +28 -0
  149. data/lib/rbs/ast/ruby/helpers/location_helper.rb +15 -0
  150. data/lib/rbs/ast/ruby/members.rb +762 -0
  151. data/lib/rbs/ast/type_param.rb +24 -4
  152. data/lib/rbs/buffer.rb +142 -20
  153. data/lib/rbs/cli/diff.rb +16 -15
  154. data/lib/rbs/cli/validate.rb +63 -126
  155. data/lib/rbs/cli.rb +59 -29
  156. data/lib/rbs/collection/config/lockfile_generator.rb +28 -3
  157. data/lib/rbs/collection/sources/git.rb +7 -0
  158. data/lib/rbs/definition.rb +6 -1
  159. data/lib/rbs/definition_builder/ancestor_builder.rb +121 -65
  160. data/lib/rbs/definition_builder/method_builder.rb +74 -33
  161. data/lib/rbs/definition_builder.rb +177 -20
  162. data/lib/rbs/diff.rb +7 -1
  163. data/lib/rbs/environment/class_entry.rb +69 -0
  164. data/lib/rbs/environment/module_entry.rb +66 -0
  165. data/lib/rbs/environment.rb +410 -215
  166. data/lib/rbs/environment_loader.rb +2 -8
  167. data/lib/rbs/errors.rb +31 -21
  168. data/lib/rbs/inline_parser/comment_association.rb +117 -0
  169. data/lib/rbs/inline_parser.rb +568 -0
  170. data/lib/rbs/location_aux.rb +36 -4
  171. data/lib/rbs/locator.rb +5 -1
  172. data/lib/rbs/method_type.rb +5 -3
  173. data/lib/rbs/namespace.rb +47 -18
  174. data/lib/rbs/parser_aux.rb +37 -7
  175. data/lib/rbs/prototype/helpers.rb +57 -0
  176. data/lib/rbs/prototype/rb.rb +3 -28
  177. data/lib/rbs/prototype/rbi.rb +196 -45
  178. data/lib/rbs/prototype/runtime.rb +12 -2
  179. data/lib/rbs/resolver/constant_resolver.rb +2 -2
  180. data/lib/rbs/resolver/type_name_resolver.rb +120 -44
  181. data/lib/rbs/rewriter.rb +70 -0
  182. data/lib/rbs/source.rb +99 -0
  183. data/lib/rbs/subtractor.rb +7 -4
  184. data/lib/rbs/test/type_check.rb +25 -3
  185. data/lib/rbs/type_name.rb +34 -21
  186. data/lib/rbs/types.rb +91 -79
  187. data/lib/rbs/unit_test/convertibles.rb +1 -0
  188. data/lib/rbs/unit_test/type_assertions.rb +44 -8
  189. data/lib/rbs/validator.rb +2 -2
  190. data/lib/rbs/version.rb +1 -1
  191. data/lib/rbs/wasm/deserializer.rb +213 -0
  192. data/lib/rbs/wasm/location.rb +61 -0
  193. data/lib/rbs/wasm/parser.rb +137 -0
  194. data/lib/rbs/wasm/runtime.rb +196 -0
  195. data/lib/rbs/wasm/serialization_schema.rb +110 -0
  196. data/lib/rbs.rb +25 -2
  197. data/lib/rbs_jars.rb +39 -0
  198. data/lib/rdoc/discover.rb +1 -1
  199. data/lib/rdoc_plugin/parser.rb +8 -3
  200. data/rbs.gemspec +37 -5
  201. data/schema/typeParam.json +17 -1
  202. data/sig/ancestor_builder.rbs +1 -1
  203. data/sig/annotate/formatter.rbs +2 -2
  204. data/sig/annotate/rdoc_annotater.rbs +13 -10
  205. data/sig/ast/ruby/annotations.rbs +470 -0
  206. data/sig/ast/ruby/comment_block.rbs +127 -0
  207. data/sig/ast/ruby/declarations.rbs +158 -0
  208. data/sig/ast/ruby/helpers/constant_helper.rbs +11 -0
  209. data/sig/ast/ruby/helpers/location_helper.rbs +15 -0
  210. data/sig/ast/ruby/members.rbs +198 -0
  211. data/sig/buffer.rbs +81 -5
  212. data/sig/cli/diff.rbs +5 -11
  213. data/sig/cli/validate.rbs +12 -8
  214. data/sig/cli.rbs +18 -18
  215. data/sig/collection/config/lockfile_generator.rbs +2 -0
  216. data/sig/definition.rbs +6 -0
  217. data/sig/definition_builder.rbs +3 -1
  218. data/sig/environment/class_entry.rbs +50 -0
  219. data/sig/environment/module_entry.rbs +50 -0
  220. data/sig/environment.rbs +94 -87
  221. data/sig/errors.rbs +26 -20
  222. data/sig/inline_parser/comment_association.rbs +71 -0
  223. data/sig/inline_parser.rbs +126 -0
  224. data/sig/location.rbs +32 -7
  225. data/sig/locator.rbs +0 -2
  226. data/sig/manifest.yaml +0 -2
  227. data/sig/method_builder.rbs +9 -4
  228. data/sig/namespace.rbs +20 -5
  229. data/sig/parser.rbs +77 -13
  230. data/sig/prototype/helpers.rbs +2 -0
  231. data/sig/prototype/rbi.rbs +33 -4
  232. data/sig/resolver/type_name_resolver.rbs +36 -10
  233. data/sig/rewriter.rbs +45 -0
  234. data/sig/source.rbs +48 -0
  235. data/sig/type_param.rbs +13 -8
  236. data/sig/typename.rbs +15 -5
  237. data/sig/types.rbs +10 -8
  238. data/sig/unit_test/spy.rbs +0 -8
  239. data/sig/unit_test/type_assertions.rbs +15 -0
  240. data/sig/wasm/deserializer.rbs +66 -0
  241. data/sig/wasm/serialization_schema.rbs +13 -0
  242. data/src/ast.c +1628 -0
  243. data/src/lexer.c +3221 -0
  244. data/src/lexer.re +155 -0
  245. data/src/lexstate.c +221 -0
  246. data/src/location.c +31 -0
  247. data/src/parser.c +4258 -0
  248. data/src/serialize.c +958 -0
  249. data/src/string.c +41 -0
  250. data/src/util/rbs_allocator.c +171 -0
  251. data/src/util/rbs_assert.c +19 -0
  252. data/src/util/rbs_buffer.c +54 -0
  253. data/src/util/rbs_constant_pool.c +18 -92
  254. data/src/util/rbs_encoding.c +21308 -0
  255. data/src/util/rbs_unescape.c +167 -0
  256. data/stdlib/abbrev/0/array.rbs +1 -1
  257. data/stdlib/bigdecimal/0/big_decimal.rbs +116 -98
  258. data/stdlib/bigdecimal-math/0/big_math.rbs +169 -8
  259. data/stdlib/cgi/0/core.rbs +9 -393
  260. data/stdlib/cgi/0/manifest.yaml +1 -0
  261. data/stdlib/cgi-escape/0/escape.rbs +171 -0
  262. data/stdlib/coverage/0/coverage.rbs +7 -4
  263. data/stdlib/csv/0/csv.rbs +5 -5
  264. data/stdlib/date/0/date.rbs +92 -79
  265. data/stdlib/date/0/date_time.rbs +25 -24
  266. data/stdlib/delegate/0/delegator.rbs +11 -7
  267. data/stdlib/did_you_mean/0/did_you_mean.rbs +17 -16
  268. data/stdlib/digest/0/digest.rbs +117 -1
  269. data/stdlib/erb/0/erb.rbs +748 -347
  270. data/stdlib/etc/0/etc.rbs +73 -54
  271. data/stdlib/fileutils/0/fileutils.rbs +179 -160
  272. data/stdlib/forwardable/0/forwardable.rbs +13 -10
  273. data/stdlib/io-console/0/io-console.rbs +2 -2
  274. data/stdlib/ipaddr/0/ipaddr.rbs +0 -5
  275. data/stdlib/json/0/json.rbs +232 -185
  276. data/stdlib/monitor/0/monitor.rbs +5 -5
  277. data/stdlib/net-http/0/net-http.rbs +162 -134
  278. data/stdlib/objspace/0/objspace.rbs +17 -34
  279. data/stdlib/open-uri/0/open-uri.rbs +48 -8
  280. data/stdlib/open3/0/open3.rbs +469 -10
  281. data/stdlib/openssl/0/openssl.rbs +521 -397
  282. data/stdlib/optparse/0/optparse.rbs +26 -17
  283. data/stdlib/pathname/0/pathname.rbs +11 -1381
  284. data/stdlib/pp/0/pp.rbs +9 -8
  285. data/stdlib/prettyprint/0/prettyprint.rbs +7 -7
  286. data/stdlib/pstore/0/pstore.rbs +35 -30
  287. data/stdlib/psych/0/psych.rbs +65 -12
  288. data/stdlib/psych/0/store.rbs +2 -4
  289. data/stdlib/pty/0/pty.rbs +9 -6
  290. data/stdlib/random-formatter/0/random-formatter.rbs +277 -0
  291. data/stdlib/rdoc/0/code_object.rbs +4 -3
  292. data/stdlib/rdoc/0/comment.rbs +2 -0
  293. data/stdlib/rdoc/0/options.rbs +76 -0
  294. data/stdlib/rdoc/0/parser.rbs +1 -1
  295. data/stdlib/rdoc/0/rdoc.rbs +7 -5
  296. data/stdlib/rdoc/0/store.rbs +2 -2
  297. data/stdlib/resolv/0/resolv.rbs +26 -69
  298. data/stdlib/ripper/0/ripper.rbs +25 -19
  299. data/stdlib/securerandom/0/manifest.yaml +2 -0
  300. data/stdlib/securerandom/0/securerandom.rbs +7 -20
  301. data/stdlib/shellwords/0/shellwords.rbs +3 -3
  302. data/stdlib/singleton/0/singleton.rbs +3 -0
  303. data/stdlib/socket/0/addrinfo.rbs +9 -9
  304. data/stdlib/socket/0/basic_socket.rbs +3 -3
  305. data/stdlib/socket/0/ip_socket.rbs +10 -8
  306. data/stdlib/socket/0/socket.rbs +23 -10
  307. data/stdlib/socket/0/tcp_server.rbs +1 -1
  308. data/stdlib/socket/0/tcp_socket.rbs +11 -3
  309. data/stdlib/socket/0/udp_socket.rbs +1 -1
  310. data/stdlib/socket/0/unix_server.rbs +1 -1
  311. data/stdlib/stringio/0/stringio.rbs +1209 -95
  312. data/stdlib/strscan/0/string_scanner.rbs +101 -80
  313. data/stdlib/tempfile/0/manifest.yaml +3 -0
  314. data/stdlib/tempfile/0/tempfile.rbs +25 -21
  315. data/stdlib/time/0/time.rbs +8 -6
  316. data/stdlib/timeout/0/timeout.rbs +58 -7
  317. data/stdlib/tsort/0/cyclic.rbs +4 -1
  318. data/stdlib/tsort/0/interfaces.rbs +8 -8
  319. data/stdlib/tsort/0/tsort.rbs +16 -15
  320. data/stdlib/uri/0/common.rbs +42 -20
  321. data/stdlib/uri/0/file.rbs +3 -3
  322. data/stdlib/uri/0/generic.rbs +21 -18
  323. data/stdlib/uri/0/http.rbs +2 -2
  324. data/stdlib/uri/0/ldap.rbs +2 -2
  325. data/stdlib/uri/0/mailto.rbs +3 -3
  326. data/stdlib/uri/0/rfc2396_parser.rbs +12 -12
  327. data/stdlib/zlib/0/deflate.rbs +4 -3
  328. data/stdlib/zlib/0/gzip_reader.rbs +8 -8
  329. data/stdlib/zlib/0/gzip_writer.rbs +14 -12
  330. data/stdlib/zlib/0/inflate.rbs +1 -1
  331. data/stdlib/zlib/0/need_dict.rbs +1 -1
  332. data/wasm/README.md +60 -0
  333. data/wasm/rbs_wasm.c +423 -0
  334. metadata +131 -19
  335. data/ext/rbs_extension/lexer.c +0 -2728
  336. data/ext/rbs_extension/lexer.h +0 -179
  337. data/ext/rbs_extension/lexer.re +0 -147
  338. data/ext/rbs_extension/lexstate.c +0 -175
  339. data/ext/rbs_extension/location.c +0 -325
  340. data/ext/rbs_extension/location.h +0 -85
  341. data/ext/rbs_extension/parser.c +0 -2982
  342. data/ext/rbs_extension/parser.h +0 -18
  343. data/ext/rbs_extension/parserstate.c +0 -411
  344. data/ext/rbs_extension/parserstate.h +0 -163
  345. data/ext/rbs_extension/unescape.c +0 -32
  346. data/include/rbs/ruby_objs.h +0 -72
  347. data/src/constants.c +0 -153
  348. data/src/ruby_objs.c +0 -799
data/src/string.c ADDED
@@ -0,0 +1,41 @@
1
+ #include "rbs/string.h"
2
+
3
+ #include <stdlib.h>
4
+ #include <string.h>
5
+ #include <stdio.h>
6
+ #include <ctype.h>
7
+
8
+ rbs_string_t rbs_string_new(const char *start, const char *end) {
9
+ return (rbs_string_t) {
10
+ .start = start,
11
+ .end = end,
12
+ };
13
+ }
14
+
15
+ rbs_string_t rbs_string_strip_whitespace(rbs_string_t *self) {
16
+ const char *new_start = self->start;
17
+ while (isspace(*new_start) && new_start < self->end) {
18
+ new_start++;
19
+ }
20
+
21
+ if (new_start == self->end) { // Handle empty string case
22
+ return rbs_string_new(new_start, new_start);
23
+ }
24
+
25
+ const char *new_end = self->end - 1;
26
+ while (isspace(*new_end) && new_start < new_end) {
27
+ new_end--;
28
+ }
29
+
30
+ return rbs_string_new(new_start, new_end + 1);
31
+ }
32
+
33
+ size_t rbs_string_len(const rbs_string_t self) {
34
+ return self.end - self.start;
35
+ }
36
+
37
+ bool rbs_string_equal(const rbs_string_t lhs, const rbs_string_t rhs) {
38
+ if (lhs.start == rhs.start && lhs.end == rhs.end) return true;
39
+ if (rbs_string_len(lhs) != rbs_string_len(rhs)) return false;
40
+ return strncmp(lhs.start, rhs.start, rbs_string_len(lhs)) == 0;
41
+ }
@@ -0,0 +1,171 @@
1
+ /**
2
+ * @file rbs_allocator.c
3
+ *
4
+ * A simple arena allocator that can be freed all at once.
5
+ *
6
+ * This allocator maintains a linked list of pages, which come in two flavours:
7
+ * 1. Small allocation pages, which are the same size as the system page size.
8
+ * 2. Large allocation pages, which are the exact size requested, for sizes greater than the small page size.
9
+ *
10
+ * Small allocations always fit into the unused space at the end of the "head" page. If there isn't enough room, a new
11
+ * page is allocated, and the small allocation is placed at its start. This approach wastes that unused slack at the
12
+ * end of the previous page, but it means that allocations are instant and never scan the linked list to find a gap.
13
+ *
14
+ * This allocator doesn't support freeing individual allocations. Only the whole arena can be freed at once at the end.
15
+ */
16
+
17
+ #include "rbs/util/rbs_allocator.h"
18
+ #include "rbs/util/rbs_assert.h"
19
+
20
+ #include <stdlib.h>
21
+ #include <string.h> // for memset()
22
+ #include <stdint.h>
23
+ #include <inttypes.h>
24
+
25
+ #ifdef _WIN32
26
+ #include <windows.h>
27
+ #else
28
+ #include <unistd.h> // for sysconf()
29
+ #endif
30
+
31
+ typedef struct rbs_allocator_page {
32
+ // The previously allocated page, or NULL if this is the first page.
33
+ struct rbs_allocator_page *next;
34
+
35
+ // The size of the payload in bytes.
36
+ size_t size;
37
+
38
+ // The offset of the next available byte.
39
+ size_t used;
40
+ } rbs_allocator_page_t;
41
+
42
+ // Normalize a raw page size to a safe value for payload_size subtraction.
43
+ // Falls back to 4096 when the raw value is <= 0 or smaller than the page
44
+ // header struct, preventing underflow in rbs_allocator_init.
45
+ // Internal API, intentionally omitted from the public header.
46
+ size_t rbs_allocator_normalize_page_size(long raw) {
47
+ if (raw <= 0) return 4096;
48
+ size_t page_size = (size_t) raw;
49
+ if (page_size <= sizeof(rbs_allocator_page_t)) return 4096;
50
+ return page_size;
51
+ }
52
+
53
+ static size_t get_system_page_size(void) {
54
+ #ifdef _WIN32
55
+ SYSTEM_INFO si;
56
+ GetSystemInfo(&si);
57
+ return rbs_allocator_normalize_page_size((long) si.dwPageSize);
58
+ #else
59
+ return rbs_allocator_normalize_page_size(sysconf(_SC_PAGESIZE));
60
+ #endif
61
+ }
62
+
63
+ static inline uintptr_t rbs_align_up_uintptr(uintptr_t value, size_t alignment) {
64
+ // alignment must be a non-zero power of two
65
+ RBS_ASSERT(alignment != 0 && (alignment & (alignment - 1)) == 0, "alignment must be a non-zero power of two. alignment: %zu", alignment);
66
+ return (value + (alignment - 1)) & ~(uintptr_t) (alignment - 1);
67
+ }
68
+
69
+ static rbs_allocator_page_t *rbs_allocator_page_new(size_t payload_size) {
70
+ const size_t page_header_size = sizeof(rbs_allocator_page_t);
71
+
72
+ rbs_allocator_page_t *page = (rbs_allocator_page_t *) malloc(page_header_size + payload_size);
73
+ page->size = payload_size;
74
+ page->used = 0;
75
+
76
+ return page;
77
+ }
78
+
79
+ rbs_allocator_t *rbs_allocator_init(void) {
80
+ rbs_allocator_t *allocator = (rbs_allocator_t *) malloc(sizeof(rbs_allocator_t));
81
+
82
+ const size_t system_page_size = get_system_page_size();
83
+
84
+ allocator->default_page_payload_size = system_page_size - sizeof(rbs_allocator_page_t);
85
+
86
+ allocator->page = rbs_allocator_page_new(allocator->default_page_payload_size);
87
+ allocator->page->next = NULL;
88
+
89
+ return allocator;
90
+ }
91
+
92
+ void rbs_allocator_free(rbs_allocator_t *allocator) {
93
+ rbs_allocator_page_t *page = allocator->page;
94
+ while (page) {
95
+ rbs_allocator_page_t *next = page->next;
96
+ free(page);
97
+ page = next;
98
+ }
99
+ free(allocator);
100
+ }
101
+
102
+ // Allocates `new_size` bytes from `allocator`, aligned to an `alignment`-byte boundary.
103
+ // Copies `old_size` bytes from `ptr` to the new allocation.
104
+ // It always reallocates the memory in new space and thus wastes the old space.
105
+ void *rbs_allocator_realloc_impl(rbs_allocator_t *allocator, void *ptr, size_t old_size, size_t new_size, size_t alignment) {
106
+ void *p = rbs_allocator_malloc_impl(allocator, new_size, alignment);
107
+ memcpy(p, ptr, old_size);
108
+ return p;
109
+ }
110
+
111
+ // Allocates `size` bytes from `allocator`, aligned to an `alignment`-byte boundary.
112
+ void *rbs_allocator_malloc_impl(rbs_allocator_t *allocator, size_t size, size_t alignment) {
113
+ if (allocator->default_page_payload_size < size) { // Big allocation, give it its own page.
114
+ // Add padding to ensure we can align the start pointer within this page
115
+ rbs_allocator_page_t *new_page = rbs_allocator_page_new(size + (alignment - 1));
116
+
117
+ // This simple allocator can only put small allocations into the head page.
118
+ // Naively prepending this large allocation page to the head of the allocator before the previous head page
119
+ // would waste the remaining space in the head page.
120
+ // So instead, we'll splice in the large page *after* the head page.
121
+ //
122
+ // +-------+ +-----------+ +-----------+
123
+ // | arena | | head page | | new_page |
124
+ // |-------| |-----------+ |-----------+
125
+ // | *page |--->| size | +--->| size | +---> ... previous tail
126
+ // +-------+ | offset | | | offset | |
127
+ // | *next ----+---+ | *next ----+---+
128
+ // | ... | | ... |
129
+ // +-----------+ +-----------+
130
+ //
131
+ new_page->next = allocator->page->next;
132
+ allocator->page->next = new_page;
133
+
134
+ uintptr_t base = (uintptr_t) new_page + sizeof(rbs_allocator_page_t);
135
+ uintptr_t aligned_ptr = rbs_align_up_uintptr(base, alignment);
136
+ return (void *) aligned_ptr;
137
+ }
138
+
139
+ rbs_allocator_page_t *page = allocator->page;
140
+ uintptr_t base = (uintptr_t) page + sizeof(rbs_allocator_page_t);
141
+
142
+ // Compute aligned offset within the payload
143
+ size_t used_aligned = (size_t) (rbs_align_up_uintptr(base + page->used, alignment) - base);
144
+
145
+ if (used_aligned + size > page->size) {
146
+ // Not enough space. Allocate a new small page and prepend it to the allocator's linked list.
147
+ rbs_allocator_page_t *new_page = rbs_allocator_page_new(allocator->default_page_payload_size);
148
+ new_page->next = allocator->page;
149
+ allocator->page = new_page;
150
+ page = new_page;
151
+ base = (uintptr_t) page + sizeof(rbs_allocator_page_t);
152
+ used_aligned = (size_t) (rbs_align_up_uintptr(base, alignment) - base); // start of fresh page (usually 0 if header is aligned)
153
+ }
154
+
155
+ uintptr_t pointer = base + used_aligned;
156
+ page->used = used_aligned + size;
157
+ return (void *) pointer;
158
+ }
159
+
160
+ // Note: This will eagerly fill with zeroes, unlike `calloc()` which can map a page in a page to be zeroed lazily.
161
+ // It's assumed that callers to this function will immediately write to the allocated memory, anyway.
162
+ void *rbs_allocator_calloc_impl(rbs_allocator_t *allocator, size_t count, size_t size, size_t alignment) {
163
+ void *p = rbs_allocator_malloc_many_impl(allocator, count, size, alignment);
164
+ memset(p, 0, count * size);
165
+ return p;
166
+ }
167
+
168
+ // Similar to `rbs_allocator_malloc_impl()`, but allocates `count` instances of `size` bytes, aligned to an `alignment`-byte boundary.
169
+ void *rbs_allocator_malloc_many_impl(rbs_allocator_t *allocator, size_t count, size_t size, size_t alignment) {
170
+ return rbs_allocator_malloc_impl(allocator, count * size, alignment);
171
+ }
@@ -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_impl(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
- #ifndef NDEBUG
111
- static bool
112
- is_power_of_two(uint32_t size) {
40
+ RBS_ATTRIBUTE_UNUSED 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
- assert(is_power_of_two(pool->capacity));
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;
@@ -130,8 +57,8 @@ rbs_constant_pool_resize(rbs_constant_pool_t *pool) {
130
57
  void *next = calloc(next_capacity, element_size);
131
58
  if (next == NULL) return false;
132
59
 
133
- rbs_constant_pool_bucket_t *next_buckets = next;
134
- rbs_constant_t *next_constants = (void *)(((char *) next) + next_capacity * sizeof(rbs_constant_pool_bucket_t));
60
+ rbs_constant_pool_bucket_t *next_buckets = (rbs_constant_pool_bucket_t *) next;
61
+ rbs_constant_t *next_constants = (rbs_constant_t *) (((char *) next) + next_capacity * sizeof(rbs_constant_pool_bucket_t));
135
62
 
136
63
  // For each bucket in the current constant pool, find the index in the
137
64
  // next constant pool, and insert it.
@@ -168,15 +95,10 @@ rbs_constant_pool_resize(rbs_constant_pool_t *pool) {
168
95
  return true;
169
96
  }
170
97
 
171
- // This storage is initialized by `Init_rbs_extension()` in `main.c`.
172
- static rbs_constant_pool_t RBS_GLOBAL_CONSTANT_POOL_STORAGE = { 0 };
173
- rbs_constant_pool_t *RBS_GLOBAL_CONSTANT_POOL = &RBS_GLOBAL_CONSTANT_POOL_STORAGE;
174
-
175
98
  /**
176
99
  * Initialize a new constant pool with a given capacity.
177
100
  */
178
- bool
179
- rbs_constant_pool_init(rbs_constant_pool_t *pool, uint32_t capacity) {
101
+ bool rbs_constant_pool_init(rbs_constant_pool_t *pool, uint32_t capacity) {
180
102
  const uint32_t maximum = (~((uint32_t) 0));
181
103
  if (capacity >= ((maximum / 2) + 1)) return false;
182
104
 
@@ -185,8 +107,8 @@ rbs_constant_pool_init(rbs_constant_pool_t *pool, uint32_t capacity) {
185
107
  void *memory = calloc(capacity, element_size);
186
108
  if (memory == NULL) return false;
187
109
 
188
- pool->buckets = memory;
189
- pool->constants = (void *)(((char *)memory) + capacity * sizeof(rbs_constant_pool_bucket_t));
110
+ pool->buckets = (rbs_constant_pool_bucket_t *) memory;
111
+ pool->constants = (rbs_constant_t *) (((char *) memory) + capacity * sizeof(rbs_constant_pool_bucket_t));
190
112
  pool->size = 0;
191
113
  pool->capacity = capacity;
192
114
  return true;
@@ -197,7 +119,7 @@ rbs_constant_pool_init(rbs_constant_pool_t *pool, uint32_t capacity) {
197
119
  */
198
120
  rbs_constant_t *
199
121
  rbs_constant_pool_id_to_constant(const rbs_constant_pool_t *pool, rbs_constant_id_t constant_id) {
200
- assert(constant_id != RBS_CONSTANT_ID_UNSET && constant_id <= pool->size);
122
+ 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
123
  return &pool->constants[constant_id - 1];
202
124
  }
203
125
 
@@ -207,7 +129,7 @@ rbs_constant_pool_id_to_constant(const rbs_constant_pool_t *pool, rbs_constant_i
207
129
  */
208
130
  rbs_constant_id_t
209
131
  rbs_constant_pool_find(const rbs_constant_pool_t *pool, const uint8_t *start, size_t length) {
210
- assert(is_power_of_two(pool->capacity));
132
+ RBS_ASSERT(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity);
211
133
  const uint32_t mask = pool->capacity - 1;
212
134
 
213
135
  uint32_t hash = rbs_constant_pool_hash(start, length);
@@ -235,7 +157,7 @@ rbs_constant_pool_insert(rbs_constant_pool_t *pool, const uint8_t *start, size_t
235
157
  if (!rbs_constant_pool_resize(pool)) return RBS_CONSTANT_ID_UNSET;
236
158
  }
237
159
 
238
- assert(is_power_of_two(pool->capacity));
160
+ RBS_ASSERT(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity);
239
161
  const uint32_t mask = pool->capacity - 1;
240
162
 
241
163
  uint32_t hash = rbs_constant_pool_hash(start, length);
@@ -276,7 +198,7 @@ rbs_constant_pool_insert(rbs_constant_pool_t *pool, const uint8_t *start, size_t
276
198
  // IDs are allocated starting at 1, since the value 0 denotes a non-existent
277
199
  // constant.
278
200
  uint32_t id = ++pool->size;
279
- assert(pool->size < ((uint32_t) (1 << 30)));
201
+ RBS_ASSERT(pool->size < ((uint32_t) (1 << 30)), "pool->size is too large. Got %i", pool->size);
280
202
 
281
203
  *bucket = (rbs_constant_pool_bucket_t) {
282
204
  .id = (unsigned int) (id & 0x3fffffff),
@@ -301,6 +223,11 @@ rbs_constant_pool_insert_shared(rbs_constant_pool_t *pool, const uint8_t *start,
301
223
  return rbs_constant_pool_insert(pool, start, length, RBS_CONSTANT_POOL_BUCKET_DEFAULT);
302
224
  }
303
225
 
226
+ rbs_constant_id_t
227
+ rbs_constant_pool_insert_shared_with_encoding(rbs_constant_pool_t *pool, const uint8_t *start, size_t length, const rbs_encoding_t *encoding) {
228
+ return rbs_constant_pool_insert_shared(pool, start, length);
229
+ }
230
+
304
231
  /**
305
232
  * Insert a constant into a constant pool from memory that is now owned by the
306
233
  * constant pool. Returns the id of the constant, or RBS_CONSTANT_ID_UNSET if any
@@ -324,8 +251,7 @@ rbs_constant_pool_insert_constant(rbs_constant_pool_t *pool, const uint8_t *star
324
251
  /**
325
252
  * Free the memory associated with a constant pool.
326
253
  */
327
- void
328
- rbs_constant_pool_free(rbs_constant_pool_t *pool) {
254
+ void rbs_constant_pool_free(rbs_constant_pool_t *pool) {
329
255
  // For each constant in the current constant pool, free the contents if the
330
256
  // contents are owned.
331
257
  for (uint32_t index = 0; index < pool->capacity; index++) {