herb 0.11.1-x86-linux-gnu → 0.11.2-x86-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 (251) 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/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/configuration.rb +11 -1
  15. data/lib/herb/dev/classifier.rb +1 -1
  16. data/lib/herb/engine/compiler.rb +5 -8
  17. data/lib/herb/engine/slots/dynamics_compiler.rb +53 -14
  18. data/lib/herb/engine/slots/subtree_compiler.rb +1 -1
  19. data/lib/herb/engine/slots/visitor.rb +32 -4
  20. data/lib/herb/engine/visitors/instrumentation_visitor.rb +18 -6
  21. data/lib/herb/parser_options.rb +6 -3
  22. data/lib/herb/project.rb +19 -8
  23. data/lib/herb/version.rb +1 -1
  24. data/lib/herb.rb +1 -1
  25. data/sig/herb/analysis/partial_resolution.rbs +8 -0
  26. data/sig/herb/configuration.rbs +3 -0
  27. data/sig/herb/engine/slots/dynamics_compiler.rbs +24 -7
  28. data/sig/herb/engine/slots/visitor.rbs +14 -0
  29. data/sig/herb/engine/visitors/instrumentation_visitor.rbs +5 -1
  30. data/sig/herb/parser_options.rbs +6 -4
  31. data/sig/herb.rbs +2 -2
  32. data/src/analyze/action_view/attribute_extraction_helpers.c +40 -21
  33. data/src/analyze/action_view/generated_handlers.c +36 -36
  34. data/src/analyze/action_view/image_tag.c +7 -3
  35. data/src/analyze/action_view/javascript_include_tag.c +6 -3
  36. data/src/analyze/action_view/link_to.c +23 -23
  37. data/src/analyze/action_view/registry.c +7 -3
  38. data/src/analyze/action_view/tag_helper_node_builders.c +6 -13
  39. data/src/analyze/action_view/tag_helpers.c +139 -90
  40. data/src/analyze/action_view/turbo_frame_tag.c +5 -4
  41. data/src/analyze/analyze.c +35 -19
  42. data/src/analyze/analyze_helpers.c +161 -188
  43. data/src/analyze/analyzed_ruby.c +8 -7
  44. data/src/analyze/control_type.c +29 -22
  45. data/src/analyze/herb_directives.c +16 -20
  46. data/src/analyze/iteration_nodes.c +69 -24
  47. data/src/analyze/parse_errors.c +32 -22
  48. data/src/analyze/postfix_conditionals.c +23 -13
  49. data/src/analyze/prism_annotate.c +29 -28
  50. data/src/analyze/render_nodes.c +51 -41
  51. data/src/analyze/strict_locals.c +14 -15
  52. data/src/analyze/ternary_conditionals.c +14 -10
  53. data/src/herb.c +10 -8
  54. data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
  55. data/src/include/analyze/action_view/tag_helper_node_builders.h +1 -0
  56. data/src/include/analyze/action_view/tag_helpers.h +1 -1
  57. data/src/include/analyze/analyze.h +3 -2
  58. data/src/include/analyze/analyzed_ruby.h +4 -2
  59. data/src/include/analyze/helpers.h +6 -6
  60. data/src/include/herb.h +3 -2
  61. data/src/include/parser/parser_options.h +5 -0
  62. data/src/include/prism/prism_context.h +12 -12
  63. data/src/include/prism/prism_helpers.h +30 -0
  64. data/src/include/prism_version.h +11 -0
  65. data/src/include/version.h +1 -1
  66. data/src/parser/parser_helpers.c +1 -2
  67. data/src/parser.c +6 -7
  68. data/src/parser_options_defaults.c +1 -0
  69. data/src/prism/prism_helpers.c +84 -50
  70. data/src/prism/ruby_parser.c +20 -20
  71. data/templates/ext/herb/nodes.c.erb +5 -5
  72. data/templates/ext/herb/parser_options_helpers.c.erb +33 -0
  73. data/templates/java/nodes.c.erb +6 -6
  74. data/templates/java/parser_options_helpers.c.erb +41 -2
  75. data/templates/java/parser_options_helpers.h.erb +2 -1
  76. data/templates/javascript/packages/node/extension/nodes.cpp.erb +5 -5
  77. data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +34 -2
  78. data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +1 -1
  79. data/templates/lib/herb/parser_options.rb.erb +1 -1
  80. data/templates/rust/src/prism/generated_deserialize.rs.erb +90 -44
  81. data/templates/rust/src/prism/generated_prettyprint.rs.erb +18 -27
  82. data/templates/src/analyze/action_view/generated_handlers.c.erb +23 -22
  83. data/templates/src/include/parser/parser_options.h.erb +10 -0
  84. data/templates/src/include/prism_version.h.erb +17 -0
  85. data/templates/src/parser_options_defaults.c.erb +1 -1
  86. data/templates/template.rb +17 -2
  87. data/templates/wasm/nodes.cpp.erb +5 -5
  88. data/templates/wasm/parser_options_helpers.cpp.erb +24 -0
  89. data/vendor/prism/Rakefile +76 -7
  90. data/vendor/prism/config.yml +174 -161
  91. data/vendor/prism/include/prism/arena.h +45 -0
  92. data/vendor/prism/include/prism/arena.hpp +42 -0
  93. data/vendor/prism/include/prism/ast.h +2738 -611
  94. data/vendor/prism/include/prism/ast.hpp +641 -0
  95. data/vendor/prism/include/prism/buffer.h +60 -0
  96. data/vendor/prism/include/prism/buffer.hpp +55 -0
  97. data/vendor/prism/include/prism/comments.h +72 -0
  98. data/vendor/prism/include/prism/compiler/accel.h +26 -0
  99. data/vendor/prism/include/prism/compiler/align.h +36 -0
  100. data/vendor/prism/include/prism/compiler/assume.h +25 -0
  101. data/vendor/prism/include/prism/compiler/branch.h +26 -0
  102. data/vendor/prism/include/prism/compiler/bswap.h +46 -0
  103. data/vendor/prism/include/prism/compiler/cplusplus.hpp +16 -0
  104. data/vendor/prism/include/prism/compiler/endianness.h +34 -0
  105. data/vendor/prism/include/prism/compiler/exceptions.hpp +17 -0
  106. data/vendor/prism/include/prism/compiler/exported.h +24 -0
  107. data/vendor/prism/include/prism/compiler/fallthrough.h +22 -0
  108. data/vendor/prism/include/prism/compiler/filesystem.h +32 -0
  109. data/vendor/prism/include/prism/compiler/flex_array.h +19 -0
  110. data/vendor/prism/include/prism/compiler/force_inline.h +21 -0
  111. data/vendor/prism/include/prism/compiler/format.h +27 -0
  112. data/vendor/prism/include/prism/compiler/inline.h +17 -0
  113. data/vendor/prism/include/prism/compiler/lifetimebound.hpp +25 -0
  114. data/vendor/prism/include/prism/compiler/nodiscard.h +22 -0
  115. data/vendor/prism/include/prism/compiler/nonnull.h +18 -0
  116. data/vendor/prism/include/prism/compiler/unused.h +18 -0
  117. data/vendor/prism/include/prism/constant_pool.h +106 -0
  118. data/vendor/prism/include/prism/diagnostic.h +55 -402
  119. data/vendor/prism/include/prism/errors_format.h +61 -0
  120. data/vendor/prism/include/prism/excludes.h +29 -0
  121. data/vendor/prism/include/prism/integer.h +41 -0
  122. data/vendor/prism/include/prism/internal/allocator.h +68 -0
  123. data/vendor/prism/include/prism/internal/allocator_debug.h +88 -0
  124. data/vendor/prism/include/prism/internal/arena.h +108 -0
  125. data/vendor/prism/include/prism/internal/bit.h +42 -0
  126. data/vendor/prism/include/prism/internal/buffer.h +94 -0
  127. data/vendor/prism/include/prism/internal/char.h +145 -0
  128. data/vendor/prism/include/prism/internal/comments.h +54 -0
  129. data/vendor/prism/include/prism/internal/constant_pool.h +152 -0
  130. data/vendor/prism/include/prism/internal/diagnostic.h +389 -0
  131. data/vendor/prism/include/prism/{encoding.h → internal/encoding.h} +27 -68
  132. data/vendor/prism/include/prism/internal/integer.h +68 -0
  133. data/vendor/prism/include/prism/internal/isinf.h +16 -0
  134. data/vendor/prism/include/prism/internal/line_offset_list.h +34 -0
  135. data/vendor/prism/include/prism/{util/pm_list.h → internal/list.h} +11 -52
  136. data/vendor/prism/include/prism/internal/magic_comments.h +23 -0
  137. data/vendor/prism/include/prism/internal/memchr.h +15 -0
  138. data/vendor/prism/include/prism/internal/node.h +42 -0
  139. data/vendor/prism/include/prism/internal/options.h +232 -0
  140. data/vendor/prism/include/prism/internal/parser.h +1015 -0
  141. data/vendor/prism/include/prism/internal/regexp.h +26 -0
  142. data/vendor/prism/include/prism/internal/serialize.h +39 -0
  143. data/vendor/prism/include/prism/internal/source.h +72 -0
  144. data/vendor/prism/include/prism/internal/static_literals.h +60 -0
  145. data/vendor/prism/include/prism/internal/stringy.h +30 -0
  146. data/vendor/prism/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
  147. data/vendor/prism/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
  148. data/vendor/prism/include/prism/internal/tokens.h +11 -0
  149. data/vendor/prism/include/prism/internal/xxh3.h +16 -0
  150. data/vendor/prism/include/prism/json.h +40 -0
  151. data/vendor/prism/include/prism/line_offset_list.h +69 -0
  152. data/vendor/prism/include/prism/magic_comments.h +53 -0
  153. data/vendor/prism/include/prism/node.h +59 -49
  154. data/vendor/prism/include/prism/node.hpp +272 -0
  155. data/vendor/prism/include/prism/node_type.hpp +38 -0
  156. data/vendor/prism/include/prism/options.h +154 -279
  157. data/vendor/prism/include/prism/options.hpp +43 -0
  158. data/vendor/prism/include/prism/parser.h +367 -870
  159. data/vendor/prism/include/prism/parser.hpp +274 -0
  160. data/vendor/prism/include/prism/prettyprint.h +14 -9
  161. data/vendor/prism/include/prism/serialize.h +123 -0
  162. data/vendor/prism/include/prism/source.h +163 -0
  163. data/vendor/prism/include/prism/stream.h +36 -0
  164. data/vendor/prism/include/prism/string_query.h +82 -0
  165. data/vendor/prism/include/prism/stringy.h +61 -0
  166. data/vendor/prism/include/prism/stringy.hpp +31 -0
  167. data/vendor/prism/include/prism/version.h +20 -3
  168. data/vendor/prism/include/prism.h +35 -320
  169. data/vendor/prism/include/prism.hpp +24 -0
  170. data/vendor/prism/src/arena.c +122 -0
  171. data/vendor/prism/src/{util/pm_buffer.c → buffer.c} +53 -21
  172. data/vendor/prism/src/{util/pm_char.c → char.c} +28 -57
  173. data/vendor/prism/src/comments.c +455 -0
  174. data/vendor/prism/src/constant_pool.c +406 -0
  175. data/vendor/prism/src/diagnostic.c +120 -68
  176. data/vendor/prism/src/encoding.c +8 -3
  177. data/vendor/prism/src/errors_format.c +519 -0
  178. data/vendor/prism/src/{util/pm_integer.c → integer.c} +38 -22
  179. data/vendor/prism/src/json.c +5733 -0
  180. data/vendor/prism/src/line_offset_list.c +100 -0
  181. data/vendor/prism/src/list.c +24 -0
  182. data/vendor/prism/src/{util/pm_memchr.c → memchr.c} +8 -6
  183. data/vendor/prism/src/node.c +3465 -7787
  184. data/vendor/prism/src/options.c +161 -54
  185. data/vendor/prism/src/parser.c +371 -0
  186. data/vendor/prism/src/prettyprint.c +421 -354
  187. data/vendor/prism/src/prism.c +8522 -7280
  188. data/vendor/prism/src/regexp.c +960 -45
  189. data/vendor/prism/src/serialize.c +2434 -2048
  190. data/vendor/prism/src/source.c +524 -0
  191. data/vendor/prism/src/static_literals.c +303 -360
  192. data/vendor/prism/src/string_query.c +180 -0
  193. data/vendor/prism/src/stringy.c +61 -0
  194. data/vendor/prism/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
  195. data/vendor/prism/src/strpbrk.c +447 -0
  196. data/vendor/prism/src/{token_type.c → tokens.c} +39 -18
  197. data/vendor/prism/src/xxh3.c +292 -0
  198. data/vendor/prism/templates/ext/prism/api_node.c.erb +58 -44
  199. data/vendor/prism/templates/include/prism/ast.h.erb +67 -17
  200. data/vendor/prism/templates/include/prism/ast.hpp.erb +31 -0
  201. data/vendor/prism/templates/include/prism/internal/diagnostic.h.erb +60 -0
  202. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/AbstractNodeVisitor.java.erb +1 -1
  203. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Loader.java.erb +232 -133
  204. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Nodes.java.erb +62 -23
  205. data/vendor/prism/templates/javascript/src/deserialize.js.erb +153 -146
  206. data/vendor/prism/templates/javascript/src/nodes.js.erb +4 -9
  207. data/vendor/prism/templates/lib/prism/compiler.rb.erb +14 -5
  208. data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +20 -12
  209. data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +37 -11
  210. data/vendor/prism/templates/lib/prism/dsl.rb.erb +43 -4
  211. data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +26 -10
  212. data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +5 -2
  213. data/vendor/prism/templates/lib/prism/node.rb.erb +283 -105
  214. data/vendor/prism/templates/lib/prism/reflection.rb.erb +11 -2
  215. data/vendor/prism/templates/lib/prism/serialize.rb.erb +291 -134
  216. data/vendor/prism/templates/lib/prism/visitor.rb.erb +18 -0
  217. data/vendor/prism/templates/src/diagnostic.c.erb +114 -63
  218. data/vendor/prism/templates/src/json.c.erb +130 -0
  219. data/vendor/prism/templates/src/node.c.erb +79 -236
  220. data/vendor/prism/templates/src/prettyprint.c.erb +24 -13
  221. data/vendor/prism/templates/src/serialize.c.erb +369 -183
  222. data/vendor/prism/templates/src/{token_type.c.erb → tokens.c.erb} +22 -11
  223. data/vendor/prism/templates/template.rb +193 -91
  224. metadata +100 -42
  225. data/vendor/prism/include/prism/defines.h +0 -260
  226. data/vendor/prism/include/prism/pack.h +0 -163
  227. data/vendor/prism/include/prism/regexp.h +0 -43
  228. data/vendor/prism/include/prism/static_literals.h +0 -121
  229. data/vendor/prism/include/prism/util/pm_buffer.h +0 -236
  230. data/vendor/prism/include/prism/util/pm_char.h +0 -204
  231. data/vendor/prism/include/prism/util/pm_constant_pool.h +0 -218
  232. data/vendor/prism/include/prism/util/pm_integer.h +0 -130
  233. data/vendor/prism/include/prism/util/pm_memchr.h +0 -29
  234. data/vendor/prism/include/prism/util/pm_newline_list.h +0 -113
  235. data/vendor/prism/include/prism/util/pm_string.h +0 -200
  236. data/vendor/prism/src/pack.c +0 -509
  237. data/vendor/prism/src/util/pm_constant_pool.c +0 -342
  238. data/vendor/prism/src/util/pm_list.c +0 -49
  239. data/vendor/prism/src/util/pm_newline_list.c +0 -125
  240. data/vendor/prism/src/util/pm_string.c +0 -381
  241. data/vendor/prism/src/util/pm_strpbrk.c +0 -206
  242. data/vendor/prism/templates/include/prism/diagnostic.h.erb +0 -130
  243. data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +0 -68
  244. data/vendor/prism/templates/rbi/prism/node.rbi.erb +0 -167
  245. data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +0 -18
  246. data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +0 -45
  247. data/vendor/prism/templates/sig/prism/dsl.rbs.erb +0 -31
  248. data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +0 -7
  249. data/vendor/prism/templates/sig/prism/node.rbs.erb +0 -136
  250. data/vendor/prism/templates/sig/prism/visitor.rbs.erb +0 -17
  251. data/vendor/prism/templates/sig/prism.rbs.erb +0 -92
@@ -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
- herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, &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
- herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, &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
@@ -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
- herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, &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
  }
@@ -1,10 +1,13 @@
1
1
  #include "parser_options_helpers.h"
2
2
 
3
- void herb_extract_parser_options(napi_env env, napi_value options, parser_options_T* parser_options) {
3
+ #include <cstring>
4
+ #include <string>
5
+
6
+ bool herb_extract_parser_options(napi_env env, napi_value options, parser_options_T* parser_options) {
4
7
  napi_valuetype valuetype;
5
8
  napi_typeof(env, options, &valuetype);
6
9
 
7
- if (valuetype != napi_object) { return; }
10
+ if (valuetype != napi_object) { return true; }
8
11
  <%- parser_options.extractable_fields_for(:javascript).each do |field| -%>
9
12
 
10
13
  {
@@ -19,6 +22,33 @@ void herb_extract_parser_options(napi_env env, napi_value options, parser_option
19
22
  bool value = false;
20
23
  napi_get_value_bool(env, property, &value);
21
24
  parser_options-><%= field.c_name %> = value;
25
+ <%- elsif field.string? -%>
26
+ napi_valuetype property_type;
27
+ napi_typeof(env, property, &property_type);
28
+
29
+ if (property_type == napi_string) {
30
+ size_t length = 0;
31
+ napi_get_value_string_utf8(env, property, nullptr, 0, &length);
32
+
33
+ std::string value(length, '\0');
34
+ napi_get_value_string_utf8(env, property, &value[0], length + 1, &length);
35
+ value.resize(length);
36
+
37
+ <%- if field.validator -%>
38
+ if (!<%= field.validator %>(value.c_str(), value.length())) {
39
+ std::string message = "<%= field.snake_case %> \"" + value + "\" is not supported";
40
+ napi_throw_error(env, nullptr, message.c_str());
41
+ return false;
42
+ }
43
+ <%- else -%>
44
+ if (value.length() >= HERB_PARSER_OPTIONS_STRING_CAPACITY) {
45
+ napi_throw_error(env, nullptr, "<%= field.snake_case %> is too long");
46
+ return false;
47
+ }
48
+ <%- end -%>
49
+
50
+ memcpy(parser_options-><%= field.c_name %>, value.c_str(), value.length() + 1);
51
+ }
22
52
  <%- elsif field.nullable? -%>
23
53
  napi_valuetype property_type;
24
54
  napi_typeof(env, property, &property_type);
@@ -38,4 +68,6 @@ void herb_extract_parser_options(napi_env env, napi_value options, parser_option
38
68
  }
39
69
  }
40
70
  <%- end -%>
71
+
72
+ return true;
41
73
  }
@@ -7,6 +7,6 @@ extern "C" {
7
7
  #include "../extension/libherb/include/parser/parser_options.h"
8
8
  }
9
9
 
10
- void herb_extract_parser_options(napi_env env, napi_value options, parser_options_T* parser_options);
10
+ bool herb_extract_parser_options(napi_env env, napi_value options, parser_options_T* parser_options);
11
11
 
12
12
  #endif
@@ -15,7 +15,7 @@ module Herb
15
15
  <%- end -%>
16
16
  end
17
17
 
18
- #: () -> Hash[Symbol, (bool | Numeric | Array[String] | nil)]
18
+ #: () -> Hash[Symbol, (bool | Numeric | String | Array[String] | nil)]
19
19
  def to_h
20
20
  {
21
21
  <%- parser_options.fields_for(:ruby).each do |field| -%>
@@ -1,55 +1,21 @@
1
- fn read_node_body(buffer: &mut SerializationBuffer, type_id: u8, pool: usize, node: &mut PrismNode) {
1
+ fn read_node_body(
2
+ buffer: &mut SerializationBuffer,
3
+ type_id: u8,
4
+ pool: usize,
5
+ node: &mut PrismNode,
6
+ stack: &mut Vec<Option<PrismNode>>,
7
+ ) {
2
8
  match type_id {
3
9
  <%- prism_nodes.each do |prism_node| -%>
4
10
  <%= prism_node.type_id %> => {
5
- <%- if prism_node.name == "DefNode" -%>
6
- buffer.read_uint32();
7
- <%- end -%>
8
-
9
11
  let flags = buffer.read_var_int() as u32;
10
12
  node.flags = flags;
11
13
 
12
14
  <%- prism_node.fields.each do |field| -%>
13
15
  <%- case field.type -%>
14
- <%- when "node" -%>
15
- {
16
- let child = read_node(buffer, pool);
17
- node.children.push(child);
18
- }
19
-
20
- <%- if field.name == "receiver" -%>
21
- node.receiver_index = Some(node.children.len() - 1);
22
- <%- elsif prism_node.name == "AssocNode" && field.name == "key" -%>
23
- node.key = Some(Box::new(node.children[node.children.len() - 1].clone()));
24
- <%- end -%>
25
-
26
- <%- when "node?" -%>
27
- if buffer.peek_byte() != 0 {
28
- let child = read_node(buffer, pool);
29
- node.children.push(child);
30
- <%- if field.name == "block" -%>
31
- node.has_block = true;
32
- <%- end -%>
33
-
34
- <%- if field.name == "receiver" -%>
35
- node.receiver_index = Some(node.children.len() - 1);
36
- <%- elsif prism_node.name == "AssocNode" && field.name == "key" -%>
37
- node.key = Some(Box::new(node.children[node.children.len() - 1].clone()));
38
- <%- end -%>
39
-
40
- } else {
41
- buffer.read_byte();
42
- }
43
- <%- when "node[]" -%>
44
- {
45
- let count = buffer.read_var_int();
46
-
47
- for _ in 0..count {
48
- let child = read_node(buffer, pool);
49
- node.children.push(child);
50
- }
51
- }
52
-
16
+ <%- when "node", "node?" -%>
17
+ <%- when "node[]" -%>
18
+ let <%= field.name %>_count = buffer.read_var_int();
53
19
  <%- when "string" -%>
54
20
  <%- if field.name == "unescaped" -%>
55
21
  node.unescaped = Some(buffer.read_string_field(flags));
@@ -93,12 +59,92 @@ fn read_node_body(buffer: &mut SerializationBuffer, type_id: u8, pool: usize, no
93
59
  <%- raise "unhandled prism field type: #{field.type}" -%>
94
60
  <%- end -%>
95
61
  <%- end -%>
62
+
63
+ <%- prism_node.fields.reverse.each do |field| -%>
64
+ <%- case field.type -%>
65
+ <%- when "node", "node?" -%>
66
+ let <%= field.name %>_child = stack.pop().flatten();
67
+ <%- when "node[]" -%>
68
+ let <%= field.name %>_children = stack.split_off(stack.len().saturating_sub(<%= field.name %>_count));
69
+ <%- end -%>
70
+ <%- end -%>
71
+
72
+ <%- prism_node.fields.each do |field| -%>
73
+ <%- case field.type -%>
74
+ <%- when "node", "node?" -%>
75
+ if let Some(child) = <%= field.name %>_child {
76
+ node.children.push(child);
77
+ <%- if field.name == "block" && field.type == "node?" -%>
78
+ node.has_block = true;
79
+ <%- end -%>
80
+ <%- if field.name == "receiver" -%>
81
+ node.receiver_index = Some(node.children.len() - 1);
82
+ <%- elsif prism_node.name == "AssocNode" && field.name == "key" -%>
83
+ node.key = Some(Box::new(node.children[node.children.len() - 1].clone()));
84
+ <%- end -%>
85
+ }
86
+
87
+ <%- when "node[]" -%>
88
+ node.children.extend(<%= field.name %>_children.into_iter().flatten());
89
+
90
+ <%- end -%>
91
+ <%- end -%>
96
92
  }
97
93
  <%- end -%>
98
94
  _ => {}
99
95
  }
100
96
  }
101
97
 
98
+ fn record_child_count(buffer: &mut SerializationBuffer, type_id: u8, pool: usize) -> usize {
99
+ #[allow(unused_mut)]
100
+ let mut count = 0;
101
+
102
+ match type_id {
103
+ <%- prism_nodes.each do |prism_node| -%>
104
+ <%= prism_node.type_id %> => {
105
+ buffer.read_var_int();
106
+
107
+ <%- prism_node.fields.each do |field| -%>
108
+ <%- case field.type -%>
109
+ <%- when "node", "node?" -%>
110
+ count += 1;
111
+ <%- when "node[]" -%>
112
+ count += buffer.read_var_int();
113
+ <%- when "string" -%>
114
+ buffer.read_string_field(0);
115
+ <%- when "constant" -%>
116
+ buffer.read_required_constant(pool);
117
+ <%- when "constant?" -%>
118
+ buffer.read_optional_constant(pool);
119
+ <%- when "constant[]" -%>
120
+ for _ in 0..buffer.read_var_int() {
121
+ buffer.read_required_constant(pool);
122
+ }
123
+ <%- when "location" -%>
124
+ buffer.read_location();
125
+ <%- when "location?" -%>
126
+ buffer.read_optional_location();
127
+ <%- when "uint8" -%>
128
+ buffer.read_byte();
129
+ <%- when "uint32" -%>
130
+ buffer.read_var_int();
131
+ <%- when "integer" -%>
132
+ buffer.read_integer();
133
+ <%- when "double" -%>
134
+ buffer.read_double();
135
+ <%- when "flags" -%>
136
+ <%- else -%>
137
+ <%- raise "unhandled prism field type: #{field.type}" -%>
138
+ <%- end -%>
139
+ <%- end -%>
140
+ }
141
+ <%- end -%>
142
+ _ => {}
143
+ }
144
+
145
+ count
146
+ }
147
+
102
148
  fn node_type_name_for(type_id: u8) -> String {
103
149
  match type_id {
104
150
  <%- prism_nodes.each do |prism_node| -%>
@@ -8,14 +8,12 @@ fn prettyprint_body(
8
8
  start_offset: usize,
9
9
  end_offset: usize,
10
10
  newlines: &[usize],
11
+ children: &mut std::vec::IntoIter<Option<PrismRecord>>,
11
12
  ) {
12
13
  match type_id {
13
14
  <%- prism_nodes.each do |prism_node| -%>
14
15
  <%- entries = prism_node.entries -%>
15
16
  <%= prism_node.type_id %> => {
16
- <%- if prism_node.name == "DefNode" -%>
17
- buffer.read_uint32();
18
- <%- end -%>
19
17
  #[allow(unused_variables)]
20
18
  let flags = buffer.read_var_int() as u32;
21
19
  output.push_str(&format!("@ <%= prism_node.name %> (location: {})\n", location_string(start_offset, end_offset, newlines)));
@@ -45,29 +43,18 @@ fn prettyprint_body(
45
43
 
46
44
  output.push('\n');
47
45
  }
48
- <%- when "node" -%>
49
- output.push('\n');
50
-
51
- {
52
- let saved = prefix.len();
53
- prefix.push_str("<%= preadd %>");
54
- let copy = prefix.clone();
55
- output.push_str(&copy);
56
- prettyprint_node(buffer, pool, output, prefix, newlines);
57
- prefix.truncate(saved);
58
- }
59
- <%- when "node?" -%>
60
- if buffer.peek_byte() == 0 {
61
- buffer.read_byte();
62
- output.push_str(" nil\n");
63
- } else {
64
- output.push('\n');
65
- let saved = prefix.len();
66
- prefix.push_str("<%= preadd %>");
67
- let copy = prefix.clone();
68
- output.push_str(&copy);
69
- prettyprint_node(buffer, pool, output, prefix, newlines);
70
- prefix.truncate(saved);
46
+ <%- when "node", "node?" -%>
47
+ match children.next().flatten() {
48
+ None => output.push_str(" nil\n"),
49
+ Some(child) => {
50
+ output.push('\n');
51
+ let saved = prefix.len();
52
+ prefix.push_str("<%= preadd %>");
53
+ let copy = prefix.clone();
54
+ output.push_str(&copy);
55
+ prettyprint_record(child, buffer, pool, output, prefix, newlines);
56
+ prefix.truncate(saved);
57
+ }
71
58
  }
72
59
  <%- when "node[]" -%>
73
60
  {
@@ -81,7 +68,11 @@ fn prettyprint_body(
81
68
  output.push_str(&copy);
82
69
  output.push_str("+-- ");
83
70
  prefix.push_str(if index == count - 1 { " " } else { "| " });
84
- prettyprint_node(buffer, pool, output, prefix, newlines);
71
+
72
+ if let Some(child) = children.next().flatten() {
73
+ prettyprint_record(child, buffer, pool, output, prefix, newlines);
74
+ }
75
+
85
76
  prefix.truncate(saved);
86
77
  }
87
78
  }