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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 44b797d87fbbc3b9eb0c31ad04466abadb286728a80a5222808072994939dc81
4
- data.tar.gz: 3e3f018b5adbfb2f2213722509d5d50fafec01efd85e92580e26234f7fd2f99e
3
+ metadata.gz: 79dd9f615898df70de6648be3805f3c0da92c80e22cd8e2cffc109958ec0811b
4
+ data.tar.gz: 7ed7e923ca5f2b3f6eaf27135a722f2a23e868fe65bce32f6700e74867e6d62c
5
5
  SHA512:
6
- metadata.gz: 9ee37b8457ecba6d8c0ae4ff82a1d9e4a5fbc72a7d9e8bd0997d13ce461d0d3894cae439ddde2836a1e48c1af481d978c66eec83cb6f9865b96c417b69a0d0ba
7
- data.tar.gz: 4d74819e5235e53cdad9c8f5ae25d761309937002a4d03858c0b979fc504535fc04ab76a45dd74ceb9165acb06d73fb643dbc02349925dc438d21155dcc342fc
6
+ metadata.gz: e16c8585ed3e8b5b23ccc5a7b79b80d6da6e96f539c008bc9e781e523c8451fec954b6f0e0948056de9feb231b30dd62989c26aea77890afc2037d91c0a4028a
7
+ data.tar.gz: b2d0d3891032b51a22ffccc600410d250da89d34332cc4797fc4e216f13ab82024520c262e43788660e041937c081a254ae7597e93e686fc23fcbd2d9df37e0c
@@ -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.4+ (including JRuby 9.2.8+). Support for EOL versions (<2.5) slightly differs though ([see below](#using-with-eol-rubies)).
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
- **NOTE:** Use Ruby Next `0.9.0.pre` to use this feature.
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.
@@ -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
- puts RubyNext::Language.transform(contents)
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)
@@ -69,7 +69,7 @@ module RubyNext
69
69
  RubyNext::Core.patches.extensions
70
70
  .values
71
71
  .flatten
72
- .filter do |patch|
72
+ .select do |patch|
73
73
  next if min_version && Gem::Version.new(patch.version) <= min_version
74
74
  next if filter && !filter.match?(patch.name)
75
75
  true
@@ -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 out_path == "stdout"
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 out_path
131
- if out_path.end_with?(".rb")
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
@@ -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)
@@ -3,7 +3,8 @@
3
3
  RubyNext::Core.patch Time, method: :ceil, version: "2.7" do
4
4
  <<~'RUBY'
5
5
  def ceil(den = 0)
6
- change = subsec.ceil(den) - subsec
6
+ sceil = (subsec * 10**den).ceil.to_r / 10**den
7
+ change = sceil - subsec
7
8
  self + change
8
9
  end
9
10
  RUBY
@@ -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
- refine Kernel do
7
- def eval(source, bind = nil, *args)
8
- new_source = ::RubyNext::Language::Runtime.transform(
9
- source,
10
- using: bind&.receiver == TOPLEVEL_BINDING.receiver || bind&.receiver&.is_a?(Module)
11
- )
12
- RubyNext.debug_source(new_source, "(#{caller_locations(1, 1).first})")
13
- super new_source, bind, *args
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,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Load rewriters only required for runtime transpiling
4
+
5
+ require "ruby-next/language/rewriters/runtime/dir"
6
+ RubyNext::Language.rewriters << RubyNext::Language::Rewriters::Dir
@@ -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
- from = caller_locations(1..1).first.absolute_path || File.join(Dir.pwd, "main")
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)),
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyNext
4
- VERSION = "0.9.0.pre"
4
+ VERSION = "0.9.0"
5
5
  end
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.pre
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-05-19 00:00:00.000000000 Z
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.4
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.4
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.4.0
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: 1.3.1
131
+ version: '0'
130
132
  requirements: []
131
133
  rubygems_version: 3.0.6
132
134
  signing_key: