ruby-next-core 0.12.0 → 0.13.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +15 -3
- data/lib/.rbnext/2.1/ruby-next/core.rb +3 -0
- data/lib/.rbnext/2.1/ruby-next/language.rb +227 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/pattern_matching.rb +1 -1
- data/lib/.rbnext/2.7/ruby-next/core.rb +3 -0
- data/lib/ruby-next/core/array/intersect.rb +9 -0
- data/lib/ruby-next/core/constants/frozen_error.rb +15 -0
- data/lib/ruby-next/core/enumerable/tally.rb +46 -7
- data/lib/ruby-next/core.rb +3 -0
- data/lib/ruby-next/language/rewriters/args_forward.rb +6 -2
- data/lib/ruby-next/language/rewriters/args_forward_leading.rb +1 -1
- data/lib/ruby-next/language/rewriters/pattern_matching.rb +1 -1
- data/lib/ruby-next/language/setup.rb +1 -1
- data/lib/ruby-next/language.rb +44 -43
- data/lib/ruby-next/setup_self.rb +3 -1
- data/lib/ruby-next/version.rb +1 -1
- metadata +11 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e73900618b0d9da915699c40c610736e19919ac0d11bce7c7dc58e7d5ddb84b
|
4
|
+
data.tar.gz: b07917f44a763467f4bed145ae1224ba8aeb03eaba7924b2787c681df4b704f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb7bc9bc3416a8b6df9e99f346fb15c2c0ae0a9d63bba739adaa6c604110eaa753a5d7b00d98443400e92d7233fba7b4fda2a43e866ce85ef04ed46cd7e89a4c
|
7
|
+
data.tar.gz: 0b6410607425aaa0afb66309fa07739e72e3b8cbf94addf85d501f136755159db968225b6d1752a1bda77911592252d48e2d2c5421dae5798d5741ef6ec33616
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.13.0 (2021-09-27)
|
6
|
+
|
7
|
+
- Added `Enumerable#tally` with the resulting hash. ([@skryukov][])
|
8
|
+
|
9
|
+
- Added `Array#intersect?`. ([@skryukov][])
|
10
|
+
|
5
11
|
## 0.12.0 (2021-01-12)
|
6
12
|
|
7
13
|
- Added required keyword arguments rewriter. ([@palkan][])
|
@@ -281,3 +287,4 @@ p a #=> 1
|
|
281
287
|
[@palkan]: https://github.com/palkan
|
282
288
|
[backports]: https://github.com/marcandre/backports
|
283
289
|
[@sl4vr]: https://github.com/sl4vr
|
290
|
+
[@skryukov]: https://github.com/skryukov
|
data/README.md
CHANGED
@@ -21,8 +21,20 @@ That's why Ruby Next implements the `master` features as fast as possible.
|
|
21
21
|
|
22
22
|
Read more about the motivation behind the Ruby Next in this post: [Ruby Next: Make all Rubies quack alike](https://evilmartians.com/chronicles/ruby-next-make-all-rubies-quack-alike).
|
23
23
|
|
24
|
-
<
|
25
|
-
<
|
24
|
+
<table style="border:none;">
|
25
|
+
<tr>
|
26
|
+
<td>
|
27
|
+
<a href="https://evilmartians.com/?utm_source=ruby-next">
|
28
|
+
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54">
|
29
|
+
</a>
|
30
|
+
</td>
|
31
|
+
<td>
|
32
|
+
<a href="http://www.digitalfukuoka.jp/topics/169">
|
33
|
+
<img src="http://www.digitalfukuoka.jp/javascripts/kcfinder/upload/images/excellence.jpg" width="200">
|
34
|
+
</a>
|
35
|
+
</td>
|
36
|
+
</tr>
|
37
|
+
</table>
|
26
38
|
|
27
39
|
## Posts
|
28
40
|
|
@@ -510,7 +522,7 @@ require "ruby-next/language/runtime"
|
|
510
522
|
|
511
523
|
### Supported edge features
|
512
524
|
|
513
|
-
|
525
|
+
`Array#intersect?` ([#15198](https://bugs.ruby-lang.org/issues/15198))
|
514
526
|
|
515
527
|
### Supported proposed features
|
516
528
|
|
@@ -181,6 +181,7 @@ unless defined?(NoMatchingPatternError)
|
|
181
181
|
end
|
182
182
|
|
183
183
|
require "ruby-next/core/constants/no_matching_pattern_error"
|
184
|
+
require "ruby-next/core/constants/frozen_error"
|
184
185
|
require "ruby-next/core/array/deconstruct"
|
185
186
|
require "ruby-next/core/hash/deconstruct_keys"
|
186
187
|
require "ruby-next/core/struct/deconstruct"
|
@@ -188,6 +189,8 @@ require "ruby-next/core/struct/deconstruct_keys"
|
|
188
189
|
|
189
190
|
require "ruby-next/core/hash/except"
|
190
191
|
|
192
|
+
require "ruby-next/core/array/intersect"
|
193
|
+
|
191
194
|
# Generate refinements
|
192
195
|
RubyNext.module_eval do
|
193
196
|
RubyNext::Core.patches.refined.each do |mod, patches|
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
gem "ruby-next-parser", ">= 2.8.0.3"
|
4
|
+
gem "unparser", ">= 0.4.7"
|
5
|
+
|
6
|
+
require "set"
|
7
|
+
|
8
|
+
require "ruby-next"
|
9
|
+
|
10
|
+
module RubyNext
|
11
|
+
# Language module contains tools to transpile newer Ruby syntax
|
12
|
+
# into an older one.
|
13
|
+
#
|
14
|
+
# It works the following way:
|
15
|
+
# - Takes a Ruby source code as input
|
16
|
+
# - Generates the AST using the edge parser (via the `parser` gem)
|
17
|
+
# - Pass this AST through the list of processors (one feature = one processor)
|
18
|
+
# - Each processor may modify the AST
|
19
|
+
# - Generates a transpiled source code from the transformed AST (via the `unparser` gem)
|
20
|
+
module Language
|
21
|
+
using RubyNext
|
22
|
+
|
23
|
+
require "ruby-next/language/parser"
|
24
|
+
require "ruby-next/language/unparser"
|
25
|
+
|
26
|
+
RewriterNotFoundError = Class.new(StandardError)
|
27
|
+
|
28
|
+
class TransformContext
|
29
|
+
attr_reader :versions, :use_ruby_next
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
# Minimum supported RubyNext version
|
33
|
+
@min_version = MIN_SUPPORTED_VERSION
|
34
|
+
@dirty = false
|
35
|
+
@versions = Set.new
|
36
|
+
@use_ruby_next = false
|
37
|
+
end
|
38
|
+
|
39
|
+
# Called by rewriter when it performs transfomrations
|
40
|
+
def track!(rewriter)
|
41
|
+
@dirty = true
|
42
|
+
versions << rewriter.class::MIN_SUPPORTED_VERSION
|
43
|
+
end
|
44
|
+
|
45
|
+
def use_ruby_next!
|
46
|
+
@use_ruby_next = true
|
47
|
+
end
|
48
|
+
|
49
|
+
alias use_ruby_next? use_ruby_next
|
50
|
+
|
51
|
+
def dirty?
|
52
|
+
@dirty == true
|
53
|
+
end
|
54
|
+
|
55
|
+
def min_version
|
56
|
+
versions.min
|
57
|
+
end
|
58
|
+
|
59
|
+
def sorted_versions
|
60
|
+
versions.to_a.sort
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class << self
|
65
|
+
attr_accessor :rewriters
|
66
|
+
attr_reader :watch_dirs
|
67
|
+
|
68
|
+
attr_accessor :strategy
|
69
|
+
|
70
|
+
MODES = %i[rewrite ast].freeze
|
71
|
+
|
72
|
+
attr_reader :mode
|
73
|
+
|
74
|
+
def mode=(val)
|
75
|
+
raise ArgumentError, "Unknown mode: #{val}. Available: #{MODES.join(",")}" unless MODES.include?(val)
|
76
|
+
@mode = val
|
77
|
+
end
|
78
|
+
|
79
|
+
def rewrite?
|
80
|
+
mode == :rewrite?
|
81
|
+
end
|
82
|
+
|
83
|
+
def ast?
|
84
|
+
mode == :ast
|
85
|
+
end
|
86
|
+
|
87
|
+
def runtime!
|
88
|
+
require "ruby-next/language/rewriters/runtime"
|
89
|
+
|
90
|
+
@runtime = true
|
91
|
+
end
|
92
|
+
|
93
|
+
def runtime?
|
94
|
+
@runtime
|
95
|
+
end
|
96
|
+
|
97
|
+
def transform(source, rewriters: self.rewriters, using: RubyNext::Core.refine?, context: TransformContext.new)
|
98
|
+
retried = 0
|
99
|
+
new_source = nil
|
100
|
+
begin
|
101
|
+
new_source =
|
102
|
+
if mode == :rewrite
|
103
|
+
rewrite(source, rewriters: rewriters, using: using, context: context)
|
104
|
+
else
|
105
|
+
regenerate(source, rewriters: rewriters, using: using, context: context)
|
106
|
+
end
|
107
|
+
rescue Unparser::UnknownNodeError => err
|
108
|
+
RubyNext.warn "Ruby Next fallbacks to \"rewrite\" transpiling mode since the version of Unparser you use doesn't support some syntax yet: #{err.message}.\n" \
|
109
|
+
"Try upgrading the Unparser or set transpiling mode to \"rewrite\" in case you use some edge or experimental syntax."
|
110
|
+
self.mode = :rewrite
|
111
|
+
retried += 1
|
112
|
+
retry unless retried > 1
|
113
|
+
raise
|
114
|
+
end
|
115
|
+
|
116
|
+
return new_source unless RubyNext::Core.refine?
|
117
|
+
return new_source unless using && context.use_ruby_next?
|
118
|
+
|
119
|
+
Core.inject! new_source.dup
|
120
|
+
end
|
121
|
+
|
122
|
+
def transformable?(path)
|
123
|
+
watch_dirs.any? { |dir| path.start_with?(dir) }
|
124
|
+
end
|
125
|
+
|
126
|
+
# Rewriters required for the current version
|
127
|
+
def current_rewriters
|
128
|
+
@current_rewriters ||= rewriters.select(&:unsupported_syntax?)
|
129
|
+
end
|
130
|
+
|
131
|
+
# This method guarantees that rewriters will be returned in order they defined in Language module
|
132
|
+
def select_rewriters(*names)
|
133
|
+
rewriters_delta = names - rewriters.map { |rewriter| rewriter::NAME }
|
134
|
+
if rewriters_delta.any?
|
135
|
+
raise RewriterNotFoundError, "Rewriters not found: #{rewriters_delta.join(",")}"
|
136
|
+
end
|
137
|
+
|
138
|
+
rewriters.select { |rewriter| names.include?(rewriter::NAME) }
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def regenerate(source, rewriters: ::Kernel.raise(::ArgumentError, "missing keyword: rewriters"), using: ::Kernel.raise(::ArgumentError, "missing keyword: using"), context: ::Kernel.raise(::ArgumentError, "missing keyword: context"))
|
144
|
+
parse_with_comments(source).then do |(ast, comments)|
|
145
|
+
rewriters.inject(ast) do |tree, rewriter|
|
146
|
+
rewriter.new(context).process(tree)
|
147
|
+
end.then do |new_ast|
|
148
|
+
next source unless context.dirty?
|
149
|
+
|
150
|
+
Unparser.unparse(new_ast, comments)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def rewrite(source, rewriters: ::Kernel.raise(::ArgumentError, "missing keyword: rewriters"), using: ::Kernel.raise(::ArgumentError, "missing keyword: using"), context: ::Kernel.raise(::ArgumentError, "missing keyword: context"))
|
156
|
+
rewriters.inject(source) do |src, rewriter|
|
157
|
+
buffer = Parser::Source::Buffer.new("<dynamic>")
|
158
|
+
buffer.source = src
|
159
|
+
|
160
|
+
rewriter.new(context).rewrite(buffer, parse(src))
|
161
|
+
end.then do |new_source|
|
162
|
+
next source unless context.dirty?
|
163
|
+
|
164
|
+
new_source
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
attr_writer :watch_dirs
|
169
|
+
end
|
170
|
+
|
171
|
+
self.rewriters = []
|
172
|
+
self.watch_dirs = %w[app lib spec test].map { |path| File.join(Dir.pwd, path) }
|
173
|
+
self.mode = ENV.fetch("RUBY_NEXT_TRANSPILE_MODE", "rewrite").to_sym
|
174
|
+
|
175
|
+
require "ruby-next/language/rewriters/base"
|
176
|
+
|
177
|
+
require "ruby-next/language/rewriters/squiggly_heredoc"
|
178
|
+
rewriters << Rewriters::SquigglyHeredoc
|
179
|
+
|
180
|
+
require "ruby-next/language/rewriters/safe_navigation"
|
181
|
+
rewriters << Rewriters::SafeNavigation
|
182
|
+
|
183
|
+
require "ruby-next/language/rewriters/numeric_literals"
|
184
|
+
rewriters << Rewriters::NumericLiterals
|
185
|
+
|
186
|
+
require "ruby-next/language/rewriters/required_kwargs"
|
187
|
+
rewriters << Rewriters::RequiredKwargs
|
188
|
+
|
189
|
+
require "ruby-next/language/rewriters/args_forward"
|
190
|
+
rewriters << Rewriters::ArgsForward
|
191
|
+
|
192
|
+
# Must be added after general args forward rewriter to become
|
193
|
+
# no-op in Ruby <2.7
|
194
|
+
require "ruby-next/language/rewriters/args_forward_leading"
|
195
|
+
rewriters << Rewriters::ArgsForwardLeading
|
196
|
+
|
197
|
+
require "ruby-next/language/rewriters/numbered_params"
|
198
|
+
rewriters << Rewriters::NumberedParams
|
199
|
+
|
200
|
+
require "ruby-next/language/rewriters/pattern_matching"
|
201
|
+
rewriters << Rewriters::PatternMatching
|
202
|
+
|
203
|
+
# Must be added after general pattern matching rewriter to become
|
204
|
+
# no-op in Ruby <2.7
|
205
|
+
require "ruby-next/language/rewriters/find_pattern"
|
206
|
+
rewriters << Rewriters::FindPattern
|
207
|
+
|
208
|
+
require "ruby-next/language/rewriters/in_pattern"
|
209
|
+
rewriters << Rewriters::InPattern
|
210
|
+
|
211
|
+
# Put endless range in the end, 'cause Parser fails to parse it in
|
212
|
+
# pattern matching
|
213
|
+
require "ruby-next/language/rewriters/endless_range"
|
214
|
+
rewriters << Rewriters::EndlessRange
|
215
|
+
|
216
|
+
require "ruby-next/language/rewriters/endless_method"
|
217
|
+
RubyNext::Language.rewriters << RubyNext::Language::Rewriters::EndlessMethod
|
218
|
+
|
219
|
+
if ENV["RUBY_NEXT_EDGE"] == "1"
|
220
|
+
require "ruby-next/language/edge"
|
221
|
+
end
|
222
|
+
|
223
|
+
if ENV["RUBY_NEXT_PROPOSED"] == "1"
|
224
|
+
require "ruby-next/language/proposed"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
@@ -181,6 +181,7 @@ unless defined?(NoMatchingPatternError)
|
|
181
181
|
end
|
182
182
|
|
183
183
|
require "ruby-next/core/constants/no_matching_pattern_error"
|
184
|
+
require "ruby-next/core/constants/frozen_error"
|
184
185
|
require "ruby-next/core/array/deconstruct"
|
185
186
|
require "ruby-next/core/hash/deconstruct_keys"
|
186
187
|
require "ruby-next/core/struct/deconstruct"
|
@@ -188,6 +189,8 @@ require "ruby-next/core/struct/deconstruct_keys"
|
|
188
189
|
|
189
190
|
require "ruby-next/core/hash/except"
|
190
191
|
|
192
|
+
require "ruby-next/core/array/intersect"
|
193
|
+
|
191
194
|
# Generate refinements
|
192
195
|
RubyNext.module_eval do
|
193
196
|
RubyNext::Core.patches.refined.each do |mod, patches|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RubyNext::Core.patch Object,
|
4
|
+
name: "FrozenError",
|
5
|
+
method: nil,
|
6
|
+
refineable: [],
|
7
|
+
version: "2.5",
|
8
|
+
# avoid defining the constant twice, 'causae it's already included in core
|
9
|
+
# we only use the contents in `ruby-next core_ext`.
|
10
|
+
supported: true,
|
11
|
+
location: [__FILE__, __LINE__ + 2] do
|
12
|
+
<<-RUBY
|
13
|
+
FrozenError ||= RuntimeError
|
14
|
+
RUBY
|
15
|
+
end
|
@@ -1,12 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
# Ruby 3.1 adds an ability to pass a hash as accumulator.
|
4
|
+
#
|
5
|
+
# NOTE: We have separate patches for MRI 3.0+ and others due to the unsupported refinements vs modules behaviour.
|
6
|
+
if Enumerable.method_defined?(:tally) && ([].method(:tally).arity == 0) && !(defined?(JRUBY_VERSION) || defined?(TruffleRuby))
|
7
|
+
RubyNext::Core.patch name: "TallyWithHash", supported: false, native: nil, method: :tally, version: "3.1", refineable: [Enumerable] do
|
8
|
+
<<-'RUBY'
|
9
|
+
def tally(*attrs)
|
10
|
+
return super() if attrs.size.zero?
|
11
|
+
|
12
|
+
raise ArgumentError, "wrong number of arguments (given #{attrs.size}, expected 0..1)" if attrs.size > 1
|
13
|
+
|
14
|
+
hash = attrs.size.zero? ? {} : attrs[0].to_hash
|
15
|
+
raise FrozenError, "can't modify frozen #{hash.class}: #{hash}" if hash.frozen?
|
16
|
+
|
17
|
+
each_with_object(hash) do |v, acc|
|
18
|
+
acc[v] = 0 unless acc.key?(v)
|
19
|
+
acc[v] += 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
RUBY
|
23
|
+
end
|
24
|
+
else
|
25
|
+
RubyNext::Core.patch Enumerable, method: :tally, version: "3.1", refineable: [Enumerable, Array] do
|
26
|
+
<<-'RUBY'
|
27
|
+
def tally(acc = {})
|
28
|
+
hash = acc.to_hash
|
29
|
+
raise FrozenError, "can't modify frozen #{hash.class}: #{hash}" if hash.frozen?
|
30
|
+
|
31
|
+
each_with_object(hash) do |v, acc|
|
32
|
+
acc[v] = 0 unless acc.key?(v)
|
33
|
+
acc[v] += 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
RUBY
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# This patch is intended for core extensions only (since we can not use prepend here)
|
41
|
+
RubyNext::Core.patch Enumerable, name: "TallyWithHashCoreExt", version: "3.1", supported: Enumerable.method_defined?(:tally) && ([].method(:tally).arity != 0), method: :tally, refineable: [] do
|
42
|
+
<<-'RUBY'
|
43
|
+
def tally(acc = {})
|
44
|
+
hash = acc.to_hash
|
45
|
+
raise FrozenError, "can't modify frozen #{hash.class}: #{hash}" if hash.frozen?
|
46
|
+
|
47
|
+
each_with_object(hash) do |v, acc|
|
48
|
+
acc[v] = 0 unless acc.key?(v)
|
10
49
|
acc[v] += 1
|
11
50
|
end
|
12
51
|
end
|
data/lib/ruby-next/core.rb
CHANGED
@@ -181,6 +181,7 @@ unless defined?(NoMatchingPatternError)
|
|
181
181
|
end
|
182
182
|
|
183
183
|
require "ruby-next/core/constants/no_matching_pattern_error"
|
184
|
+
require "ruby-next/core/constants/frozen_error"
|
184
185
|
require "ruby-next/core/array/deconstruct"
|
185
186
|
require "ruby-next/core/hash/deconstruct_keys"
|
186
187
|
require "ruby-next/core/struct/deconstruct"
|
@@ -188,6 +189,8 @@ require "ruby-next/core/struct/deconstruct_keys"
|
|
188
189
|
|
189
190
|
require "ruby-next/core/hash/except"
|
190
191
|
|
192
|
+
require "ruby-next/core/array/intersect"
|
193
|
+
|
191
194
|
# Generate refinements
|
192
195
|
RubyNext.module_eval do
|
193
196
|
RubyNext::Core.patches.refined.each do |mod, patches|
|
@@ -11,16 +11,20 @@ module RubyNext
|
|
11
11
|
REST = :__rest__
|
12
12
|
BLOCK = :__block__
|
13
13
|
|
14
|
-
def
|
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
|
+
|
15
18
|
context.track! self
|
16
19
|
|
17
20
|
node = super(node)
|
18
21
|
|
19
|
-
replace(
|
22
|
+
replace(farg.loc.expression, "*#{REST}, &#{BLOCK}")
|
20
23
|
|
21
24
|
node.updated(
|
22
25
|
:args,
|
23
26
|
[
|
27
|
+
*node.children.slice(0, node.children.index(farg)),
|
24
28
|
s(:restarg, REST),
|
25
29
|
s(:blockarg, BLOCK)
|
26
30
|
]
|
@@ -50,7 +50,7 @@ module RubyNext
|
|
50
50
|
GemTranspiler.maybe_transpile(File.dirname(dirname), lib_dir, next_dirname) if transpile
|
51
51
|
|
52
52
|
current_index = $LOAD_PATH.find_index do |load_path|
|
53
|
-
Pathname.new(load_path).
|
53
|
+
Pathname.new(load_path).realpath.to_s == dirname
|
54
54
|
end
|
55
55
|
|
56
56
|
raise "Gem's lib is not in the $LOAD_PATH: #{dirname}" if current_index.nil?
|
data/lib/ruby-next/language.rb
CHANGED
@@ -94,53 +94,29 @@ module RubyNext
|
|
94
94
|
@runtime
|
95
95
|
end
|
96
96
|
|
97
|
-
def transform(
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
97
|
+
def transform(source, rewriters: self.rewriters, using: RubyNext::Core.refine?, context: TransformContext.new)
|
98
|
+
retried = 0
|
99
|
+
new_source = nil
|
100
|
+
begin
|
101
|
+
new_source =
|
102
|
+
if mode == :rewrite
|
103
|
+
rewrite(source, rewriters: rewriters, using: using, context: context)
|
104
|
+
else
|
105
|
+
regenerate(source, rewriters: rewriters, using: using, context: context)
|
106
|
+
end
|
107
|
+
rescue Unparser::UnknownNodeError => err
|
108
|
+
RubyNext.warn "Ruby Next fallbacks to \"rewrite\" transpiling mode since the version of Unparser you use doesn't support some syntax yet: #{err.message}.\n" \
|
109
|
+
"Try upgrading the Unparser or set transpiling mode to \"rewrite\" in case you use some edge or experimental syntax."
|
107
110
|
self.mode = :rewrite
|
111
|
+
retried += 1
|
112
|
+
retry unless retried > 1
|
113
|
+
raise
|
108
114
|
end
|
109
|
-
rewrite(*args, **kwargs)
|
110
|
-
end
|
111
|
-
|
112
|
-
def regenerate(source, rewriters: self.rewriters, using: RubyNext::Core.refine?, context: TransformContext.new)
|
113
|
-
parse_with_comments(source).then do |(ast, comments)|
|
114
|
-
rewriters.inject(ast) do |tree, rewriter|
|
115
|
-
rewriter.new(context).process(tree)
|
116
|
-
end.then do |new_ast|
|
117
|
-
next source unless context.dirty?
|
118
115
|
|
119
|
-
|
120
|
-
|
121
|
-
next source unless RubyNext::Core.refine?
|
122
|
-
next source unless using && context.use_ruby_next?
|
116
|
+
return new_source unless RubyNext::Core.refine?
|
117
|
+
return new_source unless using && context.use_ruby_next?
|
123
118
|
|
124
|
-
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def rewrite(source, rewriters: self.rewriters, using: RubyNext::Core.refine?, context: TransformContext.new)
|
130
|
-
rewriters.inject(source) do |src, rewriter|
|
131
|
-
buffer = Parser::Source::Buffer.new("<dynamic>")
|
132
|
-
buffer.source = src
|
133
|
-
|
134
|
-
rewriter.new(context).rewrite(buffer, parse(src))
|
135
|
-
end.then do |new_source|
|
136
|
-
next source unless context.dirty?
|
137
|
-
new_source
|
138
|
-
end.then do |source|
|
139
|
-
next source unless RubyNext::Core.refine?
|
140
|
-
next source unless using && context.use_ruby_next?
|
141
|
-
|
142
|
-
Core.inject! source.dup
|
143
|
-
end
|
119
|
+
Core.inject! new_source.dup
|
144
120
|
end
|
145
121
|
|
146
122
|
def transformable?(path)
|
@@ -164,6 +140,31 @@ module RubyNext
|
|
164
140
|
|
165
141
|
private
|
166
142
|
|
143
|
+
def regenerate(source, rewriters:, using:, context:)
|
144
|
+
parse_with_comments(source).then do |(ast, comments)|
|
145
|
+
rewriters.inject(ast) do |tree, rewriter|
|
146
|
+
rewriter.new(context).process(tree)
|
147
|
+
end.then do |new_ast|
|
148
|
+
next source unless context.dirty?
|
149
|
+
|
150
|
+
Unparser.unparse(new_ast, comments)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def rewrite(source, rewriters:, using:, context:)
|
156
|
+
rewriters.inject(source) do |src, rewriter|
|
157
|
+
buffer = Parser::Source::Buffer.new("<dynamic>")
|
158
|
+
buffer.source = src
|
159
|
+
|
160
|
+
rewriter.new(context).rewrite(buffer, parse(src))
|
161
|
+
end.then do |new_source|
|
162
|
+
next source unless context.dirty?
|
163
|
+
|
164
|
+
new_source
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
167
168
|
attr_writer :watch_dirs
|
168
169
|
end
|
169
170
|
|
data/lib/ruby-next/setup_self.rb
CHANGED
@@ -6,7 +6,9 @@
|
|
6
6
|
version = RubyNext.next_ruby_version
|
7
7
|
next_dirname = File.join(__dir__, "..", ".rbnext")
|
8
8
|
lib_path = File.realpath(File.join(__dir__, ".."))
|
9
|
-
current_index = $LOAD_PATH.
|
9
|
+
current_index = $LOAD_PATH.find_index do |load_path|
|
10
|
+
File.exist?(load_path) && File.realpath(load_path) == lib_path
|
11
|
+
end
|
10
12
|
|
11
13
|
loop do
|
12
14
|
break unless version
|
data/lib/ruby-next/version.rb
CHANGED
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.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Dementyev
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-next-parser
|
@@ -28,20 +28,14 @@ dependencies:
|
|
28
28
|
name: unparser
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 0.5.6
|
34
|
-
- - "<"
|
31
|
+
- - "~>"
|
35
32
|
- !ruby/object:Gem::Version
|
36
33
|
version: 0.6.0
|
37
34
|
type: :development
|
38
35
|
prerelease: false
|
39
36
|
version_requirements: !ruby/object:Gem::Requirement
|
40
37
|
requirements:
|
41
|
-
- - "
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: 0.5.6
|
44
|
-
- - "<"
|
38
|
+
- - "~>"
|
45
39
|
- !ruby/object:Gem::Version
|
46
40
|
version: 0.6.0
|
47
41
|
description: "\n Ruby Next Core is a zero deps version of Ruby Next meant to be
|
@@ -63,6 +57,7 @@ files:
|
|
63
57
|
- bin/ruby-next
|
64
58
|
- bin/transform
|
65
59
|
- lib/.rbnext/2.1/ruby-next/core.rb
|
60
|
+
- lib/.rbnext/2.1/ruby-next/language.rb
|
66
61
|
- lib/.rbnext/2.3/ruby-next/commands/core_ext.rb
|
67
62
|
- lib/.rbnext/2.3/ruby-next/commands/nextify.rb
|
68
63
|
- lib/.rbnext/2.3/ruby-next/language/eval.rb
|
@@ -80,6 +75,8 @@ files:
|
|
80
75
|
- lib/ruby-next/core.rb
|
81
76
|
- lib/ruby-next/core/array/deconstruct.rb
|
82
77
|
- lib/ruby-next/core/array/difference_union_intersection.rb
|
78
|
+
- lib/ruby-next/core/array/intersect.rb
|
79
|
+
- lib/ruby-next/core/constants/frozen_error.rb
|
83
80
|
- lib/ruby-next/core/constants/no_matching_pattern_error.rb
|
84
81
|
- lib/ruby-next/core/enumerable/filter.rb
|
85
82
|
- lib/ruby-next/core/enumerable/filter_map.rb
|
@@ -141,7 +138,7 @@ metadata:
|
|
141
138
|
documentation_uri: http://github.com/ruby-next/ruby-next/blob/master/README.md
|
142
139
|
homepage_uri: http://github.com/ruby-next/ruby-next
|
143
140
|
source_code_uri: http://github.com/ruby-next/ruby-next
|
144
|
-
post_install_message:
|
141
|
+
post_install_message:
|
145
142
|
rdoc_options: []
|
146
143
|
require_paths:
|
147
144
|
- lib
|
@@ -156,8 +153,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
153
|
- !ruby/object:Gem::Version
|
157
154
|
version: '0'
|
158
155
|
requirements: []
|
159
|
-
rubygems_version: 3.
|
160
|
-
signing_key:
|
156
|
+
rubygems_version: 3.2.15
|
157
|
+
signing_key:
|
161
158
|
specification_version: 4
|
162
159
|
summary: Ruby Next core functionality
|
163
160
|
test_files: []
|