prism 0.27.0 → 0.28.0

Sign up to get free protection for your applications and to get access to all the features.
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