herb 0.11.1 → 0.11.2

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 (247) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -2
  3. data/config.yml +6 -0
  4. data/ext/herb/extconf.rb +8 -31
  5. data/ext/herb/nodes.c +75 -75
  6. data/ext/herb/parser_options_helpers.c +26 -0
  7. data/lib/herb/analysis/partial_index.rb +1 -1
  8. data/lib/herb/analysis/partial_resolution.rb +27 -0
  9. data/lib/herb/ast/helpers.rb +1 -1
  10. data/lib/herb/configuration.rb +11 -1
  11. data/lib/herb/dev/classifier.rb +1 -1
  12. data/lib/herb/engine/compiler.rb +5 -8
  13. data/lib/herb/engine/slots/dynamics_compiler.rb +53 -14
  14. data/lib/herb/engine/slots/subtree_compiler.rb +1 -1
  15. data/lib/herb/engine/slots/visitor.rb +32 -4
  16. data/lib/herb/engine/visitors/instrumentation_visitor.rb +18 -6
  17. data/lib/herb/parser_options.rb +6 -3
  18. data/lib/herb/project.rb +19 -8
  19. data/lib/herb/version.rb +1 -1
  20. data/lib/herb.rb +1 -1
  21. data/sig/herb/analysis/partial_resolution.rbs +8 -0
  22. data/sig/herb/configuration.rbs +3 -0
  23. data/sig/herb/engine/slots/dynamics_compiler.rbs +24 -7
  24. data/sig/herb/engine/slots/visitor.rbs +14 -0
  25. data/sig/herb/engine/visitors/instrumentation_visitor.rbs +5 -1
  26. data/sig/herb/parser_options.rbs +6 -4
  27. data/sig/herb.rbs +2 -2
  28. data/src/analyze/action_view/attribute_extraction_helpers.c +40 -21
  29. data/src/analyze/action_view/generated_handlers.c +36 -36
  30. data/src/analyze/action_view/image_tag.c +7 -3
  31. data/src/analyze/action_view/javascript_include_tag.c +6 -3
  32. data/src/analyze/action_view/link_to.c +23 -23
  33. data/src/analyze/action_view/registry.c +7 -3
  34. data/src/analyze/action_view/tag_helper_node_builders.c +6 -13
  35. data/src/analyze/action_view/tag_helpers.c +139 -90
  36. data/src/analyze/action_view/turbo_frame_tag.c +5 -4
  37. data/src/analyze/analyze.c +35 -19
  38. data/src/analyze/analyze_helpers.c +161 -188
  39. data/src/analyze/analyzed_ruby.c +8 -7
  40. data/src/analyze/control_type.c +29 -22
  41. data/src/analyze/herb_directives.c +16 -20
  42. data/src/analyze/iteration_nodes.c +69 -24
  43. data/src/analyze/parse_errors.c +32 -22
  44. data/src/analyze/postfix_conditionals.c +23 -13
  45. data/src/analyze/prism_annotate.c +29 -28
  46. data/src/analyze/render_nodes.c +51 -41
  47. data/src/analyze/strict_locals.c +14 -15
  48. data/src/analyze/ternary_conditionals.c +14 -10
  49. data/src/herb.c +10 -8
  50. data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
  51. data/src/include/analyze/action_view/tag_helper_node_builders.h +1 -0
  52. data/src/include/analyze/action_view/tag_helpers.h +1 -1
  53. data/src/include/analyze/analyze.h +3 -2
  54. data/src/include/analyze/analyzed_ruby.h +4 -2
  55. data/src/include/analyze/helpers.h +6 -6
  56. data/src/include/herb.h +3 -2
  57. data/src/include/parser/parser_options.h +5 -0
  58. data/src/include/prism/prism_context.h +12 -12
  59. data/src/include/prism/prism_helpers.h +30 -0
  60. data/src/include/prism_version.h +11 -0
  61. data/src/include/version.h +1 -1
  62. data/src/parser/parser_helpers.c +1 -2
  63. data/src/parser.c +6 -7
  64. data/src/parser_options_defaults.c +1 -0
  65. data/src/prism/prism_helpers.c +84 -50
  66. data/src/prism/ruby_parser.c +20 -20
  67. data/templates/ext/herb/nodes.c.erb +5 -5
  68. data/templates/ext/herb/parser_options_helpers.c.erb +33 -0
  69. data/templates/java/nodes.c.erb +6 -6
  70. data/templates/java/parser_options_helpers.c.erb +41 -2
  71. data/templates/java/parser_options_helpers.h.erb +2 -1
  72. data/templates/javascript/packages/node/extension/nodes.cpp.erb +5 -5
  73. data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +34 -2
  74. data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +1 -1
  75. data/templates/lib/herb/parser_options.rb.erb +1 -1
  76. data/templates/rust/src/prism/generated_deserialize.rs.erb +90 -44
  77. data/templates/rust/src/prism/generated_prettyprint.rs.erb +18 -27
  78. data/templates/src/analyze/action_view/generated_handlers.c.erb +23 -22
  79. data/templates/src/include/parser/parser_options.h.erb +10 -0
  80. data/templates/src/include/prism_version.h.erb +17 -0
  81. data/templates/src/parser_options_defaults.c.erb +1 -1
  82. data/templates/template.rb +17 -2
  83. data/templates/wasm/nodes.cpp.erb +5 -5
  84. data/templates/wasm/parser_options_helpers.cpp.erb +24 -0
  85. data/vendor/prism/Rakefile +76 -7
  86. data/vendor/prism/config.yml +174 -161
  87. data/vendor/prism/include/prism/arena.h +45 -0
  88. data/vendor/prism/include/prism/arena.hpp +42 -0
  89. data/vendor/prism/include/prism/ast.h +2738 -611
  90. data/vendor/prism/include/prism/ast.hpp +641 -0
  91. data/vendor/prism/include/prism/buffer.h +60 -0
  92. data/vendor/prism/include/prism/buffer.hpp +55 -0
  93. data/vendor/prism/include/prism/comments.h +72 -0
  94. data/vendor/prism/include/prism/compiler/accel.h +26 -0
  95. data/vendor/prism/include/prism/compiler/align.h +36 -0
  96. data/vendor/prism/include/prism/compiler/assume.h +25 -0
  97. data/vendor/prism/include/prism/compiler/branch.h +26 -0
  98. data/vendor/prism/include/prism/compiler/bswap.h +46 -0
  99. data/vendor/prism/include/prism/compiler/cplusplus.hpp +16 -0
  100. data/vendor/prism/include/prism/compiler/endianness.h +34 -0
  101. data/vendor/prism/include/prism/compiler/exceptions.hpp +17 -0
  102. data/vendor/prism/include/prism/compiler/exported.h +24 -0
  103. data/vendor/prism/include/prism/compiler/fallthrough.h +22 -0
  104. data/vendor/prism/include/prism/compiler/filesystem.h +32 -0
  105. data/vendor/prism/include/prism/compiler/flex_array.h +19 -0
  106. data/vendor/prism/include/prism/compiler/force_inline.h +21 -0
  107. data/vendor/prism/include/prism/compiler/format.h +27 -0
  108. data/vendor/prism/include/prism/compiler/inline.h +17 -0
  109. data/vendor/prism/include/prism/compiler/lifetimebound.hpp +25 -0
  110. data/vendor/prism/include/prism/compiler/nodiscard.h +22 -0
  111. data/vendor/prism/include/prism/compiler/nonnull.h +18 -0
  112. data/vendor/prism/include/prism/compiler/unused.h +18 -0
  113. data/vendor/prism/include/prism/constant_pool.h +106 -0
  114. data/vendor/prism/include/prism/diagnostic.h +55 -402
  115. data/vendor/prism/include/prism/errors_format.h +61 -0
  116. data/vendor/prism/include/prism/excludes.h +29 -0
  117. data/vendor/prism/include/prism/integer.h +41 -0
  118. data/vendor/prism/include/prism/internal/allocator.h +68 -0
  119. data/vendor/prism/include/prism/internal/allocator_debug.h +88 -0
  120. data/vendor/prism/include/prism/internal/arena.h +108 -0
  121. data/vendor/prism/include/prism/internal/bit.h +42 -0
  122. data/vendor/prism/include/prism/internal/buffer.h +94 -0
  123. data/vendor/prism/include/prism/internal/char.h +145 -0
  124. data/vendor/prism/include/prism/internal/comments.h +54 -0
  125. data/vendor/prism/include/prism/internal/constant_pool.h +152 -0
  126. data/vendor/prism/include/prism/internal/diagnostic.h +389 -0
  127. data/vendor/prism/include/prism/{encoding.h → internal/encoding.h} +27 -68
  128. data/vendor/prism/include/prism/internal/integer.h +68 -0
  129. data/vendor/prism/include/prism/internal/isinf.h +16 -0
  130. data/vendor/prism/include/prism/internal/line_offset_list.h +34 -0
  131. data/vendor/prism/include/prism/{util/pm_list.h → internal/list.h} +11 -52
  132. data/vendor/prism/include/prism/internal/magic_comments.h +23 -0
  133. data/vendor/prism/include/prism/internal/memchr.h +15 -0
  134. data/vendor/prism/include/prism/internal/node.h +42 -0
  135. data/vendor/prism/include/prism/internal/options.h +232 -0
  136. data/vendor/prism/include/prism/internal/parser.h +1015 -0
  137. data/vendor/prism/include/prism/internal/regexp.h +26 -0
  138. data/vendor/prism/include/prism/internal/serialize.h +39 -0
  139. data/vendor/prism/include/prism/internal/source.h +72 -0
  140. data/vendor/prism/include/prism/internal/static_literals.h +60 -0
  141. data/vendor/prism/include/prism/internal/stringy.h +30 -0
  142. data/vendor/prism/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
  143. data/vendor/prism/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
  144. data/vendor/prism/include/prism/internal/tokens.h +11 -0
  145. data/vendor/prism/include/prism/internal/xxh3.h +16 -0
  146. data/vendor/prism/include/prism/json.h +40 -0
  147. data/vendor/prism/include/prism/line_offset_list.h +69 -0
  148. data/vendor/prism/include/prism/magic_comments.h +53 -0
  149. data/vendor/prism/include/prism/node.h +59 -49
  150. data/vendor/prism/include/prism/node.hpp +272 -0
  151. data/vendor/prism/include/prism/node_type.hpp +38 -0
  152. data/vendor/prism/include/prism/options.h +154 -279
  153. data/vendor/prism/include/prism/options.hpp +43 -0
  154. data/vendor/prism/include/prism/parser.h +367 -870
  155. data/vendor/prism/include/prism/parser.hpp +274 -0
  156. data/vendor/prism/include/prism/prettyprint.h +14 -9
  157. data/vendor/prism/include/prism/serialize.h +123 -0
  158. data/vendor/prism/include/prism/source.h +163 -0
  159. data/vendor/prism/include/prism/stream.h +36 -0
  160. data/vendor/prism/include/prism/string_query.h +82 -0
  161. data/vendor/prism/include/prism/stringy.h +61 -0
  162. data/vendor/prism/include/prism/stringy.hpp +31 -0
  163. data/vendor/prism/include/prism/version.h +20 -3
  164. data/vendor/prism/include/prism.h +35 -320
  165. data/vendor/prism/include/prism.hpp +24 -0
  166. data/vendor/prism/src/arena.c +122 -0
  167. data/vendor/prism/src/{util/pm_buffer.c → buffer.c} +53 -21
  168. data/vendor/prism/src/{util/pm_char.c → char.c} +28 -57
  169. data/vendor/prism/src/comments.c +455 -0
  170. data/vendor/prism/src/constant_pool.c +406 -0
  171. data/vendor/prism/src/diagnostic.c +120 -68
  172. data/vendor/prism/src/encoding.c +8 -3
  173. data/vendor/prism/src/errors_format.c +519 -0
  174. data/vendor/prism/src/{util/pm_integer.c → integer.c} +38 -22
  175. data/vendor/prism/src/json.c +5733 -0
  176. data/vendor/prism/src/line_offset_list.c +100 -0
  177. data/vendor/prism/src/list.c +24 -0
  178. data/vendor/prism/src/{util/pm_memchr.c → memchr.c} +8 -6
  179. data/vendor/prism/src/node.c +3465 -7787
  180. data/vendor/prism/src/options.c +161 -54
  181. data/vendor/prism/src/parser.c +371 -0
  182. data/vendor/prism/src/prettyprint.c +421 -354
  183. data/vendor/prism/src/prism.c +8522 -7280
  184. data/vendor/prism/src/regexp.c +960 -45
  185. data/vendor/prism/src/serialize.c +2434 -2048
  186. data/vendor/prism/src/source.c +524 -0
  187. data/vendor/prism/src/static_literals.c +303 -360
  188. data/vendor/prism/src/string_query.c +180 -0
  189. data/vendor/prism/src/stringy.c +61 -0
  190. data/vendor/prism/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
  191. data/vendor/prism/src/strpbrk.c +447 -0
  192. data/vendor/prism/src/{token_type.c → tokens.c} +39 -18
  193. data/vendor/prism/src/xxh3.c +292 -0
  194. data/vendor/prism/templates/ext/prism/api_node.c.erb +58 -44
  195. data/vendor/prism/templates/include/prism/ast.h.erb +67 -17
  196. data/vendor/prism/templates/include/prism/ast.hpp.erb +31 -0
  197. data/vendor/prism/templates/include/prism/internal/diagnostic.h.erb +60 -0
  198. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/AbstractNodeVisitor.java.erb +1 -1
  199. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Loader.java.erb +232 -133
  200. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Nodes.java.erb +62 -23
  201. data/vendor/prism/templates/javascript/src/deserialize.js.erb +153 -146
  202. data/vendor/prism/templates/javascript/src/nodes.js.erb +4 -9
  203. data/vendor/prism/templates/lib/prism/compiler.rb.erb +14 -5
  204. data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +20 -12
  205. data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +37 -11
  206. data/vendor/prism/templates/lib/prism/dsl.rb.erb +43 -4
  207. data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +26 -10
  208. data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +5 -2
  209. data/vendor/prism/templates/lib/prism/node.rb.erb +283 -105
  210. data/vendor/prism/templates/lib/prism/reflection.rb.erb +11 -2
  211. data/vendor/prism/templates/lib/prism/serialize.rb.erb +291 -134
  212. data/vendor/prism/templates/lib/prism/visitor.rb.erb +18 -0
  213. data/vendor/prism/templates/src/diagnostic.c.erb +114 -63
  214. data/vendor/prism/templates/src/json.c.erb +130 -0
  215. data/vendor/prism/templates/src/node.c.erb +79 -236
  216. data/vendor/prism/templates/src/prettyprint.c.erb +24 -13
  217. data/vendor/prism/templates/src/serialize.c.erb +369 -183
  218. data/vendor/prism/templates/src/{token_type.c.erb → tokens.c.erb} +22 -11
  219. data/vendor/prism/templates/template.rb +193 -91
  220. metadata +100 -42
  221. data/vendor/prism/include/prism/defines.h +0 -260
  222. data/vendor/prism/include/prism/pack.h +0 -163
  223. data/vendor/prism/include/prism/regexp.h +0 -43
  224. data/vendor/prism/include/prism/static_literals.h +0 -121
  225. data/vendor/prism/include/prism/util/pm_buffer.h +0 -236
  226. data/vendor/prism/include/prism/util/pm_char.h +0 -204
  227. data/vendor/prism/include/prism/util/pm_constant_pool.h +0 -218
  228. data/vendor/prism/include/prism/util/pm_integer.h +0 -130
  229. data/vendor/prism/include/prism/util/pm_memchr.h +0 -29
  230. data/vendor/prism/include/prism/util/pm_newline_list.h +0 -113
  231. data/vendor/prism/include/prism/util/pm_string.h +0 -200
  232. data/vendor/prism/src/pack.c +0 -509
  233. data/vendor/prism/src/util/pm_constant_pool.c +0 -342
  234. data/vendor/prism/src/util/pm_list.c +0 -49
  235. data/vendor/prism/src/util/pm_newline_list.c +0 -125
  236. data/vendor/prism/src/util/pm_string.c +0 -381
  237. data/vendor/prism/src/util/pm_strpbrk.c +0 -206
  238. data/vendor/prism/templates/include/prism/diagnostic.h.erb +0 -130
  239. data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +0 -68
  240. data/vendor/prism/templates/rbi/prism/node.rbi.erb +0 -167
  241. data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +0 -18
  242. data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +0 -45
  243. data/vendor/prism/templates/sig/prism/dsl.rbs.erb +0 -31
  244. data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +0 -7
  245. data/vendor/prism/templates/sig/prism/node.rbs.erb +0 -136
  246. data/vendor/prism/templates/sig/prism/visitor.rbs.erb +0 -17
  247. data/vendor/prism/templates/sig/prism.rbs.erb +0 -92
@@ -0,0 +1,292 @@
1
+ /**
2
+ * An implementation of the XXH3 hash function.
3
+ *
4
+ * The reason some of these names do not look quite like the style of the rest
5
+ * of the code in Prism is that this was adapted straight from the XXH3
6
+ * specification here:
7
+ *
8
+ * https://github.com/Cyan4973/xxHash/blob/release/doc/xxhash_spec.md
9
+ *
10
+ * To better understand this code it is recommended to read the XXH3
11
+ * specification linked above, where you should be able to follow along with
12
+ * this implementation more easily. Note this only implements the XXH3_64
13
+ * variant with the default secret and a seed of 0. Additionally it does not
14
+ * include a lot of the various CPU-specific optimizations that exist in the
15
+ * reference implementation.
16
+ */
17
+
18
+ #include "prism/internal/xxh3.h"
19
+
20
+ #include "prism/compiler/accel.h"
21
+ #include "prism/compiler/bswap.h"
22
+ #include "prism/compiler/endianness.h"
23
+
24
+ #include <string.h>
25
+
26
+ #if defined(PRISM_HAS_NEON) && defined(PRISM_LITTLE_ENDIAN_COMPTIME)
27
+ #include <arm_neon.h>
28
+ #define XXH3_NEON
29
+ #elif defined(PRISM_HAS_SSE2)
30
+ #include <emmintrin.h>
31
+ #define XXH3_SSE2
32
+ #endif
33
+
34
+ #if defined(__SIZEOF_INT128__)
35
+ static uint64_t
36
+ XXH3_mul128_fold64(uint64_t lhs, uint64_t rhs) {
37
+ __uint128_t x = (__uint128_t) lhs * (__uint128_t) rhs;
38
+ return ((uint64_t) (x & 0xFFFFFFFFFFFFFFFFULL)) ^ ((uint64_t) (x >> 64));
39
+ }
40
+ #else
41
+ #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
42
+ #include <intrin.h>
43
+ #endif
44
+
45
+ static uint64_t
46
+ XXH3_mul128_fold64(uint64_t lhs, uint64_t rhs) {
47
+ uint64_t lo, hi;
48
+ #if defined(_MSC_VER) && defined(_M_X64)
49
+ lo = _umul128(lhs, rhs, &hi);
50
+ #elif defined(_MSC_VER) && defined(_M_ARM64)
51
+ hi = __umulh(lhs, rhs);
52
+ lo = lhs * rhs;
53
+ #else
54
+ uint64_t lo_lo = (lhs & 0xFFFFFFFF) * (rhs & 0xFFFFFFFF);
55
+ uint64_t hi_lo = (lhs >> 32) * (rhs & 0xFFFFFFFF);
56
+ uint64_t lo_hi = (lhs & 0xFFFFFFFF) * (rhs >> 32);
57
+ uint64_t hi_hi = (lhs >> 32) * (rhs >> 32);
58
+
59
+ uint64_t cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
60
+ hi = hi_hi + (hi_lo >> 32) + (cross >> 32);
61
+ lo = (cross << 32) | (lo_lo & 0xFFFFFFFF);
62
+ #endif
63
+ return lo ^ hi;
64
+ }
65
+ #endif
66
+
67
+ static uint32_t
68
+ read32(const void* ptr) {
69
+ uint32_t val;
70
+ memcpy(&val, ptr, sizeof(val));
71
+ if (!PRISM_LITTLE_ENDIAN_RUNTIME) {
72
+ val = pm_bswap32(val);
73
+ }
74
+ return val;
75
+ }
76
+
77
+ static uint64_t
78
+ read64(const void* ptr) {
79
+ uint64_t val;
80
+ memcpy(&val, ptr, sizeof(val));
81
+ if (!PRISM_LITTLE_ENDIAN_RUNTIME) {
82
+ val = pm_bswap64(val);
83
+ }
84
+ return val;
85
+ }
86
+
87
+ static const uint64_t PRIME32_1 = 0x9E3779B1U;
88
+ static const uint64_t PRIME32_2 = 0x85EBCA77U;
89
+ static const uint64_t PRIME32_3 = 0xC2B2AE3DU;
90
+ static const uint64_t PRIME64_1 = 0x9E3779B185EBCA87ULL;
91
+ static const uint64_t PRIME64_2 = 0xC2B2AE3D27D4EB4FULL;
92
+ static const uint64_t PRIME64_3 = 0x165667B19E3779F9ULL;
93
+ static const uint64_t PRIME64_4 = 0x85EBCA77C2B2AE63ULL;
94
+ static const uint64_t PRIME64_5 = 0x27D4EB2F165667C5ULL;
95
+ static const uint64_t PRIME_MX1 = 0x165667919E3779F9ULL;
96
+ static const uint64_t PRIME_MX2 = 0x9FB21C651E98DF25ULL;
97
+
98
+ static const uint8_t secret[192] = {
99
+ 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
100
+ 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
101
+ 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,
102
+ 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,
103
+ 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,
104
+ 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,
105
+ 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,
106
+ 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,
107
+ 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
108
+ 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
109
+ 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
110
+ 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
111
+ };
112
+
113
+ static uint64_t
114
+ avalanche(uint64_t x) {
115
+ x ^= (x >> 37);
116
+ x *= PRIME_MX1;
117
+ x ^= (x >> 32);
118
+ return x;
119
+ }
120
+
121
+ static uint64_t
122
+ avalanche_XXH64(uint64_t x) {
123
+ x ^= (x >> 33);
124
+ x *= PRIME64_2;
125
+ x ^= (x >> 29);
126
+ x *= PRIME64_3;
127
+ x ^= (x >> 32);
128
+ return x;
129
+ }
130
+
131
+ static uint64_t
132
+ XXH3_64_empty(void) {
133
+ return avalanche_XXH64(read64(secret + 56) ^ read64(secret + 64));
134
+ }
135
+
136
+ static uint64_t
137
+ XXH3_64_1to3(const uint8_t *input, size_t length) {
138
+ uint32_t combined = (uint32_t) input[length - 1] | ((uint32_t) length << 8) | ((uint32_t) input[0] << 16) | ((uint32_t) input[length >> 1] << 24);
139
+ return avalanche_XXH64((uint64_t) (read32(secret) ^ read32(secret + 4)) ^ (uint64_t) combined);
140
+ }
141
+
142
+ static uint64_t
143
+ XXH3_64_4to8(const uint8_t *input, size_t length) {
144
+ #define rot(x_, r_) (((x_) << (r_)) | ((x_) >> (64 - (r_))))
145
+
146
+ uint64_t combined = (uint64_t) read32(input + length - 4) | ((uint64_t) read32(input) << 32);
147
+ uint64_t value = (read64(secret + 8) ^ read64(secret + 16)) ^ combined;
148
+ value ^= rot(value, 49) ^ rot(value, 24);
149
+ value *= PRIME_MX2;
150
+ value ^= ((value >> 35) + length);
151
+ value *= PRIME_MX2;
152
+ value ^= (value >> 28);
153
+ return value;
154
+
155
+ #undef rot
156
+ }
157
+
158
+ static uint64_t
159
+ XXH3_64_9to16(const uint8_t *input, size_t length) {
160
+ uint64_t lo = (read64(secret + 24) ^ read64(secret + 32)) ^ read64(input);
161
+ uint64_t hi = (read64(secret + 40) ^ read64(secret + 48)) ^ read64(input + length - 8);
162
+ return avalanche(length + pm_bswap64(lo) + hi + XXH3_mul128_fold64(lo, hi));
163
+ }
164
+
165
+ static uint64_t
166
+ XXH3_64_17to240(const uint8_t *input, size_t length) {
167
+ #define mix(data_, offset_) XXH3_mul128_fold64(read64((data_)) ^ read64(secret + (offset_)), read64((data_) + 8) ^ read64(secret + (offset_) + 8))
168
+
169
+ uint64_t acc = length * PRIME64_1;
170
+
171
+ if (length <= 128) {
172
+ size_t idx = (length - 1) / 32;
173
+ do {
174
+ acc += mix(input + idx * 16, idx * 32) + mix(input + length - idx * 16 - 16, idx * 32 + 16);
175
+ } while (idx--);
176
+ } else {
177
+ for (size_t idx = 0; idx < 8; idx++) {
178
+ acc += mix(input + idx * 16, idx * 16);
179
+ }
180
+ acc = avalanche(acc);
181
+ for (size_t idx = 8; idx < length >> 4; idx++) {
182
+ acc += mix(input + idx * 16, (idx - 8) * 16 + 3);
183
+ }
184
+ acc += mix(input + length - 16, 119);
185
+ }
186
+
187
+ return avalanche(acc);
188
+
189
+ #undef mix
190
+ }
191
+
192
+ static void
193
+ accumulate(uint64_t acc[8], const uint8_t *stripe, size_t secret_offset) {
194
+ #if defined(XXH3_NEON)
195
+ for (int idx = 0; idx < 8; idx += 2) {
196
+ uint64x2_t data = vreinterpretq_u64_u8(vld1q_u8(stripe + 8 * idx));
197
+ uint64x2_t value = veorq_u64(data, vreinterpretq_u64_u8(vld1q_u8(secret + secret_offset + 8 * idx)));
198
+ uint64x2_t product = vmull_u32(vmovn_u64(value), vshrn_n_u64(value, 32));
199
+ vst1q_u64(acc + idx, vaddq_u64(vld1q_u64(acc + idx), vaddq_u64(vextq_u64(data, data, 1), product)));
200
+ }
201
+ #elif defined(XXH3_SSE2)
202
+ for (int idx = 0; idx < 8; idx += 2) {
203
+ __m128i data = _mm_loadu_si128((const __m128i *) (stripe + 8 * idx));
204
+ __m128i value = _mm_xor_si128(data, _mm_loadu_si128((const __m128i *) (secret + secret_offset + 8 * idx)));
205
+ __m128i product = _mm_mul_epu32(value, _mm_shuffle_epi32(value, _MM_SHUFFLE(0, 3, 0, 1)));
206
+ _mm_storeu_si128((__m128i *) (acc + idx), _mm_add_epi64(_mm_loadu_si128((const __m128i *) (acc + idx)), _mm_add_epi64(_mm_shuffle_epi32(data, _MM_SHUFFLE(1, 0, 3, 2)), product)));
207
+ }
208
+ #else
209
+ for (int idx = 0; idx < 8; idx++) {
210
+ uint64_t data = read64(stripe + 8 * idx);
211
+ uint64_t value = data ^ read64(secret + secret_offset + 8 * idx);
212
+ acc[idx ^ 1] = acc[idx ^ 1] + data;
213
+ acc[idx] += (value & 0xFFFFFFFF) * (value >> 32);
214
+ }
215
+ #endif
216
+ }
217
+
218
+ static uint64_t
219
+ XXH3_64_large(const uint8_t *input, size_t length) {
220
+ const size_t secret_length = sizeof(secret);
221
+ const size_t stripes_per_block = (secret_length - 64) / 8;
222
+ const size_t block_size = 64 * stripes_per_block;
223
+ const size_t block_count = (length - 1) / block_size;
224
+ const size_t last_offset = block_count * block_size;
225
+
226
+ uint64_t acc[8] = {
227
+ PRIME32_3, PRIME64_1, PRIME64_2, PRIME64_3,
228
+ PRIME64_4, PRIME32_2, PRIME64_5, PRIME32_1
229
+ };
230
+
231
+ for (size_t block_idx = 0; block_idx < block_count; block_idx++) {
232
+ const uint8_t *block = input + block_idx * block_size;
233
+
234
+ for (size_t stripe_idx = 0; stripe_idx < stripes_per_block; stripe_idx++) {
235
+ accumulate(acc, block + stripe_idx * 64, stripe_idx * 8);
236
+ }
237
+
238
+ #if defined(XXH3_NEON)
239
+ const uint32x2_t prime = vdup_n_u32((uint32_t) PRIME32_1);
240
+ for (size_t idx = 0; idx < 8; idx += 2) {
241
+ uint64x2_t value = vld1q_u64(acc + idx);
242
+ value = veorq_u64(value, vshrq_n_u64(value, 47));
243
+ value = veorq_u64(value, vreinterpretq_u64_u8(vld1q_u8(secret + secret_length - 64 + idx * 8)));
244
+ vst1q_u64(acc + idx, vaddq_u64(vmull_u32(vmovn_u64(value), prime), vshlq_n_u64(vmull_u32(vshrn_n_u64(value, 32), prime), 32)));
245
+ }
246
+ #elif defined(XXH3_SSE2)
247
+ const __m128i prime = _mm_set1_epi32((int) (uint32_t) PRIME32_1);
248
+ for (size_t idx = 0; idx < 8; idx += 2) {
249
+ __m128i value = _mm_loadu_si128((const __m128i *) (acc + idx));
250
+ value = _mm_xor_si128(value, _mm_srli_epi64(value, 47));
251
+ value = _mm_xor_si128(value, _mm_loadu_si128((const __m128i *) (secret + secret_length - 64 + idx * 8)));
252
+ _mm_storeu_si128((__m128i *) (acc + idx), _mm_add_epi64(_mm_mul_epu32(value, prime), _mm_slli_epi64(_mm_mul_epu32(_mm_shuffle_epi32(value, _MM_SHUFFLE(0, 3, 0, 1)), prime), 32)));
253
+ }
254
+ #else
255
+ for (size_t idx = 0; idx < 8; idx++) {
256
+ acc[idx] ^= (acc[idx] >> 47);
257
+ acc[idx] ^= read64(secret + secret_length - 64 + idx * 8);
258
+ acc[idx] *= PRIME32_1;
259
+ }
260
+ #endif
261
+ }
262
+
263
+ for (size_t stripe_idx = 0; stripe_idx < (length - last_offset - 1) / 64; stripe_idx++) {
264
+ accumulate(acc, input + last_offset + stripe_idx * 64, stripe_idx * 8);
265
+ }
266
+
267
+ accumulate(acc, input + length - 64, secret_length - 71);
268
+
269
+ uint64_t result = (uint64_t) length * PRIME64_1;
270
+ for (size_t idx = 0; idx < 4; idx++) {
271
+ result += XXH3_mul128_fold64(acc[idx * 2] ^ read64(secret + 11 + 16 * idx), acc[idx * 2 + 1] ^ read64(secret + 11 + 16 * idx + 8));
272
+ }
273
+
274
+ return avalanche(result);
275
+ }
276
+
277
+ uint64_t
278
+ pm_xxh3(const uint8_t *input, size_t length) {
279
+ if (length == 0) {
280
+ return XXH3_64_empty();
281
+ } else if (length <= 3) {
282
+ return XXH3_64_1to3(input, length);
283
+ } else if (length <= 8) {
284
+ return XXH3_64_4to8(input, length);
285
+ } else if (length <= 16) {
286
+ return XXH3_64_9to16(input, length);
287
+ } else if (length <= 240) {
288
+ return XXH3_64_17to240(input, length);
289
+ } else {
290
+ return XXH3_64_large(input, length);
291
+ }
292
+ }
@@ -1,5 +1,9 @@
1
1
  #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
2
2
  #include "prism/extension.h"
3
+ #include "prism/internal/allocator.h"
4
+ #include "prism/internal/arena.h"
5
+
6
+ #include <assert.h>
3
7
 
4
8
  extern VALUE rb_cPrism;
5
9
  extern VALUE rb_cPrismNode;
@@ -12,31 +16,26 @@ static VALUE rb_cPrism<%= node.name %>;
12
16
  <%- end -%>
13
17
 
14
18
  static VALUE
15
- pm_location_new(const pm_parser_t *parser, const uint8_t *start, const uint8_t *end, VALUE source, bool freeze) {
19
+ pm_location_new(const uint32_t start, const uint32_t length, VALUE source, bool freeze) {
16
20
  if (freeze) {
17
- VALUE location_argv[] = {
18
- source,
19
- LONG2FIX(start - parser->start),
20
- LONG2FIX(end - start)
21
- };
22
-
21
+ VALUE location_argv[] = { source, LONG2FIX(start), LONG2FIX(length) };
23
22
  return rb_obj_freeze(rb_class_new_instance(3, location_argv, rb_cPrismLocation));
24
23
  } else {
25
- uint64_t value = ((((uint64_t) (start - parser->start)) << 32) | ((uint32_t) (end - start)));
24
+ uint64_t value = ((((uint64_t) start) << 32) | ((uint64_t) length));
26
25
  return ULL2NUM(value);
27
26
  }
28
27
  }
29
28
 
30
29
  VALUE
31
30
  pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source, bool freeze) {
32
- ID type = rb_intern(pm_token_type_name(token->type));
33
- VALUE location = pm_location_new(parser, token->start, token->end, source, freeze);
31
+ ID type = rb_intern(pm_token_type(token->type));
32
+ VALUE location = pm_location_new((uint32_t) (token->start - pm_parser_start(parser)), (uint32_t) (token->end - token->start), source, freeze);
34
33
 
35
34
  VALUE slice = rb_enc_str_new((const char *) token->start, token->end - token->start, encoding);
36
35
  if (freeze) rb_obj_freeze(slice);
37
36
 
38
- VALUE argv[] = { source, ID2SYM(type), slice, location };
39
- VALUE value = rb_class_new_instance(4, argv, rb_cPrismToken);
37
+ VALUE argv[] = { source, ID2SYM(type), slice, location, INT2FIX(pm_parser_lex_state(parser)) };
38
+ VALUE value = rb_class_new_instance(5, argv, rb_cPrismToken);
40
39
  if (freeze) rb_obj_freeze(value);
41
40
 
42
41
  return value;
@@ -78,20 +77,26 @@ pm_integer_new(const pm_integer_t *integer) {
78
77
 
79
78
  // Create a Prism::Source object from the given parser, after pm_parse() was called.
80
79
  VALUE
81
- pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, bool freeze) {
82
- VALUE source_string = rb_enc_str_new((const char *) parser->start, parser->end - parser->start, encoding);
80
+ pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, VALUE comments, VALUE comment_attachments, VALUE comment_ranges, bool freeze) {
81
+ const uint8_t *start = pm_parser_start(parser);
82
+ VALUE source_string = rb_enc_str_new((const char *) start, pm_parser_end(parser) - start, encoding);
83
83
 
84
- VALUE offsets = rb_ary_new_capa(parser->newline_list.size);
85
- for (size_t index = 0; index < parser->newline_list.size; index++) {
86
- rb_ary_push(offsets, ULONG2NUM(parser->newline_list.offsets[index]));
87
- }
84
+ const pm_line_offset_list_t *line_offsets = pm_parser_line_offsets(parser);
85
+ VALUE offsets;
88
86
 
89
87
  if (freeze) {
88
+ offsets = rb_ary_new_capa(line_offsets->size);
89
+ for (size_t index = 0; index < line_offsets->size; index++) {
90
+ rb_ary_push(offsets, ULONG2NUM(line_offsets->offsets[index]));
91
+ }
92
+
90
93
  rb_obj_freeze(source_string);
91
94
  rb_obj_freeze(offsets);
95
+ } else {
96
+ offsets = rb_str_new((const char *) line_offsets->offsets, line_offsets->size * sizeof(uint32_t));
92
97
  }
93
98
 
94
- VALUE source = rb_funcall(rb_cPrismSource, rb_intern("for"), 3, source_string, LONG2NUM(parser->start_line), offsets);
99
+ VALUE source = rb_funcall(rb_cPrismSource, rb_intern("for"), 7, source_string, LONG2NUM(pm_parser_start_line(parser)), offsets, comments, comment_attachments, comment_ranges, ULL2NUM(pm_parser_checksum(parser)));
95
100
  if (freeze) rb_obj_freeze(source);
96
101
 
97
102
  return source;
@@ -104,8 +109,8 @@ typedef struct pm_node_stack_node {
104
109
  } pm_node_stack_node_t;
105
110
 
106
111
  static void
107
- pm_node_stack_push(pm_node_stack_node_t **stack, const pm_node_t *visit) {
108
- pm_node_stack_node_t *node = xmalloc(sizeof(pm_node_stack_node_t));
112
+ pm_node_stack_push(pm_arena_t *arena, pm_node_stack_node_t **stack, const pm_node_t *visit) {
113
+ pm_node_stack_node_t *node = (pm_node_stack_node_t *) pm_arena_alloc(arena, sizeof(pm_node_stack_node_t), PRISM_ALIGNOF(pm_node_stack_node_t));
109
114
  node->prev = *stack;
110
115
  node->visit = visit;
111
116
  node->visited = false;
@@ -118,32 +123,40 @@ pm_node_stack_pop(pm_node_stack_node_t **stack) {
118
123
  const pm_node_t *visit = current->visit;
119
124
 
120
125
  *stack = current->prev;
121
- xfree(current);
122
126
 
123
127
  return visit;
124
128
  }
125
129
 
126
- VALUE
127
- pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source, bool freeze) {
128
- VALUE constants = rb_ary_new_capa(parser->constant_pool.size);
130
+ /**
131
+ * Build the Symbol for the given constant.
132
+ */
133
+ static VALUE
134
+ pm_ast_constant(const pm_constant_t *constant, rb_encoding *encoding) {
135
+ int state = 0;
129
136
 
130
- for (uint32_t index = 0; index < parser->constant_pool.size; index++) {
131
- pm_constant_t *constant = &parser->constant_pool.constants[index];
132
- int state = 0;
137
+ VALUE string = rb_enc_str_new((const char *) pm_constant_start(constant), pm_constant_length(constant), encoding);
138
+ VALUE value = rb_protect(rb_str_intern, string, &state);
133
139
 
134
- VALUE string = rb_enc_str_new((const char *) constant->start, constant->length, encoding);
135
- VALUE value = rb_protect(rb_str_intern, string, &state);
140
+ if (state != 0) {
141
+ value = ID2SYM(rb_intern_const("?"));
142
+ rb_set_errinfo(Qnil);
143
+ }
136
144
 
137
- if (state != 0) {
138
- value = ID2SYM(rb_intern_const("?"));
139
- rb_set_errinfo(Qnil);
140
- }
145
+ return value;
146
+ }
147
+
148
+ VALUE
149
+ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source, bool freeze) {
150
+ size_t constants_size = pm_parser_constants_size(parser);
151
+ VALUE constants = rb_ary_new_capa((long) constants_size);
141
152
 
142
- rb_ary_push(constants, value);
153
+ for (size_t index = 0; index < constants_size; index++) {
154
+ rb_ary_push(constants, pm_ast_constant(pm_parser_constant_at(parser, index), encoding));
143
155
  }
144
156
 
157
+ pm_arena_t *node_arena = pm_arena_new();
145
158
  pm_node_stack_node_t *node_stack = NULL;
146
- pm_node_stack_push(&node_stack, node);
159
+ pm_node_stack_push(node_arena, &node_stack, node);
147
160
  VALUE value_stack = rb_ary_new();
148
161
 
149
162
  while (node_stack != NULL) {
@@ -166,10 +179,10 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
166
179
  <%- node.fields.each do |field| -%>
167
180
  <%- case field -%>
168
181
  <%- when Prism::Template::NodeField, Prism::Template::OptionalNodeField -%>
169
- pm_node_stack_push(&node_stack, (pm_node_t *) cast-><%= field.name %>);
182
+ pm_node_stack_push(node_arena, &node_stack, (pm_node_t *) cast-><%= field.name %>);
170
183
  <%- when Prism::Template::NodeListField -%>
171
184
  for (size_t index = 0; index < cast-><%= field.name %>.size; index++) {
172
- pm_node_stack_push(&node_stack, (pm_node_t *) cast-><%= field.name %>.nodes[index]);
185
+ pm_node_stack_push(node_arena, &node_stack, (pm_node_t *) cast-><%= field.name %>.nodes[index]);
173
186
  }
174
187
  <%- end -%>
175
188
  <%- end -%>
@@ -200,7 +213,7 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
200
213
  argv[1] = ULONG2NUM(node->node_id);
201
214
 
202
215
  // location
203
- argv[2] = pm_location_new(parser, node->location.start, node->location.end, source, freeze);
216
+ argv[2] = pm_location_new(node->location.start, node->location.length, source, freeze);
204
217
 
205
218
  // flags
206
219
  argv[3] = ULONG2NUM(node->flags);
@@ -224,23 +237,23 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
224
237
  <%- when Prism::Template::ConstantField -%>
225
238
  #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
226
239
  assert(cast-><%= field.name %> != 0);
227
- argv[<%= index %>] = RARRAY_AREF(constants, cast-><%= field.name %> - 1);
240
+ argv[<%= index %>] = RARRAY_AREF(constants, pm_constant_id_index(cast-><%= field.name %>));
228
241
  <%- when Prism::Template::OptionalConstantField -%>
229
- argv[<%= index %>] = cast-><%= field.name %> == 0 ? Qnil : RARRAY_AREF(constants, cast-><%= field.name %> - 1);
242
+ argv[<%= index %>] = cast-><%= field.name %> == 0 ? Qnil : RARRAY_AREF(constants, pm_constant_id_index(cast-><%= field.name %>));
230
243
  <%- when Prism::Template::ConstantListField -%>
231
244
  #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
232
245
  argv[<%= index %>] = rb_ary_new_capa(cast-><%= field.name %>.size);
233
246
  for (size_t index = 0; index < cast-><%= field.name %>.size; index++) {
234
247
  assert(cast-><%= field.name %>.ids[index] != 0);
235
- rb_ary_push(argv[<%= index %>], RARRAY_AREF(constants, cast-><%= field.name %>.ids[index] - 1));
248
+ rb_ary_push(argv[<%= index %>], RARRAY_AREF(constants, pm_constant_id_index(cast-><%= field.name %>.ids[index])));
236
249
  }
237
250
  if (freeze) rb_obj_freeze(argv[<%= index %>]);
238
251
  <%- when Prism::Template::LocationField -%>
239
252
  #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
240
- argv[<%= index %>] = pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end, source, freeze);
253
+ argv[<%= index %>] = pm_location_new(cast-><%= field.name %>.start, cast-><%= field.name %>.length, source, freeze);
241
254
  <%- when Prism::Template::OptionalLocationField -%>
242
255
  #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
243
- argv[<%= index %>] = cast-><%= field.name %>.start == NULL ? Qnil : pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end, source, freeze);
256
+ argv[<%= index %>] = cast-><%= field.name %>.length == 0 ? Qnil : pm_location_new(cast-><%= field.name %>.start, cast-><%= field.name %>.length, source, freeze);
244
257
  <%- when Prism::Template::UInt8Field -%>
245
258
  #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
246
259
  argv[<%= index %>] = UINT2NUM(cast-><%= field.name %>);
@@ -271,6 +284,7 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
271
284
  }
272
285
  }
273
286
 
287
+ pm_arena_free(node_arena);
274
288
  return rb_ary_pop(value_stack);
275
289
  }
276
290
 
@@ -8,21 +8,27 @@
8
8
  #ifndef PRISM_AST_H
9
9
  #define PRISM_AST_H
10
10
 
11
- #include "prism/defines.h"
12
- #include "prism/util/pm_constant_pool.h"
13
- #include "prism/util/pm_integer.h"
14
- #include "prism/util/pm_string.h"
11
+ #include "prism/compiler/align.h"
12
+ #include "prism/compiler/exported.h"
13
+
14
+ #include "prism/arena.h"
15
+ #include "prism/constant_pool.h"
16
+ #include "prism/integer.h"
17
+ #include "prism/stringy.h"
15
18
 
16
- #include <assert.h>
17
19
  #include <stddef.h>
18
20
  #include <stdint.h>
19
21
 
22
+ #ifdef __cplusplus
23
+ extern "C" {
24
+ #endif
25
+
20
26
  /**
21
27
  * This enum represents every type of token in the Ruby source.
22
28
  */
23
29
  typedef enum pm_token_type {
24
30
  <%- tokens.each do |token| -%>
25
- /** <%= token.comment %> */
31
+ /** <%= Prism::Template::Doxygen.verbatim(token.comment) %> */
26
32
  PM_TOKEN_<%= token.name %><%= " = #{token.value}" if token.value %>,
27
33
 
28
34
  <%- end -%>
@@ -46,15 +52,28 @@ typedef struct {
46
52
  } pm_token_t;
47
53
 
48
54
  /**
49
- * This represents a range of bytes in the source string to which a node or
50
- * token corresponds.
55
+ * Returns a string representation of the given token type.
56
+ *
57
+ * @param token_type The type of the token to get the string representation of.
58
+ * @returns A string representation of the given token type. This is meant for
59
+ * debugging purposes and is not guaranteed to be stable across versions.
60
+ */
61
+ PRISM_EXPORTED_FUNCTION const char * pm_token_type(pm_token_type_t token_type);
62
+
63
+ /**
64
+ * This struct represents a slice in the source code, defined by an offset and
65
+ * a length. Note that we have confirmation that we can represent all locations
66
+ * within Ruby source files using 32-bit integers per:
67
+ *
68
+ * https://bugs.ruby-lang.org/issues/20488#note-1
69
+ *
51
70
  */
52
71
  typedef struct {
53
- /** A pointer to the start location of the range in the source. */
54
- const uint8_t *start;
72
+ /** The offset of the location from the start of the source. */
73
+ uint32_t start;
55
74
 
56
- /** A pointer to the end location of the range in the source. */
57
- const uint8_t *end;
75
+ /** The length of the location. */
76
+ uint32_t length;
58
77
  } pm_location_t;
59
78
 
60
79
  struct pm_node;
@@ -112,7 +131,7 @@ static const pm_node_flags_t PM_NODE_FLAG_STATIC_LITERAL = 0x2;
112
131
  typedef struct pm_node {
113
132
  /**
114
133
  * This represents the type of the node. It somewhat maps to the nodes that
115
- * existed in the original grammar and ripper, but it's not a 1:1 mapping.
134
+ * existed in the original grammar and ripper, but it is not a 1:1 mapping.
116
135
  */
117
136
  pm_node_type_t type;
118
137
 
@@ -124,12 +143,14 @@ typedef struct pm_node {
124
143
 
125
144
  /**
126
145
  * The unique identifier for this node, which is deterministic based on the
127
- * source. It is used to identify unique nodes across parses.
146
+ * source. It is used to identify unique nodes across parses. Nodes created
147
+ * outside of parsing have no position in the source and can use 0, which
148
+ * no parsed node uses.
128
149
  */
129
150
  uint32_t node_id;
130
151
 
131
152
  /**
132
- * This is the location of the node in the source. It's a range of bytes
153
+ * This is the location of the node in the source. It is a range of bytes
133
154
  * containing a start and an end.
134
155
  */
135
156
  pm_location_t location;
@@ -160,6 +181,15 @@ typedef struct pm_node {
160
181
  * Return true if the given flag is set on the given node.
161
182
  */
162
183
  #define PM_NODE_FLAG_P(node_, flag_) ((PM_NODE_FLAGS(node_) & (flag_)) != 0)
184
+
185
+ /**
186
+ * The alignment required for a child node within a parent node.
187
+ */
188
+ #ifdef _MSC_VER
189
+ #define PM_NODE_ALIGNAS __declspec(align(8))
190
+ #else
191
+ #define PM_NODE_ALIGNAS PRISM_ALIGNAS(PRISM_ALIGNOF(void *))
192
+ #endif
163
193
  <%- nodes.each do |node| -%>
164
194
 
165
195
  /**
@@ -182,7 +212,6 @@ typedef struct pm_node {
182
212
  typedef struct pm_<%= node.human %> {
183
213
  /** The embedded base node. */
184
214
  pm_node_t base;
185
-
186
215
  <%- node.fields.each do |field| -%>
187
216
 
188
217
  /**
@@ -195,7 +224,7 @@ typedef struct pm_<%= node.human %> {
195
224
  <%- end -%>
196
225
  */
197
226
  <%= case field
198
- when Prism::Template::NodeField, Prism::Template::OptionalNodeField then "struct #{field.c_type} *#{field.name}"
227
+ when Prism::Template::NodeField, Prism::Template::OptionalNodeField then "PM_NODE_ALIGNAS struct #{field.c_type} *#{field.name}"
199
228
  when Prism::Template::NodeListField then "struct pm_node_list #{field.name}"
200
229
  when Prism::Template::ConstantField, Prism::Template::OptionalConstantField then "pm_constant_id_t #{field.name}"
201
230
  when Prism::Template::ConstantListField then "pm_constant_id_list_t #{field.name}"
@@ -226,6 +255,23 @@ typedef enum pm_<%= flag.human %> {
226
255
  PM_<%= flag.human.upcase %>_LAST,
227
256
  } pm_<%= flag.human %>_t;
228
257
  <%- end -%>
258
+ <%- nodes.each do |node| -%>
259
+
260
+ <%- params = node.fields.map(&:c_param) -%>
261
+ /**
262
+ * Allocate and initialize a new <%= node.name %> node.
263
+ *
264
+ * @param arena The arena to allocate from.
265
+ * @param node_id The unique identifier for this node.
266
+ * @param flags The flags for this node.
267
+ * @param location The location of this node in the source.
268
+ <%- node.fields.each do |field| -%>
269
+ * @param <%= field.name %> <%= field.comment ? Prism::Template::Doxygen.verbatim(field.comment.lines.first.strip) : "The #{field.name} field." %>
270
+ <%- end -%>
271
+ * @returns The newly allocated and initialized node.
272
+ */
273
+ PRISM_EXPORTED_FUNCTION pm_<%= node.human %>_t * pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>);
274
+ <%- end -%>
229
275
 
230
276
  /**
231
277
  * When we're serializing to Java, we want to skip serializing the location
@@ -235,4 +281,8 @@ typedef enum pm_<%= flag.human %> {
235
281
  */
236
282
  #define PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS <%= Prism::Template::SERIALIZE_ONLY_SEMANTICS_FIELDS ? 1 : 0 %>
237
283
 
284
+ #ifdef __cplusplus
285
+ }
286
+ #endif
287
+
238
288
  #endif