prism 0.27.0 → 0.28.0

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -1
  3. data/config.yml +39 -27
  4. data/docs/configuration.md +1 -0
  5. data/ext/prism/api_node.c +814 -807
  6. data/ext/prism/extension.c +5 -3
  7. data/ext/prism/extension.h +1 -1
  8. data/include/prism/ast.h +38 -16
  9. data/include/prism/diagnostic.h +12 -5
  10. data/include/prism/options.h +2 -2
  11. data/include/prism/parser.h +10 -0
  12. data/include/prism/static_literals.h +8 -6
  13. data/include/prism/version.h +2 -2
  14. data/lib/prism/dot_visitor.rb +22 -6
  15. data/lib/prism/dsl.rb +8 -8
  16. data/lib/prism/ffi.rb +3 -3
  17. data/lib/prism/inspect_visitor.rb +2156 -0
  18. data/lib/prism/lex_compat.rb +1 -1
  19. data/lib/prism/mutation_compiler.rb +2 -2
  20. data/lib/prism/node.rb +589 -1715
  21. data/lib/prism/node_ext.rb +34 -5
  22. data/lib/prism/parse_result.rb +78 -0
  23. data/lib/prism/pattern.rb +12 -6
  24. data/lib/prism/polyfill/byteindex.rb +13 -0
  25. data/lib/prism/polyfill/unpack1.rb +14 -0
  26. data/lib/prism/reflection.rb +13 -13
  27. data/lib/prism/serialize.rb +21 -14
  28. data/lib/prism/translation/parser/compiler.rb +2 -2
  29. data/lib/prism/translation/parser.rb +6 -6
  30. data/lib/prism/translation/ripper.rb +13 -9
  31. data/lib/prism/translation/ruby_parser.rb +4 -4
  32. data/lib/prism.rb +2 -1
  33. data/prism.gemspec +36 -38
  34. data/rbi/prism/compiler.rbi +3 -5
  35. data/rbi/prism/inspect_visitor.rbi +12 -0
  36. data/rbi/prism/node.rbi +354 -319
  37. data/rbi/prism/parse_result.rbi +23 -0
  38. data/rbi/prism/translation/ripper.rbi +1 -11
  39. data/sig/prism/dsl.rbs +3 -3
  40. data/sig/prism/inspect_visitor.rbs +22 -0
  41. data/sig/prism/node.rbs +64 -47
  42. data/sig/prism/parse_result.rbs +12 -0
  43. data/src/diagnostic.c +38 -24
  44. data/src/node.c +41 -16
  45. data/src/options.c +2 -2
  46. data/src/prettyprint.c +61 -18
  47. data/src/prism.c +607 -185
  48. data/src/serialize.c +5 -2
  49. data/src/static_literals.c +120 -34
  50. data/src/token_type.c +4 -4
  51. metadata +7 -9
  52. data/lib/prism/node_inspector.rb +0 -68
  53. data/lib/prism/polyfill/string.rb +0 -12
  54. data/rbi/prism/desugar_compiler.rbi +0 -5
  55. data/rbi/prism/mutation_compiler.rbi +0 -5
  56. data/rbi/prism/translation/parser/compiler.rbi +0 -13
  57. data/rbi/prism/translation/ripper/ripper_compiler.rbi +0 -5
  58. data/rbi/prism/translation/ruby_parser.rbi +0 -11
data/src/serialize.c CHANGED
@@ -590,8 +590,9 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) {
590
590
  } else {
591
591
  pm_serialize_node(parser, (pm_node_t *)((pm_constant_path_node_t *)node)->parent, buffer);
592
592
  }
593
- pm_serialize_node(parser, (pm_node_t *)((pm_constant_path_node_t *)node)->child, buffer);
593
+ pm_buffer_append_varuint(buffer, pm_sizet_to_u32(((pm_constant_path_node_t *)node)->name));
594
594
  pm_serialize_location(parser, &((pm_constant_path_node_t *)node)->delimiter_loc, buffer);
595
+ pm_serialize_location(parser, &((pm_constant_path_node_t *)node)->name_loc, buffer);
595
596
  break;
596
597
  }
597
598
  case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: {
@@ -613,8 +614,9 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) {
613
614
  } else {
614
615
  pm_serialize_node(parser, (pm_node_t *)((pm_constant_path_target_node_t *)node)->parent, buffer);
615
616
  }
616
- pm_serialize_node(parser, (pm_node_t *)((pm_constant_path_target_node_t *)node)->child, buffer);
617
+ pm_buffer_append_varuint(buffer, pm_sizet_to_u32(((pm_constant_path_target_node_t *)node)->name));
617
618
  pm_serialize_location(parser, &((pm_constant_path_target_node_t *)node)->delimiter_loc, buffer);
619
+ pm_serialize_location(parser, &((pm_constant_path_target_node_t *)node)->name_loc, buffer);
618
620
  break;
619
621
  }
620
622
  case PM_CONSTANT_PATH_WRITE_NODE: {
@@ -1625,6 +1627,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) {
1625
1627
  break;
1626
1628
  }
1627
1629
  case PM_RETURN_NODE: {
1630
+ pm_buffer_append_varuint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK));
1628
1631
  pm_serialize_location(parser, &((pm_return_node_t *)node)->keyword_loc, buffer);
1629
1632
  if (((pm_return_node_t *)node)->arguments == NULL) {
1630
1633
  pm_buffer_append_byte(buffer, 0);
@@ -1,5 +1,21 @@
1
1
  #include "prism/static_literals.h"
2
2
 
3
+ /**
4
+ * A small struct used for passing around a subset of the information that is
5
+ * stored on the parser. We use this to avoid having static literals explicitly
6
+ * depend on the parser struct.
7
+ */
8
+ typedef struct {
9
+ /** The list of newline offsets to use to calculate line numbers. */
10
+ const pm_newline_list_t *newline_list;
11
+
12
+ /** The line number that the parser starts on. */
13
+ int32_t start_line;
14
+
15
+ /** The name of the encoding that the parser is using. */
16
+ const char *encoding_name;
17
+ } pm_static_literals_metadata_t;
18
+
3
19
  static inline uint32_t
4
20
  murmur_scramble(uint32_t value) {
5
21
  value *= 0xcc9e2d51;
@@ -48,7 +64,7 @@ murmur_hash(const uint8_t *key, size_t length) {
48
64
  * these hashes to look for duplicates.
49
65
  */
50
66
  static uint32_t
51
- node_hash(const pm_parser_t *parser, const pm_node_t *node) {
67
+ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node) {
52
68
  switch (PM_NODE_TYPE(node)) {
53
69
  case PM_INTEGER_NODE: {
54
70
  // Integers hash their value.
@@ -68,7 +84,7 @@ node_hash(const pm_parser_t *parser, const pm_node_t *node) {
68
84
  }
69
85
  case PM_SOURCE_LINE_NODE: {
70
86
  // Source lines hash their line number.
71
- const pm_line_column_t line_column = pm_newline_list_line_column(&parser->newline_list, node->location.start, parser->start_line);
87
+ const pm_line_column_t line_column = pm_newline_list_line_column(metadata->newline_list, node->location.start, metadata->start_line);
72
88
  const int32_t *value = &line_column.line;
73
89
  return murmur_hash((const uint8_t *) value, sizeof(int32_t));
74
90
  }
@@ -82,14 +98,14 @@ node_hash(const pm_parser_t *parser, const pm_node_t *node) {
82
98
  // is stored as a subnode, we hash that node and then mix in the
83
99
  // fact that this is a rational node.
84
100
  const pm_node_t *numeric = ((const pm_rational_node_t *) node)->numeric;
85
- return node_hash(parser, numeric) ^ murmur_scramble((uint32_t) node->type);
101
+ return node_hash(metadata, numeric) ^ murmur_scramble((uint32_t) node->type);
86
102
  }
87
103
  case PM_IMAGINARY_NODE: {
88
104
  // Imaginaries hash their numeric value. Because their numeric value
89
105
  // is stored as a subnode, we hash that node and then mix in the
90
106
  // fact that this is an imaginary node.
91
107
  const pm_node_t *numeric = ((const pm_imaginary_node_t *) node)->numeric;
92
- return node_hash(parser, numeric) ^ murmur_scramble((uint32_t) node->type);
108
+ return node_hash(metadata, numeric) ^ murmur_scramble((uint32_t) node->type);
93
109
  }
94
110
  case PM_STRING_NODE: {
95
111
  // Strings hash their value and mix in their flags so that different
@@ -132,7 +148,7 @@ node_hash(const pm_parser_t *parser, const pm_node_t *node) {
132
148
  * and must be able to compare all node types that will be stored in this hash.
133
149
  */
134
150
  static pm_node_t *
135
- pm_node_hash_insert(pm_node_hash_t *hash, const pm_parser_t *parser, pm_node_t *node, int (*compare)(const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right)) {
151
+ pm_node_hash_insert(pm_node_hash_t *hash, const pm_static_literals_metadata_t *metadata, pm_node_t *node, int (*compare)(const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right)) {
136
152
  // If we are out of space, we need to resize the hash. This will cause all
137
153
  // of the nodes to be rehashed and reinserted into the new hash.
138
154
  if (hash->size * 2 >= hash->capacity) {
@@ -152,7 +168,7 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_parser_t *parser, pm_node_t *
152
168
  pm_node_t *node = hash->nodes[index];
153
169
 
154
170
  if (node != NULL) {
155
- uint32_t index = node_hash(parser, node) & mask;
171
+ uint32_t index = node_hash(metadata, node) & mask;
156
172
  new_nodes[index] = node;
157
173
  }
158
174
  }
@@ -165,14 +181,14 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_parser_t *parser, pm_node_t *
165
181
 
166
182
  // Now, insert the node into the hash.
167
183
  uint32_t mask = hash->capacity - 1;
168
- uint32_t index = node_hash(parser, node) & mask;
184
+ uint32_t index = node_hash(metadata, node) & mask;
169
185
 
170
186
  // We use linear probing to resolve collisions. This means that if the
171
187
  // current index is occupied, we will move to the next index and try again.
172
188
  // We are guaranteed that this will eventually find an empty slot because we
173
189
  // resize the hash when it gets too full.
174
190
  while (hash->nodes[index] != NULL) {
175
- if (compare(parser, hash->nodes[index], node) == 0) break;
191
+ if (compare(metadata, hash->nodes[index], node) == 0) break;
176
192
  index = (index + 1) & mask;
177
193
  }
178
194
 
@@ -203,7 +219,7 @@ pm_node_hash_free(pm_node_hash_t *hash) {
203
219
  * Return the integer value of the given node as an int64_t.
204
220
  */
205
221
  static int64_t
206
- pm_int64_value(const pm_parser_t *parser, const pm_node_t *node) {
222
+ pm_int64_value(const pm_static_literals_metadata_t *metadata, const pm_node_t *node) {
207
223
  switch (PM_NODE_TYPE(node)) {
208
224
  case PM_INTEGER_NODE: {
209
225
  const pm_integer_t *integer = &((const pm_integer_node_t *) node)->value;
@@ -213,7 +229,7 @@ pm_int64_value(const pm_parser_t *parser, const pm_node_t *node) {
213
229
  return integer->negative ? -value : value;
214
230
  }
215
231
  case PM_SOURCE_LINE_NODE:
216
- return (int64_t) pm_newline_list_line_column(&parser->newline_list, node->location.start, parser->start_line).line;
232
+ return (int64_t) pm_newline_list_line_column(metadata->newline_list, node->location.start, metadata->start_line).line;
217
233
  default:
218
234
  assert(false && "unreachable");
219
235
  return 0;
@@ -225,10 +241,10 @@ pm_int64_value(const pm_parser_t *parser, const pm_node_t *node) {
225
241
  * instances.
226
242
  */
227
243
  static int
228
- pm_compare_integer_nodes(const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right) {
244
+ pm_compare_integer_nodes(const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) {
229
245
  if (PM_NODE_TYPE_P(left, PM_SOURCE_LINE_NODE) || PM_NODE_TYPE_P(right, PM_SOURCE_LINE_NODE)) {
230
- int64_t left_value = pm_int64_value(parser, left);
231
- int64_t right_value = pm_int64_value(parser, right);
246
+ int64_t left_value = pm_int64_value(metadata, left);
247
+ int64_t right_value = pm_int64_value(metadata, right);
232
248
  return PM_NUMERIC_COMPARISON(left_value, right_value);
233
249
  }
234
250
 
@@ -241,7 +257,7 @@ pm_compare_integer_nodes(const pm_parser_t *parser, const pm_node_t *left, const
241
257
  * A comparison function for comparing two FloatNode instances.
242
258
  */
243
259
  static int
244
- pm_compare_float_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right) {
260
+ pm_compare_float_nodes(PRISM_ATTRIBUTE_UNUSED const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) {
245
261
  const double left_value = ((const pm_float_node_t *) left)->value;
246
262
  const double right_value = ((const pm_float_node_t *) right)->value;
247
263
  return PM_NUMERIC_COMPARISON(left_value, right_value);
@@ -251,20 +267,20 @@ pm_compare_float_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *parser, const p
251
267
  * A comparison function for comparing two nodes that have attached numbers.
252
268
  */
253
269
  static int
254
- pm_compare_number_nodes(const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right) {
270
+ pm_compare_number_nodes(const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) {
255
271
  if (PM_NODE_TYPE(left) != PM_NODE_TYPE(right)) {
256
272
  return PM_NUMERIC_COMPARISON(PM_NODE_TYPE(left), PM_NODE_TYPE(right));
257
273
  }
258
274
 
259
275
  switch (PM_NODE_TYPE(left)) {
260
276
  case PM_IMAGINARY_NODE:
261
- return pm_compare_number_nodes(parser, ((const pm_imaginary_node_t *) left)->numeric, ((const pm_imaginary_node_t *) right)->numeric);
277
+ return pm_compare_number_nodes(metadata, ((const pm_imaginary_node_t *) left)->numeric, ((const pm_imaginary_node_t *) right)->numeric);
262
278
  case PM_RATIONAL_NODE:
263
- return pm_compare_number_nodes(parser, ((const pm_rational_node_t *) left)->numeric, ((const pm_rational_node_t *) right)->numeric);
279
+ return pm_compare_number_nodes(metadata, ((const pm_rational_node_t *) left)->numeric, ((const pm_rational_node_t *) right)->numeric);
264
280
  case PM_INTEGER_NODE:
265
- return pm_compare_integer_nodes(parser, left, right);
281
+ return pm_compare_integer_nodes(metadata, left, right);
266
282
  case PM_FLOAT_NODE:
267
- return pm_compare_float_nodes(parser, left, right);
283
+ return pm_compare_float_nodes(metadata, left, right);
268
284
  default:
269
285
  assert(false && "unreachable");
270
286
  return 0;
@@ -293,7 +309,7 @@ pm_string_value(const pm_node_t *node) {
293
309
  * A comparison function for comparing two nodes that have attached strings.
294
310
  */
295
311
  static int
296
- pm_compare_string_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right) {
312
+ pm_compare_string_nodes(PRISM_ATTRIBUTE_UNUSED const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) {
297
313
  const pm_string_t *left_string = pm_string_value(left);
298
314
  const pm_string_t *right_string = pm_string_value(right);
299
315
  return pm_string_compare(left_string, right_string);
@@ -303,7 +319,7 @@ pm_compare_string_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *parser, const
303
319
  * A comparison function for comparing two RegularExpressionNode instances.
304
320
  */
305
321
  static int
306
- pm_compare_regular_expression_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right) {
322
+ pm_compare_regular_expression_nodes(PRISM_ATTRIBUTE_UNUSED const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) {
307
323
  const pm_regular_expression_node_t *left_regexp = (const pm_regular_expression_node_t *) left;
308
324
  const pm_regular_expression_node_t *right_regexp = (const pm_regular_expression_node_t *) right;
309
325
 
@@ -319,23 +335,77 @@ pm_compare_regular_expression_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *pa
319
335
  * Add a node to the set of static literals.
320
336
  */
321
337
  pm_node_t *
322
- pm_static_literals_add(const pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) {
338
+ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node) {
323
339
  switch (PM_NODE_TYPE(node)) {
324
340
  case PM_INTEGER_NODE:
325
341
  case PM_SOURCE_LINE_NODE:
326
- return pm_node_hash_insert(&literals->integer_nodes, parser, node, pm_compare_integer_nodes);
342
+ return pm_node_hash_insert(
343
+ &literals->integer_nodes,
344
+ &(pm_static_literals_metadata_t) {
345
+ .newline_list = newline_list,
346
+ .start_line = start_line,
347
+ .encoding_name = NULL
348
+ },
349
+ node,
350
+ pm_compare_integer_nodes
351
+ );
327
352
  case PM_FLOAT_NODE:
328
- return pm_node_hash_insert(&literals->float_nodes, parser, node, pm_compare_float_nodes);
353
+ return pm_node_hash_insert(
354
+ &literals->float_nodes,
355
+ &(pm_static_literals_metadata_t) {
356
+ .newline_list = newline_list,
357
+ .start_line = start_line,
358
+ .encoding_name = NULL
359
+ },
360
+ node,
361
+ pm_compare_float_nodes
362
+ );
329
363
  case PM_RATIONAL_NODE:
330
364
  case PM_IMAGINARY_NODE:
331
- return pm_node_hash_insert(&literals->number_nodes, parser, node, pm_compare_number_nodes);
365
+ return pm_node_hash_insert(
366
+ &literals->number_nodes,
367
+ &(pm_static_literals_metadata_t) {
368
+ .newline_list = newline_list,
369
+ .start_line = start_line,
370
+ .encoding_name = NULL
371
+ },
372
+ node,
373
+ pm_compare_number_nodes
374
+ );
332
375
  case PM_STRING_NODE:
333
376
  case PM_SOURCE_FILE_NODE:
334
- return pm_node_hash_insert(&literals->string_nodes, parser, node, pm_compare_string_nodes);
377
+ return pm_node_hash_insert(
378
+ &literals->string_nodes,
379
+ &(pm_static_literals_metadata_t) {
380
+ .newline_list = newline_list,
381
+ .start_line = start_line,
382
+ .encoding_name = NULL
383
+ },
384
+ node,
385
+ pm_compare_string_nodes
386
+ );
335
387
  case PM_REGULAR_EXPRESSION_NODE:
336
- return pm_node_hash_insert(&literals->regexp_nodes, parser, node, pm_compare_regular_expression_nodes);
388
+ return pm_node_hash_insert(
389
+ &literals->regexp_nodes,
390
+ &(pm_static_literals_metadata_t) {
391
+ .newline_list = newline_list,
392
+ .start_line = start_line,
393
+ .encoding_name = NULL
394
+ },
395
+ node,
396
+ pm_compare_regular_expression_nodes
397
+ );
337
398
  case PM_SYMBOL_NODE:
338
- return pm_node_hash_insert(&literals->symbol_nodes, parser, node, pm_compare_string_nodes);
399
+ return pm_node_hash_insert(
400
+ &literals->symbol_nodes,
401
+ &(pm_static_literals_metadata_t) {
402
+ .newline_list = newline_list,
403
+ .start_line = start_line,
404
+ .encoding_name = NULL
405
+ },
406
+ node,
407
+ pm_compare_string_nodes
408
+ );
339
409
  case PM_TRUE_NODE: {
340
410
  pm_node_t *duplicated = literals->true_node;
341
411
  literals->true_node = node;
@@ -435,8 +505,8 @@ pm_rational_inspect(pm_buffer_t *buffer, pm_rational_node_t *node) {
435
505
  /**
436
506
  * Create a string-based representation of the given static literal.
437
507
  */
438
- PRISM_EXPORTED_FUNCTION void
439
- pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node) {
508
+ static inline void
509
+ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_metadata_t *metadata, const pm_node_t *node) {
440
510
  switch (PM_NODE_TYPE(node)) {
441
511
  case PM_FALSE_NODE:
442
512
  pm_buffer_append_string(buffer, "false", 5);
@@ -473,7 +543,7 @@ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const
473
543
  const pm_node_t *numeric = ((const pm_imaginary_node_t *) node)->numeric;
474
544
  pm_buffer_append_string(buffer, "(0", 2);
475
545
  if (pm_static_literal_positive_p(numeric)) pm_buffer_append_byte(buffer, '+');
476
- pm_static_literal_inspect(buffer, parser, numeric);
546
+ pm_static_literal_inspect_node(buffer, metadata, numeric);
477
547
  if (PM_NODE_TYPE_P(numeric, PM_RATIONAL_NODE)) pm_buffer_append_byte(buffer, '*');
478
548
  pm_buffer_append_string(buffer, "i)", 2);
479
549
  break;
@@ -490,7 +560,7 @@ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const
490
560
  switch (PM_NODE_TYPE(numeric)) {
491
561
  case PM_INTEGER_NODE:
492
562
  pm_buffer_append_byte(buffer, '(');
493
- pm_static_literal_inspect(buffer, parser, numeric);
563
+ pm_static_literal_inspect_node(buffer, metadata, numeric);
494
564
  pm_buffer_append_string(buffer, "/1)", 3);
495
565
  break;
496
566
  case PM_FLOAT_NODE:
@@ -517,7 +587,7 @@ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const
517
587
  break;
518
588
  }
519
589
  case PM_SOURCE_ENCODING_NODE:
520
- pm_buffer_append_format(buffer, "#<Encoding:%s>", parser->encoding->name);
590
+ pm_buffer_append_format(buffer, "#<Encoding:%s>", metadata->encoding_name);
521
591
  break;
522
592
  case PM_SOURCE_FILE_NODE: {
523
593
  const pm_string_t *filepath = &((const pm_source_file_node_t *) node)->filepath;
@@ -527,7 +597,7 @@ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const
527
597
  break;
528
598
  }
529
599
  case PM_SOURCE_LINE_NODE:
530
- pm_buffer_append_format(buffer, "%d", pm_newline_list_line_column(&parser->newline_list, node->location.start, parser->start_line).line);
600
+ pm_buffer_append_format(buffer, "%d", pm_newline_list_line_column(metadata->newline_list, node->location.start, metadata->start_line).line);
531
601
  break;
532
602
  case PM_STRING_NODE: {
533
603
  const pm_string_t *unescaped = &((const pm_string_node_t *) node)->unescaped;
@@ -550,3 +620,19 @@ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const
550
620
  break;
551
621
  }
552
622
  }
623
+
624
+ /**
625
+ * Create a string-based representation of the given static literal.
626
+ */
627
+ PRISM_EXPORTED_FUNCTION void
628
+ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_newline_list_t *newline_list, int32_t start_line, const char *encoding_name, const pm_node_t *node) {
629
+ pm_static_literal_inspect_node(
630
+ buffer,
631
+ &(pm_static_literals_metadata_t) {
632
+ .newline_list = newline_list,
633
+ .start_line = start_line,
634
+ .encoding_name = encoding_name
635
+ },
636
+ node
637
+ );
638
+ }
data/src/token_type.c CHANGED
@@ -462,9 +462,9 @@ pm_token_type_human(pm_token_type_t token_type) {
462
462
  case PM_TOKEN_GREATER_EQUAL:
463
463
  return "'>='";
464
464
  case PM_TOKEN_GREATER_GREATER:
465
- return "'>>'";
465
+ return ">>";
466
466
  case PM_TOKEN_GREATER_GREATER_EQUAL:
467
- return "'>>='";
467
+ return ">>=";
468
468
  case PM_TOKEN_HEREDOC_END:
469
469
  return "heredoc ending";
470
470
  case PM_TOKEN_HEREDOC_START:
@@ -590,9 +590,9 @@ pm_token_type_human(pm_token_type_t token_type) {
590
590
  case PM_TOKEN_LESS_EQUAL_GREATER:
591
591
  return "'<=>'";
592
592
  case PM_TOKEN_LESS_LESS:
593
- return "'<<'";
593
+ return "<<";
594
594
  case PM_TOKEN_LESS_LESS_EQUAL:
595
- return "'<<='";
595
+ return "<<=";
596
596
  case PM_TOKEN_METHOD_NAME:
597
597
  return "method name";
598
598
  case PM_TOKEN_MINUS:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prism
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0
4
+ version: 0.28.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-23 00:00:00.000000000 Z
11
+ date: 2024-05-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -81,17 +81,18 @@ files:
81
81
  - lib/prism/dot_visitor.rb
82
82
  - lib/prism/dsl.rb
83
83
  - lib/prism/ffi.rb
84
+ - lib/prism/inspect_visitor.rb
84
85
  - lib/prism/lex_compat.rb
85
86
  - lib/prism/mutation_compiler.rb
86
87
  - lib/prism/node.rb
87
88
  - lib/prism/node_ext.rb
88
- - lib/prism/node_inspector.rb
89
89
  - lib/prism/pack.rb
90
90
  - lib/prism/parse_result.rb
91
91
  - lib/prism/parse_result/comments.rb
92
92
  - lib/prism/parse_result/newlines.rb
93
93
  - lib/prism/pattern.rb
94
- - lib/prism/polyfill/string.rb
94
+ - lib/prism/polyfill/byteindex.rb
95
+ - lib/prism/polyfill/unpack1.rb
95
96
  - lib/prism/reflection.rb
96
97
  - lib/prism/serialize.rb
97
98
  - lib/prism/translation.rb
@@ -109,25 +110,22 @@ files:
109
110
  - prism.gemspec
110
111
  - rbi/prism.rbi
111
112
  - rbi/prism/compiler.rbi
112
- - rbi/prism/desugar_compiler.rbi
113
- - rbi/prism/mutation_compiler.rbi
113
+ - rbi/prism/inspect_visitor.rbi
114
114
  - rbi/prism/node.rbi
115
115
  - rbi/prism/node_ext.rbi
116
116
  - rbi/prism/parse_result.rbi
117
117
  - rbi/prism/reflection.rbi
118
118
  - rbi/prism/translation/parser.rbi
119
- - rbi/prism/translation/parser/compiler.rbi
120
119
  - rbi/prism/translation/parser33.rbi
121
120
  - rbi/prism/translation/parser34.rbi
122
121
  - rbi/prism/translation/ripper.rbi
123
- - rbi/prism/translation/ripper/ripper_compiler.rbi
124
- - rbi/prism/translation/ruby_parser.rbi
125
122
  - rbi/prism/visitor.rbi
126
123
  - sig/prism.rbs
127
124
  - sig/prism/compiler.rbs
128
125
  - sig/prism/dispatcher.rbs
129
126
  - sig/prism/dot_visitor.rbs
130
127
  - sig/prism/dsl.rbs
128
+ - sig/prism/inspect_visitor.rbs
131
129
  - sig/prism/mutation_compiler.rbs
132
130
  - sig/prism/node.rbs
133
131
  - sig/prism/node_ext.rbs
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Prism
4
- # This object is responsible for generating the output for the inspect method
5
- # implementations of child nodes.
6
- class NodeInspector # :nodoc:
7
- attr_reader :prefix, :output
8
-
9
- def initialize(prefix = "")
10
- @prefix = prefix
11
- @output = +""
12
- end
13
-
14
- # Appends a line to the output with the current prefix.
15
- def <<(line)
16
- output << "#{prefix}#{line}"
17
- end
18
-
19
- # This generates a string that is used as the header of the inspect output
20
- # for any given node.
21
- def header(node)
22
- output = +"@ #{node.class.name.split("::").last} ("
23
- output << "location: (#{node.location.start_line},#{node.location.start_column})-(#{node.location.end_line},#{node.location.end_column})"
24
- output << ", newline: true" if node.newline?
25
- output << ")\n"
26
- output
27
- end
28
-
29
- # Generates a string that represents a list of nodes. It handles properly
30
- # using the box drawing characters to make the output look nice.
31
- def list(prefix, nodes)
32
- output = +"(length: #{nodes.length})\n"
33
- last_index = nodes.length - 1
34
-
35
- nodes.each_with_index do |node, index|
36
- pointer, preadd = (index == last_index) ? ["└── ", " "] : ["├── ", "│ "]
37
- node_prefix = "#{prefix}#{preadd}"
38
- output << node.inspect(NodeInspector.new(node_prefix)).sub(node_prefix, "#{prefix}#{pointer}")
39
- end
40
-
41
- output
42
- end
43
-
44
- # Generates a string that represents a location field on a node.
45
- def location(value)
46
- if value
47
- "(#{value.start_line},#{value.start_column})-(#{value.end_line},#{value.end_column}) = #{value.slice.inspect}"
48
- else
49
- "∅"
50
- end
51
- end
52
-
53
- # Generates a string that represents a child node.
54
- def child_node(node, append)
55
- node.inspect(child_inspector(append)).delete_prefix(prefix)
56
- end
57
-
58
- # Returns a new inspector that can be used to inspect a child node.
59
- def child_inspector(append)
60
- NodeInspector.new("#{prefix}#{append}")
61
- end
62
-
63
- # Returns the output as a string.
64
- def to_str
65
- output
66
- end
67
- end
68
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Polyfill for String#unpack1 with the offset parameter.
4
- if String.instance_method(:unpack1).parameters.none? { |_, name| name == :offset }
5
- String.prepend(
6
- Module.new {
7
- def unpack1(format, offset: 0) # :nodoc:
8
- offset == 0 ? super(format) : self[offset..].unpack1(format) # steep:ignore
9
- end
10
- }
11
- )
12
- end
@@ -1,5 +0,0 @@
1
- # typed: strict
2
-
3
- class Prism::DesugarCompiler < Prism::MutationCompiler
4
- Result = type_member { { fixed: Prism::Node } }
5
- end
@@ -1,5 +0,0 @@
1
- # typed: strict
2
-
3
- class Prism::MutationCompiler < Prism::Compiler
4
- Result = type_member
5
- end
@@ -1,13 +0,0 @@
1
- # typed: strict
2
-
3
- # We keep these shims in here because our client libraries might not have
4
- # ast/parser in their bundle.
5
- module AST; end
6
- class AST::Node; end
7
- module Parser; end
8
- module Parser::AST; end
9
- class Parser::AST::Node < AST::Node; end
10
-
11
- class Prism::Translation::Parser::Compiler < Prism::Compiler
12
- Result = type_member { { fixed: Parser::AST::Node } }
13
- end
@@ -1,5 +0,0 @@
1
- # typed: strict
2
-
3
- class Prism::Translation::RipperCompiler < Prism::Compiler
4
- Result = type_member
5
- end
@@ -1,11 +0,0 @@
1
- # typed: strict
2
-
3
- # We keep this shim in here because our client libraries might not have
4
- # ruby_parser in their bundle.
5
- class Sexp < ::Array
6
- Elem = type_member { { fixed: T.untyped }}
7
- end
8
-
9
- class Prism::Translation::RubyParser::Compiler < Prism::Compiler
10
- Result = type_member { { fixed: Sexp } }
11
- end