ruby-next-core 0.9.0 → 0.10.2
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 +42 -0
- data/README.md +20 -6
- data/lib/.rbnext/2.3/ruby-next/commands/core_ext.rb +167 -0
- data/lib/.rbnext/2.3/ruby-next/commands/nextify.rb +198 -0
- data/lib/.rbnext/2.3/ruby-next/language/eval.rb +66 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/base.rb +121 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/endless_range.rb +63 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/pattern_matching.rb +944 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/right_hand_assignment.rb +107 -0
- data/lib/.rbnext/2.3/ruby-next/utils.rb +65 -0
- data/lib/ruby-next.rb +8 -6
- data/lib/ruby-next/cli.rb +2 -2
- data/lib/ruby-next/commands/core_ext.rb +1 -1
- data/lib/ruby-next/commands/nextify.rb +41 -10
- data/lib/ruby-next/core.rb +27 -21
- data/lib/ruby-next/core/array/deconstruct.rb +9 -9
- data/lib/ruby-next/core/array/difference_union_intersection.rb +12 -12
- data/lib/ruby-next/core/constants/no_matching_pattern_error.rb +3 -3
- data/lib/ruby-next/core/enumerable/filter.rb +8 -8
- data/lib/ruby-next/core/enumerable/filter_map.rb +25 -25
- data/lib/ruby-next/core/enumerable/tally.rb +7 -7
- data/lib/ruby-next/core/enumerator/produce.rb +12 -12
- data/lib/ruby-next/core/hash/deconstruct_keys.rb +9 -9
- data/lib/ruby-next/core/hash/except.rb +11 -0
- data/lib/ruby-next/core/hash/merge.rb +8 -8
- data/lib/ruby-next/core/kernel/then.rb +2 -2
- data/lib/ruby-next/core/proc/compose.rb +11 -11
- data/lib/ruby-next/core/string/split.rb +6 -6
- data/lib/ruby-next/core/struct/deconstruct.rb +2 -2
- data/lib/ruby-next/core/struct/deconstruct_keys.rb +17 -17
- data/lib/ruby-next/core/symbol/end_with.rb +4 -4
- data/lib/ruby-next/core/symbol/start_with.rb +4 -4
- data/lib/ruby-next/core/time/ceil.rb +6 -6
- data/lib/ruby-next/core/time/floor.rb +4 -4
- data/lib/ruby-next/core/unboundmethod/bind_call.rb +4 -4
- data/lib/ruby-next/core_ext.rb +1 -1
- data/lib/ruby-next/language.rb +30 -6
- data/lib/ruby-next/language/proposed.rb +3 -0
- data/lib/ruby-next/language/rewriters/args_forward.rb +24 -20
- data/lib/ruby-next/language/rewriters/base.rb +1 -1
- data/lib/ruby-next/language/rewriters/endless_method.rb +26 -3
- data/lib/ruby-next/language/rewriters/endless_range.rb +1 -0
- data/lib/ruby-next/language/rewriters/find_pattern.rb +44 -0
- data/lib/ruby-next/language/rewriters/method_reference.rb +2 -1
- data/lib/ruby-next/language/rewriters/numbered_params.rb +1 -0
- data/lib/ruby-next/language/rewriters/pattern_matching.rb +103 -12
- data/lib/ruby-next/language/rewriters/right_hand_assignment.rb +74 -11
- data/lib/ruby-next/language/rewriters/safe_navigation.rb +87 -0
- data/lib/ruby-next/language/rewriters/shorthand_hash.rb +47 -0
- data/lib/ruby-next/language/rewriters/squiggly_heredoc.rb +36 -0
- data/lib/ruby-next/logging.rb +1 -1
- data/lib/ruby-next/rubocop.rb +15 -9
- data/lib/ruby-next/setup_self.rb +22 -0
- data/lib/ruby-next/version.rb +1 -1
- data/lib/uby-next.rb +8 -4
- metadata +21 -7
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RubyNext::Core.patch UnboundMethod, method: :bind_call, version: "2.7" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
<<-RUBY
|
5
|
+
def bind_call(receiver, *args, &block)
|
6
|
+
bind(receiver).call(*args, &block)
|
7
|
+
end
|
8
8
|
RUBY
|
9
9
|
end
|
data/lib/ruby-next/core_ext.rb
CHANGED
data/lib/ruby-next/language.rb
CHANGED
@@ -23,6 +23,8 @@ module RubyNext
|
|
23
23
|
require "ruby-next/language/parser"
|
24
24
|
require "ruby-next/language/unparser"
|
25
25
|
|
26
|
+
RewriterNotFoundError = Class.new(StandardError)
|
27
|
+
|
26
28
|
class TransformContext
|
27
29
|
attr_reader :versions, :use_ruby_next
|
28
30
|
|
@@ -85,12 +87,6 @@ module RubyNext
|
|
85
87
|
def runtime!
|
86
88
|
require "ruby-next/language/rewriters/runtime"
|
87
89
|
|
88
|
-
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0") && !defined?(Unparser::Emitter::CaseMatch)
|
89
|
-
RubyNext.warn "Ruby Next fallbacks to \"rewrite\" transpiling mode since Unparser doesn't support 2.7 AST yet.\n" \
|
90
|
-
"See https://github.com/mbj/unparser/pull/142"
|
91
|
-
self.mode = :rewrite
|
92
|
-
end
|
93
|
-
|
94
90
|
@runtime = true
|
95
91
|
end
|
96
92
|
|
@@ -104,6 +100,13 @@ module RubyNext
|
|
104
100
|
else
|
105
101
|
regenerate(*args, **kwargs)
|
106
102
|
end
|
103
|
+
rescue Unparser::UnknownNodeError
|
104
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0")
|
105
|
+
RubyNext.warn "Ruby Next fallbacks to \"rewrite\" transpiling mode since Unparser doesn't support 2.7+ AST yet.\n" \
|
106
|
+
"See https://github.com/mbj/unparser/pull/142"
|
107
|
+
self.mode = :rewrite
|
108
|
+
end
|
109
|
+
rewrite(*args, **kwargs)
|
107
110
|
end
|
108
111
|
|
109
112
|
def regenerate(source, rewriters: self.rewriters, using: RubyNext::Core.refine?, context: TransformContext.new)
|
@@ -149,6 +152,16 @@ module RubyNext
|
|
149
152
|
@current_rewriters ||= rewriters.select(&:unsupported_syntax?)
|
150
153
|
end
|
151
154
|
|
155
|
+
# This method guarantees that rewriters will be returned in order they defined in Language module
|
156
|
+
def select_rewriters(*names)
|
157
|
+
rewriters_delta = names - rewriters.map { |rewriter| rewriter::NAME }
|
158
|
+
if rewriters_delta.any?
|
159
|
+
raise RewriterNotFoundError, "Rewriters not found: #{rewriters_delta.join(",")}"
|
160
|
+
end
|
161
|
+
|
162
|
+
rewriters.select { |rewriter| names.include?(rewriter::NAME) }
|
163
|
+
end
|
164
|
+
|
152
165
|
private
|
153
166
|
|
154
167
|
attr_writer :watch_dirs
|
@@ -160,6 +173,12 @@ module RubyNext
|
|
160
173
|
|
161
174
|
require "ruby-next/language/rewriters/base"
|
162
175
|
|
176
|
+
require "ruby-next/language/rewriters/squiggly_heredoc"
|
177
|
+
rewriters << Rewriters::SquigglyHeredoc
|
178
|
+
|
179
|
+
require "ruby-next/language/rewriters/safe_navigation"
|
180
|
+
rewriters << Rewriters::SafeNavigation
|
181
|
+
|
163
182
|
require "ruby-next/language/rewriters/args_forward"
|
164
183
|
rewriters << Rewriters::ArgsForward
|
165
184
|
|
@@ -169,6 +188,11 @@ module RubyNext
|
|
169
188
|
require "ruby-next/language/rewriters/pattern_matching"
|
170
189
|
rewriters << Rewriters::PatternMatching
|
171
190
|
|
191
|
+
# Must be added after general pattern matching rewriter to become
|
192
|
+
# no-op in Ruby <2.7
|
193
|
+
require "ruby-next/language/rewriters/find_pattern"
|
194
|
+
rewriters << Rewriters::FindPattern
|
195
|
+
|
172
196
|
# Put endless range in the end, 'cause Parser fails to parse it in
|
173
197
|
# pattern matching
|
174
198
|
require "ruby-next/language/rewriters/endless_range"
|
@@ -4,3 +4,6 @@
|
|
4
4
|
|
5
5
|
require "ruby-next/language/rewriters/method_reference"
|
6
6
|
RubyNext::Language.rewriters << RubyNext::Language::Rewriters::MethodReference
|
7
|
+
|
8
|
+
require "ruby-next/language/rewriters/shorthand_hash"
|
9
|
+
RubyNext::Language.rewriters << RubyNext::Language::Rewriters::ShorthandHash
|
@@ -4,16 +4,19 @@ module RubyNext
|
|
4
4
|
module Language
|
5
5
|
module Rewriters
|
6
6
|
class ArgsForward < Base
|
7
|
-
|
8
|
-
|
7
|
+
NAME = "args-forward"
|
8
|
+
SYNTAX_PROBE = "obj = Object.new; def obj.foo(...) super(1, ...); end"
|
9
|
+
MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
|
9
10
|
|
10
11
|
REST = :__rest__
|
11
12
|
BLOCK = :__block__
|
12
13
|
|
13
|
-
def
|
14
|
+
def on_forward_arg(node)
|
14
15
|
context.track! self
|
15
16
|
|
16
|
-
|
17
|
+
node = super(node)
|
18
|
+
|
19
|
+
replace(node.loc.expression, "*#{REST}, &#{BLOCK}")
|
17
20
|
|
18
21
|
node.updated(
|
19
22
|
:args,
|
@@ -25,34 +28,35 @@ module RubyNext
|
|
25
28
|
end
|
26
29
|
|
27
30
|
def on_send(node)
|
28
|
-
|
31
|
+
fargs = node.children.find { |child| child.is_a?(::Parser::AST::Node) && child.type == :forwarded_args }
|
32
|
+
return super(node) unless fargs
|
33
|
+
|
34
|
+
process_fargs(node, fargs)
|
35
|
+
end
|
36
|
+
|
37
|
+
def on_super(node)
|
38
|
+
fargs = node.children.find { |child| child.is_a?(::Parser::AST::Node) && child.type == :forwarded_args }
|
39
|
+
return super(node) unless fargs
|
40
|
+
|
41
|
+
process_fargs(node, fargs)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
29
45
|
|
30
|
-
|
46
|
+
def process_fargs(node, fargs)
|
47
|
+
replace(fargs.loc.expression, "*#{REST}, &#{BLOCK}")
|
31
48
|
|
32
49
|
process(
|
33
50
|
node.updated(
|
34
51
|
nil,
|
35
52
|
[
|
36
|
-
*node.children
|
53
|
+
*node.children.take(node.children.index(fargs)),
|
37
54
|
*forwarded_args
|
38
55
|
]
|
39
56
|
)
|
40
57
|
)
|
41
58
|
end
|
42
59
|
|
43
|
-
def on_super(node)
|
44
|
-
return super(node) unless node.children[0]&.type == :forwarded_args
|
45
|
-
|
46
|
-
replace(node.children[0].loc.expression, "*#{REST}, &#{BLOCK}")
|
47
|
-
|
48
|
-
node.updated(
|
49
|
-
nil,
|
50
|
-
forwarded_args
|
51
|
-
)
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
60
|
def forwarded_args
|
57
61
|
[
|
58
62
|
s(:splat, s(:lvar, REST)),
|
@@ -4,8 +4,16 @@ module RubyNext
|
|
4
4
|
module Language
|
5
5
|
module Rewriters
|
6
6
|
class EndlessMethod < Base
|
7
|
+
NAME = "endless-method"
|
7
8
|
SYNTAX_PROBE = "obj = Object.new; def obj.foo() = 42"
|
8
|
-
MIN_SUPPORTED_VERSION = Gem::Version.new("
|
9
|
+
MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
|
10
|
+
|
11
|
+
unless Parser::Meta::NODE_TYPES.include?(:def_e)
|
12
|
+
def on_def(node)
|
13
|
+
return on_def_e(node) if node.loc.end.nil?
|
14
|
+
super(node)
|
15
|
+
end
|
16
|
+
end
|
9
17
|
|
10
18
|
def on_def_e(node)
|
11
19
|
context.track! self
|
@@ -13,24 +21,39 @@ module RubyNext
|
|
13
21
|
replace(node.loc.assignment, "; ")
|
14
22
|
insert_after(node.loc.expression, "; end")
|
15
23
|
|
24
|
+
new_loc = node.loc.dup
|
25
|
+
new_loc.instance_variable_set(:@end, node.loc.expression)
|
26
|
+
|
16
27
|
process(
|
17
28
|
node.updated(
|
18
29
|
:def,
|
19
|
-
node.children
|
30
|
+
node.children,
|
31
|
+
location: new_loc
|
20
32
|
)
|
21
33
|
)
|
22
34
|
end
|
23
35
|
|
36
|
+
unless Parser::Meta::NODE_TYPES.include?(:def_e)
|
37
|
+
def on_defs(node)
|
38
|
+
return on_defs_e(node) if node.loc.end.nil?
|
39
|
+
super(node)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
24
43
|
def on_defs_e(node)
|
25
44
|
context.track! self
|
26
45
|
|
27
46
|
replace(node.loc.assignment, "; ")
|
28
47
|
insert_after(node.loc.expression, "; end")
|
29
48
|
|
49
|
+
new_loc = node.loc.dup
|
50
|
+
new_loc.instance_variable_set(:@end, node.loc.expression)
|
51
|
+
|
30
52
|
process(
|
31
53
|
node.updated(
|
32
54
|
:defs,
|
33
|
-
node.children
|
55
|
+
node.children,
|
56
|
+
location: new_loc
|
34
57
|
)
|
35
58
|
)
|
36
59
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ruby-next/language/rewriters/pattern_matching"
|
4
|
+
|
5
|
+
module RubyNext
|
6
|
+
module Language
|
7
|
+
module Rewriters
|
8
|
+
using RubyNext
|
9
|
+
|
10
|
+
# Separate pattern matching rewriter for Ruby 2.7 to
|
11
|
+
# transpile only case...in with a find pattern
|
12
|
+
class FindPattern < PatternMatching
|
13
|
+
NAME = "pattern-matching-find-pattern"
|
14
|
+
SYNTAX_PROBE = "case 0; in [*,0,*]; true; else; 1; end"
|
15
|
+
MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
|
16
|
+
|
17
|
+
def on_case_match(node)
|
18
|
+
@has_find_pattern = false
|
19
|
+
process_regular_node(node).then do |new_node|
|
20
|
+
return new_node unless has_find_pattern
|
21
|
+
super(node)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_in_match(node)
|
26
|
+
@has_find_pattern = false
|
27
|
+
process_regular_node(node).then do |new_node|
|
28
|
+
return new_node unless has_find_pattern
|
29
|
+
super(node)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def on_find_pattern(node)
|
34
|
+
@has_find_pattern = true
|
35
|
+
super(node)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_reader :has_find_pattern
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -4,8 +4,9 @@ module RubyNext
|
|
4
4
|
module Language
|
5
5
|
module Rewriters
|
6
6
|
class MethodReference < Base
|
7
|
+
NAME = "method-reference"
|
7
8
|
SYNTAX_PROBE = "Language.:transform"
|
8
|
-
MIN_SUPPORTED_VERSION = Gem::Version.new("
|
9
|
+
MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
|
9
10
|
|
10
11
|
def on_meth_ref(node)
|
11
12
|
context.track! self
|
@@ -10,6 +10,16 @@ module RubyNext
|
|
10
10
|
def to_ast_node
|
11
11
|
self
|
12
12
|
end
|
13
|
+
|
14
|
+
# Useful to generate simple operation nodes
|
15
|
+
# (e.g., 'a + b')
|
16
|
+
def -(val)
|
17
|
+
::Parser::AST::Node.new(:send, [self, :-, val.to_ast_node])
|
18
|
+
end
|
19
|
+
|
20
|
+
def +(val)
|
21
|
+
::Parser::AST::Node.new(:send, [self, :+, val.to_ast_node])
|
22
|
+
end
|
13
23
|
end
|
14
24
|
|
15
25
|
refine String do
|
@@ -216,6 +226,7 @@ module RubyNext
|
|
216
226
|
end
|
217
227
|
|
218
228
|
class PatternMatching < Base
|
229
|
+
NAME = "pattern-matching"
|
219
230
|
SYNTAX_PROBE = "case 0; in 0; true; else; 1; end"
|
220
231
|
MIN_SUPPORTED_VERSION = Gem::Version.new("2.7.0")
|
221
232
|
|
@@ -248,7 +259,7 @@ module RubyNext
|
|
248
259
|
rewrite_case_in! node, matchee_ast, case_clause
|
249
260
|
|
250
261
|
node.updated(
|
251
|
-
:
|
262
|
+
:kwbegin,
|
252
263
|
[
|
253
264
|
matchee_ast, case_clause
|
254
265
|
]
|
@@ -287,7 +298,7 @@ module RubyNext
|
|
287
298
|
pattern
|
288
299
|
]
|
289
300
|
).tap do |new_node|
|
290
|
-
replace(node.loc.expression, new_node)
|
301
|
+
replace(node.loc.expression, inline_blocks(unparse(new_node)))
|
291
302
|
end
|
292
303
|
end
|
293
304
|
|
@@ -306,14 +317,14 @@ module RubyNext
|
|
306
317
|
body_indent = " " * clause.children[2].loc.column
|
307
318
|
replace(
|
308
319
|
clause.loc.expression,
|
309
|
-
"when #{unparse(new_node.children[i].children[0])}" \
|
320
|
+
"when #{inline_blocks(unparse(new_node.children[i].children[0]))}" \
|
310
321
|
"#{padding}" \
|
311
322
|
"#{body_indent}#{clause.children[2].loc.expression.source}"
|
312
323
|
)
|
313
324
|
else
|
314
325
|
replace(
|
315
326
|
clause.loc.keyword.end.join(clause.children[0].loc.expression.end),
|
316
|
-
new_node.children[i].children[0]
|
327
|
+
inline_blocks(unparse(new_node.children[i].children[0]))
|
317
328
|
)
|
318
329
|
remove(clause.children[1].loc.expression) if clause.children[1]
|
319
330
|
replace(clause.loc.keyword, "when ")
|
@@ -429,6 +440,8 @@ module RubyNext
|
|
429
440
|
right =
|
430
441
|
if node.children.empty?
|
431
442
|
case_eq_clause(s(:array), s(:lvar, locals[:arr]))
|
443
|
+
elsif node.children.size > 1 && node.children.first.type == :match_rest && node.children.last.type == :match_rest
|
444
|
+
array_find(*node.children)
|
432
445
|
else
|
433
446
|
array_element(0, *node.children)
|
434
447
|
end
|
@@ -442,6 +455,7 @@ module RubyNext
|
|
442
455
|
end
|
443
456
|
|
444
457
|
alias array_pattern_with_tail_clause array_pattern_clause
|
458
|
+
alias find_pattern_clause array_pattern_clause
|
445
459
|
|
446
460
|
def deconstruct_node(matchee)
|
447
461
|
context.use_ruby_next!
|
@@ -477,9 +491,80 @@ module RubyNext
|
|
477
491
|
end
|
478
492
|
end
|
479
493
|
|
494
|
+
# [*a, 1, 2, *] -> arr.find.with_index { |_, i| (a = arr.take(i)) && arr[i] == 1 && arr[i + 1] == 2 }
|
495
|
+
def array_find(head, *nodes, tail)
|
496
|
+
index = s(:lvar, :__i__)
|
497
|
+
|
498
|
+
match_vars = []
|
499
|
+
|
500
|
+
head_match =
|
501
|
+
unless head.children.empty?
|
502
|
+
match_vars << s(:lvasgn, head.children[0].children[0])
|
503
|
+
|
504
|
+
arr_take = s(:send,
|
505
|
+
s(:lvar, locals[:arr]),
|
506
|
+
:take,
|
507
|
+
index)
|
508
|
+
|
509
|
+
match_var_clause(head.children[0], arr_take)
|
510
|
+
end
|
511
|
+
|
512
|
+
tail_match =
|
513
|
+
unless tail.children.empty?
|
514
|
+
match_vars << s(:lvasgn, tail.children[0].children[0])
|
515
|
+
|
516
|
+
match_var_clause(tail.children[0], arr_slice(index + nodes.size, -1))
|
517
|
+
end
|
518
|
+
|
519
|
+
nodes.each do |node|
|
520
|
+
if node.type == :match_var
|
521
|
+
match_vars << s(:lvasgn, node.children[0])
|
522
|
+
elsif node.type == :match_as
|
523
|
+
match_vars << s(:lvasgn, node.children[1].children[0])
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
pattern = array_rest_element(*nodes, index).then do |needle|
|
528
|
+
next needle unless head_match
|
529
|
+
s(:and,
|
530
|
+
needle,
|
531
|
+
head_match)
|
532
|
+
end.then do |headed_needle|
|
533
|
+
next headed_needle unless tail_match
|
534
|
+
|
535
|
+
s(:and,
|
536
|
+
headed_needle,
|
537
|
+
tail_match)
|
538
|
+
end
|
539
|
+
|
540
|
+
s(:block,
|
541
|
+
s(:send,
|
542
|
+
s(:send,
|
543
|
+
s(:lvar, locals[:arr]),
|
544
|
+
:find),
|
545
|
+
:with_index),
|
546
|
+
s(:args,
|
547
|
+
s(:arg, :_),
|
548
|
+
s(:arg, :__i__)),
|
549
|
+
pattern).then do |block|
|
550
|
+
next block if match_vars.empty?
|
551
|
+
|
552
|
+
# We need to declare match vars outside of `find` block
|
553
|
+
locals_declare = s(:masgn,
|
554
|
+
s(:mlhs, *match_vars),
|
555
|
+
s(:nil))
|
556
|
+
|
557
|
+
s(:or,
|
558
|
+
locals_declare,
|
559
|
+
block)
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
480
563
|
def array_match_rest(index, node, *tail)
|
564
|
+
size = tail.size + 1
|
481
565
|
child = node.children[0]
|
482
|
-
|
566
|
+
|
567
|
+
rest = arr_slice(index, -size).then do |r|
|
483
568
|
next r unless child
|
484
569
|
|
485
570
|
match_var_clause(
|
@@ -492,16 +577,16 @@ module RubyNext
|
|
492
577
|
|
493
578
|
s(:and,
|
494
579
|
rest,
|
495
|
-
array_rest_element(*tail))
|
580
|
+
array_rest_element(*tail, -(size - 1)))
|
496
581
|
end
|
497
582
|
|
498
|
-
def array_rest_element(head, *tail)
|
499
|
-
send("#{head.type}_array_element", head,
|
583
|
+
def array_rest_element(head, *tail, index)
|
584
|
+
send("#{head.type}_array_element", head, index).then do |node|
|
500
585
|
next node if tail.empty?
|
501
586
|
|
502
587
|
s(:and,
|
503
588
|
node,
|
504
|
-
array_rest_element(*tail))
|
589
|
+
array_rest_element(*tail, index + 1))
|
505
590
|
end
|
506
591
|
end
|
507
592
|
|
@@ -548,12 +633,12 @@ module RubyNext
|
|
548
633
|
s(:index, arr, index.to_ast_node)
|
549
634
|
end
|
550
635
|
|
551
|
-
def
|
636
|
+
def arr_slice(lindex, rindex, arr = s(:lvar, locals[:arr]))
|
552
637
|
s(:index,
|
553
638
|
arr,
|
554
639
|
s(:irange,
|
555
|
-
|
556
|
-
|
640
|
+
lindex.to_ast_node,
|
641
|
+
rindex.to_ast_node))
|
557
642
|
end
|
558
643
|
|
559
644
|
#=========== ARRAY PATTERN (END) ===============
|
@@ -847,6 +932,12 @@ module RubyNext
|
|
847
932
|
|
848
933
|
deconstructed_keys[key] = :"k#{deconstructed_keys.size}"
|
849
934
|
end
|
935
|
+
|
936
|
+
# Unparser generates `do .. end` blocks, we want to
|
937
|
+
# have single-line blocks with `{ ... }`.
|
938
|
+
def inline_blocks(source)
|
939
|
+
source.gsub(/do \|_, __i__\|\n\s*([^\n]+)\n\s*end/, '{ |_, __i__| \1 }')
|
940
|
+
end
|
850
941
|
end
|
851
942
|
end
|
852
943
|
end
|