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
@@ -1,153 +1,93 @@
1
1
  #line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>"
2
- #include "prism/node.h"
2
+ #include "prism/internal/node.h"
3
+
4
+ #include "prism/internal/arena.h"
5
+
6
+ #include <stdlib.h>
3
7
 
4
8
  /**
5
9
  * Attempts to grow the node list to the next size. If there is already
6
- * capacity in the list, this function does nothing. Otherwise it reallocates
7
- * the list to be twice as large as it was before. If the reallocation fails,
8
- * this function returns false, otherwise it returns true.
10
+ * capacity in the list, this function does nothing. Otherwise it allocates a
11
+ * new array from the arena (abandon-and-copy strategy) and copies the existing
12
+ * data into it.
9
13
  */
10
- static bool
11
- pm_node_list_grow(pm_node_list_t *list, size_t size) {
14
+ static void
15
+ pm_node_list_grow(pm_arena_t *arena, pm_node_list_t *list, size_t size) {
12
16
  size_t requested_size = list->size + size;
13
17
 
14
- // If the requested size caused overflow, return false.
15
- if (requested_size < list->size) return false;
18
+ // Guard against overflow on the addition.
19
+ if (requested_size < list->size) abort();
16
20
 
17
- // If the requested size is within the existing capacity, return true.
18
- if (requested_size < list->capacity) return true;
21
+ // If the requested size is within the existing capacity, return.
22
+ if (requested_size <= list->capacity) return;
19
23
 
20
- // Otherwise, reallocate the list to be twice as large as it was before.
24
+ // Otherwise, compute the next capacity by doubling.
21
25
  size_t next_capacity = list->capacity == 0 ? 4 : list->capacity * 2;
22
26
 
23
- // If multiplying by 2 caused overflow, return false.
24
- if (next_capacity < list->capacity) return false;
25
-
26
- // If we didn't get enough by doubling, keep doubling until we do.
27
+ // Guard against overflow on the doubling.
27
28
  while (requested_size > next_capacity) {
28
- size_t double_capacity = next_capacity * 2;
29
-
30
- // Ensure we didn't overflow by multiplying by 2.
31
- if (double_capacity < next_capacity) return false;
32
- next_capacity = double_capacity;
29
+ if (next_capacity == 0) abort();
30
+ next_capacity *= 2;
33
31
  }
34
32
 
35
- pm_node_t **nodes = (pm_node_t **) xrealloc(list->nodes, sizeof(pm_node_t *) * next_capacity);
36
- if (nodes == NULL) return false;
33
+ // Allocate a new array from the arena (old array is abandoned).
34
+ pm_node_t **nodes = (pm_node_t **) pm_arena_alloc(arena, sizeof(pm_node_t *) * next_capacity, PRISM_ALIGNOF(pm_node_t *));
35
+
36
+ // Copy old data into the new array.
37
+ if (list->size > 0) {
38
+ memcpy(nodes, list->nodes, list->size * sizeof(pm_node_t *));
39
+ }
37
40
 
38
41
  list->nodes = nodes;
39
42
  list->capacity = next_capacity;
40
- return true;
41
43
  }
42
44
 
43
45
  /**
44
- * Append a new node onto the end of the node list.
46
+ * Slow path for pm_node_list_append_inline: grow the list and append the node.
47
+ * Do not call directly - use pm_node_list_append_inline instead.
45
48
  */
46
49
  void
47
- pm_node_list_append(pm_node_list_t *list, pm_node_t *node) {
48
- if (pm_node_list_grow(list, 1)) {
49
- list->nodes[list->size++] = node;
50
- }
50
+ pm_node_list_append_slow(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) {
51
+ pm_node_list_grow(arena, list, 1);
52
+ list->nodes[list->size++] = node;
51
53
  }
52
54
 
53
55
  /**
54
- * Prepend a new node onto the beginning of the node list.
56
+ * Append a new node onto the end of the node list.
55
57
  */
56
58
  void
57
- pm_node_list_prepend(pm_node_list_t *list, pm_node_t *node) {
58
- if (pm_node_list_grow(list, 1)) {
59
- memmove(list->nodes + 1, list->nodes, list->size * sizeof(pm_node_t *));
60
- list->nodes[0] = node;
61
- list->size++;
62
- }
59
+ pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) {
60
+ pm_node_list_append_inline(arena, list, node);
63
61
  }
64
62
 
65
63
  /**
66
- * Concatenate the given node list onto the end of the other node list.
64
+ * Prepend a new node onto the beginning of the node list.
67
65
  */
68
66
  void
69
- pm_node_list_concat(pm_node_list_t *list, pm_node_list_t *other) {
70
- if (other->size > 0 && pm_node_list_grow(list, other->size)) {
71
- memcpy(list->nodes + list->size, other->nodes, other->size * sizeof(pm_node_t *));
72
- list->size += other->size;
73
- }
67
+ pm_node_list_prepend(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) {
68
+ pm_node_list_grow(arena, list, 1);
69
+ memmove(list->nodes + 1, list->nodes, list->size * sizeof(pm_node_t *));
70
+ list->nodes[0] = node;
71
+ list->size++;
74
72
  }
75
73
 
76
74
  /**
77
- * Free the internal memory associated with the given node list.
75
+ * Concatenate the given node list onto the end of the other node list.
78
76
  */
79
77
  void
80
- pm_node_list_free(pm_node_list_t *list) {
81
- if (list->capacity > 0) {
82
- xfree(list->nodes);
83
- *list = (pm_node_list_t) { 0 };
84
- }
85
- }
86
-
87
- PRISM_EXPORTED_FUNCTION void
88
- pm_node_destroy(pm_parser_t *parser, pm_node_t *node);
89
-
90
- /**
91
- * Destroy the nodes that are contained within the given node list.
92
- */
93
- static void
94
- pm_node_list_destroy(pm_parser_t *parser, pm_node_list_t *list) {
95
- pm_node_t *node;
96
- PM_NODE_LIST_FOREACH(list, index, node) pm_node_destroy(parser, node);
97
- pm_node_list_free(list);
98
- }
99
-
100
- /**
101
- * Deallocate the space for a pm_node_t. Similarly to pm_node_alloc, we're not
102
- * using the parser argument, but it's there to allow for the future possibility
103
- * of pre-allocating larger memory pools.
104
- */
105
- PRISM_EXPORTED_FUNCTION void
106
- pm_node_destroy(pm_parser_t *parser, pm_node_t *node) {
107
- switch (PM_NODE_TYPE(node)) {
108
- <%- nodes.each do |node| -%>
109
- #line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>"
110
- case <%= node.type %>: {
111
- <%- if node.fields.any? { |field| ![Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField].include?(field.class) } -%>
112
- pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
113
- <%- end -%>
114
- <%- node.fields.each do |field| -%>
115
- <%- case field -%>
116
- <%- when Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField -%>
117
- <%- when Prism::Template::NodeField -%>
118
- pm_node_destroy(parser, (pm_node_t *)cast-><%= field.name %>);
119
- <%- when Prism::Template::OptionalNodeField -%>
120
- if (cast-><%= field.name %> != NULL) {
121
- pm_node_destroy(parser, (pm_node_t *)cast-><%= field.name %>);
122
- }
123
- <%- when Prism::Template::StringField -%>
124
- pm_string_free(&cast-><%= field.name %>);
125
- <%- when Prism::Template::NodeListField -%>
126
- pm_node_list_destroy(parser, &cast-><%= field.name %>);
127
- <%- when Prism::Template::ConstantListField -%>
128
- pm_constant_id_list_free(&cast-><%= field.name %>);
129
- <%- when Prism::Template::IntegerField -%>
130
- pm_integer_free(&cast-><%= field.name %>);
131
- <%- else -%>
132
- <%- raise -%>
133
- <%- end -%>
134
- <%- end -%>
135
- break;
136
- }
137
- <%- end -%>
138
- #line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>"
139
- default:
140
- assert(false && "unreachable");
141
- break;
78
+ pm_node_list_concat(pm_arena_t *arena, pm_node_list_t *list, pm_node_list_t *other) {
79
+ if (other->size > 0) {
80
+ pm_node_list_grow(arena, list, other->size);
81
+ memcpy(list->nodes + list->size, other->nodes, other->size * sizeof(pm_node_t *));
82
+ list->size += other->size;
142
83
  }
143
- xfree(node);
144
84
  }
145
85
 
146
86
  /**
147
87
  * Returns a string representation of the given node type.
148
88
  */
149
- PRISM_EXPORTED_FUNCTION const char *
150
- pm_node_type_to_str(pm_node_type_t node_type)
89
+ const char *
90
+ pm_node_type(pm_node_type_t node_type)
151
91
  {
152
92
  switch (node_type) {
153
93
  <%- nodes.each do |node| -%>
@@ -160,24 +100,26 @@ pm_node_type_to_str(pm_node_type_t node_type)
160
100
 
161
101
  /**
162
102
  * Visit each of the nodes in this subtree using the given visitor callback. The
163
- * callback function will be called for each node in the subtree. If it returns
164
- * false, then that node's children will not be visited. If it returns true,
165
- * then the children will be visited. The data parameter is treated as an opaque
166
- * pointer and is passed to the visitor callback for consumers to use as they
167
- * see fit.
103
+ * callback function will be called for each node in the subtree, and its
104
+ * return value determines whether the walk visits that node's children, skips
105
+ * them, or stops entirely. The data parameter is treated as an opaque pointer
106
+ * and is passed to the visitor callback for consumers to use as they see fit.
168
107
  */
169
- PRISM_EXPORTED_FUNCTION void
170
- pm_visit_node(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data) {
171
- if (visitor(node, data)) pm_visit_child_nodes(node, visitor, data);
108
+ bool
109
+ pm_visit_node(const pm_node_t *node, pm_visit_callback_t visitor, void *data) {
110
+ pm_visit_result_t result = visitor(node, data);
111
+ if (result == PM_VISIT_DESCEND) return pm_visit_child_nodes(node, visitor, data);
112
+ return result != PM_VISIT_STOP;
172
113
  }
173
114
 
174
115
  /**
175
116
  * Visit the children of the given node with the given callback. This is the
176
117
  * default behavior for walking the tree that is called from pm_visit_node if
177
- * the callback returns true.
118
+ * the callback returns PM_VISIT_DESCEND. A stop from any child returns false
119
+ * immediately, so that it propagates up through every enclosing call.
178
120
  */
179
- PRISM_EXPORTED_FUNCTION void
180
- pm_visit_child_nodes(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data) {
121
+ bool
122
+ pm_visit_child_nodes(const pm_node_t *node, pm_visit_callback_t visitor, void *data) {
181
123
  switch (PM_NODE_TYPE(node)) {
182
124
  <%- nodes.each do |node| -%>
183
125
  <%- if (fields = node.fields.select { |field| field.is_a?(Prism::Template::NodeField) || field.is_a?(Prism::Template::OptionalNodeField) || field.is_a?(Prism::Template::NodeListField) }).any? -%>
@@ -188,15 +130,13 @@ pm_visit_child_nodes(const pm_node_t *node, bool (*visitor)(const pm_node_t *nod
188
130
  // Visit the <%= field.name %> field
189
131
  <%- case field -%>
190
132
  <%- when Prism::Template::NodeField -%>
191
- pm_visit_node((const pm_node_t *) cast-><%= field.name %>, visitor, data);
133
+ if (!pm_visit_node((const pm_node_t *) cast-><%= field.name %>, visitor, data)) return false;
192
134
  <%- when Prism::Template::OptionalNodeField -%>
193
- if (cast-><%= field.name %> != NULL) {
194
- pm_visit_node((const pm_node_t *) cast-><%= field.name %>, visitor, data);
195
- }
135
+ if (cast-><%= field.name %> != NULL && !pm_visit_node((const pm_node_t *) cast-><%= field.name %>, visitor, data)) return false;
196
136
  <%- when Prism::Template::NodeListField -%>
197
137
  const pm_node_list_t *<%= field.name %> = &cast-><%= field.name %>;
198
138
  for (size_t index = 0; index < <%= field.name %>->size; index++) {
199
- pm_visit_node(<%= field.name %>->nodes[index], visitor, data);
139
+ if (!pm_visit_node(<%= field.name %>->nodes[index], visitor, data)) return false;
200
140
  }
201
141
  <%- end -%>
202
142
  <%- end -%>
@@ -211,123 +151,26 @@ pm_visit_child_nodes(const pm_node_t *node, bool (*visitor)(const pm_node_t *nod
211
151
  case PM_SCOPE_NODE:
212
152
  break;
213
153
  }
214
- }
215
-
216
- // We optionally support dumping to JSON. For systems that don't want or need
217
- // this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define.
218
- #ifndef PRISM_EXCLUDE_JSON
219
154
 
220
- static void
221
- pm_dump_json_constant(pm_buffer_t *buffer, const pm_parser_t *parser, pm_constant_id_t constant_id) {
222
- const pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id);
223
- pm_buffer_append_byte(buffer, '"');
224
- pm_buffer_append_source(buffer, constant->start, constant->length, PM_BUFFER_ESCAPING_JSON);
225
- pm_buffer_append_byte(buffer, '"');
226
- }
227
-
228
- static void
229
- pm_dump_json_location(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_location_t *location) {
230
- uint32_t start = (uint32_t) (location->start - parser->start);
231
- uint32_t end = (uint32_t) (location->end - parser->start);
232
- pm_buffer_append_format(buffer, "{\"start\":%" PRIu32 ",\"end\":%" PRIu32 "}", start, end);
155
+ return true;
233
156
  }
157
+ <%- nodes.each do |node| -%>
234
158
 
159
+ <%- params = node.fields.map(&:c_param) -%>
235
160
  /**
236
- * Dump JSON to the given buffer.
161
+ * Allocate and initialize a new <%= node.name %> node.
237
162
  */
238
- PRISM_EXPORTED_FUNCTION void
239
- pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node) {
240
- switch (PM_NODE_TYPE(node)) {
241
- <%- nodes.each do |node| -%>
242
- case <%= node.type %>: {
243
- pm_buffer_append_string(buffer, "{\"type\":\"<%= node.name %>\",\"location\":", <%= node.name.bytesize + 22 %>);
244
-
245
- const pm_<%= node.human %>_t *cast = (const pm_<%= node.human %>_t *) node;
246
- pm_dump_json_location(buffer, parser, &cast->base.location);
247
- <%- [*node.flags, *node.fields].each_with_index do |field, index| -%>
248
-
249
- // Dump the <%= field.name %> field
250
- pm_buffer_append_byte(buffer, ',');
251
- pm_buffer_append_string(buffer, "\"<%= field.name %>\":", <%= field.name.bytesize + 3 %>);
252
- <%- case field -%>
253
- <%- when Prism::Template::NodeField -%>
254
- pm_dump_json(buffer, parser, (const pm_node_t *) cast-><%= field.name %>);
255
- <%- when Prism::Template::OptionalNodeField -%>
256
- if (cast-><%= field.name %> != NULL) {
257
- pm_dump_json(buffer, parser, (const pm_node_t *) cast-><%= field.name %>);
258
- } else {
259
- pm_buffer_append_string(buffer, "null", 4);
260
- }
261
- <%- when Prism::Template::NodeListField -%>
262
- const pm_node_list_t *<%= field.name %> = &cast-><%= field.name %>;
263
- pm_buffer_append_byte(buffer, '[');
264
-
265
- for (size_t index = 0; index < <%= field.name %>->size; index++) {
266
- if (index != 0) pm_buffer_append_byte(buffer, ',');
267
- pm_dump_json(buffer, parser, <%= field.name %>->nodes[index]);
268
- }
269
- pm_buffer_append_byte(buffer, ']');
270
- <%- when Prism::Template::StringField -%>
271
- const pm_string_t *<%= field.name %> = &cast-><%= field.name %>;
272
- pm_buffer_append_byte(buffer, '"');
273
- pm_buffer_append_source(buffer, pm_string_source(<%= field.name %>), pm_string_length(<%= field.name %>), PM_BUFFER_ESCAPING_JSON);
274
- pm_buffer_append_byte(buffer, '"');
275
- <%- when Prism::Template::ConstantField -%>
276
- pm_dump_json_constant(buffer, parser, cast-><%= field.name %>);
277
- <%- when Prism::Template::OptionalConstantField -%>
278
- if (cast-><%= field.name %> != PM_CONSTANT_ID_UNSET) {
279
- pm_dump_json_constant(buffer, parser, cast-><%= field.name %>);
280
- } else {
281
- pm_buffer_append_string(buffer, "null", 4);
282
- }
283
- <%- when Prism::Template::ConstantListField -%>
284
- const pm_constant_id_list_t *<%= field.name %> = &cast-><%= field.name %>;
285
- pm_buffer_append_byte(buffer, '[');
286
-
287
- for (size_t index = 0; index < <%= field.name %>->size; index++) {
288
- if (index != 0) pm_buffer_append_byte(buffer, ',');
289
- pm_dump_json_constant(buffer, parser, <%= field.name %>->ids[index]);
290
- }
291
- pm_buffer_append_byte(buffer, ']');
292
- <%- when Prism::Template::LocationField -%>
293
- pm_dump_json_location(buffer, parser, &cast-><%= field.name %>);
294
- <%- when Prism::Template::OptionalLocationField -%>
295
- if (cast-><%= field.name %>.start != NULL) {
296
- pm_dump_json_location(buffer, parser, &cast-><%= field.name %>);
297
- } else {
298
- pm_buffer_append_string(buffer, "null", 4);
299
- }
300
- <%- when Prism::Template::UInt8Field -%>
301
- pm_buffer_append_format(buffer, "%" PRIu8, cast-><%= field.name %>);
302
- <%- when Prism::Template::UInt32Field -%>
303
- pm_buffer_append_format(buffer, "%" PRIu32, cast-><%= field.name %>);
304
- <%- when Prism::Template::Flags -%>
305
- size_t flags = 0;
306
- pm_buffer_append_byte(buffer, '[');
307
- <%- node.flags.values.each_with_index do |value, index| -%>
308
- if (PM_NODE_FLAG_P(cast, PM_<%= node.flags.human.upcase %>_<%= value.name %>)) {
309
- if (flags != 0) pm_buffer_append_byte(buffer, ',');
310
- pm_buffer_append_string(buffer, "\"<%= value.name %>\"", <%= value.name.bytesize + 2 %>);
311
- flags++;
312
- }
313
- <%- end -%>
314
- pm_buffer_append_byte(buffer, ']');
315
- <%- when Prism::Template::IntegerField -%>
316
- pm_integer_string(buffer, &cast-><%= field.name %>);
317
- <%- when Prism::Template::DoubleField -%>
318
- pm_buffer_append_format(buffer, "%f", cast-><%= field.name %>);
319
- <%- else -%>
320
- <%- raise %>
321
- <%- end -%>
322
- <%- end -%>
163
+ pm_<%= node.human %>_t *
164
+ 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(", ")}" %>) {
165
+ pm_<%= node.human %>_t *node = (pm_<%= node.human %>_t *) pm_arena_alloc(arena, sizeof(pm_<%= node.human %>_t), PRISM_ALIGNOF(pm_<%= node.human %>_t));
166
+
167
+ *node = (pm_<%= node.human %>_t) {
168
+ .base = { .type = <%= node.type %>, .flags = flags, .node_id = node_id, .location = location }<%= node.fields.empty? ? "" : "," %>
169
+ <%- node.fields.each_with_index do |field, index| -%>
170
+ .<%= field.name %> = <%= field.name %><%= index < node.fields.size - 1 ? "," : "" %>
171
+ <%- end -%>
172
+ };
323
173
 
324
- pm_buffer_append_byte(buffer, '}');
325
- break;
326
- }
327
- <%- end -%>
328
- case PM_SCOPE_NODE:
329
- break;
330
- }
174
+ return node;
331
175
  }
332
-
333
- #endif
176
+ <%- end -%>
@@ -1,23 +1,34 @@
1
1
  <%# encoding: ASCII -%>
2
2
  #include "prism/prettyprint.h"
3
3
 
4
- // We optionally support pretty printing nodes. For systems that don't want or
5
- // need this functionality, it can be turned off with the
6
- // PRISM_EXCLUDE_PRETTYPRINT define.
4
+ /* We optionally support pretty printing nodes. For systems that don't want or
5
+ * need this functionality, it can be turned off with the
6
+ * PRISM_EXCLUDE_PRETTYPRINT define. */
7
7
  #ifdef PRISM_EXCLUDE_PRETTYPRINT
8
8
 
9
- void pm_prettyprint(void) {}
9
+ /* Ensure this translation unit is never empty, even when prettyprint is
10
+ * excluded. */
11
+ typedef int pm_prettyprint_unused_t;
10
12
 
11
13
  #else
12
14
 
13
- static inline void
15
+ #include "prism/compiler/inline.h"
16
+ #include "prism/internal/buffer.h"
17
+ #include "prism/internal/constant_pool.h"
18
+ #include "prism/internal/integer.h"
19
+ #include "prism/internal/parser.h"
20
+ #include "prism/line_offset_list.h"
21
+
22
+ #include <inttypes.h>
23
+
24
+ static PRISM_INLINE void
14
25
  prettyprint_location(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_location_t *location) {
15
- pm_line_column_t start = pm_newline_list_line_column(&parser->newline_list, location->start, parser->start_line);
16
- pm_line_column_t end = pm_newline_list_line_column(&parser->newline_list, location->end, parser->start_line);
26
+ pm_line_column_t start = pm_line_offset_list_line_column(&parser->line_offsets, location->start, parser->start_line);
27
+ pm_line_column_t end = pm_line_offset_list_line_column(&parser->line_offsets, location->start + location->length, parser->start_line);
17
28
  pm_buffer_append_format(output_buffer, "(%" PRIi32 ",%" PRIu32 ")-(%" PRIi32 ",%" PRIu32 ")", start.line, start.column, end.line, end.column);
18
29
  }
19
30
 
20
- static inline void
31
+ static PRISM_INLINE void
21
32
  prettyprint_constant(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_constant_id_t constant_id) {
22
33
  pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id);
23
34
  pm_buffer_append_format(output_buffer, ":%.*s", (int) constant->length, constant->start);
@@ -106,17 +117,17 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm
106
117
  pm_buffer_append_byte(output_buffer, ' ');
107
118
  prettyprint_location(output_buffer, parser, location);
108
119
  pm_buffer_append_string(output_buffer, " = \"", 4);
109
- pm_buffer_append_source(output_buffer, location->start, (size_t) (location->end - location->start), PM_BUFFER_ESCAPING_RUBY);
120
+ pm_buffer_append_source(output_buffer, parser->start + location->start, (size_t) location->length, PM_BUFFER_ESCAPING_RUBY);
110
121
  pm_buffer_append_string(output_buffer, "\"\n", 2);
111
122
  <%- when Prism::Template::OptionalLocationField -%>
112
123
  pm_location_t *location = &cast-><%= field.name %>;
113
- if (location->start == NULL) {
124
+ if (location->length == 0) {
114
125
  pm_buffer_append_string(output_buffer, " nil\n", 5);
115
126
  } else {
116
127
  pm_buffer_append_byte(output_buffer, ' ');
117
128
  prettyprint_location(output_buffer, parser, location);
118
129
  pm_buffer_append_string(output_buffer, " = \"", 4);
119
- pm_buffer_append_source(output_buffer, location->start, (size_t) (location->end - location->start), PM_BUFFER_ESCAPING_RUBY);
130
+ pm_buffer_append_source(output_buffer, parser->start + location->start, (size_t) location->length, PM_BUFFER_ESCAPING_RUBY);
120
131
  pm_buffer_append_string(output_buffer, "\"\n", 2);
121
132
  }
122
133
  <%- when Prism::Template::UInt8Field -%>
@@ -156,11 +167,11 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm
156
167
  /**
157
168
  * Pretty-prints the AST represented by the given node to the given buffer.
158
169
  */
159
- PRISM_EXPORTED_FUNCTION void
170
+ void
160
171
  pm_prettyprint(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node) {
161
172
  pm_buffer_t prefix_buffer = { 0 };
162
173
  prettyprint_node(output_buffer, parser, node, &prefix_buffer);
163
- pm_buffer_free(&prefix_buffer);
174
+ pm_buffer_cleanup(&prefix_buffer);
164
175
  }
165
176
 
166
177
  #endif