Share
Embed
The Future of Understanding Ruby
For decades, the Ruby community has been fractured in the way that it parses and understands Ruby code. After countless tools have been developed and person-hours have been invested, we still don't have a common language for understanding Ruby code. No longer! Starting in Ruby 3.3, we will have a single API for parsing and understanding Ruby code. This talk will cover the history of how we got here, what is getting built today, and what you can expect from this exciting future.
Kevin Newton
November 14, 2023
Transcript
296 slides
-
* = <<~EOF, /(?<m\ matchy match EOF atch>\d+)/ =~ "3"
match /1+2 #/ -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications def ❨╯°□°❩╯︵┻━┻ puts "Calm down, yo." end -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications def ❨╯°□°❩╯︵┻━┻ puts "Calm down, yo." end -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications [[KEYWORD_DEF, "def"], [IDENTIFIER, "❨╯°□°❩╯︵┻━┻"], [NEWLINE, "\n"], [IDENTIFIER, "puts"], [STRING_BEGIN, "\""], [STRING_CONTENT, "Calm down, yo."], [STRING_END, "\""], [NEWLINE, "\n"], [KEYWORD_END, "end"], [NEWLINE, "\n"], [EOF, ""]] -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications @ DefNode (location: (1,0)-(3,3)) ├── name: :❨╯°□°❩╯︵┻━┻ └── body: @ StatementsNode (location: (2,2)-(2,23)) └── body: (length: 1) └── @ CallNode (location: (2,2)-(2,23)) ├── arguments: │ @ ArgumentsNode (location: (2,7)-(2,23)) │ └── arguments: (length: 1) │ └── @ StringNode (location: (2,7)-(2,23)) │ └── unescaped: "Calm down, yo." └── name: :puts -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications @ DefNode (location: (1,0)-(3,3)) ├── name: :❨╯°□°❩╯︵┻━┻ └── body: @ StatementsNode (location: (2,2)-(2,23)) └── body: (length: 1) └── @ CallNode (location: (2,2)-(2,23)) ├── arguments: │ @ ArgumentsNode (location: (2,7)-(2,23)) │ └── arguments: (length: 1) │ └── @ StringNode (location: (2,7)-(2,23)) │ └── unescaped: "Calm down, yo." └── name: :puts -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications @ DefNode (location: (1,0)-(3,3)) ├── name: :❨╯°□°❩╯︵┻━┻ └── body: @ StatementsNode (location: (2,2)-(2,23)) └── body: (length: 1) └── @ CallNode (location: (2,2)-(2,23)) ├── arguments: │ @ ArgumentsNode (location: (2,7)-(2,23)) │ └── arguments: (length: 1) │ └── @ StringNode (location: (2,7)-(2,23)) │ └── unescaped: "Calm down, yo." └── name: :puts -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications @ DefNode (location: (1,0)-(3,3)) ├── name: :❨╯°□°❩╯︵┻━┻ └── body: @ StatementsNode (location: (2,2)-(2,23)) └── body: (length: 1) └── @ CallNode (location: (2,2)-(2,23)) ├── arguments: │ @ ArgumentsNode (location: (2,7)-(2,23)) │ └── arguments: (length: 1) │ └── @ StringNode (location: (2,7)-(2,23)) │ └── unescaped: "Calm down, yo." └── name: :puts putself -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications @ DefNode (location: (1,0)-(3,3)) ├── name: :❨╯°□°❩╯︵┻━┻ └── body: @ StatementsNode (location: (2,2)-(2,23)) └── body: (length: 1) └── @ CallNode (location: (2,2)-(2,23)) ├── arguments: │ @ ArgumentsNode (location: (2,7)-(2,23)) │ └── arguments: (length: 1) │ └── @ StringNode (location: (2,7)-(2,23)) │ └── unescaped: "Calm down, yo." └── name: :puts putself -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications @ DefNode (location: (1,0)-(3,3)) ├── name: :❨╯°□°❩╯︵┻━┻ └── body: @ StatementsNode (location: (2,2)-(2,23)) └── body: (length: 1) └── @ CallNode (location: (2,2)-(2,23)) ├── arguments: │ @ ArgumentsNode (location: (2,7)-(2,23)) │ └── arguments: (length: 1) │ └── @ StringNode (location: (2,7)-(2,23)) │ └── unescaped: "Calm down, yo." └── name: :puts putself putstring "Calm down, yo.” -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications @ DefNode (location: (1,0)-(3,3)) ├── name: :❨╯°□°❩╯︵┻━┻ └── body: @ StatementsNode (location: (2,2)-(2,23)) └── body: (length: 1) └── @ CallNode (location: (2,2)-(2,23)) ├── arguments: │ @ ArgumentsNode (location: (2,7)-(2,23)) │ └── arguments: (length: 1) │ └── @ StringNode (location: (2,7)-(2,23)) │ └── unescaped: "Calm down, yo." └── name: :puts putself putstring "Calm down, yo.” -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications @ DefNode (location: (1,0)-(3,3)) ├── name: :❨╯°□°❩╯︵┻━┻ └── body: @ StatementsNode (location: (2,2)-(2,23)) └── body: (length: 1) └── @ CallNode (location: (2,2)-(2,23)) ├── arguments: │ @ ArgumentsNode (location: (2,7)-(2,23)) │ └── arguments: (length: 1) │ └── @ StringNode (location: (2,7)-(2,23)) │ └── unescaped: "Calm down, yo." └── name: :puts putself putstring "Calm down, yo.” send :puts -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications @ DefNode (location: (1,0)-(3,3)) ├── name: :❨╯°□°❩╯︵┻━┻ └── body: @ StatementsNode (location: (2,2)-(2,23)) └── body: (length: 1) └── @ CallNode (location: (2,2)-(2,23)) ├── arguments: │ @ ArgumentsNode (location: (2,7)-(2,23)) │ └── arguments: (length: 1) │ └── @ StringNode (location: (2,7)-(2,23)) │ └── unescaped: "Calm down, yo." └── name: :puts putself putstring "Calm down, yo.” send :puts -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications @ DefNode (location: (1,0)-(3,3)) ├── name: :❨╯°□°❩╯︵┻━┻ └── body: @ StatementsNode (location: (2,2)-(2,23)) └── body: (length: 1) └── @ CallNode (location: (2,2)-(2,23)) ├── arguments: │ @ ArgumentsNode (location: (2,7)-(2,23)) │ └── arguments: (length: 1) │ └── @ StringNode (location: (2,7)-(2,23)) │ └── unescaped: "Calm down, yo." └── name: :puts putself putstring "Calm down, yo.” send :puts leave -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications putself putstring "Calm down, yo.” send :puts leave -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications putself putstring "Calm down, yo.” send :puts leave -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications == disasm: #<ISeq:❨╯°□°❩╯︵┻━┻> 0000 putself 0001 putstring "Calm down, yo." 0003 send <cdata!mid:puts, argc:1> 0005 leave -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications == disasm: #<ISeq:❨╯°□°❩╯︵┻━┻> 0000 putself 0001 putstring "Calm down, yo." 0003 send <cdata!mid:puts, argc:1> 0005 leave -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications == disasm: #<ISeq:❨╯°□°❩╯︵┻━┻> 0000 putself 0001 putstring "Calm down, yo." 0003 send <cdata!mid:puts, argc:1> 0005 leave -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications == disasm: #<ISeq:❨╯°□°❩╯︵┻━┻> 0000 putself 0001 putstring "Calm down, yo." 0003 send <cdata!mid:puts, argc:1> 0005 leave -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications == disasm: #<ISeq:❨╯°□°❩╯︵┻━┻> 0000 putself 0001 putstring "Calm down, yo." 0003 send <cdata!mid:puts, argc:1> 0005 leave -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications == disasm: #<ISeq:❨╯°□°❩╯︵┻━┻> 0000 putself 0001 putstring "Calm down, yo." 0003 send <cdata!mid:puts, argc:1> 0005 leave -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications Sidekiq.❨╯°□°❩╯︵┻━┻ -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y IRBuilder.java -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y IRBuilder.java JRuby IR -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y IRBuilder.java JRuby IR JRuby stdlib -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y IRBuilder.java JRuby IR JRuby stdlib rubygems.org* -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y IRBuilder.java JRuby IR JRuby stdlib rubygems.org* Applications* -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y Translator.java -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y Translator.java Tru ff l e -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y Translator.java Tru ff l e TRuby stdlib -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y Translator.java Tru ff l e TRuby stdlib rubygems.org* -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org RubyParser.y Translator.java Tru ff l e TRuby stdlib rubygems.org* Applications* -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org natalie_parser -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org natalie_parser pass1.rb -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org natalie_parser pass1.rb instructions/*.rb -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org natalie_parser pass1.rb instructions/*.rb Natalie stdlib -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org natalie_parser pass1.rb instructions/*.rb Natalie stdlib rubygems.org* -
Ruby source Parser Compiler Byte code/IR Standard libraries External libraries
Applications parse.y compile.c YARV CRuby stdlib rubygems.org natalie_parser pass1.rb instructions/*.rb Natalie stdlib rubygems.org* Applications* -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parse.y compile.c YARV RubyParser.y IRBuilder.java JRuby IR RubyParser.y
Translator.java Tru ffl e natalie_parser pass1.rb instructions/*.rb -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard fasterer -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard fl og fasterer -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard fl og fl ay fasterer -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard fl og fl ay debride fasterer -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard fl og fl ay debride fasterer vscode-ruby -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard fl og fl ay debride fasterer vscode-ruby syntax_tree -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard fl og fl ay debride fasterer vscode-ruby syntax_tree rubyfmt -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard fl og fl ay debride fasterer vscode-ruby syntax_tree rubyfmt irb -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard fl og fl ay debride fasterer vscode-ruby syntax_tree rubyfmt irb rufo -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard fl og fl ay debride fasterer vscode-ruby syntax_tree rubyfmt irb rufo prettier -
Ruby source parser gem ruby_parser gem tree-sitter-ruby ripper rubocop solargraph
unparser ruby-next standard fl og fl ay debride fasterer vscode-ruby syntax_tree rubyfmt irb rufo prettier -
Different representations • Every tool represents Ruby di ff erently
• Every tool requires contributors to relearn -
Different representations • Every tool represents Ruby di ff erently
• Every tool requires contributors to relearn • None of this knowledge translates to contributing to CRuby -
Maintenance burden • Every parser has to update every time
new syntax is introduced -
Maintenance burden • Every parser has to update every time
new syntax is introduced • Very minor changes have very major consequences -
Maintenance burden • Every parser has to update every time
new syntax is introduced • Very minor changes have very major consequences • Helping Ruby can inadvertently hurt the Ruby ecosystem -
Fractured ecosystem • ruby/ruby/parse.y • ruby/ruby/ext/ripper/parse.y • lib-ruby-parser/lib-ruby-parser • mruby/mruby
• typedruby/typedruby, sorbet/sorbet Ruby p a rsers -
Fractured ecosystem • ruby/ruby/parse.y • ruby/ruby/ext/ripper/parse.y • lib-ruby-parser/lib-ruby-parser • mruby/mruby
• typedruby/typedruby, sorbet/sorbet • whitequark/parser Ruby p a rsers -
Fractured ecosystem • ruby/ruby/parse.y • ruby/ruby/ext/ripper/parse.y • lib-ruby-parser/lib-ruby-parser • mruby/mruby
• typedruby/typedruby, sorbet/sorbet • whitequark/parser • seattlerb/ruby_parser Ruby p a rsers -
Fractured ecosystem • ruby/ruby/parse.y • ruby/ruby/ext/ripper/parse.y • lib-ruby-parser/lib-ruby-parser • mruby/mruby
• typedruby/typedruby, sorbet/sorbet • whitequark/parser • seattlerb/ruby_parser Ruby p a rsers • jruby/jruby -
Fractured ecosystem • ruby/ruby/parse.y • ruby/ruby/ext/ripper/parse.y • lib-ruby-parser/lib-ruby-parser • mruby/mruby
• typedruby/typedruby, sorbet/sorbet • whitequark/parser • seattlerb/ruby_parser Ruby p a rsers • jruby/jruby • oracle/tru ff l eruby -
Fractured ecosystem • ruby/ruby/parse.y • ruby/ruby/ext/ripper/parse.y • lib-ruby-parser/lib-ruby-parser • mruby/mruby
• typedruby/typedruby, sorbet/sorbet • whitequark/parser • seattlerb/ruby_parser Ruby p a rsers • jruby/jruby • oracle/tru ff l eruby • tree-sitter/tree-sitter-ruby -
Fractured ecosystem • ruby/ruby/parse.y • ruby/ruby/ext/ripper/parse.y • lib-ruby-parser/lib-ruby-parser • mruby/mruby
• typedruby/typedruby, sorbet/sorbet • whitequark/parser • seattlerb/ruby_parser Ruby p a rsers • jruby/jruby • oracle/tru ff l eruby • tree-sitter/tree-sitter-ruby • sisshiki1969/ruruby -
Fractured ecosystem • ruby/ruby/parse.y • ruby/ruby/ext/ripper/parse.y • lib-ruby-parser/lib-ruby-parser • mruby/mruby
• typedruby/typedruby, sorbet/sorbet • whitequark/parser • seattlerb/ruby_parser Ruby p a rsers • jruby/jruby • oracle/tru ff l eruby • tree-sitter/tree-sitter-ruby • sisshiki1969/ruruby • natalie-lang/natalie_parser -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser Synt a x trees -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby Synt a x trees -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet Synt a x trees -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser • ruby/prism -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser • ruby/prism -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser • ruby/prism -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser • ruby/prism -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser • ruby/prism -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser • ruby/prism -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser • ruby/prism -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser • ruby/prism -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser • ruby/prism -
Fractured ecosystem • NODE, RubyVM::AbstractSyntaxTree • Ripper::SexpBuilder{,PP} • ruby-syntax-tree/syntax_tree •
lib-ruby-parser/lib-ruby-parser • mruby/mruby • typedruby/typedruby, sorbet/sorbet • whitequark/parser, rubocop/rubocop-ast Synt a x trees • seattlerb/sexp_processor • org.jruby.ast • Tru ff l e • tree-sitter/tree-sitter • sisshiki1969/ruruby • natalie-lang/natalie_parser • ruby/prism -
Fractured ecosystem • lib-ruby-parser/lib-ruby-parser • mruby/mruby Synt a x trees
• tree-sitter/tree-sitter • sisshiki1969/ruruby • ruby/prism -
Fractured ecosystem • ruby/prism • lib-ruby-parser/lib-ruby-parser • mruby/mruby • tree-sitter/tree-sitter
• sisshiki1969/ruruby Synt a x trees -
Fractured ecosystem • ruby/prism • lib-ruby-parser/lib-ruby-parser • mruby/mruby • tree-sitter/tree-sitter
• sisshiki1969/ruruby Synt a x trees -
ecosystem • ruby/prism • lib-ruby-parser/lib-ruby-parser • mruby/mruby • tree-sitter/tree-sitter •
sisshiki1969/ruruby Synt a x trees -
Timeline 2022/01/01 2023/01/01 2024/01/01 2022/07/01 2023/07/01 Prototype fi rst commit
First call with CRuby team -
Timeline 2022/01/01 2023/01/01 2024/01/01 2022/07/01 2023/07/01 Prototype fi rst commit
First call with CRuby team YARP fi rst commit -
Timeline 2022/01/01 2023/01/01 2024/01/01 2022/07/01 2023/07/01 Prototype fi rst commit
First call with CRuby team YARP fi rst commit 👶 -
Timeline 2022/01/01 2023/01/01 2024/01/01 2022/07/01 2023/07/01 Prototype fi rst commit
First call with CRuby team YARP fi rst commit Tru ff l eRuby fi rst commit 👶 -
Timeline 2022/01/01 2023/01/01 2024/01/01 2022/07/01 2023/07/01 Prototype fi rst commit
First call with CRuby team YARP fi rst commit Tru ff l eRuby fi rst commit JRuby fi rst commit 👶 -
Timeline 2022/01/01 2023/01/01 2024/01/01 2022/07/01 2023/07/01 Prototype fi rst commit
First call with CRuby team YARP fi rst commit Tru ff l eRuby fi rst commit JRuby fi rst commit CRuby fi rst commit 👶 -
Timeline 2022/01/01 2023/01/01 2024/01/01 2022/07/01 2023/07/01 Prototype fi rst commit
First call with CRuby team YARP fi rst commit Tru ff l eRuby fi rst commit JRuby fi rst commit CRuby fi rst commit Syntax Tree fi rst commit 👶 -
Timeline 2022/01/01 2023/01/01 2024/01/01 2022/07/01 2023/07/01 Prototype fi rst commit
First call with CRuby team YARP fi rst commit Tru ff l eRuby fi rst commit JRuby fi rst commit CRuby fi rst commit Syntax Tree fi rst commit Parser fi rst commit 👶 -
Timeline 2022/01/01 2023/01/01 2024/01/01 2022/07/01 2023/07/01 Prototype fi rst commit
First call with CRuby team YARP fi rst commit Tru ff l eRuby fi rst commit JRuby fi rst commit CRuby fi rst commit Syntax Tree fi rst commit Parser fi rst commit Rename to prism 👶 -
Design • Comparative analysis with existing trees • "Semantic" versus
"syntactic" trees Appro a ch -
Design • Comparative analysis with existing trees • "Semantic" versus
"syntactic" trees • Provide enough value for all consumers Appro a ch -
Design Implement a tions • Make compilation as simple as
possible • Never have to check child to compile current node -
Design Implement a tions • Make compilation as simple as
possible • Never have to check child to compile current node • Cover as much common functionality as possible -
Design Tooling • Named fi elds and known types •
Nodes with enough information to round-trip -
Design Tooling • Named fi elds and known types •
Nodes with enough information to round-trip • Location information for as much as possible -
Design M a inten a nce • Template as much
as possible -
Design M a inten a nce • Template as much
as possible • Provide as much documentation as possible -
Design M a inten a nce • Template as much
as possible • Provide as much documentation as possible • Build up as big of a test suite as possible -
Challenges Encoding • # -*- encoding: Shift_JIS -*- • 90
possible encodings for source fi les -
Challenges Encoding • # -*- encoding: Shift_JIS -*- • 90
possible encodings for source fi les • 154 aliases for those possible encodings -
Challenges Encoding • # -*- encoding: Shift_JIS -*- • 90
possible encodings for source fi les • 154 aliases for those possible encodings • => we must support them all -
Challenges Esc a ping • \\, \a, \b, \e, \f,
\n, \r, \r\n, \s, \t, \v (character(s)) -
Challenges Esc a ping • \\, \a, \b, \e, \f,
\n, \r, \r\n, \s, \t, \v (character(s)) • \000 (octal) -
Challenges Esc a ping • \\, \a, \b, \e, \f,
\n, \r, \r\n, \s, \t, \v (character(s)) • \000 (octal) • \x00 (hex, can change encoding) -
Challenges Esc a ping • \\, \a, \b, \e, \f,
\n, \r, \r\n, \s, \t, \v (character(s)) • \000 (octal) • \x00 (hex, can change encoding) • \u0000 \u{00 00} (hex, can change encoding) -
Challenges Esc a ping • \\, \a, \b, \e, \f,
\n, \r, \r\n, \s, \t, \v (character(s)) • \000 (octal) • \x00 (hex, can change encoding) • \u0000 \u{00 00} (hex, can change encoding) • \cx, \C-x, \M-x, \C-\M-x, \M-\C-x -
Challenges Esc a ping • \\, \a, \b, \e, \f,
\n, \r, \r\n, \s, \t, \v (character(s)) • \000 (octal) • \x00 (hex, can change encoding) • \u0000 \u{00 00} (hex, can change encoding) • \cx, \C-x, \M-x, \C-\M-x, \M-\C-x • => brute force testing -
Challenges Regul a r Expressions • You must know local
variables to parse correctly -
Challenges Regul a r Expressions • You must know local
variables to parse correctly • /(?<foo>\d+)/ can make local variables -
Challenges Regul a r Expressions • You must know local
variables to parse correctly • /(?<foo>\d+)/ can make local variables • => we need a regex parser -
Challenges Heredocs • Declarations function as any other expression •
=> every newline, you must check for heredoc contents -
Current status • C API • CRuby, Natalie, Rust tooling
• Sorbet, Artichoke, C/C++/Rust/Zig tools -
Current status class Natalie::Parser def ast Prism .parse(@code_str, filepath: @path)
.value .accept(PathVisitor.new(@path)) end end N a t a lie -
Current status • C API • CRuby, Natalie, Rust tooling
• Sorbet, Artichoke, C/C++/Rust/Zig tools -
Current status • C API • CRuby, Natalie, Rust tooling
• Sorbet, Artichoke, C/C++/Rust/Zig tools • Ruby API • Natalie, Ruby tools -
Current status def parse(source_buffer) @source_buffer = source_buffer build_ast( ::Prism.parse( source_buffer.source,
source_buffer.name ).value ) end p a rser-prism -
Current status • C API • CRuby, Natalie, Rust tooling
• Sorbet, Artichoke, C/C++/Rust/Zig tools • Ruby API • Natalie, Ruby tools -
Current status • C API • CRuby, Natalie, Rust tooling
• Sorbet, Artichoke, C/C++/Rust/Zig tools • Ruby API • Natalie, Ruby tools • Serialization API • JRuby, Tru ffl eRuby, JavaScript -
public interface ParserBindingPrism { void pm_serialize_parse( Buffer buffer, @In byte[]
source, int size, @In byte[] metadata ); } Current status JRuby -
JNIEXPORT jbyteArray JNICALL Java_org_prism_Parser_parseAndSerialize(...) { ... pm_parse_serialize((uint8_t*) bytes, size, &buffer,
NULL); ... } Current status Truf f leRuby -
Current status J a v a Script export async function
loadPrism() { const fileURL = new URL("prism.wasm", import.meta.url); const wasm = await WebAssembly.compile( await readFile(fileURLToPath(fileURL)) ); const wasi = new WASI({ version: "preview1" }); const imports = wasi.getImportObject(); const instance = await WebAssembly.instantiate(wasm, imports); wasi.initialize(instance); return function parse(source) { return parsePrism(instance.exports, source); } } -
What’s next? • Improved error tolerance and messaging • Performance
enhancements • Multi-version support -
What’s next? • Improved error tolerance and messaging • Performance
enhancements • Multi-version support • Further integrations into the ecosystem -
What’s next? • Improved error tolerance and messaging • Performance
enhancements • Multi-version support • Further integrations into the ecosystem • Improved Ruby library for external tools -
What’s next? • Improved error tolerance and messaging • Performance
enhancements • Multi-version support • Further integrations into the ecosystem • Improved Ruby library for external tools • Contributor community around a single tool -
* = <<~EOF, /(?<m\ matchy match EOF atch>\d+)/ =~ "3"
match /1+2 #/ -
• An ecosystem of runtimes, that get to work on
what makes each one unique. The Future of Understanding Ruby -
• An ecosystem of runtimes, that get to work on
what makes each one unique. • An ecosystem of tools, that all agree on Ruby representations. The Future of Understanding Ruby -
• An ecosystem of runtimes, that get to work on
what makes each one unique. • An ecosystem of tools, that all agree on Ruby representations. • Lower barriers to entry for contributions around the ecosystem. The Future of Understanding Ruby -
• An ecosystem of runtimes, that get to work on
what makes each one unique. • An ecosystem of tools, that all agree on Ruby representations. • Lower barriers to entry for contributions around the ecosystem. • A community that works together to empower every tool and everyone. The Future of Understanding Ruby