herb 0.8.10-arm-linux-gnu → 0.9.1-arm-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 (212) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +11 -3
  3. data/README.md +64 -34
  4. data/Rakefile +48 -40
  5. data/config.yml +473 -34
  6. data/ext/herb/error_helpers.c +535 -140
  7. data/ext/herb/error_helpers.h +1 -0
  8. data/ext/herb/extconf.rb +67 -28
  9. data/ext/herb/extension.c +321 -51
  10. data/ext/herb/extension.h +1 -0
  11. data/ext/herb/extension_helpers.c +24 -14
  12. data/ext/herb/extension_helpers.h +2 -2
  13. data/ext/herb/nodes.c +647 -270
  14. data/ext/herb/nodes.h +1 -0
  15. data/herb.gemspec +3 -2
  16. data/lib/herb/3.0/herb.so +0 -0
  17. data/lib/herb/3.1/herb.so +0 -0
  18. data/lib/herb/3.2/herb.so +0 -0
  19. data/lib/herb/3.3/herb.so +0 -0
  20. data/lib/herb/3.4/herb.so +0 -0
  21. data/lib/herb/4.0/herb.so +0 -0
  22. data/lib/herb/ast/helpers.rb +3 -3
  23. data/lib/herb/ast/node.rb +15 -2
  24. data/lib/herb/ast/nodes.rb +1530 -179
  25. data/lib/herb/bootstrap.rb +87 -0
  26. data/lib/herb/cli.rb +341 -31
  27. data/lib/herb/configuration.rb +248 -0
  28. data/lib/herb/defaults.yml +32 -0
  29. data/lib/herb/engine/compiler.rb +78 -11
  30. data/lib/herb/engine/debug_visitor.rb +13 -3
  31. data/lib/herb/engine/error_formatter.rb +13 -9
  32. data/lib/herb/engine/parser_error_overlay.rb +10 -6
  33. data/lib/herb/engine/validator.rb +8 -3
  34. data/lib/herb/engine/validators/nesting_validator.rb +2 -2
  35. data/lib/herb/engine.rb +119 -43
  36. data/lib/herb/errors.rb +808 -88
  37. data/lib/herb/lex_result.rb +1 -0
  38. data/lib/herb/location.rb +7 -3
  39. data/lib/herb/parse_result.rb +12 -2
  40. data/lib/herb/parser_options.rb +62 -0
  41. data/lib/herb/position.rb +1 -0
  42. data/lib/herb/prism_inspect.rb +120 -0
  43. data/lib/herb/project.rb +923 -331
  44. data/lib/herb/range.rb +1 -0
  45. data/lib/herb/token.rb +7 -1
  46. data/lib/herb/version.rb +1 -1
  47. data/lib/herb/visitor.rb +47 -2
  48. data/lib/herb/warnings.rb +6 -1
  49. data/lib/herb.rb +35 -3
  50. data/sig/herb/ast/helpers.rbs +2 -2
  51. data/sig/herb/ast/node.rbs +12 -2
  52. data/sig/herb/ast/nodes.rbs +773 -128
  53. data/sig/herb/bootstrap.rbs +31 -0
  54. data/sig/herb/configuration.rbs +89 -0
  55. data/sig/herb/engine/compiler.rbs +9 -1
  56. data/sig/herb/engine/debug_visitor.rbs +2 -0
  57. data/sig/herb/engine/validator.rbs +5 -1
  58. data/sig/herb/engine.rbs +21 -3
  59. data/sig/herb/errors.rbs +372 -63
  60. data/sig/herb/location.rbs +4 -0
  61. data/sig/herb/parse_result.rbs +4 -2
  62. data/sig/herb/parser_options.rbs +46 -0
  63. data/sig/herb/position.rbs +1 -0
  64. data/sig/herb/prism_inspect.rbs +28 -0
  65. data/sig/herb/range.rbs +1 -0
  66. data/sig/herb/token.rbs +6 -0
  67. data/sig/herb/visitor.rbs +31 -4
  68. data/sig/herb/warnings.rbs +6 -1
  69. data/sig/herb.rbs +14 -0
  70. data/sig/herb_c_extension.rbs +5 -2
  71. data/sig/rubyvm.rbs +5 -0
  72. data/sig/serialized_ast_errors.rbs +82 -6
  73. data/sig/serialized_ast_nodes.rbs +91 -6
  74. data/src/analyze/action_view/attribute_extraction_helpers.c +303 -0
  75. data/src/analyze/action_view/content_tag.c +78 -0
  76. data/src/analyze/action_view/link_to.c +167 -0
  77. data/src/analyze/action_view/registry.c +83 -0
  78. data/src/analyze/action_view/tag.c +70 -0
  79. data/src/analyze/action_view/tag_helper_node_builders.c +305 -0
  80. data/src/analyze/action_view/tag_helpers.c +815 -0
  81. data/src/analyze/action_view/turbo_frame_tag.c +88 -0
  82. data/src/analyze/analyze.c +885 -0
  83. data/src/{analyzed_ruby.c → analyze/analyzed_ruby.c} +13 -11
  84. data/src/analyze/builders.c +343 -0
  85. data/src/analyze/conditional_elements.c +594 -0
  86. data/src/analyze/conditional_open_tags.c +640 -0
  87. data/src/analyze/control_type.c +250 -0
  88. data/src/{analyze_helpers.c → analyze/helpers.c} +48 -23
  89. data/src/analyze/invalid_structures.c +193 -0
  90. data/src/{analyze_missing_end.c → analyze/missing_end.c} +33 -22
  91. data/src/analyze/parse_errors.c +84 -0
  92. data/src/analyze/prism_annotate.c +399 -0
  93. data/src/analyze/render_nodes.c +761 -0
  94. data/src/{analyze_transform.c → analyze/transform.c} +24 -3
  95. data/src/ast_node.c +17 -7
  96. data/src/ast_nodes.c +759 -387
  97. data/src/ast_pretty_print.c +264 -6
  98. data/src/errors.c +1454 -519
  99. data/src/extract.c +145 -49
  100. data/src/herb.c +52 -34
  101. data/src/html_util.c +241 -12
  102. data/src/include/analyze/action_view/attribute_extraction_helpers.h +36 -0
  103. data/src/include/analyze/action_view/tag_helper_handler.h +43 -0
  104. data/src/include/analyze/action_view/tag_helper_node_builders.h +70 -0
  105. data/src/include/analyze/action_view/tag_helpers.h +38 -0
  106. data/src/include/{analyze.h → analyze/analyze.h} +14 -4
  107. data/src/include/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
  108. data/src/include/analyze/builders.h +27 -0
  109. data/src/include/analyze/conditional_elements.h +9 -0
  110. data/src/include/analyze/conditional_open_tags.h +9 -0
  111. data/src/include/analyze/control_type.h +14 -0
  112. data/src/include/{analyze_helpers.h → analyze/helpers.h} +4 -2
  113. data/src/include/analyze/invalid_structures.h +11 -0
  114. data/src/include/analyze/prism_annotate.h +16 -0
  115. data/src/include/analyze/render_nodes.h +11 -0
  116. data/src/include/ast_node.h +11 -5
  117. data/src/include/ast_nodes.h +154 -38
  118. data/src/include/ast_pretty_print.h +5 -0
  119. data/src/include/element_source.h +3 -8
  120. data/src/include/errors.h +206 -55
  121. data/src/include/extract.h +21 -5
  122. data/src/include/herb.h +18 -6
  123. data/src/include/herb_prism_node.h +13 -0
  124. data/src/include/html_util.h +7 -2
  125. data/src/include/io.h +3 -1
  126. data/src/include/lex_helpers.h +29 -0
  127. data/src/include/lexer.h +1 -1
  128. data/src/include/lexer_peek_helpers.h +87 -13
  129. data/src/include/lexer_struct.h +2 -0
  130. data/src/include/location.h +2 -1
  131. data/src/include/parser.h +28 -2
  132. data/src/include/parser_helpers.h +19 -3
  133. data/src/include/pretty_print.h +10 -5
  134. data/src/include/prism_context.h +45 -0
  135. data/src/include/prism_helpers.h +10 -7
  136. data/src/include/prism_serialized.h +12 -0
  137. data/src/include/token.h +16 -4
  138. data/src/include/token_struct.h +10 -3
  139. data/src/include/utf8.h +2 -1
  140. data/src/include/util/hb_allocator.h +78 -0
  141. data/src/include/util/hb_arena.h +6 -1
  142. data/src/include/util/hb_arena_debug.h +12 -1
  143. data/src/include/util/hb_array.h +7 -3
  144. data/src/include/util/hb_buffer.h +6 -4
  145. data/src/include/util/hb_foreach.h +79 -0
  146. data/src/include/util/hb_narray.h +8 -4
  147. data/src/include/util/hb_string.h +56 -9
  148. data/src/include/util.h +6 -3
  149. data/src/include/version.h +1 -1
  150. data/src/io.c +3 -2
  151. data/src/lexer.c +42 -30
  152. data/src/lexer_peek_helpers.c +12 -74
  153. data/src/location.c +2 -2
  154. data/src/main.c +53 -28
  155. data/src/parser.c +784 -247
  156. data/src/parser_helpers.c +110 -23
  157. data/src/parser_match_tags.c +129 -48
  158. data/src/pretty_print.c +29 -24
  159. data/src/prism_helpers.c +30 -27
  160. data/src/ruby_parser.c +2 -0
  161. data/src/token.c +151 -66
  162. data/src/token_matchers.c +0 -1
  163. data/src/utf8.c +7 -6
  164. data/src/util/hb_allocator.c +341 -0
  165. data/src/util/hb_arena.c +81 -56
  166. data/src/util/hb_arena_debug.c +32 -17
  167. data/src/util/hb_array.c +30 -15
  168. data/src/util/hb_buffer.c +17 -21
  169. data/src/util/hb_narray.c +22 -7
  170. data/src/util/hb_string.c +49 -35
  171. data/src/util.c +21 -11
  172. data/src/visitor.c +67 -0
  173. data/templates/ext/herb/error_helpers.c.erb +24 -11
  174. data/templates/ext/herb/error_helpers.h.erb +1 -0
  175. data/templates/ext/herb/nodes.c.erb +50 -16
  176. data/templates/ext/herb/nodes.h.erb +1 -0
  177. data/templates/java/error_helpers.c.erb +1 -1
  178. data/templates/java/nodes.c.erb +30 -8
  179. data/templates/java/org/herb/ast/Errors.java.erb +24 -1
  180. data/templates/java/org/herb/ast/Nodes.java.erb +80 -21
  181. data/templates/javascript/packages/core/src/errors.ts.erb +16 -3
  182. data/templates/javascript/packages/core/src/node-type-guards.ts.erb +3 -1
  183. data/templates/javascript/packages/core/src/nodes.ts.erb +109 -32
  184. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +13 -4
  185. data/templates/javascript/packages/node/extension/nodes.cpp.erb +43 -4
  186. data/templates/lib/herb/ast/nodes.rb.erb +95 -32
  187. data/templates/lib/herb/errors.rb.erb +15 -3
  188. data/templates/lib/herb/visitor.rb.erb +2 -2
  189. data/templates/rust/src/ast/nodes.rs.erb +97 -44
  190. data/templates/rust/src/errors.rs.erb +2 -1
  191. data/templates/rust/src/nodes.rs.erb +168 -16
  192. data/templates/rust/src/union_types.rs.erb +60 -0
  193. data/templates/rust/src/visitor.rs.erb +81 -0
  194. data/templates/src/{analyze_missing_end.c.erb → analyze/missing_end.c.erb} +9 -6
  195. data/templates/src/{analyze_transform.c.erb → analyze/transform.c.erb} +2 -2
  196. data/templates/src/ast_nodes.c.erb +34 -26
  197. data/templates/src/ast_pretty_print.c.erb +24 -5
  198. data/templates/src/errors.c.erb +60 -54
  199. data/templates/src/include/ast_nodes.h.erb +6 -2
  200. data/templates/src/include/ast_pretty_print.h.erb +5 -0
  201. data/templates/src/include/errors.h.erb +15 -11
  202. data/templates/src/include/util/hb_foreach.h.erb +20 -0
  203. data/templates/src/parser_match_tags.c.erb +10 -4
  204. data/templates/src/visitor.c.erb +2 -2
  205. data/templates/template.rb +204 -29
  206. data/templates/wasm/error_helpers.cpp.erb +9 -5
  207. data/templates/wasm/nodes.cpp.erb +41 -4
  208. metadata +60 -16
  209. data/src/analyze.c +0 -1608
  210. data/src/element_source.c +0 -12
  211. data/src/include/util/hb_system.h +0 -9
  212. data/src/util/hb_system.c +0 -30
@@ -0,0 +1,81 @@
1
+ use crate::nodes::*;
2
+ use crate::union_types::*;
3
+
4
+ /// Visitor trait for traversing the Herb AST.
5
+ ///
6
+ /// Provides a visit/walk separation pattern:
7
+ /// - `visit_*` methods are the entry points for each node type (override these in rules)
8
+ /// - `walk_*` methods traverse child nodes (call these explicitly from `visit_*` overrides)
9
+ ///
10
+ /// Default `visit_*` implementations call the corresponding `walk_*` method.
11
+ /// Override `visit_*` to add custom behavior, then call `walk_*` to continue traversal.
12
+ pub trait Visitor {
13
+ fn visit(&mut self, node: &AnyNode) {
14
+ match node {
15
+ <%- nodes.each do |node| -%>
16
+ AnyNode::<%= node.name %>(n) => self.visit_<%= node.human %>(n),
17
+ <%- end -%>
18
+ }
19
+ }
20
+
21
+ fn visit_all(&mut self, nodes: &[AnyNode]) {
22
+ for node in nodes {
23
+ self.visit(node);
24
+ }
25
+ }
26
+
27
+ fn visit_erb_node(&mut self, _node: &dyn ERBNode) {
28
+ // Default implementation does nothing
29
+ }
30
+
31
+ <%- nodes.each do |node| -%>
32
+ fn visit_<%= node.human %>(&mut self, node: &<%= node.name %>) {
33
+ <%- if node.name.start_with?("ERB") -%>
34
+ self.visit_erb_node(node);
35
+ <%- end -%>
36
+ self.walk_<%= node.human %>(node);
37
+ }
38
+
39
+ fn walk_<%= node.human %>(&mut self, node: &<%= node.name %>) {
40
+ <%- children_fields = node.fields.select { |field|
41
+ case field
42
+ when Herb::Template::ArrayField
43
+ true
44
+ when Herb::Template::NodeField, Herb::Template::BorrowedNodeField
45
+ true
46
+ else
47
+ false
48
+ end
49
+ } -%>
50
+ <%- if children_fields.any? -%>
51
+ <%- children_fields.each do |field| -%>
52
+ <%- case field -%>
53
+ <%- when Herb::Template::ArrayField -%>
54
+ self.visit_all(&node.<%= field.name %>);
55
+ <%- when Herb::Template::NodeField, Herb::Template::BorrowedNodeField -%>
56
+ <%- if field.specific_kind && field.specific_kind != "Node" -%>
57
+ if let Some(ref child) = node.<%= field.name %> {
58
+ self.visit_<%= Herb::Template.underscore(field.specific_kind).downcase %>(child);
59
+ }
60
+ <%- elsif field.union_kind -%>
61
+ if let Some(ref child) = node.<%= field.name %> {
62
+ match child {
63
+ <%- field.union_kind.each do |kind| -%>
64
+ <%= field.union_type_name %>::<%= kind %>(n) => self.visit_<%= Herb::Template.underscore(kind).downcase %>(n),
65
+ <%- end -%>
66
+ }
67
+ }
68
+ <%- else -%>
69
+ if let Some(ref child) = node.<%= field.name %> {
70
+ self.visit(child);
71
+ }
72
+ <%- end -%>
73
+ <%- end -%>
74
+ <%- end -%>
75
+ <%- else -%>
76
+ let _ = node;
77
+ <%- end -%>
78
+ }
79
+
80
+ <%- end -%>
81
+ }
@@ -1,5 +1,7 @@
1
- #include "include/analyze_helpers.h"
2
- #include "include/errors.h"
1
+ #include "../include/analyze/helpers.h"
2
+ #include "../include/errors.h"
3
+ #include "../include/util/hb_allocator.h"
4
+ #include "../include/util/hb_string.h"
3
5
 
4
6
  <%-
5
7
  nodes_with_end_node = nodes.select do |node|
@@ -7,7 +9,7 @@
7
9
  end
8
10
  -%>
9
11
 
10
- void check_erb_node_for_missing_end(const AST_NODE_T* node) {
12
+ void check_erb_node_for_missing_end(const AST_NODE_T* node, hb_allocator_T* allocator) {
11
13
  switch (node->type) {
12
14
  <%- nodes_with_end_node.each do |node| -%>
13
15
  <%- keyword = node.name.gsub(/^ERB/, '').gsub(/Match|Node$/, '').downcase -%>
@@ -15,14 +17,15 @@ void check_erb_node_for_missing_end(const AST_NODE_T* node) {
15
17
  const <%= node.struct_type %>* <%= node.human %> = (const <%= node.struct_type %>*) node;
16
18
 
17
19
  if (<%= node.human %>->end_node == NULL) {
18
- append_missingerb_end_tag_error(
20
+ <%= "append_#{errors.find { |e| e.name == 'MissingERBEndTagError' }.human}" %>(
19
21
  <%- if keyword == "block" -%>
20
- "ERB block",
22
+ hb_string("ERB block"),
21
23
  <%- else -%>
22
- "`<" "%" " <%= keyword %> " "%" ">`",
24
+ hb_string("`<" "%" " <%= keyword %> " "%" ">`"),
23
25
  <%- end -%>
24
26
  <%= node.human %>->tag_opening->location.start,
25
27
  <%= node.human %>->tag_closing->location.end,
28
+ allocator,
26
29
  node->errors
27
30
  );
28
31
  }
@@ -1,5 +1,5 @@
1
- #include "include/analyze.h"
2
- #include "include/visitor.h"
1
+ #include "../include/analyze/analyze.h"
2
+ #include "../include/visitor.h"
3
3
 
4
4
  bool transform_erb_nodes(const AST_NODE_T* node, void* data) {
5
5
  analyze_ruby_context_T* context = (analyze_ruby_context_T*) data;
@@ -3,27 +3,31 @@
3
3
 
4
4
  #include <prism.h>
5
5
 
6
- #include "include/analyzed_ruby.h"
6
+ #include "include/analyze/analyzed_ruby.h"
7
7
  #include "include/ast_node.h"
8
8
  #include "include/ast_nodes.h"
9
9
  #include "include/errors.h"
10
10
  #include "include/token.h"
11
11
  #include "include/util.h"
12
+ #include "include/util/hb_allocator.h"
12
13
  #include "include/util/hb_array.h"
14
+ #include "include/util/hb_string.h"
13
15
 
14
16
  <%- nodes.each do |node| -%>
15
17
  <%- node_arguments = node.fields.any? ? node.fields.map { |field| [field.c_type, " ", field.name].join } : [] -%>
16
- <%- arguments = node_arguments + ["position_T start_position", "position_T end_position", "hb_array_T* errors"] -%>
18
+ <%- arguments = node_arguments + ["position_T start_position", "position_T end_position", "hb_array_T* errors", "hb_allocator_T* allocator"] -%>
17
19
 
18
20
  <%= node.struct_type %>* ast_<%= node.human %>_init(<%= arguments.join(", ") %>) {
19
- <%= node.struct_type %>* <%= node.human %> = malloc(sizeof(<%= node.struct_type %>));
21
+ <%= node.struct_type %>* <%= node.human %> = hb_allocator_alloc(allocator, sizeof(<%= node.struct_type %>));
20
22
 
21
- ast_node_init(&<%= node.human %>->base, <%= node.type %>, start_position, end_position, errors);
23
+ if (!<%= node.human %>) { return NULL; }
24
+
25
+ ast_node_init(&<%= node.human %>->base, <%= node.type %>, start_position, end_position, errors, allocator);
22
26
 
23
27
  <%- node.fields.each do |field| -%>
24
28
  <%- case field -%>
25
29
  <%- when Herb::Template::TokenField -%>
26
- <%= node.human %>-><%= field.name %> = token_copy(<%= field.name %>);
30
+ <%= node.human %>-><%= field.name %> = token_copy(<%= field.name %>, allocator);
27
31
  <%- when Herb::Template::NodeField -%>
28
32
  <%= node.human %>-><%= field.name %> = <%= field.name %>;
29
33
  <%- when Herb::Template::ArrayField -%>
@@ -35,9 +39,13 @@
35
39
  <%- when Herb::Template::PrismNodeField -%>
36
40
  <%= node.human %>-><%= field.name %> = <%= field.name %>;
37
41
  <%- when Herb::Template::StringField -%>
38
- <%= node.human %>-><%= field.name %> = herb_strdup(<%= field.name %>);
42
+ <%= node.human %>-><%= field.name %> = hb_string_copy(<%= field.name %>, allocator);
39
43
  <%- when Herb::Template::AnalyzedRubyField -%>
40
44
  <%= node.human %>-><%= field.name %> = <%= field.name %>;
45
+ <%- when Herb::Template::PrismSerializedField -%>
46
+ <%= node.human %>-><%= field.name %> = <%= field.name %>;
47
+ <%- when Herb::Template::PrismContextField -%>
48
+ <%= node.human %>-><%= field.name %> = <%= field.name %>;
41
49
  <%- when Herb::Template::VoidPointerField -%>
42
50
  <%= node.human %>-><%= field.name %> = <%= field.name %>;
43
51
  <%- when Herb::Template::LocationField -%>
@@ -71,77 +79,77 @@ hb_string_T ast_node_human_type(AST_NODE_T* node) {
71
79
  return hb_string("Unknown ast_node_type_T");
72
80
  }
73
81
 
74
- void ast_free_base_node(AST_NODE_T* node) {
82
+ void ast_free_base_node(AST_NODE_T* node, hb_allocator_T* allocator) {
75
83
  if (node == NULL) { return; }
76
84
 
77
85
  if (node->errors) {
78
86
  for (size_t i = 0; i < hb_array_size(node->errors); i++) {
79
87
  ERROR_T* child = hb_array_get(node->errors, i);
80
- if (child != NULL) { error_free(child); }
88
+ if (child != NULL) { error_free(child, allocator); }
81
89
  }
82
90
 
83
91
  hb_array_free(&node->errors);
84
92
  }
85
93
 
86
- free(node);
94
+ hb_allocator_dealloc(allocator, node);
87
95
  }
88
96
 
89
97
  <%- nodes.each do |node| -%>
90
- <%- arguments = node.fields.any? ? node.fields.map { |field| [field.c_type, " ", field.name].join }.join(", ") : "void" -%>
91
98
 
92
- static void ast_free_<%= node.human %>(<%= node.struct_type %>* <%= node.human %>) {
99
+ static void ast_free_<%= node.human %>(<%= node.struct_type %>* <%= node.human %>, hb_allocator_T* allocator) {
93
100
  <%- if node.fields.none? -%>
94
101
  /* no <%= node.struct_type %> specific fields to free up */
95
102
  <%- end -%>
96
103
  <%- node.fields.each do |field| -%>
97
104
  <%- case field -%>
98
105
  <%- when Herb::Template::TokenField -%>
99
- if (<%= node.human %>-><%= field.name %> != NULL) { token_free(<%= node.human %>-><%= field.name %>); }
106
+ if (<%= node.human %>-><%= field.name %> != NULL) { token_free(<%= node.human %>-><%= field.name %>, allocator); }
107
+ <%- when Herb::Template::BorrowedNodeField -%>
108
+ /* <%= field.name %> is a borrowed reference, not freed here (owned by another field) */
100
109
  <%- when Herb::Template::NodeField -%>
101
- ast_node_free((AST_NODE_T*) <%= node.human %>-><%= field.name %>);
110
+ ast_node_free((AST_NODE_T*) <%= node.human %>-><%= field.name %>, allocator);
102
111
  <%- when Herb::Template::ArrayField -%>
103
112
  if (<%= node.human %>-><%= field.name %> != NULL) {
104
113
  for (size_t i = 0; i < hb_array_size(<%= node.human %>-><%= field.name %>); i++) {
105
114
  AST_NODE_T* child = hb_array_get(<%= node.human %>-><%= field.name %>, i);
106
- if (child) { ast_node_free(child); }
115
+ if (child) { ast_node_free(child, allocator); }
107
116
  }
108
117
 
109
118
  hb_array_free(&<%= node.human %>-><%= field.name %>);
110
119
  }
111
120
  <%- when Herb::Template::StringField -%>
112
- if (<%= node.human %>-><%= field.name %> != NULL) { free((char*) <%= node.human %>-><%= field.name %>); }
121
+ if (<%= node.human %>-><%= field.name %>.data != NULL) { hb_allocator_dealloc(allocator, <%= node.human %>-><%= field.name %>.data); }
113
122
  <%- when Herb::Template::PrismNodeField -%>
114
- if (<%= node.human %>-><%= field.name %> != NULL) {
115
- // The first argument to `pm_node_destroy` is a `pm_parser_t`, but it's currently unused:
116
- // See: https://github.com/ruby/ruby/blob/efb2d4363709b36a205791787f6812259027c6e1/prism/templates/src/node.c.erb#L100-L104
117
- //
118
- pm_node_destroy(NULL, <%= node.human %>-><%= field.name %>);
119
- }
123
+ /* prism_node is a borrowed reference into the prism context, not freed here */
120
124
  <%- when Herb::Template::AnalyzedRubyField -%>
121
125
  if (<%= node.human %>-><%= field.name %> != NULL) {
122
126
  free_analyzed_ruby(<%= node.human %>-><%= field.name %>);
123
127
  }
128
+ <%- when Herb::Template::PrismSerializedField -%>
129
+ if (<%= node.human %>-><%= field.name %>.data != NULL) { hb_allocator_dealloc(allocator, <%= node.human %>-><%= field.name %>.data); }
130
+ <%- when Herb::Template::PrismContextField -%>
131
+ if (<%= node.human %>-><%= field.name %> != NULL) { herb_prism_context_free(<%= node.human %>-><%= field.name %>); }
124
132
  <%- when Herb::Template::VoidPointerField -%>
125
- free(<%= node.human %>-><%= field.name %>);
133
+ if (<%= node.human %>-><%= field.name %> != NULL) { hb_allocator_dealloc(allocator, <%= node.human %>-><%= field.name %>); }
126
134
  <%- when Herb::Template::BooleanField -%>
127
135
  <%- when Herb::Template::ElementSourceField -%>
128
136
  <%- when Herb::Template::LocationField -%>
129
- if (<%= node.human %>-><%= field.name %> != NULL) { free(<%= node.human %>-><%= field.name %>); }
137
+ if (<%= node.human %>-><%= field.name %> != NULL) { hb_allocator_dealloc(allocator, <%= node.human %>-><%= field.name %>); }
130
138
  <%- else -%>
131
139
  <%= field.inspect %>
132
140
  <%- end -%>
133
141
  <%- end -%>
134
142
 
135
- ast_free_base_node(&<%= node.human %>->base);
143
+ ast_free_base_node(&<%= node.human %>->base, allocator);
136
144
  }
137
145
  <%- end -%>
138
146
 
139
- void ast_node_free(AST_NODE_T* node) {
147
+ void ast_node_free(AST_NODE_T* node, hb_allocator_T* allocator) {
140
148
  if (!node) { return; }
141
149
 
142
150
  switch (node->type) {
143
151
  <%- nodes.each do |node| -%>
144
- case <%= node.type %>: ast_free_<%= node.human %>((<%= node.struct_type %>*) node); break;
152
+ case <%= node.type %>: ast_free_<%= node.human %>((<%= node.struct_type %>*) node, allocator); break;
145
153
  <%- end -%>
146
154
  }
147
155
  }
@@ -1,4 +1,8 @@
1
- #include "include/analyze_helpers.h"
1
+ #ifdef HERB_EXCLUDE_PRETTYPRINT
2
+ // Pretty print support excluded
3
+ #else
4
+
5
+ #include "include/analyze/helpers.h"
2
6
  #include "include/ast_node.h"
3
7
  #include "include/ast_nodes.h"
4
8
  #include "include/errors.h"
@@ -40,12 +44,17 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
40
44
  <%- when Herb::Template::BooleanField -%>
41
45
  pretty_print_boolean_property(hb_string("<%= field.name %>"), <%= node.human %>-><%= field.name %>, indent, relative_indent, <%= last %>, buffer);
42
46
  <%- when Herb::Template::ElementSourceField -%>
43
- pretty_print_string_property(element_source_to_string(<%= node.human %>-><%= field.name %>), hb_string("<%= field.name %>"), indent, relative_indent, <%= last %>, buffer);
47
+ pretty_print_string_property(<%= node.human %>-><%= field.name %>, hb_string("<%= field.name %>"), indent, relative_indent, <%= last %>, buffer);
44
48
  <%- when Herb::Template::StringField -%>
45
- pretty_print_string_property(hb_string(<%= node.human %>-><%= field.name %>), hb_string("<%= field.name %>"), indent, relative_indent, <%= last %>, buffer);
49
+ pretty_print_string_property(<%= node.human %>-><%= field.name %>, hb_string("<%= field.name %>"), indent, relative_indent, <%= last %>, buffer);
46
50
  <%- when Herb::Template::PrismNodeField -%>
47
- pretty_print_string_property(hb_string("<%= field.name %>"), hb_string("<%= field.name %>"), indent, relative_indent, <%= last %>, buffer);
48
- <%- when Herb::Template::NodeField -%>
51
+ if (<%= node.human %>-><%= field.name %>.node != NULL) {
52
+ pretty_print_label(hb_string("<%= field.name %>"), indent, relative_indent, <%= last %>, buffer);
53
+ hb_buffer_append(buffer, " (pm_node_t*)\n");
54
+ }
55
+ <%- when Herb::Template::PrismContextField -%>
56
+ /* prism_context is internal state, not pretty printed */
57
+ <%- when Herb::Template::NodeField, Herb::Template::BorrowedNodeField -%>
49
58
 
50
59
  pretty_print_label(hb_string("<%= field.name %>"), indent, relative_indent, <%= last %>, buffer);
51
60
 
@@ -101,6 +110,14 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
101
110
  hb_buffer_append(buffer, " ∅\n");
102
111
  }
103
112
 
113
+ <%- when Herb::Template::PrismSerializedField -%>
114
+ if (<%= node.human %>-><%= field.name %>.data != NULL && <%= node.human %>-><%= field.name %>.length > 0) {
115
+ pretty_print_label(hb_string("<%= field.name %>"), indent, relative_indent, <%= last %>, buffer);
116
+ char <%= field.name %>_size_string[64];
117
+ sprintf(<%= field.name %>_size_string, " (%zu bytes)\n", <%= node.human %>-><%= field.name %>.length);
118
+ hb_buffer_append(buffer, <%= field.name %>_size_string);
119
+ }
120
+
104
121
  <%- else -%>
105
122
  <%= field.inspect %>
106
123
  <%- end -%>
@@ -110,3 +127,5 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
110
127
  <%- end -%>
111
128
  }
112
129
  }
130
+
131
+ #endif
@@ -4,7 +4,9 @@
4
4
  #include "include/pretty_print.h"
5
5
  #include "include/token.h"
6
6
  #include "include/util.h"
7
+ #include "include/util/hb_allocator.h"
7
8
  #include "include/util/hb_array.h"
9
+ #include "include/util/hb_string.h"
8
10
 
9
11
  #include <stdio.h>
10
12
  #include <stdbool.h>
@@ -26,48 +28,47 @@ void error_init(ERROR_T* error, const error_type_T type, position_T start, posit
26
28
  }
27
29
  <%- errors.each do |error| -%>
28
30
  <%- error_arguments = error.fields.any? ? error.fields.map { |field| [field.c_type, " ", field.name].join } : [] -%>
29
- <%- arguments = error_arguments + ["position_T start", "position_T end"] -%>
31
+ <%- arguments = error_arguments + ["position_T start", "position_T end", "hb_allocator_T* allocator"] -%>
30
32
 
31
33
  <%= error.struct_type %>* <%= error.human %>_init(<%= arguments.join(", ") %>) {
32
- <%= error.struct_type %>* <%= error.human %> = malloc(sizeof(<%= error.struct_type %>));
34
+ <%= error.struct_type %>* <%= error.human %> = hb_allocator_alloc(allocator, sizeof(<%= error.struct_type %>));
35
+
36
+ if (!<%= error.human %>) { return NULL; }
33
37
 
34
38
  error_init(&<%= error.human %>->base, <%= error.type %>, start, end);
35
39
 
36
40
  <%- if error.message_arguments.any? -%>
37
41
  const char* message_template = "<%= error.message_template %>";
38
42
 
39
- size_t message_size = <%= Herb::Template::PrintfMessageTemplate.estimate_buffer_size(error.message_template) %>;
40
- char* message = (char*) malloc(message_size);
41
-
42
- if (message) {
43
- <%- error.message_arguments.each_with_index do |argument, i| -%>
44
- <%- if error.message_template.scan(/%[sdulfz]/)[i] == "%s" -%>
45
- char truncated_argument_<%= i %>[ERROR_MESSAGES_TRUNCATED_LENGTH + 1];
46
- strncpy(truncated_argument_<%= i %>, <%= argument %>, ERROR_MESSAGES_TRUNCATED_LENGTH);
47
- truncated_argument_<%= i %>[ERROR_MESSAGES_TRUNCATED_LENGTH] = '\0';
43
+ <%- error.message_arguments.each_with_index do |argument, i| -%>
44
+ <%- if error.message_template.scan(/%(?:zu|llu|lf|ld|[sdulf])/)[i] == "%s" -%>
45
+ hb_string_T truncated_argument_<%= i %> = hb_string_truncate(<%= argument %>, ERROR_MESSAGES_TRUNCATED_LENGTH);
46
+ char* truncated_c_string_<%= i %> = hb_string_to_c_string_using_malloc(truncated_argument_<%= i %>);
48
47
 
48
+ <%- end -%>
49
+ <%- end -%>
50
+ char message[<%= Herb::Template::PrintfMessageTemplate.estimate_buffer_size(error.message_template) %>];
51
+ snprintf(
52
+ message,
53
+ sizeof(message),
54
+ message_template,
55
+ <%- error.message_arguments.each_with_index do |argument, index| -%>
56
+ <%- if error.message_template.scan(/%(?:zu|llu|lf|ld|[sdulf])/)[index] == "%s" -%>
57
+ truncated_c_string_<%= index %> ? truncated_c_string_<%= index %> : ""<% if index != error.message_arguments.length - 1 %>,<% end %>
58
+ <%- else -%>
59
+ <%= argument %><% if index != error.message_arguments.length - 1 %>,<% end %>
49
60
  <%- end -%>
50
61
  <%- end -%>
51
- snprintf(
52
- message,
53
- message_size,
54
- message_template,
55
- <%- error.message_arguments.each_with_index do |argument, index| -%>
56
- <%- if error.message_template.scan(/%[sdulfz]/)[index] == "%s" -%>
57
- truncated_argument_<%= index %><% if index != error.message_arguments.length - 1 %>,<% end %>
58
- <%- else -%>
59
- <%= argument %><% if index != error.message_arguments.length - 1 %>,<% end %>
60
- <%- end -%>
61
- <%- end -%>
62
- );
63
-
64
- <%= error.human %>->base.message = herb_strdup(message);
65
- free(message);
66
- } else {
67
- <%= error.human %>->base.message = herb_strdup("<%= error.message_template %>");
68
- }
62
+ );
63
+
64
+ <%- error.message_arguments.each_with_index do |argument, i| -%>
65
+ <%- if error.message_template.scan(/%(?:zu|llu|lf|ld|[sdulf])/)[i] == "%s" -%>
66
+ if (truncated_c_string_<%= i %>) { free(truncated_c_string_<%= i %>); }
67
+ <%- end -%>
68
+ <%- end -%>
69
+ <%= error.human %>->base.message = hb_string_copy(hb_string(message), allocator);
69
70
  <%- else -%>
70
- <%= error.human %>->base.message = herb_strdup("<%= error.message_template %>");
71
+ <%= error.human %>->base.message = hb_string_copy(hb_string("<%= error.message_template %>"), allocator);
71
72
  <%- end -%>
72
73
 
73
74
  <%- error.fields.each do |field| -%>
@@ -75,13 +76,13 @@ void error_init(ERROR_T* error, const error_type_T type, position_T start, posit
75
76
  <%- when Herb::Template::PositionField -%>
76
77
  <%= error.human %>-><%= field.name %> = <%= field.name %>;
77
78
  <%- when Herb::Template::TokenField -%>
78
- <%= error.human %>-><%= field.name %> = token_copy(<%= field.name %>);
79
+ <%= error.human %>-><%= field.name %> = token_copy(<%= field.name %>, allocator);
79
80
  <%- when Herb::Template::TokenTypeField -%>
80
81
  <%= error.human %>-><%= field.name %> = <%= field.name %>;
81
82
  <%- when Herb::Template::SizeTField -%>
82
83
  <%= error.human %>-><%= field.name %> = <%= field.name %>;
83
84
  <%- when Herb::Template::StringField -%>
84
- <%= error.human %>-><%= field.name %> = herb_strdup(<%= field.name %>);
85
+ <%= error.human %>-><%= field.name %> = hb_string_copy(<%= field.name %>, allocator);
85
86
  <%- else -%>
86
87
  <%= field.inspect %>
87
88
  <%- end -%>
@@ -94,69 +95,72 @@ void append_<%= error.human %>(<%= (arguments + ["hb_array_T* errors"]).join(",
94
95
  }
95
96
  <%- end -%>
96
97
 
97
- const char* error_type_to_string(ERROR_T* error) {
98
+ hb_string_T error_type_to_string(ERROR_T* error) {
98
99
  switch (error->type) {
99
100
  <%- errors.each do |error| -%>
100
- case <%= error.type %>: return "<%= error.type %>";
101
+ case <%= error.type %>: return hb_string("<%= error.type %>");
101
102
  <%- end -%>
102
103
  }
103
104
 
104
- return "Unknown error_type_T";
105
+ return hb_string("Unknown error_type_T");
105
106
  }
106
107
 
107
- const char* error_human_type(ERROR_T* error) {
108
+ hb_string_T error_human_type(ERROR_T* error) {
108
109
  switch (error->type) {
109
110
  <%- errors.each do |error| -%>
110
- case <%= error.type %>: return "<%= error.name %>";
111
+ case <%= error.type %>: return hb_string("<%= error.name %>");
111
112
  <%- end -%>
112
113
  }
113
114
 
114
- return "Unknown error_type_T";
115
+ return hb_string("Unknown error_type_T");
115
116
  }
116
117
 
117
- void error_free_base_error(ERROR_T* error) {
118
+ void error_free_base_error(ERROR_T* error, hb_allocator_T* allocator) {
118
119
  if (error == NULL) { return; }
119
120
 
120
- if (error->message != NULL) { free(error->message); }
121
+ if (!hb_string_is_null(error->message)) { hb_allocator_dealloc(allocator, error->message.data); }
121
122
 
122
- free(error);
123
+ hb_allocator_dealloc(allocator, error);
123
124
  }
124
125
  <%- errors.each do |error| -%>
125
- <%- arguments = error.fields.any? ? error.fields.map { |field| [field.c_type, " ", field.name].join }.join(", ") : "void" -%>
126
126
 
127
- static void error_free_<%= error.human %>(<%= error.struct_type %>* <%= error.human %>) {
127
+ static void error_free_<%= error.human %>(<%= error.struct_type %>* <%= error.human %>, hb_allocator_T* allocator) {
128
128
  <%- if error.fields.none? -%>
129
129
  /* no <%= error.struct_type %> specific fields to free up */
130
130
  <%- end -%>
131
131
  <%- error.fields.each do |field| -%>
132
132
  <%- case field -%>
133
133
  <%- when Herb::Template::TokenField -%>
134
- if (<%= error.human %>-><%= field.name %> != NULL) { token_free(<%= error.human %>-><%= field.name %>); }
134
+ if (<%= error.human %>-><%= field.name %> != NULL) { token_free(<%= error.human %>-><%= field.name %>, allocator); }
135
135
  <%- when Herb::Template::TokenTypeField -%>
136
136
  // token_type_T is part of struct
137
137
  <%- when Herb::Template::SizeTField -%>
138
138
  // size_t is part of struct
139
+ <%- when Herb::Template::PositionField -%>
140
+ // position_T is part of struct
139
141
  <%- when Herb::Template::StringField -%>
140
- if (<%= error.human %>-><%= field.name %> != NULL) { free((char*) <%= error.human %>-><%= field.name %>); }
142
+ if (<%= error.human %>-><%= field.name %>.data != NULL) { hb_allocator_dealloc(allocator, <%= error.human %>-><%= field.name %>.data); }
141
143
  <%- else -%>
142
144
  <%= field.inspect %>
143
145
  <%- end -%>
144
146
  <%- end -%>
145
147
 
146
- error_free_base_error(&<%= error.human %>->base);
148
+ error_free_base_error(&<%= error.human %>->base, allocator);
147
149
  }
148
150
  <%- end -%>
149
151
 
150
- void error_free(ERROR_T* error) {
152
+ void error_free(ERROR_T* error, hb_allocator_T* allocator) {
151
153
  if (!error) { return; }
152
154
 
153
155
  switch (error->type) {
154
156
  <%- errors.each do |error| -%>
155
- case <%= error.type %>: error_free_<%= error.human %>((<%= error.struct_type %>*) error); break;
157
+ case <%= error.type %>: error_free_<%= error.human %>((<%= error.struct_type %>*) error, allocator); break;
156
158
  <%- end -%>
157
159
  }
158
160
  }
159
161
 
162
+ #ifndef HERB_EXCLUDE_PRETTYPRINT
163
+
160
164
  void error_pretty_print_array(
161
165
  const char* name, hb_array_T* array, const size_t indent, const size_t relative_indent, const bool last_property,
162
166
  hb_buffer_T* buffer
@@ -206,25 +210,25 @@ static void error_pretty_print_<%= error.human %>(<%= error.struct_type %>* erro
206
210
  if (!error) { return; }
207
211
 
208
212
  hb_buffer_append(buffer, "@ ");
209
- hb_buffer_append(buffer, error_human_type((ERROR_T*) error));
213
+ hb_buffer_append_string(buffer, error_human_type((ERROR_T*) error));
210
214
  hb_buffer_append(buffer, " ");
211
215
 
212
216
  pretty_print_location(error->base.location, buffer);
213
217
  hb_buffer_append(buffer, "\n");
214
218
 
215
- pretty_print_quoted_property(hb_string("message"), hb_string(error->base.message), indent, relative_indent, <%= error.fields.none? %>, buffer);
219
+ pretty_print_quoted_property(hb_string("message"), error->base.message, indent, relative_indent, <%= error.fields.none? %>, buffer);
216
220
  <%- error.fields.each_with_index do |field, index| -%>
217
221
  <%- case field -%>
218
222
  <%- when Herb::Template::PositionField -%>
219
- pretty_print_position_property(hb_string(error-><%= field.name %>), hb_string("<%= field.name %>"), indent, relative_indent, <%= error.fields.length - 1 == index %>, buffer);
223
+ pretty_print_position_property(&error-><%= field.name %>, hb_string("<%= field.name %>"), indent, relative_indent, <%= error.fields.length - 1 == index %>, buffer);
220
224
  <%- when Herb::Template::TokenField -%>
221
225
  pretty_print_token_property(error-><%= field.name %>, hb_string("<%= field.name %>"), indent, relative_indent, <%= error.fields.length - 1 == index %>, buffer);
222
226
  <%- when Herb::Template::TokenTypeField -%>
223
- pretty_print_property(hb_string(token_type_to_string(error-><%= field.name %>)), hb_string("<%= field.name %>"), indent, relative_indent, <%= error.fields.length - 1 == index %>, buffer);
227
+ pretty_print_property(token_type_to_string(error-><%= field.name %>), hb_string("<%= field.name %>"), indent, relative_indent, <%= error.fields.length - 1 == index %>, buffer);
224
228
  <%- when Herb::Template::SizeTField -%>
225
- pretty_print_size_t_property(hb_string(error-><%= field.name %>), hb_string("<%= field.name %>"), indent, relative_indent, <%= error.fields.length - 1 == index %>, buffer);
229
+ pretty_print_size_t_property(error-><%= field.name %>, hb_string("<%= field.name %>"), indent, relative_indent, <%= error.fields.length - 1 == index %>, buffer);
226
230
  <%- when Herb::Template::StringField -%>
227
- pretty_print_quoted_property(hb_string("<%= field.name %>"), hb_string(error-><%= field.name %>), indent, relative_indent, <%= error.fields.length - 1 == index %>, buffer);
231
+ pretty_print_quoted_property(hb_string("<%= field.name %>"), error-><%= field.name %>, indent, relative_indent, <%= error.fields.length - 1 == index %>, buffer);
228
232
  <%- else -%>
229
233
  <%= field.inspect %>
230
234
  <%- end -%>
@@ -241,3 +245,5 @@ void error_pretty_print(ERROR_T* error, const size_t indent, const size_t relati
241
245
  <%- end -%>
242
246
  }
243
247
  }
248
+
249
+ #endif
@@ -4,11 +4,15 @@
4
4
  #include <stdbool.h>
5
5
  #include <prism.h>
6
6
 
7
- #include "analyzed_ruby.h"
7
+ #include "analyze/analyzed_ruby.h"
8
8
  #include "element_source.h"
9
+ #include "herb_prism_node.h"
10
+ #include "prism_context.h"
11
+ #include "prism_serialized.h"
9
12
  #include "location.h"
10
13
  #include "position.h"
11
14
  #include "token_struct.h"
15
+ #include "util/hb_allocator.h"
12
16
  #include "util/hb_array.h"
13
17
  #include "util/hb_buffer.h"
14
18
  #include "util/hb_string.h"
@@ -37,7 +41,7 @@ typedef struct <%= node.struct_name %> {
37
41
 
38
42
  <%- nodes.each do |node| -%>
39
43
  <%- node_arguments = node.fields.any? ? node.fields.map { |field| [field.c_type, " ", field.name].join } : [] -%>
40
- <%- arguments = node_arguments + ["position_T start_position", "position_T end_position", "hb_array_T* errors"] -%>
44
+ <%- arguments = node_arguments + ["position_T start_position", "position_T end_position", "hb_array_T* errors", "hb_allocator_T* allocator"] -%>
41
45
  <%= node.struct_type %>* ast_<%= node.human %>_init(<%= arguments.join(", ") %>);
42
46
  <%- end -%>
43
47
 
@@ -1,6 +1,10 @@
1
1
  #ifndef HERB_AST_PRETTY_PRINT_H
2
2
  #define HERB_AST_PRETTY_PRINT_H
3
3
 
4
+ #ifdef HERB_EXCLUDE_PRETTYPRINT
5
+ // Pretty print support excluded
6
+ #else
7
+
4
8
  #include "ast_nodes.h"
5
9
  #include "util/hb_buffer.h"
6
10
 
@@ -12,3 +16,4 @@ void ast_pretty_print_node(
12
16
  );
13
17
 
14
18
  #endif
19
+ #endif