ruby-next-core 0.15.2 → 1.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|