Comments (17)
@palkan yeah unfortunately deconstruct_keys
was showing up quite a lot in the profile. Switching back to a case..when
gave me some performance back.
I think we can do a better job in CRuby of rewriting the iseqs to do some smarter matching when common patterns are found. Or just let YJIT do its thing. But in the meantime I decided to just roll with eliminating the pattern matching for now.
from ruby-next.
In general when using RubyNext in a gem I'd want to avoid the runtime dependency, hence I did the manual $LOAD_PATH.unshift "#{__dir__}/.rbnext"
above.
from ruby-next.
I also tried:
$ ruby-next nextify --rewrite=pattern-matching,pattern-matching-find-pattern,pattern-matching-in,pattern-matching-oneline-parensless,pattern-matching-pin-vars ./lib
Rewriters not found: pattern-matching,pattern-matching-find-pattern,pattern-matching-in,pattern-matching-oneline-parensless,pattern-matching-pin-vars
Try --list-rewriters to see list of available rewriters
from ruby-next.
I noticed this succeeds:
$ ruby-next nextify -V --rewrite=pattern-matching ./lib
RubyNext core strategy: refine
RubyNext transpile mode: rewrite
Remove old files: ./lib/.rbnext
Generated: ./lib/.rbnext/syntax_tree/language_server/inlay_hints.rb
Generated: ./lib/.rbnext/syntax_tree/language_server.rb
Generated: ./lib/.rbnext/syntax_tree/node.rb
Generated: ./lib/.rbnext/syntax_tree/parser.rb
but this fails:
$ ruby-next nextify -V --rewrite=pattern-matching --rewrite=pattern-matching-find-pattern ./lib
RubyNext core strategy: refine
RubyNext transpile mode: rewrite
Remove old files: ./lib/.rbnext
Generated: ./lib/.rbnext/syntax_tree/language_server/inlay_hints.rb
Generated: ./lib/.rbnext/syntax_tree/language_server.rb
Failed to transpile ./lib/syntax_tree/node.rb: SyntaxError — unexpected token tRBRACK
from ruby-next.
With the first one, then line 2147 becomes (which TruffleRuby cannot parse: syntax_tree/lib/.rbnext/syntax_tree/node.rb:2147: syntax error, unexpected '{ arg'
):
when (__p_1__ && __p_3__ = (1 == __m_arr__.size) and (Paren(contents: {body: [ArrayLiteral(contents: {parts: [_, _, *]}) => array]}) === __m_arr__[0]))
the original is:
in [
Paren[
contents: {
body: [ArrayLiteral[contents: { parts: [_, _, *] }] => array] }
]
]
from ruby-next.
I noticed that with commenting out diagnostics.all_errors_are_fatal = true
, but I get the same error and translation for that line, there is still the ArrayLiteral(contents: {parts: [_, _, *]}) => array
.
So maybe it is a parser gem issue?
from ruby-next.
Adding some debugging in Parser::Diagnostic::Engine#process
:
def process(diagnostic)
if ignore?(diagnostic)
# do nothing
elsif @consumer
@consumer.call(diagnostic)
end
if raise?(diagnostic)
p diagnostic
p diagnostic.message
p diagnostic.location.line
p diagnostic.location.source_line
raise Parser::SyntaxError, diagnostic
end
self
end
it shows
$ ruby-next nextify -V --rewrite=pattern-matching --rewrite=pattern-matching-find-pattern --rewrite=pattern-matching-in --rewrite=pattern-matching-oneline-parensless --rewrite=pattern-matching-pin-vars ./lib
...
#<Parser::Diagnostic:0x00007f2c344abc00 @level=:error, @reason=:unexpected_token, @arguments={:token=>"tRBRACK"}, @location=#<Parser::Source::Range (string) 55137...55138>, @highlights=[]>
"unexpected token tRBRACK"
2147
" when (__p_1__ && __p_3__ = (1 == __m_arr__.size) and (Paren(contents: {body: [ArrayLiteral(contents: {parts: [_, _, *]}) => array]}) === __m_arr__[0]))"
Failed to transpile ./lib/syntax_tree/node.rb: SyntaxError — unexpected token tRBRACK
So it seems ruby-next tries to reparse what it produced, and that fails. So maybe the issue is that ruby-next doesn't desugar that ArrayLiteral(contents: {parts: [_, _, *]}) => array
?
from ruby-next.
I guess [_, _, *]
is actually "basic" pattern matching, not find pattern. And that should be the case since anyway syntax_tree
supports CRuby 2.7 and its "basic" pattern matching.
from ruby-next.
Thanks for the investigation, @eregon!
when (p_1 && p_3 = (1 == m_arr.size) and (Paren(contents: {body: [ArrayLiteral(contents: {parts: [_, _, *]}) => array]}) === m_arr[0]))
I guess [_, _, *] is actually "basic" pattern matching, not find pattern
These two things look suspicious. I will take a look.
from ruby-next.
Fixed in 0.15.3.
Tested against syntax_tree
main and 3.6.3 (since @kddnewton got rid of pattern matching recently—performance reasons? Curious to hear more about it 🙂)
from ruby-next.
unfortunately deconstruct_keys was showing up quite a lot in the profile
Yeah, it hasn't been optimized yet. We added some optimization for #deconstruct
(ruby/ruby#3104) in 3.0, but doing the same for #deconstruct_keys
is much trickier, since it depends on the args.
Switching back to a case..when gave me some performance back.
I'm curious, how the transpired code would perform (since transpiled pattern matching is better optimized than a native one). Do you have a benchmark script available somewhere, so I could try to experiment with it?
from ruby-next.
Fixed in 0.15.3.
Thanks!
I tried ruby-next nextify -V --rewrite=pattern-matching ./lib
on ruby-syntax-tree/syntax_tree@cb72efc and that succeeded.
Together with the change below, the files load on TruffleRuby but the test suite can't be run because it itself uses pattern matching.
I also briefly tried require "ruby-next/language/runtime"
but that didn't seem to handle eval
(and it was a pretty high startup overhead).
FWIW I also tried ruby-next nextify -V --rewrite=pattern-matching ./test/*_test.rb
but that doesn't work, it seems to ignore the 2nd and later files.
It'd be quite convenient to have a mode where the files are rewritten inplace actually for such experiments :)
This is the change to pick up the rewritten lib files under lib/.rbnext
:
diff --git a/lib/syntax_tree.rb b/lib/syntax_tree.rb
index 88c6636..04fa0ae 100644
--- a/lib/syntax_tree.rb
+++ b/lib/syntax_tree.rb
@@ -1,5 +1,10 @@
# frozen_string_literal: true
+if RUBY_ENGINE == "truffleruby"
+ module RubyNext; end
+ $LOAD_PATH.unshift "#{__dir__}/.rbnext"
+end
+
require "delegate"
require "etc"
require "json"
@@ -9,7 +14,7 @@ require "ripper"
require "stringio"
require_relative "syntax_tree/formatter"
-require_relative "syntax_tree/node"
+require "syntax_tree/node"
require_relative "syntax_tree/parser"
require_relative "syntax_tree/version"
Ideally module RubyNext; end
wouldn't be needed but RubyNext currently adds using RubyNext;
even if it's only syntax desugaring and no method backports.
from ruby-next.
Ah and last thing I noticed this warning when using the runtime mode:
/home/eregon/.rubies/truffleruby-dev/lib/gems/gems/ruby-next-core-0.15.3/lib/.rbnext/2.7/ruby-next/language/rewriters/2.7/pattern_matching.rb:1010: warning: `_1' is reserved for numbered parameter; consider another name
@palkan Would you like I open separate issues with what I mentioned here? Or a single issue with various items?
from ruby-next.
Thanks @eregon!
Let's create separate issues, please. (I will add the "hacktoberfest" label, so the work could be parallelized 🙂).
from ruby-next.
I also briefly tried require "ruby-next/language/runtime" but that didn't seem to handle eval
Yeah, for eval support, a refinement must be activated explicitly: using RubyNext::Language::Eval
.
but RubyNext currently adds using RubyNext; even if it's only syntax desugaring and no method backports.
You can run nextify
with --no-refine
to not inject using RubyNext
from ruby-next.
the test suite can't be run because it itself uses pattern matching.
One option to try adding -ruby-next
to the Rake task's ruby_opts
(or add it when running a single test file, ruby -ruby-next ...
. Haven't tried this though.
from ruby-next.
You can run
nextify
with--no-refine
to not injectusing RubyNext
Oh, right, somehow I missed that in the --help
.
from ruby-next.
Related Issues (20)
- `ruby-next nextify -V --rewrite=pattern-matching file1 file2 file3` ignores file2 and file3
- A runtime mode which monkey-patches eval HOT 2
- Using RubyNext in gems without a runtime dependency HOT 3
- An option to rewrite file inplace for `ruby-next nextify`
- Non-obvious syntax error HOT 3
- String#bytesplice HOT 2
- Support `it` as a default block parameter
- Data#initialize doesn't support positional args HOT 5
- Facing issues in new builds impacting production env HOT 1
- Rewrite not persisted HOT 3
- can't require on Ruby 3.4.0dev HOT 1
- Access to file path during rewriting? HOT 3
- Pattern matching pin for instance/global/class vars and expressions HOT 1
- Ruby 3.1 checklist
- ruby-next causes random segmentation faults in Ruby 2.7.x HOT 2
- Truffleruby Compatbility HOT 1
- Proposal: heredoc extensions
- Ruby 3.2 Data HOT 3
- MatchData#{deconstruct,deconstruct_keys}
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ruby-next.