Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Heredoc In Demon Castle

yui-knk
July 14, 2018

Heredoc In Demon Castle

yui-knk

July 14, 2018
Tweet

More Decks by yui-knk

Other Decks in Programming

Transcript

  1. ѱຐͷ৓ͷώΞυΩϡϝϯτ
    ۚࢠ༤Ұ࿠(@yui-knk)
    2018/07/14
    Rails Developers Meetup 2018 Day 3 Extreme

    View Slide

  2. Thank you !!

    View Slide

  3. ࣗݾ঺հ
    • ۚࢠ ༤Ұ࿠

    • Treasure Data ॴଐ

    • APIνʔϜ (RailsΞϓϦΛॻ͍͍ͯ·͢)

    • CRuby Committer 2015/12~

    • GitHub (yui-knk)

    View Slide

  4. "1*νʔϜ 3BJMTΞϓϦΛॻ͍
    ͍ͯ·͢

    View Slide

  5. https://www.treasuredata.com/company/careers/jobs/?team=Engineering

    View Slide

  6. View Slide

  7. View Slide

  8. Rubyͷ࿩Λ͠Α͏

    View Slide

  9. ࠓ೔ͷτϐοΫ
    • Ruby 2.6ͷ࿩

    • ѱຐͷ৓ͷ࿩

    • RubyͷώΞυΩϡϝϯτ

    • parser͔ΒΈͨώΞυΩϡϝϯτ

    View Slide

  10. ࠓ೔ͷτϐοΫ
    • Ruby 2.6ͷ࿩

    • ѱຐͷ৓ͷ࿩

    • RubyͷώΞυΩϡϝϯτ

    • parser͔ΒΈͨώΞυΩϡϝϯτ

    • Railsͷ࿩͸ͳ͍Ͱ͢

    View Slide

  11. ࠓ೔ͷ໨ඪ
    • RubyͷώΞυΩϡϝϯτʹ͍ͭͯཧղΛਂΊΔ

    • parserʹڵຯΛ΋ͭ

    View Slide

  12. Ruby 2.6ͷ࿩

    View Slide

  13. 3VCZQSFWJFX
    • 2018/05/31 ϦϦʔε

    • JIT

    • RubyVM::AST

    View Slide

  14. 3VCZ7."45
    • ΋ͱ΋ͱRubyʹ͸ `--dump=parsetree` ͱ͍͏Φϓγϣϯ
    ͕͋Δ

    • Rubyͷ಺෦తͳσʔλΛDump͢Δ΋ͷ

    View Slide

  15. $ ruby --dump=p -e '1 + 2'
    ###########################################################
    ## Do NOT use this node dump for any purpose other than ##
    ## debug and research. Compatibility is not guaranteed. ##
    ###########################################################
    # @ NODE_SCOPE (line: 1, location: (1,0)-(1,5))
    # +- nd_tbl: (empty)
    # +- nd_args:
    # | (null node)
    # +- nd_body:
    # @ NODE_OPCALL (line: 1, location: (1,0)-(1,5))*
    # +- nd_mid: :+
    # +- nd_recv:
    # | @ NODE_LIT (line: 1, location: (1,0)-(1,1))
    # | +- nd_lit: 1
    # +- nd_args:
    # @ NODE_ARRAY (line: 1, location: (1,4)-(1,5))
    # +- nd_alen: 1
    # +- nd_head:
    # | @ NODE_LIT (line: 1, location: (1,4)-(1,5))
    # | +- nd_lit: 2
    # +- nd_next:
    # (null node)

    View Slide

  16. 3VCZ7."45
    • ಺෦తͳσʔλΛRubyͷੈքͰѻ͑ΔΑ͏ʹ͢Δ΋ͷ

    • Ruby 2.6͔Βಋೖ͞ΕΔ༧ఆ

    • ಛʹ require ͳͲ͸ෆཁ

    • ASTͷߏ଄ʹ͍ͭͯ͸ޓ׵ੑ͕อূ͞Εͳ͍

    View Slide

  17. 3VCZ7."45
    RubyVM::AST.parse("1 + 2")
    # => #
    RubyVM::AST.parse("1 + 2").children[1].children
    # => [
    # #,
    # #
    # ]

    View Slide

  18. 3VCZUSVOL
    • Syntax Error͕ग़ΔΑ͏ʹमਖ਼͞Εͨ

    • #children ͕֦ு͞Εͨ

    View Slide

  19. 4ZOUBY&SSPS
    $ ruby -e 'RubyVM::AST.parse("1 + ")'
    Traceback (most recent call last):
    1: from -e:1:in `'
    -e:1:in `parse': no file name:1: syntax error,
    unexpected end-of-input (SyntaxError)

    View Slide

  20. DIJMESFO
    # 2.6.0-preview2
    RubyVM::AST.parse("1 + 2").children[1].children
    # => [
    # #,
    # #
    # ]
    # trunk
    RubyVM::AST.parse("1 + 2").children[2].children
    # => [
    # #,
    # :+,
    # #
    # ]
    mid

    View Slide

  21. DIJMESFO
    # trunk
    RubyVM::AST.parse("def a; end").children[2].children
    # => [
    # :a,
    # #
    # ]

    View Slide

  22. *OTUBMM
    $ rbenv install 2.6.0-dev

    View Slide

  23. ѱຐͷ৓ͷ࿩

    View Slide

  24. ͋Δ͍͸ͳͥࠓ೔ώΞυΩϡ
    ϝϯτͷ࿩Λ͢Δ͔

    View Slide

  25. ѱຐ৓
    • ѱຐ৓ parse.y ͱ͍ΘΕΔϑΝΠϧ͕͋Δ

    • https://slide.rabbit-shocker.org/authors/nobu/
    rubykaigi-2017/

    • parse.y ͸Rubyͷจ๏Λఆ͍ٛͯ͠ΔϑΝΠϧ

    • Bison ͱ͍͏πʔϧͰ Cݴޠͷίʔυʹม׵͢Δ
    op : '|' { ifndef_ripper($$ = '|'); }
    | '^' { ifndef_ripper($$ = '^'); }
    | '&' { ifndef_ripper($$ = '&'); }

    View Slide

  26. QBSTFZ
    $ git shortlog -s -n parse.y | head -10
    912 nobu
    362 matz
    140 mame
    91 yui-knk
    55 ko1
    38 aamine
    37 akr
    33 naruse
    25 usa
    8 normal

    View Slide

  27. ͳͥѱຐ৓ʁ
    • Large file (10000ߦҎ্͋Δ)

    • ripper standard library ͱϑΝΠϧΛڞ༗͍ͯ͠Δ

    • “#ifdef RIPPER” macro

    • stateful lexer

    • here document

    View Slide

  28. Ґஔ৘ใ
    # trunk
    RubyVM::AST.parse("1 + 2").children[2].children
    # => [
    # #,
    # :+,
    # #
    # ]

    View Slide

  29. https://rubykaigi.org/2018/presentations/spikeolaf.html#jun01

    View Slide

  30. https://twitter.com/tagomoris/status/1005018203313979392

    View Slide

  31. https://twitter.com/n0kada/status/1005030519334006785

    View Slide

  32. https://twitter.com/n0kada/status/1005030519334006785
    proc do<͜͜͸endͷޙ
    S

    View Slide

  33. 3VCZJTU)PUMJOLT
    ʲୈճʳ
    def foo; <In foo!
    bar
    In baz!
    quux
    p foo
    # => " In foo!\n"
    p baz
    # => " In baz!\n"
    https://magazine.rubyist.net/articles/0042/0042-Hotlinks.html#ruby
    %E3%81%AE%E7%BF%92%E5%BE%97

    View Slide


  34. https://magazine.rubyist.net/articles/0042/0042-index.html

    View Slide

  35. ͳͥώΞυΩϡϝϯτͷ࿩ʁ
    • parse.y Λཧղ͢ΔҰॿʹͳΔ

    • ΤοδέʔεʹͳΓ΍͍͢

    View Slide

  36. RubyͷώΞυΩϡϝϯτ

    View Slide

  37. Do you know here
    document?

    View Slide

  38. 3VCZͷώΞυΩϡϝϯτ
    str = <Ruby is...
    A dynamic, open source programming language with a focus on simplicity and
    productivity. It has an elegant syntax that is natural to read and easy to write.
    STR
    puts str
    # Ruby is...
    # A dynamic, open source programming language with a focus on simplicity and
    productivity. It
    # has an elegant syntax that is natural to read and easy to write.

    View Slide

  39. 3VCZͷώΞυΩϡϝϯτ
    str = <Ruby is...
    A dynamic, open source programming language with a focus on simplicity and
    productivity. It has an elegant syntax that is natural to read and easy to write.
    STR
    puts str
    # Ruby is...
    # A dynamic, open source programming language with a focus on simplicity and
    productivity. It
    # has an elegant syntax that is natural to read and easy to write.

    View Slide

  40. 3VCZͷώΞυΩϡϝϯτ
    str = <Ruby is...
    A dynamic, open source programming language with a focus on simplicity and
    productivity. It has an elegant syntax that is natural to read and easy to write.
    STR
    puts str
    # Ruby is...
    # A dynamic, open source programming language with a focus on simplicity and
    productivity. It
    # has an elegant syntax that is natural to read and easy to write.

    View Slide

  41. 3VCZͷώΞυΩϡϝϯτ
    • <
    • <<-STR

    • <<~STR

    View Slide

  42. 453
    • υΩϡϝϯτͷΠϯσϯτ͸ͦͷ··

    • ऴ୺ߦͷΠϯσϯτ͕ڐՄ͞Εͳ͍
    puts <abcde
    fghij
    STR
    abcde
    fghij

    View Slide

  43. 453
    puts <abcde
    fghij
    STR
    # => syntax error, unexpected end-of-input

    View Slide

  44. 453
    • υΩϡϝϯτͷΠϯσϯτ͸ͦͷ··

    • ऴ୺ߦ͕ΠϯσϯτՄೳ
    puts <<-STR
    abcde
    fghij
    STR
    abcde
    fghij

    View Slide

  45. d453
    • υΩϡϝϯτͷΠϯσϯτ͕Ұ൪ઙ͍ͱ͜Ζʹௐ੔͞Ε
    Δ

    • ऴ୺ߦ͕ΠϯσϯτՄೳ
    puts <<~STR
    abcde
    fghij
    STR
    abcde
    fghij

    View Slide

  46. 3VCZͷώΞυΩϡϝϯτ
    • <<"STR" (ࣜల։͢Δ)

    • <<'STR' (ࣜల։͠ͳ͍)

    • <<`STR` (ίϚϯυ࣮ߦ)
    puts <<"STR"
    #{1 + 2}
    STR
    # => 3
    puts <<'STR'
    #{1 + 2}
    STR
    # => #{1 + 2}
    puts <<`STR`
    uname
    STR
    # => Darwin

    View Slide

  47. ώΞυΩϡϝϯτ͕ศརͳͱ͜
    • ώΞυΩϡϝϯτΛϨγʔόʹͰ͖Δ

    • ώΞυΩϡϝϯτͷͳ͔ʹώΞυΩϡϝϯτ͕ॻ͚Δ

    • 1ߦʹෳ਺ͷώΞυΩϡϝϯτ͕ॻ͚Δ

    View Slide

  48. • STR1 ͕Ϩγʔό

    • #upcase ͕ϝιου
    ϨγʔόʹͰ͖Δ
    p <This is str1.
    STR1
    # "THIS IS STR1.\n"

    View Slide

  49. ͳ͔ʹώΞυΩϡϝϯτ͕ॻ͚Δ
    p <This is str1.
    #{<This is str2.
    STR2
    ABCDE
    STR1
    # "This is str1.\nThis is str2.\n. 12345\nABCDE\n"

    View Slide

  50. • String#+ ͸จࣈྻ݁߹
    ߦʹෳ਺ͷώΞυΩϡϝϯτ͕ॻ͚Δ
    p (<This is str1.
    STR1
    This is str2.
    STR2
    # "This is str1.\nThis is str2.\n"

    View Slide

  51. • p ( ·ͰಡΉ
    ߦʹෳ਺ͷώΞυΩϡϝϯτ͕ॻ͚Δ
    p (
    # "This is str1.\nThis is str2.\n"

    View Slide

  52. • <ߦʹෳ਺ͷώΞυΩϡϝϯτ͕ॻ͚Δ
    p (<# "This is str1.\nThis is str2.\n"

    View Slide

  53. • STR1 ·ͰಡΜͰɺheredocΛಡΈͱΔঢ়ଶΛ͵͚Δ
    ߦʹෳ਺ͷώΞυΩϡϝϯτ͕ॻ͚Δ
    p (<This is str1.
    STR1
    # "This is str1.\nThis is str2.\n"

    View Slide

  54. • + ΛಡΉ
    ߦʹෳ਺ͷώΞυΩϡϝϯτ͕ॻ͚Δ
    p (<This is str1.
    STR1
    # "This is str1.\nThis is str2.\n"

    View Slide

  55. • <ߦʹෳ਺ͷώΞυΩϡϝϯτ͕ॻ͚Δ
    p (<This is str1.
    STR1
    # "This is str1.\nThis is str2.\n"

    View Slide

  56. • STR2 ·ͰಡΜͰɺheredocΛಡΈͱΔঢ়ଶΛ͵͚Δ
    ߦʹෳ਺ͷώΞυΩϡϝϯτ͕ॻ͚Δ
    p (<This is str1.
    STR1
    This is str2.
    STR2
    # "This is str1.\nThis is str2.\n"

    View Slide

  57. • ) ΛಡΉ
    ߦʹෳ਺ͷώΞυΩϡϝϯτ͕ॻ͚Δ
    p (<This is str1.
    STR1
    This is str2.
    STR2
    # "This is str1.\nThis is str2.\n"

    View Slide

  58. ߦʹෳ਺ͷώΞυΩϡϝϯτ͕ॻ͚Δ
    • ͋ΔߦΛॲཧ͍ͯ͠Δ్தͰ࣍ͷߦʹ͍͚Δ

    View Slide

  59. # +- nd_body:
    # @ NODE_DASGN_CURR (line: 1, location: (1,0)-
    (1,10))*
    # +- nd_vid: :s
    # +- nd_value:
    # @ NODE_STR (line: 1, location: (1,4)-
    (1,10))*
    # +- nd_lit: "abcde\n fghij\n"
    Ґஔ৘ใ
    s = <<~STR
    abcde
    fghij
    STR

    View Slide

  60. ༨ஊ (1)

    View Slide

  61. ࣮༻ྫ
    • 1ߦʹෳ਺ώΞυΩϡϝϯτ

    • จࣈྻల։தʹώΞυΩϡϝϯτ
    https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L2010

    View Slide

  62. ༨ஊ (2)

    View Slide

  63. https://twitter.com/mametter/status/936197656824619008

    View Slide

  64. • pi ͸ π (ԁप཰)

    • e ͸ωΠϐΞ਺
    $ ruby pie.rb
    Traceback (most recent call last):
    11: from pie.rb:3:in `'
    10: from pie.rb:1:in `_2_'
    9: from pie.rb:4:in `_7_'
    8: from pie.rb:1:in `_1_'
    7: from pie.rb:5:in `_8_'
    6: from pie.rb:9:in `_2_'
    5: from pie.rb:2:in `_8_'
    4: from pie.rb:6:in `_1_'
    3: from pie.rb:5:in `_8_'
    2: from pie.rb:3:in `_2_'
    1: from pie.rb:5:in `_8_'
    pie.rb:10:in `end': ^ ^ (Look_Forward_Ruby_2_5)
    | |
    pi e

    View Slide

  65. • “Look_Forward_Ruby_2_5” exception ͷbacktrace
    $ ruby pie.rb
    Traceback (most recent call last):
    11: from pie.rb:3:in `'
    10: from pie.rb:1:in `_2_'
    9: from pie.rb:4:in `_7_'
    8: from pie.rb:1:in `_1_'
    7: from pie.rb:5:in `_8_'
    6: from pie.rb:9:in `_2_'
    5: from pie.rb:2:in `_8_'
    4: from pie.rb:6:in `_1_'
    3: from pie.rb:5:in `_8_'
    2: from pie.rb:3:in `_2_'
    1: from pie.rb:5:in `_8_'
    pie.rb:10:in `end': ^ ^ (Look_Forward_Ruby_2_5)
    | |
    pi e

    View Slide

  66. • e ͸ method name (easy)

    • pi ͸ backtrace (strange)
    $ ruby pie.rb
    Traceback (most recent call last):
    11: from pie.rb:3:in `'
    10: from pie.rb:1:in `_2_'
    9: from pie.rb:4:in `_7_'
    8: from pie.rb:1:in `_1_'
    7: from pie.rb:5:in `_8_'
    6: from pie.rb:9:in `_2_'
    5: from pie.rb:2:in `_8_'
    4: from pie.rb:6:in `_1_'
    3: from pie.rb:5:in `_8_'
    2: from pie.rb:3:in `_2_'
    1: from pie.rb:5:in `_8_'
    pie.rb:10:in `end': ^ ^ (Look_Forward_Ruby_2_5)
    | |
    pi e

    View Slide

  67. • e ͸ method name (easy)

    • pi ͸ backtrace (strange)
    $ ruby pie.rb
    Traceback (most recent call last):
    11: from pie.rb:3:in `'
    10: from pie.rb:1:in `_2_'
    9: from pie.rb:4:in `_7_'
    8: from pie.rb:1:in `_1_'
    7: from pie.rb:5:in `_8_'
    6: from pie.rb:9:in `_2_'
    5: from pie.rb:2:in `_8_'
    4: from pie.rb:6:in `_1_'
    3: from pie.rb:5:in `_8_'
    2: from pie.rb:3:in `_2_'
    1: from pie.rb:5:in `_8_'
    pie.rb:10:in `end': ^ ^ (Look_Forward_Ruby_2_5)
    | |
    pi e

    View Slide

  68. ߦʹෳ਺ͷώΞυΩϡϝϯτ͕ॻ͚Δ
    • ͋ΔߦΛॲཧ͍ͯ͠Δ్தͰ࣍ͷߦʹ͍͚Δ

    View Slide

  69. module M1;def self._1_; M51._8_;end;end; module M1;def self._2_;
    _7_;end;end
    module M2;def self._8_;M6._1_;end;end
    module M3;def self._2_; M53._8_;end;end; <#{def _7_; M1._1_; end}
    #{module M51;def self._8_;M9._2_;end;end; module M52;def
    self._8_;M3._2_;end;end; module M53;def self._8_; M10.end;end;end}
    #{module M6;def self._1_; M52._8_;end;end;}
    #{def _1_; raise; end}
    #{module M9;def self._2_; M2._8_;end;end}
    #{class Look_Forward_Ruby_2_5 < Exception;end; module M10; def
    self.end; raise Look_Forward_Ruby_2_5.new(" ^ ^\n
    | |\n pi e");end;end}
    STR1

    View Slide

  70. module M1;def self._1_; M51._8_;end;end; module M1;def self._2_;
    _7_;end;end
    module M2;def self._8_;M6._1_;end;end
    module M3;def self._2_; M53._8_;end;end; <#{def _7_; M1._1_; end}
    #{module M51;def self._8_;M9._2_;end;end; module M52;def
    self._8_;M3._2_;end;end; module M53;def self._8_; M10.end;end;end}
    #{module M6;def self._1_; M52._8_;end;end;}
    #{def _1_; raise; end}
    #{module M9;def self._2_; M2._8_;end;end}
    #{class Look_Forward_Ruby_2_5 < Exception;end; module M10; def
    self.end; raise Look_Forward_Ruby_2_5.new(" ^ ^\n
    | |\n pi e");end;end}
    STR1
    Go to next line

    View Slide

  71. module M1;def self._1_; M51._8_;end;end; module M1;def self._2_;
    _7_;end;end
    module M2;def self._8_;M6._1_;end;end
    module M3;def self._2_; M53._8_;end;end; <#{def _7_; M1._1_; end}
    #{module M51;def self._8_;M9._2_;end;end; module M52;def
    self._8_;M3._2_;end;end; module M53;def self._8_; M10.end;end;end}
    #{module M6;def self._1_; M52._8_;end;end;}
    #{def _1_; raise; end}
    #{module M9;def self._2_; M2._8_;end;end}
    #{class Look_Forward_Ruby_2_5 < Exception;end; module M10; def
    self.end; raise Look_Forward_Ruby_2_5.new(" ^ ^\n
    | |\n pi e");end;end}
    STR1
    Go to next line
    Define method(s)

    View Slide

  72. module M1;def self._1_; M51._8_;end;end; module M1;def self._2_;
    _7_;end;end
    module M2;def self._8_;M6._1_;end;end
    module M3;def self._2_; M53._8_;end;end; <#{def _7_; M1._1_; end}
    #{module M51;def self._8_;M9._2_;end;end; module M52;def
    self._8_;M3._2_;end;end; module M53;def self._8_; M10.end;end;end}
    #{module M6;def self._1_; M52._8_;end;end;}
    #{def _1_; raise; end}
    #{module M9;def self._2_; M2._8_;end;end}
    #{class Look_Forward_Ruby_2_5 < Exception;end; module M10; def
    self.end; raise Look_Forward_Ruby_2_5.new(" ^ ^\n
    | |\n pi e");end;end}
    STR1
    Go to next line
    Define method(s)
    Go back

    View Slide

  73. module M1;def self._1_; M51._8_;end;end; module M1;def self._2_;
    _7_;end;end
    module M2;def self._8_;M6._1_;end;end
    module M3;def self._2_; M53._8_;end;end; <#{def _7_; M1._1_; end}
    #{module M51;def self._8_;M9._2_;end;end; module M52;def
    self._8_;M3._2_;end;end; module M53;def self._8_; M10.end;end;end}
    #{module M6;def self._1_; M52._8_;end;end;}
    #{def _1_; raise; end}
    #{module M9;def self._2_; M2._8_;end;end}
    #{class Look_Forward_Ruby_2_5 < Exception;end; module M10; def
    self.end; raise Look_Forward_Ruby_2_5.new(" ^ ^\n
    | |\n pi e");end;end}
    STR1
    Go to next line
    Define method(s)
    Go back
    Call entry point

    View Slide

  74. parser͔ΒΈͨ
    ώΞυΩϡϝϯτ

    View Slide

  75. IFSFEPDNPEFͱ͸
    • lex.strtermͷঢ়ଶͷ͜ͱ
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    ...
    if (p->lex.strterm) {
    if (p->lex.strterm->flags & STRTERM_HEREDOC) {
    return here_document(p, &p->lex.strterm->u.heredoc);
    }
    else {
    token_flush(p);
    return parse_string(p, &p->lex.strterm->u.literal);
    }
    }
    ...

    View Slide

  76. ॏཁͳؔ਺
    • heredoc_identifier

    • heredoc modeʹೖΔ

    • heredoc_restore

    • heredoc mode͔Βग़Δ

    View Slide

  77. IFSFEPD@JEFOUJpFS
    • func: Indent΍Quoteͷ৘ใ

    • term_len: <
    • term: STR ͱ͍͏String

    • lastline: ݱࡏͷߦ΁ͷϙΠϯλ

    • lastidx: <
    • ruby_sourceline: ݱࡏͷߦ൪߸

    View Slide

  78. • func: 0x22 (INDENT & EXPAND)
    p <<-STR1.upcase
    This is str1.
    STR1

    View Slide

  79. • func: 0x22 (INDENT & EXPAND)

    • term_len: 3

    • term: STR1
    p <<-STR1.upcase
    This is str1.
    STR1
    term_len term

    View Slide

  80. • func: 0x22 (INDENT & EXPAND)

    • term_len: 3

    • term: STR1
    p <<-STR1.upcase
    This is str1.
    STR1
    Ґஔ৘ใ = term_len + term

    View Slide

  81. • func: 0x22 (INDENT & EXPAND)

    • term_len: 3

    • term: STR1

    • lastidx: 9

    • ruby_sourceline: 1
    p <<-STR1.upcase
    This is str1.
    STR1
    lastidx
    lastline

    View Slide

  82. • func: 0x22 (INDENT & EXPAND)

    • term_len: 3

    • term: STR1

    • lastidx: 9

    • ruby_sourceline: 1
    p <<-STR1.upcase
    This is str1.
    STR1
    lastidx
    lastline

    View Slide

  83. • ҎԼͷ3ͭ͸1ͭͷStringΦϒδΣΫτʹͳ͍ͬͯΔ

    • term_len: 3

    • func: 0x22 (INDENT & EXPAND)

    • term: STR1
    p <<-STR1.upcase
    This is str1.
    STR1
    term_len term
    3 0x22 STR1
    ͸·ΓͲ͜Ζ
    String

    View Slide

  84. ·ͱΊ
    • Ruby 2.6Ͱ͸ RubyVM::AST ͕ಋೖ͞ΕΔ༧ఆ

    • RubyͷώΞυΩϡϝϯτ͸ػೳ͕ͨ͘͞Μ͋Δ

    • ώΞυΩϡϝϯτ͸ΤοδέʔεʹͳΓ΍͍͢

    View Slide

  85. Thank you !!

    View Slide