prism 1.3.0 → 1.5.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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -1
  3. data/Makefile +2 -1
  4. data/README.md +1 -0
  5. data/config.yml +273 -37
  6. data/docs/parser_translation.md +8 -23
  7. data/docs/releasing.md +1 -1
  8. data/docs/ripper_translation.md +1 -1
  9. data/docs/ruby_api.md +1 -1
  10. data/ext/prism/api_node.c +1816 -1303
  11. data/ext/prism/extension.c +244 -110
  12. data/ext/prism/extension.h +4 -4
  13. data/include/prism/ast.h +291 -49
  14. data/include/prism/defines.h +4 -1
  15. data/include/prism/diagnostic.h +4 -0
  16. data/include/prism/options.h +89 -3
  17. data/include/prism/regexp.h +2 -2
  18. data/include/prism/util/pm_buffer.h +18 -0
  19. data/include/prism/util/pm_integer.h +4 -0
  20. data/include/prism/util/pm_list.h +6 -0
  21. data/include/prism/util/pm_string.h +12 -2
  22. data/include/prism/version.h +2 -2
  23. data/include/prism.h +41 -16
  24. data/lib/prism/compiler.rb +456 -151
  25. data/lib/prism/desugar_compiler.rb +1 -0
  26. data/lib/prism/dispatcher.rb +16 -0
  27. data/lib/prism/dot_visitor.rb +21 -1
  28. data/lib/prism/dsl.rb +13 -2
  29. data/lib/prism/ffi.rb +62 -34
  30. data/lib/prism/inspect_visitor.rb +5 -1
  31. data/lib/prism/lex_compat.rb +1 -0
  32. data/lib/prism/mutation_compiler.rb +3 -0
  33. data/lib/prism/node.rb +554 -345
  34. data/lib/prism/node_ext.rb +4 -1
  35. data/lib/prism/pack.rb +2 -0
  36. data/lib/prism/parse_result/comments.rb +1 -0
  37. data/lib/prism/parse_result/errors.rb +1 -0
  38. data/lib/prism/parse_result/newlines.rb +2 -1
  39. data/lib/prism/parse_result.rb +53 -0
  40. data/lib/prism/pattern.rb +1 -0
  41. data/lib/prism/polyfill/append_as_bytes.rb +15 -0
  42. data/lib/prism/polyfill/scan_byte.rb +14 -0
  43. data/lib/prism/polyfill/warn.rb +42 -0
  44. data/lib/prism/reflection.rb +5 -2
  45. data/lib/prism/relocation.rb +1 -0
  46. data/lib/prism/serialize.rb +1275 -783
  47. data/lib/prism/string_query.rb +1 -0
  48. data/lib/prism/translation/parser/builder.rb +62 -0
  49. data/lib/prism/translation/parser/compiler.rb +230 -152
  50. data/lib/prism/translation/parser/lexer.rb +446 -64
  51. data/lib/prism/translation/parser.rb +64 -4
  52. data/lib/prism/translation/parser33.rb +1 -0
  53. data/lib/prism/translation/parser34.rb +1 -0
  54. data/lib/prism/translation/parser35.rb +13 -0
  55. data/lib/prism/translation/parser_current.rb +24 -0
  56. data/lib/prism/translation/ripper/sexp.rb +1 -0
  57. data/lib/prism/translation/ripper.rb +30 -4
  58. data/lib/prism/translation/ruby_parser.rb +291 -7
  59. data/lib/prism/translation.rb +3 -0
  60. data/lib/prism/visitor.rb +457 -152
  61. data/lib/prism.rb +5 -3
  62. data/prism.gemspec +9 -1
  63. data/rbi/prism/dsl.rbi +9 -6
  64. data/rbi/prism/node.rbi +43 -16
  65. data/rbi/prism/parse_result.rbi +17 -0
  66. data/rbi/prism/translation/parser35.rbi +6 -0
  67. data/rbi/prism.rbi +39 -36
  68. data/sig/prism/dispatcher.rbs +3 -0
  69. data/sig/prism/dsl.rbs +7 -5
  70. data/sig/prism/node.rbs +461 -37
  71. data/sig/prism/node_ext.rbs +84 -17
  72. data/sig/prism/parse_result/comments.rbs +38 -0
  73. data/sig/prism/parse_result.rbs +14 -0
  74. data/sig/prism/reflection.rbs +1 -1
  75. data/sig/prism/serialize.rbs +4 -2
  76. data/sig/prism.rbs +22 -1
  77. data/src/diagnostic.c +9 -3
  78. data/src/node.c +23 -0
  79. data/src/options.c +33 -2
  80. data/src/prettyprint.c +32 -0
  81. data/src/prism.c +620 -242
  82. data/src/serialize.c +8 -0
  83. data/src/token_type.c +36 -34
  84. data/src/util/pm_buffer.c +40 -0
  85. data/src/util/pm_constant_pool.c +6 -2
  86. data/src/util/pm_strncasecmp.c +13 -1
  87. metadata +11 -7
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
+ # :markup: markdown
2
3
 
4
+ #--
3
5
  # Here we are reopening the prism module to provide methods on nodes that aren't
4
6
  # templated and are meant as convenience methods.
7
+ #++
5
8
  module Prism
6
9
  class Node
7
10
  def deprecated(*replacements) # :nodoc:
@@ -9,7 +12,7 @@ module Prism
9
12
  location = location[0].label if location
10
13
  suggest = replacements.map { |replacement| "#{self.class}##{replacement}" }
11
14
 
12
- warn(<<~MSG, category: :deprecated)
15
+ warn(<<~MSG, uplevel: 1, category: :deprecated)
13
16
  [deprecation]: #{self.class}##{location} is deprecated and will be \
14
17
  removed in the next major version. Use #{suggest.join("/")} instead.
15
18
  #{(caller(1, 3) || []).join("\n")}
data/lib/prism/pack.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
+ # :markup: markdown
2
3
  # typed: ignore
3
4
 
5
+ #
4
6
  module Prism
5
7
  # A parser for the pack template language.
6
8
  module Pack
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # :markup: markdown
2
3
 
3
4
  module Prism
4
5
  class ParseResult < Result
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # :markup: markdown
2
3
 
3
4
  require "stringio"
4
5
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # :markup: markdown
2
3
 
3
4
  module Prism
4
5
  class ParseResult < Result
@@ -63,7 +64,7 @@ module Prism
63
64
 
64
65
  class Node
65
66
  def newline_flag? # :nodoc:
66
- @newline_flag ? true : false
67
+ !!defined?(@newline_flag)
67
68
  end
68
69
 
69
70
  def newline_flag!(lines) # :nodoc:
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # :markup: markdown
2
3
 
3
4
  module Prism
4
5
  # This represents a source of Ruby code that has been parsed. It is used in
@@ -48,6 +49,16 @@ module Prism
48
49
  @offsets = offsets # set after parsing is done
49
50
  end
50
51
 
52
+ # Replace the value of start_line with the given value.
53
+ def replace_start_line(start_line)
54
+ @start_line = start_line
55
+ end
56
+
57
+ # Replace the value of offsets with the given value.
58
+ def replace_offsets(offsets)
59
+ @offsets.replace(offsets)
60
+ end
61
+
51
62
  # Returns the encoding of the source code, which is set by parameters to the
52
63
  # parser or by the encoding magic comment.
53
64
  def encoding
@@ -132,6 +143,13 @@ module Prism
132
143
  code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding)
133
144
  end
134
145
 
146
+ # Freeze this object and the objects it contains.
147
+ def deep_freeze
148
+ source.freeze
149
+ offsets.freeze
150
+ freeze
151
+ end
152
+
135
153
  private
136
154
 
137
155
  # Binary search through the offsets to find the line number for the given
@@ -854,5 +872,40 @@ module Prism
854
872
  location
855
873
  super
856
874
  end
875
+
876
+ # Freeze this object and the objects it contains.
877
+ def deep_freeze
878
+ value.freeze
879
+ location.freeze
880
+ freeze
881
+ end
882
+ end
883
+
884
+ # This object is passed to the various Prism.* methods that accept the
885
+ # `scopes` option as an element of the list. It defines both the local
886
+ # variables visible at that scope as well as the forwarding parameters
887
+ # available at that scope.
888
+ class Scope
889
+ # The list of local variables that are defined in this scope. This should be
890
+ # defined as an array of symbols.
891
+ attr_reader :locals
892
+
893
+ # The list of local variables that are forwarded to the next scope. This
894
+ # should by defined as an array of symbols containing the specific values of
895
+ # :*, :**, :&, or :"...".
896
+ attr_reader :forwarding
897
+
898
+ # Create a new scope object with the given locals and forwarding.
899
+ def initialize(locals, forwarding)
900
+ @locals = locals
901
+ @forwarding = forwarding
902
+ end
903
+ end
904
+
905
+ # Create a new scope with the given locals and forwarding options that is
906
+ # suitable for passing into one of the Prism.* methods that accepts the
907
+ # `scopes` option.
908
+ def self.scope(locals: [], forwarding: [])
909
+ Scope.new(locals, forwarding)
857
910
  end
858
911
  end
data/lib/prism/pattern.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # :markup: markdown
2
3
 
3
4
  module Prism
4
5
  # A pattern is an object that wraps a Ruby pattern matching expression. The
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Polyfill for String#append_as_bytes, which didn't exist until Ruby 3.4.
4
+ if !("".respond_to?(:append_as_bytes))
5
+ String.include(
6
+ Module.new {
7
+ def append_as_bytes(*args)
8
+ args.each do |arg|
9
+ arg = Integer === arg ? [arg].pack("C") : arg.b
10
+ self.<<(arg) # steep:ignore
11
+ end
12
+ end
13
+ }
14
+ )
15
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "strscan"
4
+
5
+ # Polyfill for StringScanner#scan_byte, which didn't exist until Ruby 3.4.
6
+ if !(StringScanner.instance_methods.include?(:scan_byte))
7
+ StringScanner.include(
8
+ Module.new {
9
+ def scan_byte # :nodoc:
10
+ get_byte&.b&.ord
11
+ end
12
+ }
13
+ )
14
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Polyfill for Kernel#warn with the category parameter. Not all Ruby engines
4
+ # have Method#parameters implemented, so we check the arity instead if
5
+ # necessary.
6
+ if (method = Kernel.instance_method(:warn)).respond_to?(:parameters) ? method.parameters.none? { |_, name| name == :category } : (method.arity == -1)
7
+ Kernel.prepend(
8
+ Module.new {
9
+ def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
10
+ uplevel =
11
+ case uplevel
12
+ when nil
13
+ 1
14
+ when Integer
15
+ uplevel + 1
16
+ else
17
+ uplevel.to_int + 1
18
+ end
19
+
20
+ super(*msgs, uplevel: uplevel)
21
+ end
22
+ }
23
+ )
24
+
25
+ Object.prepend(
26
+ Module.new {
27
+ def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
28
+ uplevel =
29
+ case uplevel
30
+ when nil
31
+ 1
32
+ when Integer
33
+ uplevel + 1
34
+ else
35
+ uplevel.to_int + 1
36
+ end
37
+
38
+ super(*msgs, uplevel: uplevel)
39
+ end
40
+ }
41
+ )
42
+ end
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
+ # :markup: markdown
2
3
 
3
4
  =begin
5
+ --
4
6
  This file is generated by the templates/template.rb script and should not be
5
7
  modified manually. See templates/lib/prism/reflection.rb.erb
6
8
  if you are looking to modify the template
9
+ ++
7
10
  =end
8
11
 
9
12
  module Prism
@@ -334,7 +337,7 @@ module Prism
334
337
  when :parameters_node
335
338
  [NodeListField.new(:requireds), NodeListField.new(:optionals), OptionalNodeField.new(:rest), NodeListField.new(:posts), NodeListField.new(:keywords), OptionalNodeField.new(:keyword_rest), OptionalNodeField.new(:block)]
336
339
  when :parentheses_node
337
- [OptionalNodeField.new(:body), LocationField.new(:opening_loc), LocationField.new(:closing_loc)]
340
+ [FlagsField.new(:flags, [:multiple_statements?]), OptionalNodeField.new(:body), LocationField.new(:opening_loc), LocationField.new(:closing_loc)]
338
341
  when :pinned_expression_node
339
342
  [NodeField.new(:expression), LocationField.new(:operator_loc), LocationField.new(:lparen_loc), LocationField.new(:rparen_loc)]
340
343
  when :pinned_variable_node
@@ -360,7 +363,7 @@ module Prism
360
363
  when :rescue_modifier_node
361
364
  [NodeField.new(:expression), LocationField.new(:keyword_loc), NodeField.new(:rescue_expression)]
362
365
  when :rescue_node
363
- [LocationField.new(:keyword_loc), NodeListField.new(:exceptions), OptionalLocationField.new(:operator_loc), OptionalNodeField.new(:reference), OptionalNodeField.new(:statements), OptionalNodeField.new(:subsequent)]
366
+ [LocationField.new(:keyword_loc), NodeListField.new(:exceptions), OptionalLocationField.new(:operator_loc), OptionalNodeField.new(:reference), OptionalLocationField.new(:then_keyword_loc), OptionalNodeField.new(:statements), OptionalNodeField.new(:subsequent)]
364
367
  when :rest_parameter_node
365
368
  [FlagsField.new(:flags, [:repeated_parameter?]), OptionalConstantField.new(:name), OptionalLocationField.new(:name_loc), LocationField.new(:operator_loc)]
366
369
  when :retry_node
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # :markup: markdown
2
3
 
3
4
  module Prism
4
5
  # Prism parses deterministically for the same input. This provides a nice