ruby-next-core 0.15.1 → 0.15.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc36fd395eedfde5c29e65f1f3a75c683630d5111349b3070d3b4e6d200477ad
4
- data.tar.gz: e53e28aec62f7e425a98ba1eeb9591778ca1dbab13a0390113fc7440aab9663d
3
+ metadata.gz: 6020fe263af1a0313e82b5633c45ee76950e7d39bd1f4e70f9d2613eb6ba3fec
4
+ data.tar.gz: 3a1c6da894f68e5e703f0515239bf342852d45f4f5672f68f8fe4011a0e76c57
5
5
  SHA512:
6
- metadata.gz: 50069c2ef6b59005d7efc640e1d84a74e17e4e385aaadce3ac54c2e3e061c7f71b727943140899210af997196f0bdf5a1157b86b97ce7af3de307e68a1cffe12
7
- data.tar.gz: edf464100a254380bee320c586f48afc35782027303840fd319f32260ac5cf771c6f349d7447b9ed2f8a55bab424395664099dbd58600a05ffcd79e49080509f
6
+ metadata.gz: dffe0bf9d32e02cd71aee8f5818d4413a62d96c8d595706c476bee2990823cf960240162b79d51d62036d2bb4a0076b46cba5af93c58760064aae165a82cd6e4
7
+ data.tar.gz: 22879525ffbbbd38921b096ef909ad79d5a87d726dae39f6a108aea2dc82ae5605e6a8e1bd9a190689e0a5da66fc897c6d8d22590f9a237416cd9a79aca43a38
data/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.15.3 (2022-10-16)
6
+
7
+ - Fix handling nested const patterns. ([@palkan][])
8
+
9
+ ## 0.15.2 (2022-08-02)
10
+
11
+ - Fix loading transpiled in TruffleRuby. ([@palkan][])
12
+
13
+ TruffleRuby doesn't support all Ruby 3.0 features yet, so we should treat as an older Ruby.
14
+
15
+ - Use `ruby2_keywords` when transpiling arguments forwarding. ([@palkan][])
16
+
17
+ That makes transpiled code forward compatible with the modern Ruby versions.
18
+
5
19
  ## 0.15.1 (2022-04-05)
6
20
 
7
21
  - Fix transpiling `rescue` within nested blocks. ([@palkan][])
@@ -125,7 +125,7 @@ module RubyNext
125
125
 
126
126
  def patch(*__rest__, &__block__)
127
127
  patches << Patch.new(*__rest__, &__block__)
128
- end
128
+ end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :patch)
129
129
 
130
130
  # Inject `using RubyNext` at the top of the source code
131
131
  def inject!(contents)
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyNext
4
+ module Language
5
+ module Rewriters
6
+ class ArgsForward < Base
7
+ NAME = "args-forward"
8
+ SYNTAX_PROBE = "obj = Object.new; def obj.foo(...) super(...); end"
9
+ MIN_SUPPORTED_VERSION = Gem::Version.new("2.7.0")
10
+
11
+ REST = :__rest__
12
+ BLOCK = :__block__
13
+
14
+ def on_args(node)
15
+ farg = node.children.find { |child| child.is_a?(::Parser::AST::Node) && child.type == :forward_arg }
16
+ return unless farg
17
+
18
+ context.track! self
19
+
20
+ node = super(node)
21
+
22
+ replace(farg.loc.expression, "*#{REST}, &#{BLOCK}")
23
+
24
+ node.updated(
25
+ :args,
26
+ [
27
+ *node.children.slice(0, node.children.index(farg)),
28
+ s(:restarg, REST),
29
+ s(:blockarg, BLOCK)
30
+ ]
31
+ )
32
+ end
33
+
34
+ def on_send(node)
35
+ fargs = extract_fargs(node)
36
+ return super(node) unless fargs
37
+
38
+ process_fargs(node, fargs)
39
+ end
40
+
41
+ def on_super(node)
42
+ fargs = extract_fargs(node)
43
+ return super(node) unless fargs
44
+
45
+ process_fargs(node, fargs)
46
+ end
47
+
48
+ def on_def(node)
49
+ return super unless forward_arg?(node.children[1])
50
+
51
+ new_node = super
52
+
53
+ name = node.children[0]
54
+
55
+ insert_after(node.loc.expression, "; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :#{name})")
56
+
57
+ s(:begin,
58
+ new_node,
59
+ ruby2_keywords_node(nil, name))
60
+ end
61
+
62
+ def on_defs(node)
63
+ return super unless forward_arg?(node.children[2])
64
+
65
+ new_node = super
66
+
67
+ receiver = node.children[0]
68
+ name = node.children[1]
69
+
70
+ # Using self.ruby2_keywords :name results in undefined method error,
71
+ # singleton_class works as expected
72
+ receiver = s(:send, nil, :singleton_class) if receiver.type == :self
73
+
74
+ receiver_name =
75
+ case receiver.type
76
+ when :send
77
+ receiver.children[1]
78
+ when :const
79
+ receiver.children[1]
80
+ end
81
+
82
+ insert_after(node.loc.expression, "; #{receiver_name}.respond_to?(:ruby2_keywords, true) && (#{receiver_name}.send(:ruby2_keywords, :#{name}))")
83
+
84
+ s(:begin,
85
+ new_node,
86
+ ruby2_keywords_node(receiver, name))
87
+ end
88
+
89
+ private
90
+
91
+ def ruby2_keywords_node(receiver, name)
92
+ s(:and,
93
+ s(:send, receiver, :respond_to?,
94
+ s(:sym, :ruby2_keywords), s(:true)),
95
+ s(:begin,
96
+ s(:send, receiver, :send,
97
+ s(:sym, :ruby2_keywords),
98
+ s(:sym, name))))
99
+ end
100
+
101
+ def forward_arg?(args)
102
+ return false unless ((((__safe_lvar__ = args) || true) && (!__safe_lvar__.nil? || nil)) && __safe_lvar__.children)
103
+
104
+ args.children.any? { |arg| arg.type == :forward_arg }
105
+ end
106
+
107
+ def extract_fargs(node)
108
+ node.children.find { |child| child.is_a?(::Parser::AST::Node) && child.type == :forwarded_args }
109
+ end
110
+
111
+ def process_fargs(node, fargs)
112
+ replace(fargs.loc.expression, "*#{REST}, &#{BLOCK}")
113
+
114
+ process(
115
+ node.updated(
116
+ nil,
117
+ [
118
+ *node.children.take(node.children.index(fargs)),
119
+ *forwarded_args
120
+ ]
121
+ )
122
+ )
123
+ end
124
+
125
+ def forwarded_args
126
+ [
127
+ s(:splat, s(:lvar, REST)),
128
+ s(:block_pass, s(:lvar, BLOCK))
129
+ ]
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -425,15 +425,15 @@ module RubyNext
425
425
  s(:begin,
426
426
  s(:and,
427
427
  node,
428
- send(:"#{pattern.type}_clause", pattern)))
428
+ send(:"#{pattern.type}_clause", pattern, right)))
429
429
  end
430
430
  end
431
431
 
432
- def match_alt_clause(node)
432
+ def match_alt_clause(node, matchee = s(:lvar, locals[:matchee]))
433
433
  children = locals.with(ALTERNATION_MARKER => true) do
434
434
  node.children.map.with_index do |child, i|
435
435
  predicates.terminate! if i == 1
436
- send :"#{child.type}_clause", child
436
+ send :"#{child.type}_clause", child, matchee
437
437
  end
438
438
  end
439
439
  s(:begin, s(:or, *children))
@@ -663,6 +663,14 @@ module RubyNext
663
663
  end
664
664
  end
665
665
 
666
+ def const_pattern_array_element(node, index)
667
+ element = arr_item_at(index)
668
+ locals.with(arr: locals[:arr, index]) do
669
+ predicates.push :"i#{index}"
670
+ const_pattern_clause(node, element).tap { predicates.pop }
671
+ end
672
+ end
673
+
666
674
  def match_alt_array_element(node, index)
667
675
  children = node.children.map do |child, i|
668
676
  send :"#{child.type}_array_element", child, index
@@ -671,11 +679,19 @@ module RubyNext
671
679
  end
672
680
 
673
681
  def match_var_array_element(node, index)
674
- match_var_clause(node, arr_item_at(index))
682
+ element = arr_item_at(index)
683
+ locals.with(arr: locals[:arr, index]) do
684
+ predicates.push :"i#{index}"
685
+ match_var_clause(node, element).tap { predicates.pop }
686
+ end
675
687
  end
676
688
 
677
689
  def match_as_array_element(node, index)
678
- match_as_clause(node, arr_item_at(index))
690
+ element = arr_item_at(index)
691
+ locals.with(arr: locals[:arr, index]) do
692
+ predicates.push :"i#{index}"
693
+ match_as_clause(node, element).tap { predicates.pop }
694
+ end
679
695
  end
680
696
 
681
697
  def pin_array_element(node, index)
@@ -844,6 +860,15 @@ module RubyNext
844
860
  end
845
861
  end
846
862
 
863
+ def const_pattern_hash_element(node, key)
864
+ element = hash_value_at(key)
865
+ key_index = deconstructed_key(key)
866
+ locals.with(hash: locals[:hash, key_index]) do
867
+ predicates.push :"k#{key_index}"
868
+ const_pattern_clause(node, element).tap { predicates.pop }
869
+ end
870
+ end
871
+
847
872
  def hash_element(head, *tail)
848
873
  send("#{head.type}_hash_element", head).then do |node|
849
874
  next node if tail.empty?
@@ -884,12 +909,22 @@ module RubyNext
884
909
  end
885
910
 
886
911
  def match_as_hash_element(node, key)
887
- match_as_clause(node, hash_value_at(key))
912
+ element = hash_value_at(key)
913
+ key_index = deconstructed_key(key)
914
+ locals.with(hash: locals[:hash, key_index]) do
915
+ predicates.push :"k#{key_index}"
916
+ match_as_clause(node, element).tap { predicates.pop }
917
+ end
888
918
  end
889
919
 
890
920
  def match_var_hash_element(node, key = nil)
891
921
  key ||= node.children[0]
892
- match_var_clause(node, hash_value_at(key))
922
+ element = hash_value_at(key)
923
+ key_index = deconstructed_key(key)
924
+ locals.with(hash: locals[:hash, key_index]) do
925
+ predicates.push :"k#{key_index}"
926
+ match_var_clause(node, element).tap { predicates.pop }
927
+ end
893
928
  end
894
929
 
895
930
  def match_nil_pattern_hash_element(node, _key = nil)
@@ -125,7 +125,7 @@ module RubyNext
125
125
 
126
126
  def patch(*__rest__, &__block__)
127
127
  patches << Patch.new(*__rest__, &__block__)
128
- end
128
+ end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :patch)
129
129
 
130
130
  # Inject `using RubyNext` at the top of the source code
131
131
  def inject!(contents)
@@ -425,15 +425,15 @@ module RubyNext
425
425
  s(:begin,
426
426
  s(:and,
427
427
  node,
428
- send(:"#{pattern.type}_clause", pattern)))
428
+ send(:"#{pattern.type}_clause", pattern, right)))
429
429
  end
430
430
  end
431
431
 
432
- def match_alt_clause(node)
432
+ def match_alt_clause(node, matchee = s(:lvar, locals[:matchee]))
433
433
  children = locals.with(ALTERNATION_MARKER => true) do
434
434
  node.children.map.with_index do |child, i|
435
435
  predicates.terminate! if i == 1
436
- send :"#{child.type}_clause", child
436
+ send :"#{child.type}_clause", child, matchee
437
437
  end
438
438
  end
439
439
  s(:begin, s(:or, *children))
@@ -663,6 +663,14 @@ module RubyNext
663
663
  end
664
664
  end
665
665
 
666
+ def const_pattern_array_element(node, index)
667
+ element = arr_item_at(index)
668
+ locals.with(arr: locals[:arr, index]) do
669
+ predicates.push :"i#{index}"
670
+ const_pattern_clause(node, element).tap { predicates.pop }
671
+ end
672
+ end
673
+
666
674
  def match_alt_array_element(node, index)
667
675
  children = node.children.map do |child, i|
668
676
  send :"#{child.type}_array_element", child, index
@@ -671,11 +679,19 @@ module RubyNext
671
679
  end
672
680
 
673
681
  def match_var_array_element(node, index)
674
- match_var_clause(node, arr_item_at(index))
682
+ element = arr_item_at(index)
683
+ locals.with(arr: locals[:arr, index]) do
684
+ predicates.push :"i#{index}"
685
+ match_var_clause(node, element).tap { predicates.pop }
686
+ end
675
687
  end
676
688
 
677
689
  def match_as_array_element(node, index)
678
- match_as_clause(node, arr_item_at(index))
690
+ element = arr_item_at(index)
691
+ locals.with(arr: locals[:arr, index]) do
692
+ predicates.push :"i#{index}"
693
+ match_as_clause(node, element).tap { predicates.pop }
694
+ end
679
695
  end
680
696
 
681
697
  def pin_array_element(node, index)
@@ -844,6 +860,15 @@ module RubyNext
844
860
  end
845
861
  end
846
862
 
863
+ def const_pattern_hash_element(node, key)
864
+ element = hash_value_at(key)
865
+ key_index = deconstructed_key(key)
866
+ locals.with(hash: locals[:hash, key_index]) do
867
+ predicates.push :"k#{key_index}"
868
+ const_pattern_clause(node, element).tap { predicates.pop }
869
+ end
870
+ end
871
+
847
872
  def hash_element(head, *tail)
848
873
  send("#{head.type}_hash_element", head).then do |node|
849
874
  next node if tail.empty?
@@ -884,12 +909,22 @@ module RubyNext
884
909
  end
885
910
 
886
911
  def match_as_hash_element(node, key)
887
- match_as_clause(node, hash_value_at(key))
912
+ element = hash_value_at(key)
913
+ key_index = deconstructed_key(key)
914
+ locals.with(hash: locals[:hash, key_index]) do
915
+ predicates.push :"k#{key_index}"
916
+ match_as_clause(node, element).tap { predicates.pop }
917
+ end
888
918
  end
889
919
 
890
920
  def match_var_hash_element(node, key = nil)
891
921
  key ||= node.children[0]
892
- match_var_clause(node, hash_value_at(key))
922
+ element = hash_value_at(key)
923
+ key_index = deconstructed_key(key)
924
+ locals.with(hash: locals[:hash, key_index]) do
925
+ predicates.push :"k#{key_index}"
926
+ match_var_clause(node, element).tap { predicates.pop }
927
+ end
893
928
  end
894
929
 
895
930
  def match_nil_pattern_hash_element(node, _key = nil)
data/lib/ruby-next/cli.rb CHANGED
@@ -24,9 +24,6 @@ module RubyNext
24
24
  "core_ext" => Commands::CoreExt
25
25
  }.freeze
26
26
 
27
- def initialize
28
- end
29
-
30
27
  def run(args = ARGV)
31
28
  maybe_print_version(args)
32
29
 
@@ -19,8 +19,8 @@ module RubyNext
19
19
  NEXT_VERSION = "1995.next.0"
20
20
 
21
21
  class << self
22
- # TruffleRuby claims it's 2.7.2 compatible but...
23
- if defined?(TruffleRuby) && ::RUBY_VERSION =~ /^2\.7/
22
+ # TruffleRuby claims its RUBY_VERSION to be X.Y while not supporting all the features
23
+ if defined?(TruffleRuby)
24
24
  def current_ruby_version
25
25
  "2.6.5"
26
26
  end
@@ -45,8 +45,65 @@ module RubyNext
45
45
  process_fargs(node, fargs)
46
46
  end
47
47
 
48
+ def on_def(node)
49
+ return super unless forward_arg?(node.children[1])
50
+
51
+ new_node = super
52
+
53
+ name = node.children[0]
54
+
55
+ insert_after(node.loc.expression, "; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :#{name})")
56
+
57
+ s(:begin,
58
+ new_node,
59
+ ruby2_keywords_node(nil, name))
60
+ end
61
+
62
+ def on_defs(node)
63
+ return super unless forward_arg?(node.children[2])
64
+
65
+ new_node = super
66
+
67
+ receiver = node.children[0]
68
+ name = node.children[1]
69
+
70
+ # Using self.ruby2_keywords :name results in undefined method error,
71
+ # singleton_class works as expected
72
+ receiver = s(:send, nil, :singleton_class) if receiver.type == :self
73
+
74
+ receiver_name =
75
+ case receiver.type
76
+ when :send
77
+ receiver.children[1]
78
+ when :const
79
+ receiver.children[1]
80
+ end
81
+
82
+ insert_after(node.loc.expression, "; #{receiver_name}.respond_to?(:ruby2_keywords, true) && (#{receiver_name}.send(:ruby2_keywords, :#{name}))")
83
+
84
+ s(:begin,
85
+ new_node,
86
+ ruby2_keywords_node(receiver, name))
87
+ end
88
+
48
89
  private
49
90
 
91
+ def ruby2_keywords_node(receiver, name)
92
+ s(:and,
93
+ s(:send, receiver, :respond_to?,
94
+ s(:sym, :ruby2_keywords), s(:true)),
95
+ s(:begin,
96
+ s(:send, receiver, :send,
97
+ s(:sym, :ruby2_keywords),
98
+ s(:sym, name))))
99
+ end
100
+
101
+ def forward_arg?(args)
102
+ return false unless args&.children
103
+
104
+ args.children.any? { |arg| arg.type == :forward_arg }
105
+ end
106
+
50
107
  def extract_fargs(node)
51
108
  node.children.find { |child| child.is_a?(::Parser::AST::Node) && child.type == :forwarded_args }
52
109
  end
@@ -425,15 +425,15 @@ module RubyNext
425
425
  s(:begin,
426
426
  s(:and,
427
427
  node,
428
- send(:"#{pattern.type}_clause", pattern)))
428
+ send(:"#{pattern.type}_clause", pattern, right)))
429
429
  end
430
430
  end
431
431
 
432
- def match_alt_clause(node)
432
+ def match_alt_clause(node, matchee = s(:lvar, locals[:matchee]))
433
433
  children = locals.with(ALTERNATION_MARKER => true) do
434
434
  node.children.map.with_index do |child, i|
435
435
  predicates.terminate! if i == 1
436
- send :"#{child.type}_clause", child
436
+ send :"#{child.type}_clause", child, matchee
437
437
  end
438
438
  end
439
439
  s(:begin, s(:or, *children))
@@ -663,6 +663,14 @@ module RubyNext
663
663
  end
664
664
  end
665
665
 
666
+ def const_pattern_array_element(node, index)
667
+ element = arr_item_at(index)
668
+ locals.with(arr: locals[:arr, index]) do
669
+ predicates.push :"i#{index}"
670
+ const_pattern_clause(node, element).tap { predicates.pop }
671
+ end
672
+ end
673
+
666
674
  def match_alt_array_element(node, index)
667
675
  children = node.children.map do |child, i|
668
676
  send :"#{child.type}_array_element", child, index
@@ -671,11 +679,19 @@ module RubyNext
671
679
  end
672
680
 
673
681
  def match_var_array_element(node, index)
674
- match_var_clause(node, arr_item_at(index))
682
+ element = arr_item_at(index)
683
+ locals.with(arr: locals[:arr, index]) do
684
+ predicates.push :"i#{index}"
685
+ match_var_clause(node, element).tap { predicates.pop }
686
+ end
675
687
  end
676
688
 
677
689
  def match_as_array_element(node, index)
678
- match_as_clause(node, arr_item_at(index))
690
+ element = arr_item_at(index)
691
+ locals.with(arr: locals[:arr, index]) do
692
+ predicates.push :"i#{index}"
693
+ match_as_clause(node, element).tap { predicates.pop }
694
+ end
679
695
  end
680
696
 
681
697
  def pin_array_element(node, index)
@@ -844,6 +860,15 @@ module RubyNext
844
860
  end
845
861
  end
846
862
 
863
+ def const_pattern_hash_element(node, key)
864
+ element = hash_value_at(key)
865
+ key_index = deconstructed_key(key)
866
+ locals.with(hash: locals[:hash, key_index]) do
867
+ predicates.push :"k#{key_index}"
868
+ const_pattern_clause(node, element).tap { predicates.pop }
869
+ end
870
+ end
871
+
847
872
  def hash_element(head, *tail)
848
873
  send("#{head.type}_hash_element", head).then do |node|
849
874
  next node if tail.empty?
@@ -884,12 +909,22 @@ module RubyNext
884
909
  end
885
910
 
886
911
  def match_as_hash_element(node, key)
887
- match_as_clause(node, hash_value_at(key))
912
+ element = hash_value_at(key)
913
+ key_index = deconstructed_key(key)
914
+ locals.with(hash: locals[:hash, key_index]) do
915
+ predicates.push :"k#{key_index}"
916
+ match_as_clause(node, element).tap { predicates.pop }
917
+ end
888
918
  end
889
919
 
890
920
  def match_var_hash_element(node, key = nil)
891
921
  key ||= node.children[0]
892
- match_var_clause(node, hash_value_at(key))
922
+ element = hash_value_at(key)
923
+ key_index = deconstructed_key(key)
924
+ locals.with(hash: locals[:hash, key_index]) do
925
+ predicates.push :"k#{key_index}"
926
+ match_var_clause(node, element).tap { predicates.pop }
927
+ end
893
928
  end
894
929
 
895
930
  def match_nil_pattern_hash_element(node, _key = nil)
@@ -12,7 +12,7 @@ module RubyNext
12
12
  return if File.directory?(target_dir)
13
13
 
14
14
  Dir.chdir(root_dir) do
15
- unless system("bundle exec ruby-next nextify ./#{lib_dir} -o #{target_dir} --min-version=#{RUBY_VERSION} > /dev/null 2>&1")
15
+ unless system("bundle exec ruby-next nextify ./#{lib_dir} -o #{target_dir} --min-version=#{RubyNext.current_ruby_version} > /dev/null 2>&1")
16
16
  RubyNext.warn "Traspiled files are missing in: #{target_dir}. \n" \
17
17
  "Make sure you have gem 'ruby-next' in your Gemfile to auto-transpile the required files from source on load. " \
18
18
  "Otherwise the code from #{root_dir} may not work correctly."
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyNext
4
- VERSION = "0.15.1"
4
+ VERSION = "0.15.3"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-next-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.1
4
+ version: 0.15.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-05 00:00:00.000000000 Z
11
+ date: 2022-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-next-parser
@@ -62,6 +62,7 @@ files:
62
62
  - lib/.rbnext/2.3/ruby-next/commands/nextify.rb
63
63
  - lib/.rbnext/2.3/ruby-next/language/eval.rb
64
64
  - lib/.rbnext/2.3/ruby-next/language/rewriters/2.6/endless_range.rb
65
+ - lib/.rbnext/2.3/ruby-next/language/rewriters/2.7/args_forward.rb
65
66
  - lib/.rbnext/2.3/ruby-next/language/rewriters/2.7/pattern_matching.rb
66
67
  - lib/.rbnext/2.3/ruby-next/language/rewriters/3.1/anonymous_block.rb
67
68
  - lib/.rbnext/2.3/ruby-next/language/rewriters/base.rb
@@ -170,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
171
  - !ruby/object:Gem::Version
171
172
  version: '0'
172
173
  requirements: []
173
- rubygems_version: 3.3.7
174
+ rubygems_version: 3.3.11
174
175
  signing_key:
175
176
  specification_version: 4
176
177
  summary: Ruby Next core functionality