ruby-next-core 0.15.2 → 1.0.0.rc.1
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 +32 -0
- data/README.md +118 -48
- data/bin/mspec +11 -0
- data/lib/.rbnext/2.1/ruby-next/commands/nextify.rb +295 -0
- data/lib/.rbnext/2.1/ruby-next/core.rb +10 -2
- data/lib/.rbnext/2.1/ruby-next/language.rb +54 -10
- data/lib/.rbnext/2.3/ruby-next/commands/nextify.rb +82 -2
- data/lib/.rbnext/2.3/ruby-next/config.rb +79 -0
- data/lib/.rbnext/2.3/ruby-next/core/data.rb +159 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/2.7/pattern_matching.rb +44 -9
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/base.rb +6 -32
- data/lib/.rbnext/2.3/ruby-next/utils.rb +3 -22
- data/lib/.rbnext/2.6/ruby-next/core/data.rb +159 -0
- data/lib/.rbnext/2.7/ruby-next/core/data.rb +159 -0
- data/lib/.rbnext/2.7/ruby-next/core.rb +10 -2
- data/lib/.rbnext/2.7/ruby-next/language/paco_parsers/string_literals.rb +109 -0
- data/lib/.rbnext/2.7/ruby-next/language/rewriters/2.7/pattern_matching.rb +44 -9
- data/lib/.rbnext/2.7/ruby-next/language/rewriters/text.rb +132 -0
- data/lib/.rbnext/3.2/ruby-next/commands/base.rb +55 -0
- data/lib/.rbnext/3.2/ruby-next/language/rewriters/2.7/pattern_matching.rb +1095 -0
- data/lib/.rbnext/3.2/ruby-next/rubocop.rb +210 -0
- data/lib/ruby-next/commands/nextify.rb +84 -2
- data/lib/ruby-next/config.rb +27 -0
- data/lib/ruby-next/core/data.rb +159 -0
- data/lib/ruby-next/core/matchdata/deconstruct.rb +9 -0
- data/lib/ruby-next/core/matchdata/deconstruct_keys.rb +20 -0
- data/lib/ruby-next/core/matchdata/named_captures.rb +11 -0
- data/lib/ruby-next/core/refinement/import.rb +44 -36
- data/lib/ruby-next/core/time/deconstruct_keys.rb +30 -0
- data/lib/ruby-next/core.rb +10 -2
- data/lib/ruby-next/irb.rb +2 -2
- data/lib/ruby-next/language/bootsnap.rb +2 -25
- data/lib/ruby-next/language/paco_parser.rb +7 -0
- data/lib/ruby-next/language/paco_parsers/base.rb +47 -0
- data/lib/ruby-next/language/paco_parsers/comments.rb +26 -0
- data/lib/ruby-next/language/paco_parsers/string_literals.rb +109 -0
- data/lib/ruby-next/language/parser.rb +24 -2
- data/lib/ruby-next/language/rewriters/2.7/pattern_matching.rb +42 -7
- data/lib/ruby-next/language/rewriters/3.0/args_forward_leading.rb +2 -2
- data/lib/ruby-next/language/rewriters/3.1/oneline_pattern_parensless.rb +1 -1
- data/lib/ruby-next/language/rewriters/3.2/anonymous_restargs.rb +104 -0
- data/lib/ruby-next/language/rewriters/abstract.rb +57 -0
- data/lib/ruby-next/language/rewriters/base.rb +6 -32
- data/lib/ruby-next/language/rewriters/edge/it_param.rb +58 -0
- data/lib/ruby-next/language/rewriters/edge.rb +12 -0
- data/lib/ruby-next/language/rewriters/proposed/bind_vars_pattern.rb +3 -0
- data/lib/ruby-next/language/rewriters/proposed/method_reference.rb +9 -20
- data/lib/ruby-next/language/rewriters/text.rb +132 -0
- data/lib/ruby-next/language/runtime.rb +9 -86
- data/lib/ruby-next/language/setup.rb +5 -2
- data/lib/ruby-next/language/unparser.rb +5 -0
- data/lib/ruby-next/language.rb +54 -10
- data/lib/ruby-next/pry.rb +1 -1
- data/lib/ruby-next/rubocop.rb +2 -0
- data/lib/ruby-next/utils.rb +3 -22
- data/lib/ruby-next/version.rb +1 -1
- data/lib/uby-next.rb +2 -2
- metadata +65 -12
@@ -4,57 +4,65 @@
|
|
4
4
|
# So, we use a defined method instead (and transpile source code to use it).
|
5
5
|
# NOTE: We have to transpile the source code anyway, since we need to pass a binding.
|
6
6
|
RubyNext::Core.singleton_class.module_eval do
|
7
|
-
def import_methods(
|
7
|
+
def import_methods(*others, bind)
|
8
8
|
import = []
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
# First, validate passed modules
|
11
|
+
others.each do |other|
|
12
|
+
raise TypeError, "wrong argument type #{other.class} (expected Module)" unless other.is_a?(::Module)
|
13
|
+
raise TypeError, "wrong argument type Class (expected Module)" if other.is_a?(::Class)
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
others.each do |other|
|
17
|
+
(other.instance_methods(false) + other.private_instance_methods(false)).each do |mid|
|
18
|
+
# check for non-Ruby methods
|
19
|
+
meth = other.instance_method(mid)
|
20
|
+
location = meth.source_location
|
18
21
|
|
19
|
-
|
22
|
+
if location.nil? || location.first.match?(/(<internal:|resource:\/truffleruby\/core|uri:classloader:\/jruby)/)
|
23
|
+
raise ArgumentError, "Can't import method which is not defined with Ruby code: #{other}##{mid} from #{location}"
|
24
|
+
end
|
20
25
|
|
21
|
-
|
26
|
+
source_file, lineno = *location
|
22
27
|
|
23
|
-
|
28
|
+
raise ArgumentError, "Can't import dynamicly added methods: #{other}##{mid}" unless File.file?(source_file)
|
24
29
|
|
25
|
-
|
30
|
+
lines = File.open(source_file).readlines
|
26
31
|
|
27
|
-
|
28
|
-
buffer << line + "\n"
|
32
|
+
buffer = []
|
29
33
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
lines[(lineno - 1)..-1].each do |line|
|
35
|
+
buffer << line + "\n"
|
36
|
+
|
37
|
+
begin
|
38
|
+
if defined?(::RubyNext::Language) && ::RubyNext::Language.runtime?
|
39
|
+
new_source = ::RubyNext::Language.transform(buffer.join, rewriters: RubyNext::Language.current_rewriters, using: false)
|
40
|
+
# Transformed successfully => valid method => evaluate transpiled code
|
41
|
+
import << [new_source, source_file, lineno]
|
42
|
+
buffer.clear
|
43
|
+
break
|
44
|
+
end
|
38
45
|
|
39
|
-
|
40
|
-
|
41
|
-
|
46
|
+
# Borrowed from https://github.com/banister/method_source/blob/81d039c966ffd95d26e12eb2e205c0eb8377f49d/lib/method_source/code_helpers.rb#L66
|
47
|
+
catch(:valid) do
|
48
|
+
eval("BEGIN{throw :valid}\nObject.new.instance_eval { #{buffer.join} }") # rubocop:disable all
|
49
|
+
end
|
50
|
+
break
|
51
|
+
rescue SyntaxError
|
42
52
|
end
|
43
|
-
break
|
44
|
-
rescue SyntaxError
|
45
53
|
end
|
46
|
-
end
|
47
54
|
|
48
|
-
|
49
|
-
|
55
|
+
import << [buffer.join, source_file, lineno] unless buffer.empty?
|
56
|
+
end
|
50
57
|
|
51
|
-
|
52
|
-
|
53
|
-
|
58
|
+
import.each do |(definition, file, lino)|
|
59
|
+
Kernel.eval definition, bind, file, lino
|
60
|
+
end
|
54
61
|
|
55
|
-
|
56
|
-
|
57
|
-
|
62
|
+
# Copy constants (they could be accessed from methods)
|
63
|
+
other.constants.each do |name|
|
64
|
+
Kernel.eval "#{name} = #{other}::#{name}", bind # rubocop:disable Style/EvalWithLocation
|
65
|
+
end
|
58
66
|
end
|
59
67
|
end
|
60
68
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RubyNext::Core.patch Time, method: :deconstruct_keys, version: "3.2" do
|
4
|
+
<<-'RUBY'
|
5
|
+
def deconstruct_keys(keys)
|
6
|
+
raise TypeError, "wrong argument type #{keys.class} (expected Array or nil)" if keys && !keys.is_a?(Array)
|
7
|
+
|
8
|
+
if !keys
|
9
|
+
return {
|
10
|
+
year: year,
|
11
|
+
month: month,
|
12
|
+
day: day,
|
13
|
+
yday: yday,
|
14
|
+
wday: wday,
|
15
|
+
hour: hour,
|
16
|
+
min: min,
|
17
|
+
sec: sec,
|
18
|
+
subsec: subsec,
|
19
|
+
dst: dst?,
|
20
|
+
zone: zone
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
keys.each_with_object({}) do |key, hash|
|
25
|
+
hash[key] = public_send(key) if key.is_a?(Symbol) && respond_to?(key)
|
26
|
+
hash
|
27
|
+
end
|
28
|
+
end
|
29
|
+
RUBY
|
30
|
+
end
|
data/lib/ruby-next/core.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "set"
|
3
|
+
require "set" # rubocop:disable Lint/RedundantRequireStatement
|
4
4
|
|
5
5
|
require "ruby-next/config"
|
6
6
|
require "ruby-next/utils"
|
@@ -78,7 +78,7 @@ module RubyNext
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def native_location?(location)
|
81
|
-
location.nil? || location.first.match?(/(<internal:|resource:\/truffleruby\/core)/)
|
81
|
+
location.nil? || location.first.match?(/(<internal:|resource:\/truffleruby\/core|uri:classloader:\/jruby)/)
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
@@ -197,6 +197,11 @@ require "ruby-next/core/matchdata/match"
|
|
197
197
|
require "ruby-next/core/enumerable/compact"
|
198
198
|
require "ruby-next/core/integer/try_convert"
|
199
199
|
|
200
|
+
require "ruby-next/core/matchdata/deconstruct"
|
201
|
+
require "ruby-next/core/matchdata/deconstruct_keys"
|
202
|
+
require "ruby-next/core/matchdata/named_captures"
|
203
|
+
require "ruby-next/core/time/deconstruct_keys"
|
204
|
+
|
200
205
|
# Generate refinements
|
201
206
|
RubyNext.module_eval do
|
202
207
|
RubyNext::Core.patches.refined.each do |mod, patches|
|
@@ -210,3 +215,6 @@ RubyNext.module_eval do
|
|
210
215
|
end
|
211
216
|
end
|
212
217
|
end
|
218
|
+
|
219
|
+
# Load backports
|
220
|
+
require "ruby-next/core/data" unless ENV["RUBY_NEXT_DISABLE_DATA"] == "true"
|
data/lib/ruby-next/irb.rb
CHANGED
@@ -9,14 +9,14 @@ require "ruby-next/language"
|
|
9
9
|
# IRB extension to transpile code before evaluating
|
10
10
|
module RubyNext
|
11
11
|
module IRBExt
|
12
|
-
def
|
12
|
+
def eval(statements, *args)
|
13
13
|
new_statements = ::RubyNext::Language.transform(
|
14
14
|
statements,
|
15
15
|
rewriters: ::RubyNext::Language.current_rewriters,
|
16
16
|
using: false
|
17
17
|
)
|
18
18
|
|
19
|
-
super(
|
19
|
+
super(new_statements, *args)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -1,28 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require "ruby-next/utils"
|
5
|
-
require "ruby-next/language"
|
3
|
+
warn "[DEPRECATED] Using ruby-next/language/bootsnap is deprecated. Please use ruby-next/language/runtime instead."
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
# Patch bootsnap to transform source code.
|
10
|
-
# Based on https://github.com/kddeisz/preval/blob/master/lib/preval.rb
|
11
|
-
load_iseq = RubyVM::InstructionSequence.method(:load_iseq)
|
12
|
-
|
13
|
-
if load_iseq.source_location[0].include?("/bootsnap/")
|
14
|
-
Bootsnap::CompileCache::ISeq.singleton_class.prepend(
|
15
|
-
Module.new do
|
16
|
-
def input_to_storage(source, path, *)
|
17
|
-
return super unless RubyNext::Language.transformable?(path)
|
18
|
-
source = RubyNext::Language.transform(source, rewriters: RubyNext::Language.current_rewriters)
|
19
|
-
|
20
|
-
RubyNext.debug_source(source, path)
|
21
|
-
|
22
|
-
RubyVM::InstructionSequence.compile(source, path, path).to_binary
|
23
|
-
rescue SyntaxError
|
24
|
-
raise Bootsnap::CompileCache::Uncompilable, "syntax error"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
)
|
28
|
-
end
|
5
|
+
require "ruby-next/language/runtime"
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyNext
|
4
|
+
module Language
|
5
|
+
module PacoParsers
|
6
|
+
class Base
|
7
|
+
include Paco
|
8
|
+
|
9
|
+
def parse(io)
|
10
|
+
default.parse(io)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def anything_between(left, right)
|
16
|
+
seq(
|
17
|
+
left,
|
18
|
+
many(not_followed_by(right).bind { any_char }).join,
|
19
|
+
right
|
20
|
+
).join
|
21
|
+
end
|
22
|
+
|
23
|
+
def starting_string(str)
|
24
|
+
index.bind do |index|
|
25
|
+
(index.column > 1) ? failed("1 column") : string(str)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def balanced(l, r, inner)
|
30
|
+
left = string(l)
|
31
|
+
right = string(r)
|
32
|
+
|
33
|
+
many(
|
34
|
+
alt(
|
35
|
+
seq(
|
36
|
+
left,
|
37
|
+
lazy { balanced(l, r, inner) },
|
38
|
+
right
|
39
|
+
),
|
40
|
+
not_followed_by(right).bind { inner }
|
41
|
+
)
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyNext
|
4
|
+
module Language
|
5
|
+
module PacoParsers
|
6
|
+
class Comments < Base
|
7
|
+
def default
|
8
|
+
alt(
|
9
|
+
line_comment,
|
10
|
+
block_comment
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Matches a Ruby line comment (from `#` till the end of the line)
|
15
|
+
def line_comment
|
16
|
+
anything_between(string("#"), end_of_line)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Matches a Ruby block comment (from `=begin` till `=end`)
|
20
|
+
def block_comment
|
21
|
+
anything_between(starting_string("=begin"), starting_string("=end"))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyNext
|
4
|
+
module Language
|
5
|
+
module PacoParsers
|
6
|
+
class StringLiterals < Base
|
7
|
+
PAIRS = {"[" => "]", "{" => "}", "<" => ">"}.freeze
|
8
|
+
|
9
|
+
def default
|
10
|
+
all_strings.fmap do |result|
|
11
|
+
reduce_tokens(result.flatten)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def all_strings
|
16
|
+
alt(
|
17
|
+
single_quoted,
|
18
|
+
double_quoted,
|
19
|
+
external_cmd_exec,
|
20
|
+
quoted,
|
21
|
+
quoted_expanded
|
22
|
+
)
|
23
|
+
# heredoc,
|
24
|
+
# heredoc_expanded
|
25
|
+
end
|
26
|
+
|
27
|
+
def quoted
|
28
|
+
seq(
|
29
|
+
string("%q"),
|
30
|
+
any_char.bind do |char|
|
31
|
+
end_symbol = string(PAIRS[char] || char)
|
32
|
+
escapable_string(succeed(char), end_symbol)
|
33
|
+
end
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def single_quoted
|
38
|
+
escapable_string(string("'"))
|
39
|
+
end
|
40
|
+
|
41
|
+
def quoted_expanded
|
42
|
+
seq(
|
43
|
+
alt(string("%Q"), string("%")),
|
44
|
+
any_char.bind do |char|
|
45
|
+
end_symbol = string(PAIRS[char] || char)
|
46
|
+
escapable_string(succeed(char), end_symbol, interpolate: true)
|
47
|
+
end
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
def external_cmd_exec
|
52
|
+
escapable_string(string("`"), interpolate: true)
|
53
|
+
end
|
54
|
+
|
55
|
+
def double_quoted
|
56
|
+
escapable_string(string('"'), interpolate: true)
|
57
|
+
end
|
58
|
+
|
59
|
+
def escapable_string(left, right = nil, interpolate: false)
|
60
|
+
right ||= left
|
61
|
+
seq(
|
62
|
+
left,
|
63
|
+
many(
|
64
|
+
alt(
|
65
|
+
*[
|
66
|
+
seq(string("\\"), right).fmap { [:literal, _1] },
|
67
|
+
interpolate ? seq(
|
68
|
+
string('#{'),
|
69
|
+
lazy { alt(balanced("{", "}", alt(all_strings, any_char)), many(none_of("}"))) },
|
70
|
+
string("}")
|
71
|
+
) : nil,
|
72
|
+
not_followed_by(right).bind { any_char }.fmap { [:literal, _1] }
|
73
|
+
].compact
|
74
|
+
)
|
75
|
+
),
|
76
|
+
right
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def reduce_tokens(tokens)
|
83
|
+
state = :literal
|
84
|
+
|
85
|
+
tokens.each_with_object([]) do |v, acc|
|
86
|
+
if v == :literal
|
87
|
+
acc << [:literal, +""] unless state == :literal
|
88
|
+
state = :next_literal
|
89
|
+
next acc
|
90
|
+
end
|
91
|
+
|
92
|
+
if state == :next_literal
|
93
|
+
state = :literal
|
94
|
+
acc.last[1] << v
|
95
|
+
next acc
|
96
|
+
end
|
97
|
+
|
98
|
+
if state == :literal
|
99
|
+
acc << [:code, +""]
|
100
|
+
end
|
101
|
+
|
102
|
+
state = :code
|
103
|
+
acc.last[1] << v
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
begin
|
4
|
+
require "parser/prism"
|
5
|
+
rescue LoadError
|
6
|
+
require "parser/ruby33"
|
7
|
+
end
|
4
8
|
|
5
9
|
module RubyNext
|
6
10
|
module Language
|
@@ -22,11 +26,18 @@ module RubyNext
|
|
22
26
|
unless method_defined?(:match_pattern_p)
|
23
27
|
include BuilderExt
|
24
28
|
end
|
29
|
+
|
30
|
+
def check_reserved_for_numparam(name, loc)
|
31
|
+
# We don't want to raise SyntaxError, 'cause we want to use _x vars for older Rubies.
|
32
|
+
# The exception should be raised by Ruby itself for versions supporting numbered parameters
|
33
|
+
end
|
25
34
|
end
|
26
35
|
|
27
36
|
class << self
|
37
|
+
attr_accessor :parser_class
|
38
|
+
|
28
39
|
def parser
|
29
|
-
|
40
|
+
parser_class.new(Builder.new).tap do |prs|
|
30
41
|
prs.diagnostics.tap do |diagnostics|
|
31
42
|
diagnostics.all_errors_are_fatal = true
|
32
43
|
end
|
@@ -53,5 +64,16 @@ module RubyNext
|
|
53
64
|
raise ::SyntaxError, e.message
|
54
65
|
end
|
55
66
|
end
|
67
|
+
|
68
|
+
# Set up default parser
|
69
|
+
unless parser_class
|
70
|
+
self.parser_class = if defined?(::Parser::RubyNext)
|
71
|
+
::Parser::RubyNext
|
72
|
+
elsif defined?(::Parser::Prism)
|
73
|
+
::Parser::Prism
|
74
|
+
else
|
75
|
+
::Parser::Ruby33
|
76
|
+
end
|
77
|
+
end
|
56
78
|
end
|
57
79
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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)
|
@@ -50,7 +50,7 @@ module RubyNext
|
|
50
50
|
|
51
51
|
return false unless fargs
|
52
52
|
|
53
|
-
node.children.index(fargs) > (node.type == :send ? 2 : 0)
|
53
|
+
node.children.index(fargs) > ((node.type == :send) ? 2 : 0)
|
54
54
|
end
|
55
55
|
|
56
56
|
def method_with_leading_arg(node)
|
@@ -62,7 +62,7 @@ module RubyNext
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def def_with_leading_farg(node)
|
65
|
-
args = node.type == :defs ? node.children[2] : node.children[1]
|
65
|
+
args = (node.type == :defs) ? node.children[2] : node.children[1]
|
66
66
|
args = args.children
|
67
67
|
|
68
68
|
farg = args.detect { |child| child.type == :forward_arg }
|
@@ -25,7 +25,7 @@ module RubyNext
|
|
25
25
|
|
26
26
|
context.track! self
|
27
27
|
|
28
|
-
left_p, right_p = pattern.type == :array_pattern ? %w([ ]) : %w[{ }]
|
28
|
+
left_p, right_p = (pattern.type == :array_pattern) ? %w([ ]) : %w[{ }]
|
29
29
|
|
30
30
|
insert_before(pattern.loc.expression, left_p)
|
31
31
|
insert_after(pattern.loc.expression, right_p)
|