herb 0.11.0-aarch64-linux-gnu → 0.11.2-aarch64-linux-gnu

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 (273) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -2
  3. data/config.yml +9 -0
  4. data/ext/herb/extconf.rb +8 -31
  5. data/ext/herb/nodes.c +90 -73
  6. data/ext/herb/parser_options_helpers.c +26 -0
  7. data/lib/herb/3.2/herb.so +0 -0
  8. data/lib/herb/3.3/herb.so +0 -0
  9. data/lib/herb/3.4/herb.so +0 -0
  10. data/lib/herb/4.0/herb.so +0 -0
  11. data/lib/herb/analysis/partial_index.rb +1 -1
  12. data/lib/herb/analysis/partial_resolution.rb +27 -0
  13. data/lib/herb/ast/helpers.rb +1 -1
  14. data/lib/herb/ast/nodes.rb +32 -6
  15. data/lib/herb/bootstrap.rb +6 -2
  16. data/lib/herb/configuration.rb +11 -1
  17. data/lib/herb/dev/classifier.rb +1 -1
  18. data/lib/herb/dev/runner.rb +6 -1
  19. data/lib/herb/engine/compiler.rb +52 -19
  20. data/lib/herb/engine/slots/dynamics_compiler.rb +63 -14
  21. data/lib/herb/engine/slots/markers.rb +24 -0
  22. data/lib/herb/engine/slots/state_compiler.rb +1 -2
  23. data/lib/herb/engine/slots/subtree_compiler.rb +1 -1
  24. data/lib/herb/engine/slots/visitor.rb +71 -32
  25. data/lib/herb/engine/visitors/instrumentation_visitor.rb +18 -6
  26. data/lib/herb/engine.rb +0 -2
  27. data/lib/herb/parser_options.rb +6 -3
  28. data/lib/herb/project.rb +19 -8
  29. data/lib/herb/version.rb +1 -1
  30. data/lib/herb.rb +1 -1
  31. data/sig/herb/analysis/partial_resolution.rbs +8 -0
  32. data/sig/herb/ast/nodes.rbs +10 -4
  33. data/sig/herb/bootstrap.rbs +2 -0
  34. data/sig/herb/configuration.rbs +3 -0
  35. data/sig/herb/dev/runner.rbs +3 -0
  36. data/sig/herb/engine/compiler.rbs +14 -3
  37. data/sig/herb/engine/slots/dynamics_compiler.rbs +27 -7
  38. data/sig/herb/engine/slots/markers.rbs +14 -0
  39. data/sig/herb/engine/slots/visitor.rbs +31 -13
  40. data/sig/herb/engine/visitors/instrumentation_visitor.rbs +5 -1
  41. data/sig/herb/parser_options.rbs +6 -4
  42. data/sig/herb.rbs +2 -2
  43. data/sig/serialized_ast_nodes.rbs +1 -0
  44. data/src/analyze/action_view/attribute_extraction_helpers.c +40 -21
  45. data/src/analyze/action_view/generated_handlers.c +36 -36
  46. data/src/analyze/action_view/image_tag.c +7 -3
  47. data/src/analyze/action_view/javascript_include_tag.c +6 -3
  48. data/src/analyze/action_view/link_to.c +23 -23
  49. data/src/analyze/action_view/registry.c +7 -3
  50. data/src/analyze/action_view/tag_helper_node_builders.c +12 -16
  51. data/src/analyze/action_view/tag_helpers.c +215 -110
  52. data/src/analyze/action_view/turbo_frame_tag.c +5 -4
  53. data/src/analyze/analyze.c +41 -45
  54. data/src/analyze/analyze_helpers.c +240 -405
  55. data/src/analyze/analyzed_ruby.c +10 -7
  56. data/src/analyze/builders.c +1 -0
  57. data/src/analyze/control_type.c +46 -29
  58. data/src/analyze/herb_directives.c +16 -20
  59. data/src/analyze/iteration_nodes.c +69 -24
  60. data/src/analyze/parse_errors.c +32 -22
  61. data/src/analyze/postfix_conditionals.c +23 -13
  62. data/src/analyze/prism_annotate.c +56 -32
  63. data/src/analyze/render_nodes.c +51 -41
  64. data/src/analyze/strict_locals.c +14 -15
  65. data/src/analyze/ternary_conditionals.c +14 -10
  66. data/src/ast/ast_nodes.c +3 -1
  67. data/src/ast/ast_pretty_print.c +5 -1
  68. data/src/extract.c +204 -143
  69. data/src/herb.c +10 -8
  70. data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
  71. data/src/include/analyze/action_view/tag_helper_node_builders.h +1 -0
  72. data/src/include/analyze/action_view/tag_helpers.h +1 -1
  73. data/src/include/analyze/analyze.h +3 -24
  74. data/src/include/analyze/analyzed_ruby.h +29 -2
  75. data/src/include/analyze/helpers.h +7 -27
  76. data/src/include/ast/ast_nodes.h +2 -1
  77. data/src/include/herb.h +3 -2
  78. data/src/include/lexer/lexer.h +1 -0
  79. data/src/include/parser/parser_options.h +5 -0
  80. data/src/include/prism/herb_prism_node.h +6 -1
  81. data/src/include/prism/prism_context.h +12 -12
  82. data/src/include/prism/prism_helpers.h +30 -0
  83. data/src/include/prism_version.h +11 -0
  84. data/src/include/version.h +1 -1
  85. data/src/lexer.c +32 -0
  86. data/src/parser/parser_helpers.c +1 -2
  87. data/src/parser.c +6 -7
  88. data/src/parser_options_defaults.c +1 -0
  89. data/src/prism/prism_helpers.c +167 -42
  90. data/src/prism/ruby_parser.c +20 -20
  91. data/templates/ext/herb/nodes.c.erb +5 -5
  92. data/templates/ext/herb/parser_options_helpers.c.erb +33 -0
  93. data/templates/java/nodes.c.erb +6 -6
  94. data/templates/java/parser_options_helpers.c.erb +41 -2
  95. data/templates/java/parser_options_helpers.h.erb +2 -1
  96. data/templates/javascript/packages/core/src/nodes.ts.erb +21 -1
  97. data/templates/javascript/packages/node/extension/nodes.cpp.erb +5 -5
  98. data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +34 -2
  99. data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +1 -1
  100. data/templates/lib/herb/parser_options.rb.erb +1 -1
  101. data/templates/rust/src/ast/nodes.rs.erb +1 -4
  102. data/templates/rust/src/prism/generated_deserialize.rs.erb +90 -44
  103. data/templates/rust/src/prism/generated_prettyprint.rs.erb +18 -27
  104. data/templates/src/analyze/action_view/generated_handlers.c.erb +23 -22
  105. data/templates/src/include/parser/parser_options.h.erb +10 -0
  106. data/templates/src/include/prism_version.h.erb +17 -0
  107. data/templates/src/parser_options_defaults.c.erb +1 -1
  108. data/templates/template.rb +17 -2
  109. data/templates/wasm/nodes.cpp.erb +8 -18
  110. data/templates/wasm/parser_options_helpers.cpp.erb +24 -0
  111. data/vendor/prism/Rakefile +76 -7
  112. data/vendor/prism/config.yml +174 -161
  113. data/vendor/prism/include/prism/arena.h +45 -0
  114. data/vendor/prism/include/prism/arena.hpp +42 -0
  115. data/vendor/prism/include/prism/ast.h +2738 -611
  116. data/vendor/prism/include/prism/ast.hpp +641 -0
  117. data/vendor/prism/include/prism/buffer.h +60 -0
  118. data/vendor/prism/include/prism/buffer.hpp +55 -0
  119. data/vendor/prism/include/prism/comments.h +72 -0
  120. data/vendor/prism/include/prism/compiler/accel.h +26 -0
  121. data/vendor/prism/include/prism/compiler/align.h +36 -0
  122. data/vendor/prism/include/prism/compiler/assume.h +25 -0
  123. data/vendor/prism/include/prism/compiler/branch.h +26 -0
  124. data/vendor/prism/include/prism/compiler/bswap.h +46 -0
  125. data/vendor/prism/include/prism/compiler/cplusplus.hpp +16 -0
  126. data/vendor/prism/include/prism/compiler/endianness.h +34 -0
  127. data/vendor/prism/include/prism/compiler/exceptions.hpp +17 -0
  128. data/vendor/prism/include/prism/compiler/exported.h +24 -0
  129. data/vendor/prism/include/prism/compiler/fallthrough.h +22 -0
  130. data/vendor/prism/include/prism/compiler/filesystem.h +32 -0
  131. data/vendor/prism/include/prism/compiler/flex_array.h +19 -0
  132. data/vendor/prism/include/prism/compiler/force_inline.h +21 -0
  133. data/vendor/prism/include/prism/compiler/format.h +27 -0
  134. data/vendor/prism/include/prism/compiler/inline.h +17 -0
  135. data/vendor/prism/include/prism/compiler/lifetimebound.hpp +25 -0
  136. data/vendor/prism/include/prism/compiler/nodiscard.h +22 -0
  137. data/vendor/prism/include/prism/compiler/nonnull.h +18 -0
  138. data/vendor/prism/include/prism/compiler/unused.h +18 -0
  139. data/vendor/prism/include/prism/constant_pool.h +106 -0
  140. data/vendor/prism/include/prism/diagnostic.h +55 -402
  141. data/vendor/prism/include/prism/errors_format.h +61 -0
  142. data/vendor/prism/include/prism/excludes.h +29 -0
  143. data/vendor/prism/include/prism/integer.h +41 -0
  144. data/vendor/prism/include/prism/internal/allocator.h +68 -0
  145. data/vendor/prism/include/prism/internal/allocator_debug.h +88 -0
  146. data/vendor/prism/include/prism/internal/arena.h +108 -0
  147. data/vendor/prism/include/prism/internal/bit.h +42 -0
  148. data/vendor/prism/include/prism/internal/buffer.h +94 -0
  149. data/vendor/prism/include/prism/internal/char.h +145 -0
  150. data/vendor/prism/include/prism/internal/comments.h +54 -0
  151. data/vendor/prism/include/prism/internal/constant_pool.h +152 -0
  152. data/vendor/prism/include/prism/internal/diagnostic.h +389 -0
  153. data/vendor/prism/include/prism/{encoding.h → internal/encoding.h} +27 -68
  154. data/vendor/prism/include/prism/internal/integer.h +68 -0
  155. data/vendor/prism/include/prism/internal/isinf.h +16 -0
  156. data/vendor/prism/include/prism/internal/line_offset_list.h +34 -0
  157. data/vendor/prism/include/prism/{util/pm_list.h → internal/list.h} +11 -52
  158. data/vendor/prism/include/prism/internal/magic_comments.h +23 -0
  159. data/vendor/prism/include/prism/internal/memchr.h +15 -0
  160. data/vendor/prism/include/prism/internal/node.h +42 -0
  161. data/vendor/prism/include/prism/internal/options.h +232 -0
  162. data/vendor/prism/include/prism/internal/parser.h +1015 -0
  163. data/vendor/prism/include/prism/internal/regexp.h +26 -0
  164. data/vendor/prism/include/prism/internal/serialize.h +39 -0
  165. data/vendor/prism/include/prism/internal/source.h +72 -0
  166. data/vendor/prism/include/prism/internal/static_literals.h +60 -0
  167. data/vendor/prism/include/prism/internal/stringy.h +30 -0
  168. data/vendor/prism/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
  169. data/vendor/prism/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
  170. data/vendor/prism/include/prism/internal/tokens.h +11 -0
  171. data/vendor/prism/include/prism/internal/xxh3.h +16 -0
  172. data/vendor/prism/include/prism/json.h +40 -0
  173. data/vendor/prism/include/prism/line_offset_list.h +69 -0
  174. data/vendor/prism/include/prism/magic_comments.h +53 -0
  175. data/vendor/prism/include/prism/node.h +59 -49
  176. data/vendor/prism/include/prism/node.hpp +272 -0
  177. data/vendor/prism/include/prism/node_type.hpp +38 -0
  178. data/vendor/prism/include/prism/options.h +154 -279
  179. data/vendor/prism/include/prism/options.hpp +43 -0
  180. data/vendor/prism/include/prism/parser.h +367 -870
  181. data/vendor/prism/include/prism/parser.hpp +274 -0
  182. data/vendor/prism/include/prism/prettyprint.h +14 -9
  183. data/vendor/prism/include/prism/serialize.h +123 -0
  184. data/vendor/prism/include/prism/source.h +163 -0
  185. data/vendor/prism/include/prism/stream.h +36 -0
  186. data/vendor/prism/include/prism/string_query.h +82 -0
  187. data/vendor/prism/include/prism/stringy.h +61 -0
  188. data/vendor/prism/include/prism/stringy.hpp +31 -0
  189. data/vendor/prism/include/prism/version.h +20 -3
  190. data/vendor/prism/include/prism.h +35 -320
  191. data/vendor/prism/include/prism.hpp +24 -0
  192. data/vendor/prism/src/arena.c +122 -0
  193. data/vendor/prism/src/{util/pm_buffer.c → buffer.c} +53 -21
  194. data/vendor/prism/src/{util/pm_char.c → char.c} +28 -57
  195. data/vendor/prism/src/comments.c +455 -0
  196. data/vendor/prism/src/constant_pool.c +406 -0
  197. data/vendor/prism/src/diagnostic.c +120 -68
  198. data/vendor/prism/src/encoding.c +8 -3
  199. data/vendor/prism/src/errors_format.c +519 -0
  200. data/vendor/prism/src/{util/pm_integer.c → integer.c} +38 -22
  201. data/vendor/prism/src/json.c +5733 -0
  202. data/vendor/prism/src/line_offset_list.c +100 -0
  203. data/vendor/prism/src/list.c +24 -0
  204. data/vendor/prism/src/{util/pm_memchr.c → memchr.c} +8 -6
  205. data/vendor/prism/src/node.c +3465 -7787
  206. data/vendor/prism/src/options.c +161 -54
  207. data/vendor/prism/src/parser.c +371 -0
  208. data/vendor/prism/src/prettyprint.c +421 -354
  209. data/vendor/prism/src/prism.c +8522 -7280
  210. data/vendor/prism/src/regexp.c +960 -45
  211. data/vendor/prism/src/serialize.c +2434 -2048
  212. data/vendor/prism/src/source.c +524 -0
  213. data/vendor/prism/src/static_literals.c +303 -360
  214. data/vendor/prism/src/string_query.c +180 -0
  215. data/vendor/prism/src/stringy.c +61 -0
  216. data/vendor/prism/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
  217. data/vendor/prism/src/strpbrk.c +447 -0
  218. data/vendor/prism/src/{token_type.c → tokens.c} +39 -18
  219. data/vendor/prism/src/xxh3.c +292 -0
  220. data/vendor/prism/templates/ext/prism/api_node.c.erb +58 -44
  221. data/vendor/prism/templates/include/prism/ast.h.erb +67 -17
  222. data/vendor/prism/templates/include/prism/ast.hpp.erb +31 -0
  223. data/vendor/prism/templates/include/prism/internal/diagnostic.h.erb +60 -0
  224. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/AbstractNodeVisitor.java.erb +1 -1
  225. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Loader.java.erb +232 -133
  226. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Nodes.java.erb +62 -23
  227. data/vendor/prism/templates/javascript/src/deserialize.js.erb +153 -146
  228. data/vendor/prism/templates/javascript/src/nodes.js.erb +4 -9
  229. data/vendor/prism/templates/lib/prism/compiler.rb.erb +14 -5
  230. data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +20 -12
  231. data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +37 -11
  232. data/vendor/prism/templates/lib/prism/dsl.rb.erb +43 -4
  233. data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +26 -10
  234. data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +5 -2
  235. data/vendor/prism/templates/lib/prism/node.rb.erb +283 -105
  236. data/vendor/prism/templates/lib/prism/reflection.rb.erb +11 -2
  237. data/vendor/prism/templates/lib/prism/serialize.rb.erb +291 -134
  238. data/vendor/prism/templates/lib/prism/visitor.rb.erb +18 -0
  239. data/vendor/prism/templates/src/diagnostic.c.erb +114 -63
  240. data/vendor/prism/templates/src/json.c.erb +130 -0
  241. data/vendor/prism/templates/src/node.c.erb +79 -236
  242. data/vendor/prism/templates/src/prettyprint.c.erb +24 -13
  243. data/vendor/prism/templates/src/serialize.c.erb +369 -183
  244. data/vendor/prism/templates/src/{token_type.c.erb → tokens.c.erb} +22 -11
  245. data/vendor/prism/templates/template.rb +193 -91
  246. metadata +100 -42
  247. data/vendor/prism/include/prism/defines.h +0 -260
  248. data/vendor/prism/include/prism/pack.h +0 -163
  249. data/vendor/prism/include/prism/regexp.h +0 -43
  250. data/vendor/prism/include/prism/static_literals.h +0 -121
  251. data/vendor/prism/include/prism/util/pm_buffer.h +0 -236
  252. data/vendor/prism/include/prism/util/pm_char.h +0 -204
  253. data/vendor/prism/include/prism/util/pm_constant_pool.h +0 -218
  254. data/vendor/prism/include/prism/util/pm_integer.h +0 -130
  255. data/vendor/prism/include/prism/util/pm_memchr.h +0 -29
  256. data/vendor/prism/include/prism/util/pm_newline_list.h +0 -113
  257. data/vendor/prism/include/prism/util/pm_string.h +0 -200
  258. data/vendor/prism/src/pack.c +0 -509
  259. data/vendor/prism/src/util/pm_constant_pool.c +0 -342
  260. data/vendor/prism/src/util/pm_list.c +0 -49
  261. data/vendor/prism/src/util/pm_newline_list.c +0 -125
  262. data/vendor/prism/src/util/pm_string.c +0 -381
  263. data/vendor/prism/src/util/pm_strpbrk.c +0 -206
  264. data/vendor/prism/templates/include/prism/diagnostic.h.erb +0 -130
  265. data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +0 -68
  266. data/vendor/prism/templates/rbi/prism/node.rbi.erb +0 -167
  267. data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +0 -18
  268. data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +0 -45
  269. data/vendor/prism/templates/sig/prism/dsl.rbs.erb +0 -31
  270. data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +0 -7
  271. data/vendor/prism/templates/sig/prism/node.rbs.erb +0 -136
  272. data/vendor/prism/templates/sig/prism/visitor.rbs.erb +0 -17
  273. data/vendor/prism/templates/sig/prism.rbs.erb +0 -92
@@ -7,9 +7,47 @@
7
7
  #include "../include/location/position.h"
8
8
 
9
9
  #include <prism.h>
10
+ #include <prism/internal/comments.h>
11
+ #include <prism/internal/parser.h>
10
12
  #include <stdlib.h>
11
13
  #include <string.h>
12
14
 
15
+ bool herb_ruby_version_supported(const char* value, size_t length) {
16
+ if (value == NULL || length == 0 || length >= HERB_PARSER_OPTIONS_STRING_CAPACITY) { return false; }
17
+
18
+ pm_options_t* options = pm_options_new();
19
+ bool supported = pm_options_version_set(options, value, length);
20
+ pm_options_free(options);
21
+
22
+ return supported;
23
+ }
24
+
25
+ void herb_prism_options_set_ruby_version(pm_options_t* options, const parser_options_T* parser_options) {
26
+ if (options == NULL || parser_options == NULL || parser_options->ruby_version[0] == '\0') { return; }
27
+
28
+ const char* version = parser_options->ruby_version;
29
+ pm_options_version_set(options, version, strnlen(version, HERB_PARSER_OPTIONS_STRING_CAPACITY));
30
+ }
31
+
32
+ pm_parser_t* herb_prism_parser_new(
33
+ pm_arena_t* arena,
34
+ const uint8_t* source,
35
+ size_t length,
36
+ const parser_options_T* parser_options
37
+ ) {
38
+ if (parser_options == NULL || parser_options->ruby_version[0] == '\0') {
39
+ return pm_parser_new(arena, source, length, NULL);
40
+ }
41
+
42
+ pm_options_t* options = pm_options_new();
43
+ herb_prism_options_set_ruby_version(options, parser_options);
44
+
45
+ pm_parser_t* parser = pm_parser_new(arena, source, length, options);
46
+ pm_options_free(options);
47
+
48
+ return parser;
49
+ }
50
+
13
51
  hb_string_T pm_error_level_to_string(pm_error_level_t level) {
14
52
  switch (level) {
15
53
  case PM_ERROR_LEVEL_SYNTAX: return hb_string("syntax");
@@ -25,16 +63,17 @@ RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error(
25
63
  pm_parser_t* parser,
26
64
  hb_allocator_T* allocator
27
65
  ) {
28
- size_t start_offset = (size_t) (error->location.start - parser->start);
29
- size_t end_offset = (size_t) (error->location.end - parser->start);
66
+ (void) parser;
30
67
 
31
- position_T start = position_from_source_with_offset(source, start_offset);
32
- position_T end = position_from_source_with_offset(source, end_offset);
68
+ pm_location_t location = pm_diagnostic_location(error);
69
+
70
+ position_T start = position_from_source_with_offset(source, location.start);
71
+ position_T end = position_from_source_with_offset(source, herb_prism_location_end(location));
33
72
 
34
73
  return ruby_parse_error_init(
35
- hb_string(error->message),
36
- hb_string(pm_diagnostic_id_human(error->diag_id)),
37
- pm_error_level_to_string(error->level),
74
+ hb_string(pm_diagnostic_message(error)),
75
+ hb_string(pm_diagnostic_type(error)),
76
+ pm_error_level_to_string(pm_diagnostic_error_level(error)),
38
77
  start,
39
78
  end,
40
79
  allocator
@@ -48,9 +87,9 @@ RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error_with_positions(
48
87
  hb_allocator_T* allocator
49
88
  ) {
50
89
  return ruby_parse_error_init(
51
- hb_string(error->message),
52
- hb_string(pm_diagnostic_id_human(error->diag_id)),
53
- pm_error_level_to_string(error->level),
90
+ hb_string(pm_diagnostic_message(error)),
91
+ hb_string(pm_diagnostic_type(error)),
92
+ pm_error_level_to_string(pm_diagnostic_error_level(error)),
54
93
  start,
55
94
  end,
56
95
  allocator
@@ -62,55 +101,51 @@ typedef struct {
62
101
  bool found;
63
102
  } then_keyword_search_context_T;
64
103
 
65
- static bool has_pm_location(pm_location_t location) {
66
- return location.start != NULL && location.end != NULL && (location.end - location.start) > 0;
67
- }
68
-
69
- static bool search_then_keyword_location(const pm_node_t* node, void* data) {
104
+ static pm_visit_result_t search_then_keyword_location(const pm_node_t* node, void* data) {
70
105
  then_keyword_search_context_T* context = (then_keyword_search_context_T*) data;
71
106
 
72
- if (context->found) { return false; }
107
+ if (context->found) { return PM_VISIT_SKIP; }
73
108
 
74
109
  switch (node->type) {
75
110
  case PM_IF_NODE: {
76
111
  const pm_if_node_t* if_node = (const pm_if_node_t*) node;
77
112
 
78
- if (!has_pm_location(if_node->if_keyword_loc)) { break; }
113
+ if (!herb_prism_location_present(if_node->if_keyword_loc)) { break; }
79
114
 
80
- if (has_pm_location(if_node->then_keyword_loc)) {
115
+ if (herb_prism_location_present(if_node->then_keyword_loc)) {
81
116
  context->then_keyword_loc = if_node->then_keyword_loc;
82
117
  context->found = true;
83
- return false;
118
+ return PM_VISIT_SKIP;
84
119
  }
85
120
  break;
86
121
  }
87
122
 
88
123
  case PM_UNLESS_NODE: {
89
124
  const pm_unless_node_t* unless_node = (const pm_unless_node_t*) node;
90
- if (has_pm_location(unless_node->then_keyword_loc)) {
125
+ if (herb_prism_location_present(unless_node->then_keyword_loc)) {
91
126
  context->then_keyword_loc = unless_node->then_keyword_loc;
92
127
  context->found = true;
93
- return false;
128
+ return PM_VISIT_SKIP;
94
129
  }
95
130
  break;
96
131
  }
97
132
 
98
133
  case PM_WHEN_NODE: {
99
134
  const pm_when_node_t* when_node = (const pm_when_node_t*) node;
100
- if (has_pm_location(when_node->then_keyword_loc)) {
135
+ if (herb_prism_location_present(when_node->then_keyword_loc)) {
101
136
  context->then_keyword_loc = when_node->then_keyword_loc;
102
137
  context->found = true;
103
- return false;
138
+ return PM_VISIT_SKIP;
104
139
  }
105
140
  break;
106
141
  }
107
142
 
108
143
  case PM_IN_NODE: {
109
144
  const pm_in_node_t* in_node = (const pm_in_node_t*) node;
110
- if (has_pm_location(in_node->then_loc)) {
111
- context->then_keyword_loc = in_node->then_loc;
145
+ if (herb_prism_location_present(in_node->then_keyword_loc)) {
146
+ context->then_keyword_loc = in_node->then_keyword_loc;
112
147
  context->found = true;
113
- return false;
148
+ return PM_VISIT_SKIP;
114
149
  }
115
150
  break;
116
151
  }
@@ -120,23 +155,20 @@ static bool search_then_keyword_location(const pm_node_t* node, void* data) {
120
155
 
121
156
  pm_visit_child_nodes(node, search_then_keyword_location, context);
122
157
 
123
- return false;
158
+ return PM_VISIT_SKIP;
124
159
  }
125
160
 
126
161
  location_T* get_then_keyword_location(analyzed_ruby_T* analyzed, const char* source, hb_allocator_T* allocator) {
127
162
  if (analyzed == NULL || analyzed->root == NULL || source == NULL) { return NULL; }
128
163
 
129
- then_keyword_search_context_T context = { .then_keyword_loc = { .start = NULL, .end = NULL }, .found = false };
164
+ then_keyword_search_context_T context = { .then_keyword_loc = { .start = 0, .length = 0 }, .found = false };
130
165
 
131
166
  pm_visit_child_nodes(analyzed->root, search_then_keyword_location, &context);
132
167
 
133
168
  if (!context.found) { return NULL; }
134
169
 
135
- size_t start_offset = (size_t) (context.then_keyword_loc.start - analyzed->parser.start);
136
- size_t end_offset = (size_t) (context.then_keyword_loc.end - analyzed->parser.start);
137
-
138
- position_T start_position = position_from_source_with_offset(source, start_offset);
139
- position_T end_position = position_from_source_with_offset(source, end_offset);
170
+ position_T start_position = position_from_source_with_offset(source, context.then_keyword_loc.start);
171
+ position_T end_position = position_from_source_with_offset(source, herb_prism_location_end(context.then_keyword_loc));
140
172
 
141
173
  return location_create(start_position, end_position, allocator);
142
174
  }
@@ -150,25 +182,26 @@ static location_T* parse_wrapped_and_find_then_keyword(
150
182
  size_t adjustment_amount,
151
183
  hb_allocator_T* allocator
152
184
  ) {
153
- pm_parser_t parser;
154
- pm_parser_init(&parser, (const uint8_t*) hb_buffer_value(buffer), hb_buffer_length(buffer), NULL);
155
- pm_node_t* root = pm_parse(&parser);
185
+ pm_arena_t* arena = pm_arena_new();
186
+ pm_parser_t* parser = pm_parser_new(arena, (const uint8_t*) hb_buffer_value(buffer), hb_buffer_length(buffer), NULL);
187
+ pm_node_t* root = pm_parse(parser);
156
188
 
157
189
  if (root == NULL) {
158
- pm_parser_free(&parser);
190
+ pm_parser_free(parser);
191
+ pm_arena_free(arena);
159
192
 
160
193
  return NULL;
161
194
  }
162
195
 
163
- then_keyword_search_context_T context = { .then_keyword_loc = { .start = NULL, .end = NULL }, .found = false };
196
+ then_keyword_search_context_T context = { .then_keyword_loc = { .start = 0, .length = 0 }, .found = false };
164
197
 
165
198
  pm_visit_child_nodes(root, search_then_keyword_location, &context);
166
199
 
167
200
  location_T* location = NULL;
168
201
 
169
202
  if (context.found) {
170
- size_t start_offset = (size_t) (context.then_keyword_loc.start - parser.start);
171
- size_t end_offset = (size_t) (context.then_keyword_loc.end - parser.start);
203
+ size_t start_offset = context.then_keyword_loc.start;
204
+ size_t end_offset = herb_prism_location_end(context.then_keyword_loc);
172
205
 
173
206
  if (start_offset >= prefix_length && end_offset >= prefix_length) {
174
207
  start_offset -= prefix_length;
@@ -188,8 +221,8 @@ static location_T* parse_wrapped_and_find_then_keyword(
188
221
  }
189
222
  }
190
223
 
191
- pm_node_destroy(&parser, root);
192
- pm_parser_free(&parser);
224
+ pm_parser_free(parser);
225
+ pm_arena_free(arena);
193
226
 
194
227
  return location;
195
228
  }
@@ -244,3 +277,95 @@ location_T* get_then_keyword_location_elsif_wrapped(const char* source, hb_alloc
244
277
 
245
278
  return location;
246
279
  }
280
+
281
+ static size_t newline_index_for_offset(const pm_line_offset_list_t* newlines, size_t offset) {
282
+ size_t low = 0;
283
+ size_t high = newlines->size;
284
+
285
+ while (low < high) {
286
+ size_t middle = low + (high - low) / 2;
287
+
288
+ if (newlines->offsets[middle] <= offset) {
289
+ low = middle + 1;
290
+ } else {
291
+ high = middle;
292
+ }
293
+ }
294
+
295
+ return low > 0 ? low - 1 : 0;
296
+ }
297
+
298
+ void herb_prism_node_serialize(herb_prism_node_T prism_node, pm_buffer_t* buffer) {
299
+ if (!prism_node.node || !prism_node.parser) { return; }
300
+
301
+ pm_parser_t* parser = prism_node.parser;
302
+
303
+ if (prism_node.source_end == 0 || parser->line_offsets.size == 0) {
304
+ pm_serialize(parser, prism_node.node, buffer);
305
+ return;
306
+ }
307
+
308
+ const pm_line_offset_list_t* newlines = &parser->line_offsets;
309
+ size_t first_line = newline_index_for_offset(newlines, prism_node.source_start);
310
+ size_t last_line = newline_index_for_offset(newlines, prism_node.source_end);
311
+ size_t line_count = last_line - first_line + 1;
312
+
313
+ if (last_line + 1 < newlines->size) { line_count++; }
314
+
315
+ pm_parser_t view = *parser;
316
+
317
+ view.line_offsets.offsets = newlines->offsets + first_line;
318
+ view.line_offsets.size = line_count;
319
+ view.line_offsets.capacity = line_count;
320
+ view.start_line = parser->start_line + (int32_t) first_line;
321
+
322
+ memset(&view.magic_comment_list, 0, sizeof(pm_list_t));
323
+ memset(&view.error_list, 0, sizeof(pm_list_t));
324
+ memset(&view.warning_list, 0, sizeof(pm_list_t));
325
+ memset(&view.comment_list, 0, sizeof(pm_list_t));
326
+ memset(&view.comment_attachments, 0, sizeof(view.comment_attachments));
327
+
328
+ size_t comment_count = 0;
329
+
330
+ for (pm_list_node_t* entry = parser->comment_list.head; entry; entry = entry->next) {
331
+ pm_comment_t* comment = (pm_comment_t*) entry;
332
+ size_t start = comment->location.start;
333
+
334
+ if (start >= prism_node.source_start && start < prism_node.source_end) { comment_count++; }
335
+ }
336
+
337
+ pm_comment_t* comments = NULL;
338
+
339
+ if (comment_count > 0) {
340
+ comments = malloc(comment_count * sizeof(pm_comment_t));
341
+
342
+ if (!comments) {
343
+ pm_serialize(parser, prism_node.node, buffer);
344
+ return;
345
+ }
346
+
347
+ size_t index = 0;
348
+
349
+ for (pm_list_node_t* entry = parser->comment_list.head; entry; entry = entry->next) {
350
+ pm_comment_t* comment = (pm_comment_t*) entry;
351
+ size_t start = comment->location.start;
352
+
353
+ if (start < prism_node.source_start || start >= prism_node.source_end) { continue; }
354
+
355
+ comments[index] = *comment;
356
+ comments[index].node.next = NULL;
357
+
358
+ if (index > 0) { comments[index - 1].node.next = &comments[index].node; }
359
+
360
+ index++;
361
+ }
362
+
363
+ view.comment_list.size = comment_count;
364
+ view.comment_list.head = &comments[0].node;
365
+ view.comment_list.tail = &comments[comment_count - 1].node;
366
+ }
367
+
368
+ pm_serialize(&view, prism_node.node, buffer);
369
+
370
+ free(comments);
371
+ }
@@ -2,51 +2,51 @@
2
2
 
3
3
  #include <prism.h>
4
4
  #include <stdbool.h>
5
+ #include <stdio.h>
5
6
  #include <stdlib.h>
6
7
  #include <string.h>
7
8
 
8
- static bool herb_prism_visit(const pm_node_t* node, void* data) {
9
+ static pm_visit_result_t herb_prism_visit(const pm_node_t* node, void* data) {
9
10
  const size_t* indent = (size_t*) data;
10
11
 
11
12
  for (size_t i = 0; i < *indent * 2; i++) {
12
13
  putc(' ', stdout);
13
14
  }
14
15
 
15
- printf("%s\n", pm_node_type_to_str(node->type));
16
+ printf("%s\n", pm_node_type(node->type));
16
17
 
17
18
  size_t next_indent = *indent + 1;
18
19
  size_t* next_data = &next_indent;
19
20
  pm_visit_child_nodes(node, herb_prism_visit, next_data);
20
21
 
21
- return false;
22
+ return PM_VISIT_SKIP;
22
23
  }
23
24
 
24
25
  void herb_parse_ruby_to_stdout(char* source) {
25
26
  size_t length = strlen(source);
26
27
 
27
- pm_parser_t parser;
28
- pm_parser_init(&parser, (const uint8_t*) source, length, NULL);
28
+ pm_arena_t* arena = pm_arena_new();
29
+ pm_parser_t* parser = pm_parser_new(arena, (const uint8_t*) source, length, NULL);
29
30
 
30
- pm_buffer_t buffer;
31
- pm_buffer_init(&buffer);
31
+ pm_buffer_t* buffer = pm_buffer_new();
32
32
 
33
33
  size_t indent = 0;
34
- pm_node_t* root = pm_parse(&parser);
34
+ pm_node_t* root = pm_parse(parser);
35
35
  size_t* data = &indent;
36
36
 
37
- const char* root_type = pm_node_type_to_str(root->type);
37
+ const char* root_type = pm_node_type(root->type);
38
38
  printf("Root Type: %s\n", root_type);
39
39
 
40
40
  pm_visit_node(root, herb_prism_visit, data);
41
41
 
42
42
  #ifndef PRISM_EXCLUDE_PRETTYPRINT
43
- pm_prettyprint(&buffer, &parser, root);
44
- printf("%s\n", buffer.value);
43
+ pm_prettyprint(buffer, parser, root);
44
+ printf("%.*s\n", (int) pm_buffer_length(buffer), pm_buffer_value(buffer));
45
45
  #endif
46
46
 
47
- pm_buffer_free(&buffer);
48
- pm_node_destroy(&parser, root);
49
- pm_parser_free(&parser);
47
+ pm_buffer_free(buffer);
48
+ pm_parser_free(parser);
49
+ pm_arena_free(arena);
50
50
  }
51
51
 
52
52
  static const char* const RUBY_FRAGMENT_PREFIXES[] = {
@@ -56,14 +56,14 @@ static const char* const RUBY_FRAGMENT_PREFIXES[] = {
56
56
  static const char* const RUBY_FRAGMENT_SUFFIXES[] = { "", "\nend", "", "\nend", "\nend", "\nend" };
57
57
 
58
58
  static bool ruby_source_parses(const char* source, size_t length) {
59
- pm_parser_t parser;
60
- pm_parser_init(&parser, (const uint8_t*) source, length, NULL);
59
+ pm_arena_t* arena = pm_arena_new();
60
+ pm_parser_t* parser = pm_parser_new(arena, (const uint8_t*) source, length, NULL);
61
61
 
62
- pm_node_t* root = pm_parse(&parser);
63
- bool parses = (parser.error_list.size == 0);
62
+ pm_parse(parser);
63
+ bool parses = (pm_parser_errors_size(parser) == 0);
64
64
 
65
- if (root != NULL) { pm_node_destroy(&parser, root); }
66
- pm_parser_free(&parser);
65
+ pm_parser_free(parser);
66
+ pm_arena_free(arena);
67
67
 
68
68
  return parses;
69
69
  }
@@ -69,17 +69,17 @@ static VALUE rb_<%= node.human %>_from_c_struct(<%= node.struct_type %>* <%= nod
69
69
  <%- when Herb::Template::PrismNodeField -%>
70
70
  VALUE <%= node.human %>_<%= field.name %>;
71
71
  if (<%= node.human %>-><%= field.name %>.node != NULL && <%= node.human %>-><%= field.name %>.parser != NULL) {
72
- pm_buffer_t pm_buffer = { 0 };
73
- pm_serialize(<%= node.human %>-><%= field.name %>.parser, <%= node.human %>-><%= field.name %>.node, &pm_buffer);
72
+ pm_buffer_t* pm_buffer = pm_buffer_new();
73
+ herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, pm_buffer);
74
74
 
75
- if (pm_buffer.length > 0) {
76
- <%= node.human %>_<%= field.name %> = rb_str_new(pm_buffer.value, pm_buffer.length);
75
+ if (pm_buffer_length(pm_buffer) > 0) {
76
+ <%= node.human %>_<%= field.name %> = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
77
77
  rb_enc_associate(<%= node.human %>_<%= field.name %>, rb_ascii8bit_encoding());
78
78
  OBJ_FREEZE(<%= node.human %>_<%= field.name %>);
79
79
  } else {
80
80
  <%= node.human %>_<%= field.name %> = Qnil;
81
81
  }
82
- pm_buffer_free(&pm_buffer);
82
+ pm_buffer_free(pm_buffer);
83
83
  } else {
84
84
  <%= node.human %>_<%= field.name %> = Qnil;
85
85
  }
@@ -1,5 +1,7 @@
1
1
  #include "parser_options_helpers.h"
2
2
 
3
+ #include <string.h>
4
+
3
5
  void herb_extract_parser_options(VALUE options, parser_options_T* parser_options) {
4
6
  if (NIL_P(options)) { return; }
5
7
  <%- parser_options.extractable_fields_for(:ruby).each do |field| -%>
@@ -10,6 +12,31 @@ void herb_extract_parser_options(VALUE options, parser_options_T* parser_options
10
12
  if (NIL_P(value)) { value = rb_hash_lookup(options, ID2SYM(rb_intern("<%= field.snake_case %>"))); }
11
13
  if (!NIL_P(value)) { parser_options-><%= field.c_name %> = RTEST(value); }
12
14
  }
15
+ <%- elsif field.string? -%>
16
+ {
17
+ VALUE value = rb_hash_lookup(options, rb_utf8_str_new_cstr("<%= field.snake_case %>"));
18
+ if (NIL_P(value)) { value = rb_hash_lookup(options, ID2SYM(rb_intern("<%= field.snake_case %>"))); }
19
+
20
+ if (!NIL_P(value)) {
21
+ Check_Type(value, T_STRING);
22
+
23
+ const char* data = RSTRING_PTR(value);
24
+ size_t length = (size_t) RSTRING_LEN(value);
25
+
26
+ <%- if field.validator -%>
27
+ if (!<%= field.validator %>(data, length)) {
28
+ rb_raise(rb_eArgError, "<%= field.snake_case %> %+" PRIsVALUE " is not supported", value);
29
+ }
30
+ <%- else -%>
31
+ if (length >= HERB_PARSER_OPTIONS_STRING_CAPACITY) {
32
+ rb_raise(rb_eArgError, "<%= field.snake_case %> must be shorter than %d bytes", HERB_PARSER_OPTIONS_STRING_CAPACITY);
33
+ }
34
+ <%- end -%>
35
+
36
+ memcpy(parser_options-><%= field.c_name %>, data, length);
37
+ parser_options-><%= field.c_name %>[length] = '\0';
38
+ }
39
+ }
13
40
  <%- elsif field.ruby_unit == "seconds" -%>
14
41
  {
15
42
  VALUE value = rb_hash_lookup(options, rb_utf8_str_new_cstr("<%= field.snake_case %>"));
@@ -52,6 +79,12 @@ VALUE herb_build_parser_options_hash(const parser_options_T* options) {
52
79
 
53
80
  rb_hash_aset(kwargs, ID2SYM(rb_intern("<%= field.snake_case %>")), <%= field.snake_case %>);
54
81
  }
82
+ <%- elsif field.string? -%>
83
+ rb_hash_aset(
84
+ kwargs,
85
+ ID2SYM(rb_intern("<%= field.snake_case %>")),
86
+ options-><%= field.c_name %>[0] == '\0' ? Qnil : rb_utf8_str_new_cstr(options-><%= field.c_name %>)
87
+ );
55
88
  <%- elsif field.ruby_unit == "seconds" -%>
56
89
  rb_hash_aset(kwargs, ID2SYM(rb_intern("<%= field.snake_case %>")), DBL2NUM((double) options-><%= field.c_name %> / 1000.0));
57
90
  <%- elsif field.nullable? -%>
@@ -49,15 +49,15 @@ jobject <%= node.name %>FromCStruct(JNIEnv* env, <%= node.struct_type %>* <%= no
49
49
  <%- elsif field.is_a?(Herb::Template::PrismNodeField) -%>
50
50
  jbyteArray <%= field.name %>;
51
51
  if (<%= node.human %>-><%= field.name %>.node != NULL && <%= node.human %>-><%= field.name %>.parser != NULL) {
52
- pm_buffer_t pm_buffer = { 0 };
53
- pm_serialize(<%= node.human %>-><%= field.name %>.parser, <%= node.human %>-><%= field.name %>.node, &pm_buffer);
54
- if (pm_buffer.length > 0) {
55
- <%= field.name %> = (*env)->NewByteArray(env, (jsize)pm_buffer.length);
56
- (*env)->SetByteArrayRegion(env, <%= field.name %>, 0, (jsize)pm_buffer.length, (const jbyte*)pm_buffer.value);
52
+ pm_buffer_t* pm_buffer = pm_buffer_new();
53
+ herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, pm_buffer);
54
+ if (pm_buffer_length(pm_buffer) > 0) {
55
+ <%= field.name %> = (*env)->NewByteArray(env, (jsize)pm_buffer_length(pm_buffer));
56
+ (*env)->SetByteArrayRegion(env, <%= field.name %>, 0, (jsize)pm_buffer_length(pm_buffer), (const jbyte*)pm_buffer_value(pm_buffer));
57
57
  } else {
58
58
  <%= field.name %> = NULL;
59
59
  }
60
- pm_buffer_free(&pm_buffer);
60
+ pm_buffer_free(pm_buffer);
61
61
  } else {
62
62
  <%= field.name %> = NULL;
63
63
  }
@@ -1,7 +1,10 @@
1
1
  #include "parser_options_helpers.h"
2
2
 
3
- void herb_extract_parser_options(JNIEnv* env, jobject options, parser_options_T* parser_options) {
4
- if (options == NULL) { return; }
3
+ #include <stdio.h>
4
+ #include <string.h>
5
+
6
+ bool herb_extract_parser_options(JNIEnv* env, jobject options, parser_options_T* parser_options) {
7
+ if (options == NULL) { return true; }
5
8
 
6
9
  jclass optionsClass = (*env)->GetObjectClass(env, options);
7
10
  <%- parser_options.extractable_fields_for(:java).each do |field| -%>
@@ -15,6 +18,40 @@ void herb_extract_parser_options(JNIEnv* env, jobject options, parser_options_T*
15
18
  parser_options-><%= field.c_name %> = (value == JNI_TRUE);
16
19
  }
17
20
  }
21
+ <%- elsif field.string? -%>
22
+ {
23
+ jmethodID method = (*env)->GetMethodID(env, optionsClass, "<%= field.java_getter %>", "<%= field.java_jni_signature %>");
24
+
25
+ if (method != NULL) {
26
+ jstring value = (jstring) (*env)->CallObjectMethod(env, options, method);
27
+
28
+ if (value != NULL) {
29
+ const char* string = (*env)->GetStringUTFChars(env, value, NULL);
30
+ size_t length = strlen(string);
31
+
32
+ <%- if field.validator -%>
33
+ if (!<%= field.validator %>(string, length)) {
34
+ char message[96];
35
+ snprintf(message, sizeof(message), "<%= field.snake_case %> \"%.32s\" is not supported", string);
36
+ (*env)->ReleaseStringUTFChars(env, value, string);
37
+ (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/IllegalArgumentException"), message);
38
+
39
+ return false;
40
+ }
41
+ <%- else -%>
42
+ if (length >= HERB_PARSER_OPTIONS_STRING_CAPACITY) {
43
+ (*env)->ReleaseStringUTFChars(env, value, string);
44
+ (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/IllegalArgumentException"), "<%= field.snake_case %> is too long");
45
+
46
+ return false;
47
+ }
48
+ <%- end -%>
49
+
50
+ memcpy(parser_options-><%= field.c_name %>, string, length + 1);
51
+ (*env)->ReleaseStringUTFChars(env, value, string);
52
+ }
53
+ }
54
+ }
18
55
  <%- elsif field.nullable? -%>
19
56
  {
20
57
  jmethodID method = (*env)->GetMethodID(env, optionsClass, "<%= field.java_getter %>", "<%= field.java_jni_signature %>");
@@ -42,4 +79,6 @@ void herb_extract_parser_options(JNIEnv* env, jobject options, parser_options_T*
42
79
  }
43
80
  <%- end -%>
44
81
  <%- end -%>
82
+
83
+ return true;
45
84
  }
@@ -4,7 +4,8 @@
4
4
  #include "../src/include/parser/parser_options.h"
5
5
 
6
6
  #include <jni.h>
7
+ #include <stdbool.h>
7
8
 
8
- void herb_extract_parser_options(JNIEnv* env, jobject options, parser_options_T* parser_options);
9
+ bool herb_extract_parser_options(JNIEnv* env, jobject options, parser_options_T* parser_options);
9
10
 
10
11
  #endif
@@ -13,6 +13,26 @@ import type { LocateResult } from "./locate.js"
13
13
 
14
14
  export type SerializedNodeType = string
15
15
 
16
+ type PrismNodeCacheEntry = {
17
+ bytes: Uint8Array
18
+ source: string
19
+ node: PrismNode | null
20
+ }
21
+
22
+ const prismNodeCache = new WeakMap<Node, PrismNodeCacheEntry>()
23
+
24
+ function cachedPrismNode(owner: Node, bytes: Uint8Array, source: string): PrismNode | null {
25
+ const cached = prismNodeCache.get(owner)
26
+
27
+ if (cached && cached.bytes === bytes && cached.source === source) return cached.node
28
+
29
+ const node = deserializePrismNode(bytes, source)
30
+
31
+ prismNodeCache.set(owner, { bytes, source, node })
32
+
33
+ return node
34
+ }
35
+
16
36
  export interface SerializedNode {
17
37
  type: SerializedNodeType
18
38
  location: SerializedLocation
@@ -388,7 +408,7 @@ export class <%= node.name %> extends Node {
388
408
  <%- prism_field = node.fields.find { |f| f.is_a?(Herb::Template::PrismSerializedField) || f.is_a?(Herb::Template::PrismNodeField) } -%>
389
409
  get prismNode(): PrismNode | null {
390
410
  if (!this.<%= prism_field.name %> || !this.source) return null;
391
- return deserializePrismNode(this.<%= prism_field.name %>, this.source);
411
+ return cachedPrismNode(this, this.<%= prism_field.name %>, this.source);
392
412
  }
393
413
  <%- end -%>
394
414
 
@@ -89,17 +89,17 @@ napi_value <%= node.human %>NodeFromCStruct(napi_env env, <%= node.struct_type %
89
89
  <%- when Herb::Template::PrismNodeField -%>
90
90
  napi_value <%= field.name %>;
91
91
  if (<%= node.human %>-><%= field.name %>.node != NULL && <%= node.human %>-><%= field.name %>.parser != NULL) {
92
- pm_buffer_t pm_buffer = { 0 };
93
- pm_serialize(<%= node.human %>-><%= field.name %>.parser, <%= node.human %>-><%= field.name %>.node, &pm_buffer);
92
+ pm_buffer_t* pm_buffer = pm_buffer_new();
93
+ herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, pm_buffer);
94
94
 
95
- if (pm_buffer.length > 0) {
95
+ if (pm_buffer_length(pm_buffer) > 0) {
96
96
  void* buffer_data;
97
- napi_create_buffer_copy(env, pm_buffer.length, pm_buffer.value, &buffer_data, &<%= field.name %>);
97
+ napi_create_buffer_copy(env, pm_buffer_length(pm_buffer), pm_buffer_value(pm_buffer), &buffer_data, &<%= field.name %>);
98
98
  } else {
99
99
  napi_get_null(env, &<%= field.name %>);
100
100
  }
101
101
 
102
- pm_buffer_free(&pm_buffer);
102
+ pm_buffer_free(pm_buffer);
103
103
  } else {
104
104
  napi_get_null(env, &<%= field.name %>);
105
105
  }