Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Maccro Strikes Back

6,722 views

Published on

TokyuRubyKaigi, LT and Keynote

Published in: Software
  • Login to see the comments

  • Be the first to like this

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... ?

×