O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Maccro Strikes Back

6.316 visualizações

Publicada em

TokyuRubyKaigi, LT and Keynote

Publicada em: Software
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

Maccro Strikes Back

  1. 1. Invitation to the Dark Side of Ruby: Maccro Strikes Back #tqrk13 Satoshi Tagomori (@tagomoris)
  2. 2. Satoshi Tagomori (@tagomoris) Fluentd, MessagePack-Ruby, Norikra, Woothee, ... Arm Ltd.
  3. 3. "If you only knew the power of the dark side" << >>
  4. 4. Vote!!!!!!
  5. 5. Maccro
  6. 6. Demonstration
  7. 7. Maccro: register • Register rules with "before" and "after" matchers • "before"/"after": code in Ruby, with DSL for code placeholders • Placeholders (N: integer, >= 1): • eN: expressions which returns a value or values • vN: a single value (e.g., variable, constant, literal, etc)
  8. 8. Maccro: Apply on Methods • Macro rules applied to methods • manually: apply(ModName, ModName.method(:method_name) • automatically: using TracePoint (:end)
  9. 9. • Registered matchers: • replace placeholders w/ matcher nodes for RubyVM::AST::Node Maccro: Prepare VCALL: e1 VCALL: e2 VCALL: e3 Matcher: e1 Matcher: e2 Matcher: e3 OPCALL: < OPCALL: < OPCALL: < OPCALL: < Matcher code e1 < e2 < e3 Placeholders Matcher tree
  10. 10. • Applied methods: • parsed into AST using RubyVM::AbstractSyntaxTree#of • get the source of the method #<UnboundMethod: Mod#foo> def foo(v) if bar(v) < 1 # ... elsif bar(v) == 1 # ... elsif 1 < bar(v) < 2 # ... else # ... Maccro: Match to Method
  11. 11. def foo(v) if bar(v) < 1 # ... elsif bar(v) == 1 # ... elsif 1 < bar(v) < 2 # ... else # ... end end • Matched tree: • get code snippets for matcher nodes • e1: 1 (literal) • e2: bar(v) (func call with v) • e3: 2 (literal) e1 < e2 < e3 Matcher: e1 Matcher: e2 Matcher: e3 Maccro: Rewrite code (1)
  12. 12. • Matched tree: • replace patterns in "after" code with captured snippets • e1: 1 (literal) • e2: bar(v) • e3: 2 (literal) e1 < e2 && e2 < e3 "After" code 1 < bar(v) && bar(v) < 2 "After" code for this method "Before" code e1 < e2 < e3 Maccro: Rewrite code (2)
  13. 13. • Matched tree: • rewrite original method code
 with updated "after" code def foo(v) if bar(v) < 1 # ... elsif bar(v) == 1 # ... elsif 1 < bar(v) < 2 # ... else # ... end end e1 < e2 && e2 < e3 "After" code 1 < bar(v) && bar(v) < 2 "After" code for this method "Before" code e1 < e2 < e3 Original code of this method Maccro: Rewrite code (3)
  14. 14. Maccro: Rewrite code (3) • Matched tree: • rewrite original method code
 with updated "after" code 1 < bar(v) && bar(v) < 2 "After" code for this method def foo(v) if bar(v) < 1 # ... elsif bar(v) == 1 # ... elsif 1 < bar(v) && bar(v) < 2 # ... else # ... end end Updated code of this method e1 < e2 && e2 < e3 "After" code "Before" code e1 < e2 < e3
  15. 15. • Rewritten method source: • call Modue#module_eval to replace the method definition def foo(v) if bar(v) < 1 # ... elsif bar(v) == 1 # ... elsif 1 < bar(v) < 2 # ... else # ... end end def foo(v) if bar(v) < 1 # ... elsif bar(v) == 1 # ... elsif 1 < bar(v) && bar(v) < 2 # ... else # ... end end Overwrite the method definition by Module#module_eval Maccro: Rewrite Method
  16. 16. Nice stuffs • Less performance penalty • Macro processor works only when methods are defined • Ruby version independent Macro rules • Compatible between Ruby versions • Because of rules written in Ruby code • Built-in rules, useful for some cases • Continuous inequality operators (<=, <, >, >=) • ActiveRecord utilities
  17. 17. • Supported only on Ruby 2.6 or later • Only code in def in module/class are rewritable • Calling class method just after definition can't be updated • Same method can't be rewritten twice • Non-idempotent methods causes unexpected result • Updating Lambda and local variable name matching is not implemented yet • Stack trace of updated methods would be confusing • Source from STDIN or command line (and irb/pry) cause errors • Rule-order-dependent issues will be caused • Method visibility are not taken care right now • Non-self singleton method definition causes errors • Placeholder validations are not implemented yet Limitations Just Few Limitations at April (RubyKaigi 2019)
  18. 18. Limitations • Supported only on Ruby 2.6 or later • Calling class method just after definition can't be updated • Non-idempotent methods causes unexpected result • Stack trace of updated methods would be confusing • Source from STDIN or command line (and irb/pry) cause errors • Rule-order-dependent issues will be caused • Method visibility are not taken care right now • Non-self singleton method definition causes errors • Placeholder validations are not implemented yet Just Few Limitations (now)
  19. 19. Maccro v0.2.0 • Support to rewrite (+call) any lambda/proc code • Support new placeholders
 for strings, symbols, numbers and regexps
  20. 20. #tqrk13 Satoshi Tagomori (@tagomoris)
  21. 21. Rails • ActiveRecord ! • I WANT YOU
  22. 22. "Join me and I will complete your training." << >> https://github.com/tagomoris/maccro https://rubygems.org/gems/maccro
  23. 23. • • #tqrk13 2
  24. 24. • • limited • 3kg
  25. 25. 4kg • 1kg → • 1kg → • 2kg →
  26. 26. • • #asakusarb •
  27. 27. tqrk14... ?

×