herb 0.7.2-x86_64-linux-gnu → 0.7.4-x86_64-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 (133) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +2 -0
  3. data/README.md +1 -1
  4. data/Rakefile +46 -1
  5. data/config.yml +714 -0
  6. data/ext/herb/extconf.rb +2 -1
  7. data/ext/herb/nodes.c +1 -1
  8. data/herb.gemspec +3 -0
  9. data/lib/herb/3.0/herb.so +0 -0
  10. data/lib/herb/3.1/herb.so +0 -0
  11. data/lib/herb/3.2/herb.so +0 -0
  12. data/lib/herb/3.3/herb.so +0 -0
  13. data/lib/herb/3.4/herb.so +0 -0
  14. data/lib/herb/engine.rb +8 -1
  15. data/lib/herb/version.rb +1 -1
  16. data/src/analyze.c +5 -9
  17. data/src/analyze_helpers.c +17 -6
  18. data/src/herb.c +2 -2
  19. data/src/include/parser.h +2 -2
  20. data/src/include/pretty_print.h +1 -1
  21. data/src/include/version.h +1 -1
  22. data/src/parser.c +3 -2
  23. data/src/pretty_print.c +1 -1
  24. data/templates/ext/herb/error_helpers.c.erb +85 -0
  25. data/templates/ext/herb/error_helpers.h.erb +12 -0
  26. data/templates/ext/herb/nodes.c.erb +90 -0
  27. data/templates/ext/herb/nodes.h.erb +9 -0
  28. data/templates/javascript/packages/core/src/errors.ts.erb +193 -0
  29. data/templates/javascript/packages/core/src/node-type-guards.ts.erb +325 -0
  30. data/templates/javascript/packages/core/src/nodes.ts.erb +414 -0
  31. data/templates/javascript/packages/core/src/visitor.ts.erb +29 -0
  32. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +113 -0
  33. data/templates/javascript/packages/node/extension/error_helpers.h.erb +17 -0
  34. data/templates/javascript/packages/node/extension/nodes.cpp.erb +111 -0
  35. data/templates/javascript/packages/node/extension/nodes.h.erb +17 -0
  36. data/templates/lib/herb/ast/nodes.rb.erb +117 -0
  37. data/templates/lib/herb/errors.rb.erb +106 -0
  38. data/templates/lib/herb/visitor.rb.erb +28 -0
  39. data/templates/sig/serialized_ast_errors.rbs.erb +10 -0
  40. data/templates/sig/serialized_ast_nodes.rbs.erb +10 -0
  41. data/templates/src/ast_nodes.c.erb +145 -0
  42. data/templates/src/ast_pretty_print.c.erb +97 -0
  43. data/templates/src/errors.c.erb +245 -0
  44. data/templates/src/include/ast_nodes.h.erb +46 -0
  45. data/templates/src/include/ast_pretty_print.h.erb +14 -0
  46. data/templates/src/include/errors.h.erb +58 -0
  47. data/templates/src/visitor.c.erb +47 -0
  48. data/templates/template.rb +406 -0
  49. data/templates/wasm/error_helpers.cpp.erb +93 -0
  50. data/templates/wasm/error_helpers.h.erb +15 -0
  51. data/templates/wasm/nodes.cpp.erb +79 -0
  52. data/templates/wasm/nodes.h.erb +15 -0
  53. data/vendor/prism/Rakefile +75 -0
  54. data/vendor/prism/config.yml +4713 -0
  55. data/vendor/prism/include/prism/ast.h +8190 -0
  56. data/vendor/prism/include/prism/defines.h +260 -0
  57. data/vendor/prism/include/prism/diagnostic.h +455 -0
  58. data/vendor/prism/include/prism/encoding.h +283 -0
  59. data/vendor/prism/include/prism/node.h +129 -0
  60. data/vendor/prism/include/prism/options.h +482 -0
  61. data/vendor/prism/include/prism/pack.h +163 -0
  62. data/vendor/prism/include/prism/parser.h +933 -0
  63. data/vendor/prism/include/prism/prettyprint.h +34 -0
  64. data/vendor/prism/include/prism/regexp.h +43 -0
  65. data/vendor/prism/include/prism/static_literals.h +121 -0
  66. data/vendor/prism/include/prism/util/pm_buffer.h +236 -0
  67. data/vendor/prism/include/prism/util/pm_char.h +204 -0
  68. data/vendor/prism/include/prism/util/pm_constant_pool.h +218 -0
  69. data/vendor/prism/include/prism/util/pm_integer.h +130 -0
  70. data/vendor/prism/include/prism/util/pm_list.h +103 -0
  71. data/vendor/prism/include/prism/util/pm_memchr.h +29 -0
  72. data/vendor/prism/include/prism/util/pm_newline_list.h +113 -0
  73. data/vendor/prism/include/prism/util/pm_string.h +200 -0
  74. data/vendor/prism/include/prism/util/pm_strncasecmp.h +32 -0
  75. data/vendor/prism/include/prism/util/pm_strpbrk.h +46 -0
  76. data/vendor/prism/include/prism/version.h +29 -0
  77. data/vendor/prism/include/prism.h +408 -0
  78. data/vendor/prism/src/diagnostic.c +848 -0
  79. data/vendor/prism/src/encoding.c +5235 -0
  80. data/vendor/prism/src/node.c +8676 -0
  81. data/vendor/prism/src/options.c +328 -0
  82. data/vendor/prism/src/pack.c +509 -0
  83. data/vendor/prism/src/prettyprint.c +8941 -0
  84. data/vendor/prism/src/prism.c +23302 -0
  85. data/vendor/prism/src/regexp.c +790 -0
  86. data/vendor/prism/src/serialize.c +2268 -0
  87. data/vendor/prism/src/static_literals.c +617 -0
  88. data/vendor/prism/src/token_type.c +703 -0
  89. data/vendor/prism/src/util/pm_buffer.c +357 -0
  90. data/vendor/prism/src/util/pm_char.c +318 -0
  91. data/vendor/prism/src/util/pm_constant_pool.c +342 -0
  92. data/vendor/prism/src/util/pm_integer.c +670 -0
  93. data/vendor/prism/src/util/pm_list.c +49 -0
  94. data/vendor/prism/src/util/pm_memchr.c +35 -0
  95. data/vendor/prism/src/util/pm_newline_list.c +125 -0
  96. data/vendor/prism/src/util/pm_string.c +383 -0
  97. data/vendor/prism/src/util/pm_strncasecmp.c +36 -0
  98. data/vendor/prism/src/util/pm_strpbrk.c +206 -0
  99. data/vendor/prism/templates/ext/prism/api_node.c.erb +282 -0
  100. data/vendor/prism/templates/include/prism/ast.h.erb +226 -0
  101. data/vendor/prism/templates/include/prism/diagnostic.h.erb +130 -0
  102. data/vendor/prism/templates/java/org/prism/AbstractNodeVisitor.java.erb +22 -0
  103. data/vendor/prism/templates/java/org/prism/Loader.java.erb +434 -0
  104. data/vendor/prism/templates/java/org/prism/Nodes.java.erb +403 -0
  105. data/vendor/prism/templates/javascript/src/deserialize.js.erb +448 -0
  106. data/vendor/prism/templates/javascript/src/nodes.js.erb +197 -0
  107. data/vendor/prism/templates/javascript/src/visitor.js.erb +78 -0
  108. data/vendor/prism/templates/lib/prism/compiler.rb.erb +43 -0
  109. data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +103 -0
  110. data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +189 -0
  111. data/vendor/prism/templates/lib/prism/dsl.rb.erb +133 -0
  112. data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +131 -0
  113. data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +19 -0
  114. data/vendor/prism/templates/lib/prism/node.rb.erb +515 -0
  115. data/vendor/prism/templates/lib/prism/reflection.rb.erb +136 -0
  116. data/vendor/prism/templates/lib/prism/serialize.rb.erb +602 -0
  117. data/vendor/prism/templates/lib/prism/visitor.rb.erb +55 -0
  118. data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +68 -0
  119. data/vendor/prism/templates/rbi/prism/node.rbi.erb +164 -0
  120. data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +18 -0
  121. data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +45 -0
  122. data/vendor/prism/templates/sig/prism/dsl.rbs.erb +31 -0
  123. data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +7 -0
  124. data/vendor/prism/templates/sig/prism/node.rbs.erb +132 -0
  125. data/vendor/prism/templates/sig/prism/visitor.rbs.erb +17 -0
  126. data/vendor/prism/templates/sig/prism.rbs.erb +89 -0
  127. data/vendor/prism/templates/src/diagnostic.c.erb +523 -0
  128. data/vendor/prism/templates/src/node.c.erb +333 -0
  129. data/vendor/prism/templates/src/prettyprint.c.erb +166 -0
  130. data/vendor/prism/templates/src/serialize.c.erb +406 -0
  131. data/vendor/prism/templates/src/token_type.c.erb +369 -0
  132. data/vendor/prism/templates/template.rb +689 -0
  133. metadata +112 -2
@@ -0,0 +1,333 @@
1
+ #line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>"
2
+ #include "prism/node.h"
3
+
4
+ /**
5
+ * 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.
9
+ */
10
+ static bool
11
+ pm_node_list_grow(pm_node_list_t *list, size_t size) {
12
+ size_t requested_size = list->size + size;
13
+
14
+ // If the requested size caused overflow, return false.
15
+ if (requested_size < list->size) return false;
16
+
17
+ // If the requested size is within the existing capacity, return true.
18
+ if (requested_size < list->capacity) return true;
19
+
20
+ // Otherwise, reallocate the list to be twice as large as it was before.
21
+ size_t next_capacity = list->capacity == 0 ? 4 : list->capacity * 2;
22
+
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
+ 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;
33
+ }
34
+
35
+ pm_node_t **nodes = (pm_node_t **) xrealloc(list->nodes, sizeof(pm_node_t *) * next_capacity);
36
+ if (nodes == NULL) return false;
37
+
38
+ list->nodes = nodes;
39
+ list->capacity = next_capacity;
40
+ return true;
41
+ }
42
+
43
+ /**
44
+ * Append a new node onto the end of the node list.
45
+ */
46
+ 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
+ }
51
+ }
52
+
53
+ /**
54
+ * Prepend a new node onto the beginning of the node list.
55
+ */
56
+ 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
+ }
63
+ }
64
+
65
+ /**
66
+ * Concatenate the given node list onto the end of the other node list.
67
+ */
68
+ 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
+ }
74
+ }
75
+
76
+ /**
77
+ * Free the internal memory associated with the given node list.
78
+ */
79
+ 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;
142
+ }
143
+ xfree(node);
144
+ }
145
+
146
+ /**
147
+ * Returns a string representation of the given node type.
148
+ */
149
+ PRISM_EXPORTED_FUNCTION const char *
150
+ pm_node_type_to_str(pm_node_type_t node_type)
151
+ {
152
+ switch (node_type) {
153
+ <%- nodes.each do |node| -%>
154
+ case <%= node.type %>:
155
+ return "<%= node.type %>";
156
+ <%- end -%>
157
+ }
158
+ return "";
159
+ }
160
+
161
+ /**
162
+ * 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.
168
+ */
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);
172
+ }
173
+
174
+ /**
175
+ * Visit the children of the given node with the given callback. This is the
176
+ * default behavior for walking the tree that is called from pm_visit_node if
177
+ * the callback returns true.
178
+ */
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) {
181
+ switch (PM_NODE_TYPE(node)) {
182
+ <%- nodes.each do |node| -%>
183
+ <%- 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? -%>
184
+ case <%= node.type %>: {
185
+ const pm_<%= node.human %>_t *cast = (const pm_<%= node.human %>_t *) node;
186
+ <%- fields.each do |field| -%>
187
+
188
+ // Visit the <%= field.name %> field
189
+ <%- case field -%>
190
+ <%- when Prism::Template::NodeField -%>
191
+ pm_visit_node((const pm_node_t *) cast-><%= field.name %>, visitor, data);
192
+ <%- when Prism::Template::OptionalNodeField -%>
193
+ if (cast-><%= field.name %> != NULL) {
194
+ pm_visit_node((const pm_node_t *) cast-><%= field.name %>, visitor, data);
195
+ }
196
+ <%- when Prism::Template::NodeListField -%>
197
+ const pm_node_list_t *<%= field.name %> = &cast-><%= field.name %>;
198
+ for (size_t index = 0; index < <%= field.name %>->size; index++) {
199
+ pm_visit_node(<%= field.name %>->nodes[index], visitor, data);
200
+ }
201
+ <%- end -%>
202
+ <%- end -%>
203
+
204
+ break;
205
+ }
206
+ <%- else -%>
207
+ case <%= node.type %>:
208
+ break;
209
+ <%- end -%>
210
+ <%- end -%>
211
+ case PM_SCOPE_NODE:
212
+ break;
213
+ }
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
+
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);
233
+ }
234
+
235
+ /**
236
+ * Dump JSON to the given buffer.
237
+ */
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 -%>
323
+
324
+ pm_buffer_append_byte(buffer, '}');
325
+ break;
326
+ }
327
+ <%- end -%>
328
+ case PM_SCOPE_NODE:
329
+ break;
330
+ }
331
+ }
332
+
333
+ #endif
@@ -0,0 +1,166 @@
1
+ <%# encoding: ASCII -%>
2
+ #include "prism/prettyprint.h"
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.
7
+ #ifdef PRISM_EXCLUDE_PRETTYPRINT
8
+
9
+ void pm_prettyprint(void) {}
10
+
11
+ #else
12
+
13
+ static inline void
14
+ 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);
17
+ pm_buffer_append_format(output_buffer, "(%" PRIi32 ",%" PRIu32 ")-(%" PRIi32 ",%" PRIu32 ")", start.line, start.column, end.line, end.column);
18
+ }
19
+
20
+ static inline void
21
+ prettyprint_constant(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_constant_id_t constant_id) {
22
+ pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id);
23
+ pm_buffer_append_format(output_buffer, ":%.*s", (int) constant->length, constant->start);
24
+ }
25
+
26
+ static void
27
+ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node, pm_buffer_t *prefix_buffer) {
28
+ switch (PM_NODE_TYPE(node)) {
29
+ case PM_SCOPE_NODE:
30
+ // We do not need to print a ScopeNode as it's not part of the AST.
31
+ return;
32
+ <%- nodes.each do |node| -%>
33
+ case <%= node.type %>: {
34
+ <%- if !node.flags.nil? || node.fields.any? -%>
35
+ pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
36
+ <%- end -%>
37
+ pm_buffer_append_string(output_buffer, "@ <%= node.name %> (location: ", <%= node.name.length + 14 %>);
38
+ prettyprint_location(output_buffer, parser, &node->location);
39
+ pm_buffer_append_string(output_buffer, ")\n", 2);
40
+ <%- (fields = [*node.flags, *node.fields]).each_with_index do |field, index| -%>
41
+ <%- preadd = index == fields.length - 1 ? " " : "| " -%>
42
+
43
+ // <%= field.name %>
44
+ {
45
+ pm_buffer_concat(output_buffer, prefix_buffer);
46
+ pm_buffer_append_string(output_buffer, "+-- <%= field.name %>:", <%= 4 + field.name.length + 1 %>);
47
+ <%- case field -%>
48
+ <%- when Prism::Template::NodeField -%>
49
+ pm_buffer_append_byte(output_buffer, '\n');
50
+
51
+ size_t prefix_length = prefix_buffer->length;
52
+ pm_buffer_append_string(prefix_buffer, "<%= preadd %>", 4);
53
+ pm_buffer_concat(output_buffer, prefix_buffer);
54
+ prettyprint_node(output_buffer, parser, (pm_node_t *) cast-><%= field.name %>, prefix_buffer);
55
+ prefix_buffer->length = prefix_length;
56
+ <%- when Prism::Template::OptionalNodeField -%>
57
+ if (cast-><%= field.name %> == NULL) {
58
+ pm_buffer_append_string(output_buffer, " nil\n", 5);
59
+ } else {
60
+ pm_buffer_append_byte(output_buffer, '\n');
61
+
62
+ size_t prefix_length = prefix_buffer->length;
63
+ pm_buffer_append_string(prefix_buffer, "<%= preadd %>", 4);
64
+ pm_buffer_concat(output_buffer, prefix_buffer);
65
+ prettyprint_node(output_buffer, parser, (pm_node_t *) cast-><%= field.name %>, prefix_buffer);
66
+ prefix_buffer->length = prefix_length;
67
+ }
68
+ <%- when Prism::Template::StringField -%>
69
+ pm_buffer_append_string(output_buffer, " \"", 2);
70
+ pm_buffer_append_source(output_buffer, pm_string_source(&cast-><%= field.name %>), pm_string_length(&cast-><%= field.name %>), PM_BUFFER_ESCAPING_RUBY);
71
+ pm_buffer_append_string(output_buffer, "\"\n", 2);
72
+ <%- when Prism::Template::NodeListField -%>
73
+ pm_buffer_append_format(output_buffer, " (length: %lu)\n", (unsigned long) (cast-><%= field.name %>.size));
74
+
75
+ size_t last_index = cast-><%= field.name %>.size;
76
+ for (uint32_t index = 0; index < last_index; index++) {
77
+ size_t prefix_length = prefix_buffer->length;
78
+ pm_buffer_append_string(prefix_buffer, "<%= preadd %>", 4);
79
+ pm_buffer_concat(output_buffer, prefix_buffer);
80
+ pm_buffer_append_string(output_buffer, "+-- ", 4);
81
+ pm_buffer_append_string(prefix_buffer, (index == last_index - 1) ? " " : "| ", 4);
82
+ prettyprint_node(output_buffer, parser, (pm_node_t *) cast-><%= field.name %>.nodes[index], prefix_buffer);
83
+ prefix_buffer->length = prefix_length;
84
+ }
85
+ <%- when Prism::Template::ConstantField -%>
86
+ pm_buffer_append_byte(output_buffer, ' ');
87
+ prettyprint_constant(output_buffer, parser, cast-><%= field.name %>);
88
+ pm_buffer_append_byte(output_buffer, '\n');
89
+ <%- when Prism::Template::OptionalConstantField -%>
90
+ if (cast-><%= field.name %> == 0) {
91
+ pm_buffer_append_string(output_buffer, " nil\n", 5);
92
+ } else {
93
+ pm_buffer_append_byte(output_buffer, ' ');
94
+ prettyprint_constant(output_buffer, parser, cast-><%= field.name %>);
95
+ pm_buffer_append_byte(output_buffer, '\n');
96
+ }
97
+ <%- when Prism::Template::ConstantListField -%>
98
+ pm_buffer_append_string(output_buffer, " [", 2);
99
+ for (uint32_t index = 0; index < cast-><%= field.name %>.size; index++) {
100
+ if (index != 0) pm_buffer_append_string(output_buffer, ", ", 2);
101
+ prettyprint_constant(output_buffer, parser, cast-><%= field.name %>.ids[index]);
102
+ }
103
+ pm_buffer_append_string(output_buffer, "]\n", 2);
104
+ <%- when Prism::Template::LocationField -%>
105
+ pm_location_t *location = &cast-><%= field.name %>;
106
+ pm_buffer_append_byte(output_buffer, ' ');
107
+ prettyprint_location(output_buffer, parser, location);
108
+ 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);
110
+ pm_buffer_append_string(output_buffer, "\"\n", 2);
111
+ <%- when Prism::Template::OptionalLocationField -%>
112
+ pm_location_t *location = &cast-><%= field.name %>;
113
+ if (location->start == NULL) {
114
+ pm_buffer_append_string(output_buffer, " nil\n", 5);
115
+ } else {
116
+ pm_buffer_append_byte(output_buffer, ' ');
117
+ prettyprint_location(output_buffer, parser, location);
118
+ 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);
120
+ pm_buffer_append_string(output_buffer, "\"\n", 2);
121
+ }
122
+ <%- when Prism::Template::UInt8Field -%>
123
+ pm_buffer_append_format(output_buffer, " %" PRIu8 "\n", cast-><%= field.name %>);
124
+ <%- when Prism::Template::UInt32Field -%>
125
+ pm_buffer_append_format(output_buffer, " %" PRIu32 "\n", cast-><%= field.name %>);
126
+ <%- when Prism::Template::Flags -%>
127
+ bool found = false;
128
+ <%- field.values.each do |value| -%>
129
+ if (cast->base.flags & PM_<%= field.human.upcase %>_<%= value.name %>) {
130
+ if (found) pm_buffer_append_byte(output_buffer, ',');
131
+ pm_buffer_append_string(output_buffer, " <%= value.name.downcase %>", <%= value.name.bytesize + 1 %>);
132
+ found = true;
133
+ }
134
+ <%- end -%>
135
+ if (!found) pm_buffer_append_string(output_buffer, " nil", 4);
136
+ pm_buffer_append_byte(output_buffer, '\n');
137
+ <%- when Prism::Template::IntegerField -%>
138
+ const pm_integer_t *integer = &cast-><%= field.name %>;
139
+ pm_buffer_append_byte(output_buffer, ' ');
140
+ pm_integer_string(output_buffer, integer);
141
+ pm_buffer_append_byte(output_buffer, '\n');
142
+ <%- when Prism::Template::DoubleField -%>
143
+ pm_buffer_append_format(output_buffer, " %f\n", cast-><%= field.name %>);
144
+ <%- else -%>
145
+ <%- raise -%>
146
+ <%- end -%>
147
+ }
148
+ <%- end -%>
149
+
150
+ break;
151
+ }
152
+ <%- end -%>
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Pretty-prints the AST represented by the given node to the given buffer.
158
+ */
159
+ PRISM_EXPORTED_FUNCTION void
160
+ pm_prettyprint(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node) {
161
+ pm_buffer_t prefix_buffer = { 0 };
162
+ prettyprint_node(output_buffer, parser, node, &prefix_buffer);
163
+ pm_buffer_free(&prefix_buffer);
164
+ }
165
+
166
+ #endif