ruby-next-core 0.9.1 → 0.10.3
Sign up to get free protection for your applications and to get access to all the features.
- 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 +201 -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 +44 -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 +91 -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
|