prism 0.29.0 → 0.30.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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -1
  3. data/CONTRIBUTING.md +0 -4
  4. data/README.md +1 -0
  5. data/config.yml +66 -9
  6. data/docs/fuzzing.md +1 -1
  7. data/docs/ripper_translation.md +22 -0
  8. data/ext/prism/api_node.c +30 -12
  9. data/ext/prism/extension.c +107 -372
  10. data/ext/prism/extension.h +1 -1
  11. data/include/prism/ast.h +138 -70
  12. data/include/prism/diagnostic.h +7 -2
  13. data/include/prism/node.h +0 -21
  14. data/include/prism/parser.h +23 -25
  15. data/include/prism/regexp.h +17 -8
  16. data/include/prism/static_literals.h +3 -2
  17. data/include/prism/util/pm_char.h +1 -2
  18. data/include/prism/util/pm_constant_pool.h +0 -8
  19. data/include/prism/util/pm_integer.h +16 -9
  20. data/include/prism/util/pm_string.h +0 -8
  21. data/include/prism/version.h +2 -2
  22. data/include/prism.h +0 -11
  23. data/lib/prism/compiler.rb +3 -0
  24. data/lib/prism/dispatcher.rb +14 -0
  25. data/lib/prism/dot_visitor.rb +22 -3
  26. data/lib/prism/dsl.rb +7 -2
  27. data/lib/prism/ffi.rb +24 -3
  28. data/lib/prism/inspect_visitor.rb +10 -8
  29. data/lib/prism/mutation_compiler.rb +6 -1
  30. data/lib/prism/node.rb +166 -241
  31. data/lib/prism/node_ext.rb +21 -5
  32. data/lib/prism/parse_result/comments.rb +0 -7
  33. data/lib/prism/parse_result/newlines.rb +101 -11
  34. data/lib/prism/parse_result.rb +17 -0
  35. data/lib/prism/reflection.rb +3 -1
  36. data/lib/prism/serialize.rb +80 -67
  37. data/lib/prism/translation/parser/compiler.rb +134 -114
  38. data/lib/prism/translation/parser.rb +6 -1
  39. data/lib/prism/translation/ripper.rb +8 -6
  40. data/lib/prism/translation/ruby_parser.rb +23 -5
  41. data/lib/prism/visitor.rb +3 -0
  42. data/lib/prism.rb +0 -4
  43. data/prism.gemspec +1 -4
  44. data/rbi/prism/node.rbi +63 -6
  45. data/rbi/prism/visitor.rbi +3 -0
  46. data/rbi/prism.rbi +6 -0
  47. data/sig/prism/dsl.rbs +4 -1
  48. data/sig/prism/mutation_compiler.rbs +1 -0
  49. data/sig/prism/node.rbs +28 -4
  50. data/sig/prism/visitor.rbs +1 -0
  51. data/sig/prism.rbs +21 -0
  52. data/src/diagnostic.c +27 -17
  53. data/src/node.c +408 -1666
  54. data/src/prettyprint.c +49 -6
  55. data/src/prism.c +958 -991
  56. data/src/regexp.c +133 -68
  57. data/src/serialize.c +6 -1
  58. data/src/static_literals.c +63 -84
  59. data/src/token_type.c +2 -2
  60. data/src/util/pm_constant_pool.c +0 -8
  61. data/src/util/pm_integer.c +39 -11
  62. data/src/util/pm_string.c +0 -12
  63. data/src/util/pm_strpbrk.c +32 -6
  64. metadata +2 -5
  65. data/include/prism/util/pm_string_list.h +0 -44
  66. data/lib/prism/debug.rb +0 -249
  67. data/src/util/pm_string_list.c +0 -28
@@ -48,6 +48,9 @@ typedef struct {
48
48
  * from the string itself.
49
49
  */
50
50
  typedef enum {
51
+ /** The default decimal base, with no prefix. Leading 0s will be ignored. */
52
+ PM_INTEGER_BASE_DEFAULT,
53
+
51
54
  /** The binary base, indicated by a 0b or 0B prefix. */
52
55
  PM_INTEGER_BASE_BINARY,
53
56
 
@@ -79,15 +82,7 @@ typedef enum {
79
82
  * @param start The start of the string.
80
83
  * @param end The end of the string.
81
84
  */
82
- PRISM_EXPORTED_FUNCTION void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end);
83
-
84
- /**
85
- * Return the memory size of the integer.
86
- *
87
- * @param integer The integer to get the memory size of.
88
- * @return The size of the memory associated with the integer.
89
- */
90
- size_t pm_integer_memsize(const pm_integer_t *integer);
85
+ void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end);
91
86
 
92
87
  /**
93
88
  * Compare two integers. This function returns -1 if the left integer is less
@@ -100,6 +95,18 @@ size_t pm_integer_memsize(const pm_integer_t *integer);
100
95
  */
101
96
  int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right);
102
97
 
98
+ /**
99
+ * Reduce a ratio of integers to its simplest form.
100
+ *
101
+ * If either the numerator or denominator do not fit into a 32-bit integer, then
102
+ * this function is a no-op. In the future, we may consider reducing even the
103
+ * larger numbers, but for now we're going to keep it simple.
104
+ *
105
+ * @param numerator The numerator of the ratio.
106
+ * @param denominator The denominator of the ratio.
107
+ */
108
+ void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator);
109
+
103
110
  /**
104
111
  * Convert an integer to a decimal string.
105
112
  *
@@ -120,14 +120,6 @@ PRISM_EXPORTED_FUNCTION bool pm_string_mapped_init(pm_string_t *string, const ch
120
120
  */
121
121
  PRISM_EXPORTED_FUNCTION bool pm_string_file_init(pm_string_t *string, const char *filepath);
122
122
 
123
- /**
124
- * Returns the memory size associated with the string.
125
- *
126
- * @param string The string to get the memory size of.
127
- * @return The size of the memory associated with the string.
128
- */
129
- size_t pm_string_memsize(const pm_string_t *string);
130
-
131
123
  /**
132
124
  * Ensure the string is owned. If it is not, then reinitialize it as owned and
133
125
  * copy over the previous source.
@@ -14,7 +14,7 @@
14
14
  /**
15
15
  * The minor version of the Prism library as an int.
16
16
  */
17
- #define PRISM_VERSION_MINOR 29
17
+ #define PRISM_VERSION_MINOR 30
18
18
 
19
19
  /**
20
20
  * The patch version of the Prism library as an int.
@@ -24,6 +24,6 @@
24
24
  /**
25
25
  * The version of the Prism library as a constant string.
26
26
  */
27
- #define PRISM_VERSION "0.29.0"
27
+ #define PRISM_VERSION "0.30.0"
28
28
 
29
29
  #endif
data/include/prism.h CHANGED
@@ -219,17 +219,6 @@ PRISM_EXPORTED_FUNCTION const char * pm_token_type_name(pm_token_type_t token_ty
219
219
  */
220
220
  const char * pm_token_type_human(pm_token_type_t token_type);
221
221
 
222
- /**
223
- * Format the errors on the parser into the given buffer.
224
- *
225
- * @param parser The parser to format the errors for.
226
- * @param error_list The list of errors to format.
227
- * @param buffer The buffer to format the errors into.
228
- * @param colorize Whether or not to colorize the errors with ANSI escape sequences.
229
- * @param inline_messages Whether or not to inline the messages with the source.
230
- */
231
- PRISM_EXPORTED_FUNCTION void pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, pm_buffer_t *buffer, bool colorize, bool inline_messages);
232
-
233
222
  // We optionally support dumping to JSON. For systems that don't want or need
234
223
  // this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define.
235
224
  #ifndef PRISM_EXCLUDE_JSON
@@ -301,6 +301,9 @@ module Prism
301
301
  # Compile a InterpolatedXStringNode node
302
302
  alias visit_interpolated_x_string_node visit_child_nodes
303
303
 
304
+ # Compile a ItLocalVariableReadNode node
305
+ alias visit_it_local_variable_read_node visit_child_nodes
306
+
304
307
  # Compile a ItParametersNode node
305
308
  alias visit_it_parameters_node visit_child_nodes
306
309
 
@@ -762,6 +762,14 @@ module Prism
762
762
  listeners[:on_interpolated_x_string_node_leave]&.each { |listener| listener.on_interpolated_x_string_node_leave(node) }
763
763
  end
764
764
 
765
+ # Dispatch enter and leave events for ItLocalVariableReadNode nodes and continue
766
+ # walking the tree.
767
+ def visit_it_local_variable_read_node(node)
768
+ listeners[:on_it_local_variable_read_node_enter]&.each { |listener| listener.on_it_local_variable_read_node_enter(node) }
769
+ super
770
+ listeners[:on_it_local_variable_read_node_leave]&.each { |listener| listener.on_it_local_variable_read_node_leave(node) }
771
+ end
772
+
765
773
  # Dispatch enter and leave events for ItParametersNode nodes and continue
766
774
  # walking the tree.
767
775
  def visit_it_parameters_node(node)
@@ -1795,6 +1803,12 @@ module Prism
1795
1803
  listeners[:on_interpolated_x_string_node_leave]&.each { |listener| listener.on_interpolated_x_string_node_leave(node) }
1796
1804
  end
1797
1805
 
1806
+ # Dispatch enter and leave events for ItLocalVariableReadNode nodes.
1807
+ def visit_it_local_variable_read_node(node)
1808
+ listeners[:on_it_local_variable_read_node_enter]&.each { |listener| listener.on_it_local_variable_read_node_enter(node) }
1809
+ listeners[:on_it_local_variable_read_node_leave]&.each { |listener| listener.on_it_local_variable_read_node_leave(node) }
1810
+ end
1811
+
1798
1812
  # Dispatch enter and leave events for ItParametersNode nodes.
1799
1813
  def visit_it_parameters_node(node)
1800
1814
  listeners[:on_it_parameters_node_enter]&.each { |listener| listener.on_it_parameters_node_enter(node) }
@@ -2780,6 +2780,20 @@ module Prism
2780
2780
  super
2781
2781
  end
2782
2782
 
2783
+ # Visit a ItLocalVariableReadNode node.
2784
+ def visit_it_local_variable_read_node(node)
2785
+ table = Table.new("ItLocalVariableReadNode")
2786
+ id = node_id(node)
2787
+
2788
+ digraph.nodes << <<~DOT
2789
+ #{id} [
2790
+ label=<#{table.to_dot.gsub(/\n/, "\n ")}>
2791
+ ];
2792
+ DOT
2793
+
2794
+ super
2795
+ end
2796
+
2783
2797
  # Visit a ItParametersNode node.
2784
2798
  def visit_it_parameters_node(node)
2785
2799
  table = Table.new("ItParametersNode")
@@ -3779,9 +3793,14 @@ module Prism
3779
3793
  table = Table.new("RationalNode")
3780
3794
  id = node_id(node)
3781
3795
 
3782
- # numeric
3783
- table.field("numeric", port: true)
3784
- digraph.edge("#{id}:numeric -> #{node_id(node.numeric)};")
3796
+ # flags
3797
+ table.field("flags", integer_base_flags_inspect(node))
3798
+
3799
+ # numerator
3800
+ table.field("numerator", node.numerator.inspect)
3801
+
3802
+ # denominator
3803
+ table.field("denominator", node.denominator.inspect)
3785
3804
 
3786
3805
  digraph.nodes << <<~DOT
3787
3806
  #{id} [
data/lib/prism/dsl.rb CHANGED
@@ -482,6 +482,11 @@ module Prism
482
482
  InterpolatedXStringNode.new(source, opening_loc, parts, closing_loc, location)
483
483
  end
484
484
 
485
+ # Create a new ItLocalVariableReadNode node
486
+ def ItLocalVariableReadNode(source = nil, location = Location())
487
+ ItLocalVariableReadNode.new(source, location)
488
+ end
489
+
485
490
  # Create a new ItParametersNode node
486
491
  def ItParametersNode(source = nil, location = Location())
487
492
  ItParametersNode.new(source, location)
@@ -653,8 +658,8 @@ module Prism
653
658
  end
654
659
 
655
660
  # Create a new RationalNode node
656
- def RationalNode(numeric, source = nil, location = Location())
657
- RationalNode.new(source, numeric, location)
661
+ def RationalNode(flags, numerator, denominator, source = nil, location = Location())
662
+ RationalNode.new(source, flags, numerator, denominator, location)
658
663
  end
659
664
 
660
665
  # Create a new RedoNode node
data/lib/prism/ffi.rb CHANGED
@@ -200,8 +200,8 @@ module Prism
200
200
 
201
201
  class << self
202
202
  # Mirror the Prism.dump API by using the serialization API.
203
- def dump(code, **options)
204
- LibRubyParser::PrismString.with_string(code) { |string| dump_common(string, options) }
203
+ def dump(source, **options)
204
+ LibRubyParser::PrismString.with_string(source) { |string| dump_common(string, options) }
205
205
  end
206
206
 
207
207
  # Mirror the Prism.dump_file API by using the serialization API.
@@ -302,6 +302,27 @@ module Prism
302
302
  !parse_file_success?(filepath, **options)
303
303
  end
304
304
 
305
+ # Mirror the Prism.profile API by using the serialization API.
306
+ def profile(source, **options)
307
+ LibRubyParser::PrismString.with_string(source) do |string|
308
+ LibRubyParser::PrismBuffer.with do |buffer|
309
+ LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options))
310
+ nil
311
+ end
312
+ end
313
+ end
314
+
315
+ # Mirror the Prism.profile_file API by using the serialization API.
316
+ def profile_file(filepath, **options)
317
+ LibRubyParser::PrismString.with_file(filepath) do |string|
318
+ LibRubyParser::PrismBuffer.with do |buffer|
319
+ options[:filepath] = filepath
320
+ LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options))
321
+ nil
322
+ end
323
+ end
324
+ end
325
+
305
326
  private
306
327
 
307
328
  def dump_common(string, options) # :nodoc:
@@ -394,7 +415,7 @@ module Prism
394
415
 
395
416
  template << "L"
396
417
  if (encoding = options[:encoding])
397
- name = encoding.name
418
+ name = encoding.is_a?(Encoding) ? encoding.name : encoding
398
419
  values.push(name.bytesize, name.b)
399
420
  template << "A*"
400
421
  else
@@ -1310,6 +1310,11 @@ module Prism
1310
1310
  commands << ["└── closing_loc: #{inspect_location(node.closing_loc)}\n", indent]
1311
1311
  end
1312
1312
 
1313
+ # Inspect a ItLocalVariableReadNode node.
1314
+ def visit_it_local_variable_read_node(node)
1315
+ commands << [inspect_node("ItLocalVariableReadNode", node), indent]
1316
+ end
1317
+
1313
1318
  # Inspect a ItParametersNode node.
1314
1319
  def visit_it_parameters_node(node)
1315
1320
  commands << [inspect_node("ItParametersNode", node), indent]
@@ -1777,8 +1782,10 @@ module Prism
1777
1782
  # Inspect a RationalNode node.
1778
1783
  def visit_rational_node(node)
1779
1784
  commands << [inspect_node("RationalNode", node), indent]
1780
- commands << ["└── numeric:\n", indent]
1781
- commands << [node.numeric, "#{indent} "]
1785
+ flags = [("binary" if node.binary?), ("decimal" if node.decimal?), ("octal" if node.octal?), ("hexadecimal" if node.hexadecimal?)].compact
1786
+ commands << ["├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n", indent]
1787
+ commands << ["├── numerator: #{node.numerator.inspect}\n", indent]
1788
+ commands << ["└── denominator: #{node.denominator.inspect}\n", indent]
1782
1789
  end
1783
1790
 
1784
1791
  # Inspect a RedoNode node.
@@ -2135,13 +2142,8 @@ module Prism
2135
2142
 
2136
2143
  # Compose a header for the given node.
2137
2144
  def inspect_node(name, node)
2138
- result = +"@ #{name} ("
2139
-
2140
2145
  location = node.location
2141
- result << "location: (#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column})"
2142
- result << ", newline: true" if node.newline?
2143
-
2144
- result << ")\n"
2146
+ "@ #{name} (location: (#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column}))\n"
2145
2147
  end
2146
2148
 
2147
2149
  # Compose a string representing the given inner location field.
@@ -446,6 +446,11 @@ module Prism
446
446
  node.copy(parts: visit_all(node.parts))
447
447
  end
448
448
 
449
+ # Copy a ItLocalVariableReadNode node
450
+ def visit_it_local_variable_read_node(node)
451
+ node.copy
452
+ end
453
+
449
454
  # Copy a ItParametersNode node
450
455
  def visit_it_parameters_node(node)
451
456
  node.copy
@@ -618,7 +623,7 @@ module Prism
618
623
 
619
624
  # Copy a RationalNode node
620
625
  def visit_rational_node(node)
621
- node.copy(numeric: visit(node.numeric))
626
+ node.copy
622
627
  end
623
628
 
624
629
  # Copy a RedoNode node