ruby-next-core 0.9.0.pre → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +12 -5
- data/bin/transform +9 -1
- data/lib/ruby-next/commands/core_ext.rb +1 -1
- data/lib/ruby-next/commands/nextify.rb +23 -12
- data/lib/ruby-next/core.rb +5 -0
- data/lib/ruby-next/core/time/ceil.rb +2 -1
- data/lib/ruby-next/language.rb +2 -0
- data/lib/ruby-next/language/eval.rb +10 -8
- data/lib/ruby-next/language/rewriters/base.rb +1 -1
- data/lib/ruby-next/language/rewriters/pattern_matching.rb +2 -1
- data/lib/ruby-next/language/rewriters/runtime.rb +6 -0
- data/lib/ruby-next/language/rewriters/runtime/dir.rb +32 -0
- data/lib/ruby-next/language/runtime.rb +3 -2
- data/lib/ruby-next/utils.rb +30 -0
- data/lib/ruby-next/version.rb +1 -1
- metadata +9 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79dd9f615898df70de6648be3805f3c0da92c80e22cd8e2cffc109958ec0811b
|
4
|
+
data.tar.gz: 7ed7e923ca5f2b3f6eaf27135a722f2a23e868fe65bce32f6700e74867e6d62c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e16c8585ed3e8b5b23ccc5a7b79b80d6da6e96f539c008bc9e781e523c8451fec954b6f0e0948056de9feb231b30dd62989c26aea77890afc2037d91c0a4028a
|
7
|
+
data.tar.gz: b2d0d3891032b51a22ffccc600410d250da89d34332cc4797fc4e216f13ab82024520c262e43788660e041937c081a254ae7597e93e686fc23fcbd2d9df37e0c
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.9.0 (2020-06-04)
|
6
|
+
|
7
|
+
- Add Ruby 2.3 support. ([@palkan][])
|
8
|
+
|
9
|
+
- Remove stale transpiled files when running `ruby-next nextify`. ([@palkan][])
|
10
|
+
|
5
11
|
- Add Ruby 2.4 support. ([@palkan][])
|
6
12
|
|
7
13
|
APIs for <2.5 must be backported via [backports][] gem. Refinements are not supported.
|
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
[![Gem Version](https://badge.fury.io/rb/ruby-next.svg)](https://rubygems.org/gems/ruby-next) [![Build](https://github.com/ruby-next/ruby-next/workflows/Build/badge.svg)](https://github.com/ruby-next/ruby-next/actions)
|
2
|
-
[![JRuby Build](https://github.com/ruby-next/ruby-next/workflows/JRuby%20Build/badge.svg)](https://github.com/ruby-next/ruby-next/actions)
|
2
|
+
[![JRuby Build](https://github.com/ruby-next/ruby-next/workflows/JRuby%20Build/badge.svg)](https://github.com/ruby-next/ruby-next/actions?query=workflow%3A%22TruffleRuby+Build%22)
|
3
|
+
[![TruffleRuby Build](https://github.com/ruby-next/ruby-next/workflows/TruffleRuby%20Build/badge.svg)](https://github.com/ruby-next/ruby-next/actions?query=workflow%3A%22TruffleRuby+Build%22)
|
3
4
|
|
4
5
|
# Ruby Next
|
5
6
|
|
@@ -66,7 +67,7 @@ Core provides **polyfills** for Ruby core classes APIs via Refinements (default
|
|
66
67
|
Language is responsible for **transpiling** edge Ruby syntax into older versions. It could be done
|
67
68
|
programmatically or via CLI. It also could be done in runtime.
|
68
69
|
|
69
|
-
Currently, Ruby Next supports Ruby versions 2.
|
70
|
+
Currently, Ruby Next supports Ruby versions 2.3+, including JRuby 9.2.8+ and TruffleRuby 20.1+ (with some limitations). Support for EOL versions (<2.5) slightly differs though ([see below](#using-with-eol-rubies)).
|
70
71
|
|
71
72
|
Please, [open an issue](https://github.com/ruby-next/ruby-next/issues/new/choose) or join the discussion in the existing ones if you would like us to support older Ruby versions.
|
72
73
|
|
@@ -137,6 +138,8 @@ The following _rule of thumb_ is recommended when choosing between refinements a
|
|
137
138
|
- Using core extensions could be considered for application development (no need to think about `using RubyNext`); this approach could potentially lead to conflicts with dependencies (if these dependencies are not using refinements 🙂)
|
138
139
|
- Use core extensions if refinements are not supported by your platform
|
139
140
|
|
141
|
+
**NOTE:** TruffleRuby doesn't fully support refinements (refining modules is not supported as of v20.1.0).
|
142
|
+
|
140
143
|
[**The list of supported APIs.**][features_core]
|
141
144
|
|
142
145
|
## Transpiling
|
@@ -390,6 +393,12 @@ RUBYOPT="-ruby-next" ruby my_ruby_script.rb
|
|
390
393
|
ruby -ruby-next -e "puts [2, 4, 5].tally"
|
391
394
|
```
|
392
395
|
|
396
|
+
**NOTE:** running Ruby scripts directly or executing code via `-e` option is not supported in TruffleRuby. You can still use `-ruby-next` to transpile required files, e.g.:
|
397
|
+
|
398
|
+
```sh
|
399
|
+
ruby -ruby-next -r my_ruby_script.rb -e "puts my_method"
|
400
|
+
```
|
401
|
+
|
393
402
|
## Logging and debugging
|
394
403
|
|
395
404
|
Ruby Next prints some debugging information when fails to load a file in the runtime mode (and fallbacks to the built-in loading mechanism).
|
@@ -426,9 +435,7 @@ AllCops:
|
|
426
435
|
|
427
436
|
## Using with EOL Rubies
|
428
437
|
|
429
|
-
|
430
|
-
|
431
|
-
We currently provide experimental support for Ruby 2.4. Work on older Rubies (down to 2.2) is in progress.
|
438
|
+
We currently provide support for Ruby 2.3 and 2.4. Work on 2.2 is in progress.
|
432
439
|
|
433
440
|
Ruby Next itself relies on 2.5 features and contains polyfills only for version 2.5+ (and that won't change).
|
434
441
|
Thus, to make it work with <2.5 we need to backport some APIs ourselves.
|
data/bin/transform
CHANGED
@@ -9,6 +9,7 @@ ENV["RUBY_NEXT_EDGE"] = "1"
|
|
9
9
|
ENV["RUBY_NEXT_PROPOSED"] = "1"
|
10
10
|
|
11
11
|
require "ruby-next/language"
|
12
|
+
require "ruby-next/language/rewriters/runtime"
|
12
13
|
|
13
14
|
contents =
|
14
15
|
if File.exist?(ARGV[0])
|
@@ -17,4 +18,11 @@ contents =
|
|
17
18
|
ARGV[0]
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
+
opts =
|
22
|
+
if ARGV[1] && ARGV[1] == "--current"
|
23
|
+
{rewriters: RubyNext::Language.current_rewriters}
|
24
|
+
else
|
25
|
+
{}
|
26
|
+
end
|
27
|
+
|
28
|
+
puts RubyNext::Language.transform(contents, **opts)
|
@@ -16,6 +16,8 @@ module RubyNext
|
|
16
16
|
log "RubyNext core strategy: #{RubyNext::Core.strategy}"
|
17
17
|
log "RubyNext transpile mode: #{RubyNext::Language.mode}"
|
18
18
|
|
19
|
+
remove_rbnext!
|
20
|
+
|
19
21
|
paths.each do |path|
|
20
22
|
contents = File.read(path)
|
21
23
|
transpile path, contents
|
@@ -120,25 +122,17 @@ module RubyNext
|
|
120
122
|
end
|
121
123
|
|
122
124
|
def save(contents, path, version)
|
123
|
-
return $stdout.puts(contents) if
|
125
|
+
return $stdout.puts(contents) if stdout?
|
124
126
|
|
125
127
|
paths = [Pathname.new(path).relative_path_from(Pathname.new(lib_path))]
|
126
128
|
|
127
129
|
paths.unshift(version.segments[0..1].join(".")) unless single_version?
|
128
130
|
|
129
131
|
next_path =
|
130
|
-
if
|
131
|
-
|
132
|
-
out_path
|
133
|
-
else
|
134
|
-
File.join(out_path, *paths)
|
135
|
-
end
|
132
|
+
if next_dir_path.end_with?(".rb")
|
133
|
+
out_path
|
136
134
|
else
|
137
|
-
File.join(
|
138
|
-
lib_path,
|
139
|
-
RUBY_NEXT_DIR,
|
140
|
-
*paths
|
141
|
-
)
|
135
|
+
File.join(next_dir_path, *paths)
|
142
136
|
end
|
143
137
|
|
144
138
|
unless CLI.dry_run?
|
@@ -150,6 +144,23 @@ module RubyNext
|
|
150
144
|
log "Generated: #{next_path}"
|
151
145
|
end
|
152
146
|
|
147
|
+
def remove_rbnext!
|
148
|
+
return if CLI.dry_run? || stdout?
|
149
|
+
|
150
|
+
return unless File.directory?(next_dir_path)
|
151
|
+
|
152
|
+
log "Remove old files: #{next_dir_path}"
|
153
|
+
FileUtils.rm_r(next_dir_path)
|
154
|
+
end
|
155
|
+
|
156
|
+
def next_dir_path
|
157
|
+
@next_dir_path ||= (out_path || File.join(lib_path, RUBY_NEXT_DIR))
|
158
|
+
end
|
159
|
+
|
160
|
+
def stdout?
|
161
|
+
out_path == "stdout"
|
162
|
+
end
|
163
|
+
|
153
164
|
alias single_version? single_version
|
154
165
|
end
|
155
166
|
end
|
data/lib/ruby-next/core.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require "set"
|
4
4
|
|
5
|
+
require_relative "utils"
|
6
|
+
|
5
7
|
module RubyNext
|
6
8
|
module Core
|
7
9
|
# Patch contains the extension implementation
|
@@ -182,6 +184,9 @@ require_relative "core/struct/deconstruct_keys"
|
|
182
184
|
# Generate refinements
|
183
185
|
RubyNext.module_eval do
|
184
186
|
RubyNext::Core.patches.refined.each do |mod, patches|
|
187
|
+
# Only refine modules when supported
|
188
|
+
next unless mod.is_a?(Class) || RubyNext::Utils.refine_modules?
|
189
|
+
|
185
190
|
refine mod do
|
186
191
|
patches.each do |patch|
|
187
192
|
module_eval(patch.body, *patch.location)
|
data/lib/ruby-next/language.rb
CHANGED
@@ -83,6 +83,8 @@ module RubyNext
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def runtime!
|
86
|
+
require "ruby-next/language/rewriters/runtime"
|
87
|
+
|
86
88
|
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0") && !defined?(Unparser::Emitter::CaseMatch)
|
87
89
|
RubyNext.warn "Ruby Next fallbacks to \"rewrite\" transpiling mode since Unparser doesn't support 2.7 AST yet.\n" \
|
88
90
|
"See https://github.com/mbj/unparser/pull/142"
|
@@ -3,14 +3,16 @@
|
|
3
3
|
module RubyNext
|
4
4
|
module Language
|
5
5
|
module KernelEval
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
if Utils.refine_modules?
|
7
|
+
refine Kernel do
|
8
|
+
def eval(source, bind = nil, *args)
|
9
|
+
new_source = ::RubyNext::Language::Runtime.transform(
|
10
|
+
source,
|
11
|
+
using: bind&.receiver == TOPLEVEL_BINDING.receiver || bind&.receiver&.is_a?(Module)
|
12
|
+
)
|
13
|
+
RubyNext.debug_source(new_source, "(#{caller_locations(1, 1).first})")
|
14
|
+
super new_source, bind, *args
|
15
|
+
end
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
@@ -59,7 +59,7 @@ module RubyNext
|
|
59
59
|
def unsupported_syntax?
|
60
60
|
save_verbose, $VERBOSE = $VERBOSE, nil
|
61
61
|
eval_mid = Kernel.respond_to?(:eval_without_ruby_next) ? :eval_without_ruby_next : :eval
|
62
|
-
Kernel.send eval_mid, self::SYNTAX_PROBE
|
62
|
+
Kernel.send eval_mid, self::SYNTAX_PROBE, nil, __FILE__, __LINE__
|
63
63
|
false
|
64
64
|
rescue SyntaxError, NameError
|
65
65
|
true
|
@@ -816,11 +816,12 @@ module RubyNext
|
|
816
816
|
end
|
817
817
|
|
818
818
|
def respond_to_missing?(mid, *)
|
819
|
-
return true if mid.match?(/_(clause|array_element)/)
|
819
|
+
return true if mid.to_s.match?(/_(clause|array_element)/)
|
820
820
|
super
|
821
821
|
end
|
822
822
|
|
823
823
|
def method_missing(mid, *args, &block)
|
824
|
+
mid = mid.to_s
|
824
825
|
return case_eq_clause(*args) if mid.match?(/_clause$/)
|
825
826
|
return case_eq_array_element(*args) if mid.match?(/_array_element$/)
|
826
827
|
return case_eq_hash_element(*args) if mid.match?(/_hash_element$/)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyNext
|
4
|
+
module Language
|
5
|
+
module Rewriters
|
6
|
+
# Special rewriter for Ruby <=2.3, which doesn't support __dir__ in iseq.eval
|
7
|
+
class Dir < Base
|
8
|
+
SYNTAX_PROBE = "defined?(RubyVM::InstructionSequence) && RubyVM::InstructionSequence.compile('raise SyntaxError if __dir__.nil?', 'test.rb').eval"
|
9
|
+
MIN_SUPPORTED_VERSION = Gem::Version.new("2.4.0")
|
10
|
+
|
11
|
+
def on_send(node)
|
12
|
+
return super(node) unless node.children[1] == :__dir__
|
13
|
+
|
14
|
+
context.track! self
|
15
|
+
|
16
|
+
replace(node.loc.expression, "File.dirname(__FILE__)")
|
17
|
+
|
18
|
+
process(
|
19
|
+
node.updated(
|
20
|
+
nil,
|
21
|
+
[
|
22
|
+
s(:const, nil, :File),
|
23
|
+
:dirname,
|
24
|
+
s(:send, nil, "__FILE__")
|
25
|
+
]
|
26
|
+
)
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -42,7 +42,7 @@ module RubyNext
|
|
42
42
|
path
|
43
43
|
end
|
44
44
|
|
45
|
-
if defined?(JRUBY_VERSION)
|
45
|
+
if defined?(JRUBY_VERSION) || defined?(TruffleRuby)
|
46
46
|
def evaluate(code, filepath)
|
47
47
|
new_toplevel.eval(code, filepath)
|
48
48
|
end
|
@@ -89,7 +89,8 @@ module Kernel
|
|
89
89
|
|
90
90
|
alias_method :require_relative_without_ruby_next, :require_relative
|
91
91
|
def require_relative(path)
|
92
|
-
|
92
|
+
loc = caller_locations(1..1).first
|
93
|
+
from = loc.absolute_path || loc.path || File.join(Dir.pwd, "main")
|
93
94
|
realpath = File.absolute_path(
|
94
95
|
File.join(
|
95
96
|
File.dirname(File.absolute_path(from)),
|
data/lib/ruby-next/utils.rb
CHANGED
@@ -33,5 +33,35 @@ module RubyNext
|
|
33
33
|
lines.unshift " 0: # source: #{path}"
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
# Returns true if modules refinement is supported in current version
|
38
|
+
def refine_modules?
|
39
|
+
@refine_modules ||=
|
40
|
+
begin
|
41
|
+
# Make sure that including modules within refinements works
|
42
|
+
# See https://github.com/oracle/truffleruby/issues/2026
|
43
|
+
eval <<~RUBY, TOPLEVEL_BINDING, __FILE__, __LINE__ + 1
|
44
|
+
module RubyNext::Utils::A; end
|
45
|
+
class RubyNext::Utils::B
|
46
|
+
include RubyNext::Utils::A
|
47
|
+
end
|
48
|
+
|
49
|
+
using(Module.new do
|
50
|
+
refine RubyNext::Utils::A do
|
51
|
+
include(Module.new do
|
52
|
+
def i_am_refinement
|
53
|
+
"yes, you are!"
|
54
|
+
end
|
55
|
+
end)
|
56
|
+
end
|
57
|
+
end)
|
58
|
+
|
59
|
+
RubyNext::Utils::B.new.i_am_refinement
|
60
|
+
RUBY
|
61
|
+
true
|
62
|
+
rescue TypeError, NoMethodError
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
36
66
|
end
|
37
67
|
end
|
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.9.0
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Dementyev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-next-parser
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.8.0.
|
19
|
+
version: 2.8.0.6
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.8.0.
|
26
|
+
version: 2.8.0.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: unparser
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -96,6 +96,8 @@ files:
|
|
96
96
|
- lib/ruby-next/language/rewriters/numbered_params.rb
|
97
97
|
- lib/ruby-next/language/rewriters/pattern_matching.rb
|
98
98
|
- lib/ruby-next/language/rewriters/right_hand_assignment.rb
|
99
|
+
- lib/ruby-next/language/rewriters/runtime.rb
|
100
|
+
- lib/ruby-next/language/rewriters/runtime/dir.rb
|
99
101
|
- lib/ruby-next/language/runtime.rb
|
100
102
|
- lib/ruby-next/language/setup.rb
|
101
103
|
- lib/ruby-next/language/unparser.rb
|
@@ -121,12 +123,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
121
123
|
requirements:
|
122
124
|
- - ">="
|
123
125
|
- !ruby/object:Gem::Version
|
124
|
-
version: 2.
|
126
|
+
version: 2.3.0
|
125
127
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
128
|
requirements:
|
127
|
-
- - "
|
129
|
+
- - ">="
|
128
130
|
- !ruby/object:Gem::Version
|
129
|
-
version:
|
131
|
+
version: '0'
|
130
132
|
requirements: []
|
131
133
|
rubygems_version: 3.0.6
|
132
134
|
signing_key:
|