rakulangで実装する! RubyVM
by
AnaTofuZ
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
rakulangで実装する! RubyVM 八雲アナグラ id:anatofuz 2024/02/10 YAPC::Hiroshima 2024 1
Slide 2
Slide 2 text
このトークの対象者 ● 令和最新版Rakulangの最新情報を知りたい方 ● 特に明日すぐに役に立たない話を聞きたい方 ● ノリと勢い 2
Slide 3
Slide 3 text
$self 3 ● 八雲アナグラ(@AnaTofuZ) ● 株式会社はてな ノベルチーム ● 沖縄から引っ越して今は京都は宇治にいます ● 普段はPerlとTypeScriptを書いてます ● 推しは宝灯桃汁です
Slide 4
Slide 4 text
【PR】 来週は推しのイベントです 4
Slide 5
Slide 5 text
目次 5 ● Rakulangについて ● RubyVMとは ● 実際にやってみた
Slide 6
Slide 6 text
6 Rakulangについて
Slide 7
Slide 7 text
Raku ● かつてのPerl6 ○ Python2とPython3の違いではない ■ むしろJavaとJavaScriptの関係だった ○ 2019年にRakuに改名 ● 仕様と実装が分離している ○ テストスイート(仕様)に合格したら”Raku” ○ 歴史的にはPugs, Pallot, Yapsi, Nieczaなど ○ 今はRakudo一択 7
Slide 8
Slide 8 text
Raku 8 ● マスコットはCamelia ○ Perl6からのマスコット ● 海外ではWebでも使われてる ○ Cro ■ Rakuでよく使われてるヤツ ■ Edument社からRakuコミュニティ移管 ○ Humming-Bird ■ Sinatraっぽいやつ
Slide 9
Slide 9 text
Raku 最近単独 カンファレンスが 行われたりしてる 9
Slide 10
Slide 10 text
世界観 ● シジルがある ○ 1要素も@%を使う ● 型も書ける ● .でメソッドが呼び出 せる ● オブジェクト指向 ● Perlとは似てるが 微妙に異なる 10
Slide 11
Slide 11 text
Webっぽい 11
Slide 12
Slide 12 text
Rakudo ● ナウでヤングなRaku処理系 ○ MoarVM (実行環境) ○ NQP (NotQuitPerl, Rakuのサブセット) ○ Raku自身 ■ RakuはNQPとRakuで書かれてる ● だいたい月イチでリリース ○ https://github.com/rakudo/rakudo/releases ● JVMで動くバージョンもある ○ …が、MoarVMに比べてバグりがち 12
Slide 13
Slide 13 text
インストール方法 13 ● rakudo-star(*)がオススメ ○ $brew install rakudo-star ● env系もいろいろ ○ rakudobrew ○ rakuenv ○ asdf-raku ■ mise(rtx)でも入るぜ
Slide 14
Slide 14 text
コーディング支援系 ● RakuNavigator ○ https://github.com/bscan/RakuNavigator ○ RakuのLSP ○ PerlNavigatorインスパイア作品 ○ VSCode使うならオススメ 14
Slide 15
Slide 15 text
簡単にわかる! Rakulang 15 アレ Perl5 Rakulang 実行コマンド perl raku ファイル拡張子 *.pl *.raku モジュール拡張子 *.pm *.rakumod テスト *.t *.rakutest
Slide 16
Slide 16 text
モジュール ● zef コマンドでいれられる ○ cpanm的なヤツ ○ かつてはpandaというのもあったが... ● https://raku.land/ でモジュールを探せる ○ landだけに土アイコン!!!! ● 歴史的にエコシステムが2つある ○ fez (zefで使われてるヤツ・主流) ○ p6c (歴史的にいるヤツ・fezに移行中) 16
Slide 17
Slide 17 text
17 RubyVM
Slide 18
Slide 18 text
18 …の前にプログラミング言語について ● コンピューターはCPUが命令を 実行することで処理がすすむ ● CPUの命令(機械語) ● 機械語に対応したプログラミング言語に CPUの種類に応じたアセンブラがある
Slide 19
Slide 19 text
こういうヤツ 19
Slide 20
Slide 20 text
20 コンパイル言語 Cやgolangはコンパイルをして ソースコードを機械語に変換する ソースコード コンパイル 機械語をCPUが実行
Slide 21
Slide 21 text
21 スクリプト言語 RubyやPerlはコンパイルをして ソースコードをバイトコードに変換する ソースコード コンパイル バイトコードをVMが 実行 VM
Slide 22
Slide 22 text
コンパイル vs スクリプト ● 最近の言語は両方ともコンパイルする ● 実行するヤツが違う ○ コンパイル ■ 直接CPU ○ スクリプト ■ プロセスVM経由でCPUが実行 ■ JITがあると直接CPUが実行する(ので早いぜ) 22
Slide 23
Slide 23 text
プロセスVM ● OS上のプロセスとして動くVM ○ OSを動かす目的なVMではない ● VMさえハードウェアに対応すれば動くソフト はハードウェアの制約がない ● JVM,MoarVMもこの一種 ● RubyはYARVが該当 23
Slide 24
Slide 24 text
プロセスVMを実装する ● 複雑ではあるがソフトウェアであるので何か しらの言語で再実装が可能 ● 極端なことを言うと巨大なfor文とif文を実装 すればOK ○ バイトコードな命令セットを特定の条件で読む(for) ○ 命令セットに応じた処理をする(if文) 24
Slide 25
Slide 25 text
言語開発系の鉄則 ● いきなり頑張らない ● 無理をしない ● インクリメンタルに開発する 25
Slide 26
Slide 26 text
いきなり頑張らない ● 初手バイトコードを読みに行ったりしない ○ 普段しないことなので大変 ○ バイトコードの読解から実行まで距離がある ● 次から次へと新情報がやってくるので全部真 面目に最初からやろうとすると疲れて飽きる ○ 最初は普段のプログラミングに近いところから行く 26
Slide 27
Slide 27 text
無理をしない ● 関数定義とかは一旦おいておこう ○ 意外とFizzBuzzまで行くのがムズい ● HelloWorldとIF文が動けば優勝 ○ ここまで動くと楽しくなってくる 27
Slide 28
Slide 28 text
インクリメンタルに開発する 28 ● ちょっとずつ実装する ○ まずはHello Worldから ● 命令セット全部移植しようとしない ● 完全にうまくやろうとしない ○ 面倒なところは諦める ○ 仕事のコードではない
Slide 29
Slide 29 text
29 RakulangでRubyVM を作るぞ!!
Slide 30
Slide 30 text
RubyVM 30 ● Rubyバイトコードを実際に実行する処理系 ● YARV ○ C言語で実装されているいわゆるCRuby ○ 最近はRustで書かれたYJITもあるがここでは割愛 ● スタックマシン
Slide 31
Slide 31 text
スタックマシン vs レジスタマシン ● スタックマシン ○ クソデカスタックを使って計算をする ■ push, popみたいな動作が主 ○ こっちの方が実装が簡単(とされている) ● レジスタマシン ○ 現実のCPUと同じようにレジスタ(変数)を持つ ■ レジスタ同士で計算する ● なんと今日2つ出てきます 31
Slide 32
Slide 32 text
実装するぞ!!! 1. Rakuで実行したいRubyのコードを書く 2. バイトコードを取り出す 3. バイトコードを実行するRakuを書く 32
Slide 33
Slide 33 text
実装するぞ!!! 1. Rakuで実行したいRubyのコードを書く 2. バイトコードを取り出す 3. バイトコードを実行するRakuを書く たいへん!!! 33
Slide 34
Slide 34 text
実装するぞ!!! 1. Rakuで実行したいRubyのコードを書く 2. バイトコードを取り出す 3. バイトコードを人間が読める形式にする 4. 人間が読める形式の文字列をRakuで評価する なのでバイト列は今回はノータッチ!!! 34
Slide 35
Slide 35 text
class RubyVM 35 https://docs.ruby-lang.org/ja/latest/class/RubyVM.html
Slide 36
Slide 36 text
RubyVM::InstructionSequence 36 https://docs.ruby-lang.org/ja/latest/class/RubyVM=3a=3aInstructionSequence.html
Slide 37
Slide 37 text
37
Slide 38
Slide 38 text
38
Slide 39
Slide 39 text
RubyVMの命令セット ● RubyVM::InstructionSequenceのdisasmを 使うといい感じに命令を見ることが出来る ● それぞれどういった意味の命令かは調べる必 要がある ○ C言語のソースコードを読む ○ ググって有識者の解説を確認する ○ フィーリング ■ 仕事じゃないので動けばよかろう 39
Slide 40
Slide 40 text
HelloWorld 40
Slide 41
Slide 41 text
HelloWorld 41 アドレス
Slide 42
Slide 42 text
HelloWorld 42 アドレス オペコード (命令)
Slide 43
Slide 43 text
HelloWorld 43 アドレス オペコード (命令) オペランド (引数)
Slide 44
Slide 44 text
RubyVMの雰囲気 ● 上から順に命令を実行していけばだいたいOK ● HelloWorldではアドレスは無視する 44
Slide 45
Slide 45 text
HelloWorld 45 今回はスルー
Slide 46
Slide 46 text
HelloWorld 46 スタックに文字 列をpush
Slide 47
Slide 47 text
HelloWorld 47 スタックに文字 列をpush
Slide 48
Slide 48 text
HelloWorld 48 スタックに文字 列をpush momojiru
Slide 49
Slide 49 text
HelloWorld 49 メソッド呼び出 し(今回はputs) momojiru
Slide 50
Slide 50 text
HelloWorld 50 メソッド呼び出 し(今回はputs) momojiru 引数が取られる
Slide 51
Slide 51 text
HelloWorld 51 return
Slide 52
Slide 52 text
ヒアドキュメントでコードをコピペ 52
Slide 53
Slide 53 text
ヒアドキュメントでコードをコピペ 53
Slide 54
Slide 54 text
3ブロックに分解する 54
Slide 55
Slide 55 text
3ブロックに分解する 55 行単位で分割 しながら配列に 変換
Slide 56
Slide 56 text
3ブロックに分解する 56 素朴に空白で 3分割
Slide 57
Slide 57 text
3ブロックに分解する 57 ハッシュを作る
Slide 58
Slide 58 text
最初なのでputstringでputsしちゃう 58
Slide 59
Slide 59 text
HelloWorld ● 完全にエミュレートしてるわけではないがそ れっぽく動いた ● 次はif文にチャレンジする 59
Slide 60
Slide 60 text
60
Slide 61
Slide 61 text
61
Slide 62
Slide 62 text
62 2024
Slide 63
Slide 63 text
63 2024 2
Slide 64
Slide 64 text
64 0
Slide 65
Slide 65 text
65 0
Slide 66
Slide 66 text
66 0 0
Slide 67
Slide 67 text
67 true
Slide 68
Slide 68 text
68 true 0017にjumpす ると終わる
Slide 69
Slide 69 text
RubyVMの雰囲気 ● 上から順に命令を実行していけばだいたいOK ● HelloWorldではアドレスは無視する ● IF文では分岐が必要 ○ True/Falseで実行する命令を変える必要がある ● このためにはアドレスを見て処理していく必 要がある ○ プログラムカウンタを導入 69
Slide 70
Slide 70 text
RubyVMの雰囲気 ● 上から順に命令を実行していけばだいたいOK ● HelloWorldではアドレスは無視する ● IF文では分岐が必要 ○ True/Falseで実行する命令を変える必要がある ● このためにはアドレスを見て処理していく必 要がある ○ プログラムカウンタを導入 70 今実行しているア ドレスを保持する 変数
Slide 71
Slide 71 text
そろそろ命令をちゃんと管理する 71
Slide 72
Slide 72 text
実行する命令のclass導入 72
Slide 73
Slide 73 text
実行する命令のclass導入 73 hasでインス タンス変数
Slide 74
Slide 74 text
実行する命令のclass導入 74 次のアドレスを計 算するために命令 の長さを出す
Slide 75
Slide 75 text
75
Slide 76
Slide 76 text
76
Slide 77
Slide 77 text
77 スタックとプログ ラムカウンタ導入
Slide 78
Slide 78 text
78 実行処理 (public method)
Slide 79
Slide 79 text
79 loopで無限ループ
Slide 80
Slide 80 text
80 アドレスに 該当する命令を 持ってくる
Slide 81
Slide 81 text
81 !をつけると private method
Slide 82
Slide 82 text
82 given-whenで パターンマッチ (Opcode型)
Slide 83
Slide 83 text
83 今回は真面目に stack操作する
Slide 84
Slide 84 text
84 今回は真面目に stack操作する
Slide 85
Slide 85 text
85 stackの値を使って 演算
Slide 86
Slide 86 text
86 stackの値がfalse ならjump
Slide 87
Slide 87 text
87 どうせsayだけなの で手抜き
Slide 88
Slide 88 text
88 ここで終了
Slide 89
Slide 89 text
89
Slide 90
Slide 90 text
90 if文実装成功!!!
Slide 91
Slide 91 text
91 if文実装成功!!! if-elseを導入する ● 今のままだとif文の条件分岐が動いてなくて も正常に動作した(ように見える)のでelseを 導入してみる
Slide 92
Slide 92 text
92
Slide 93
Slide 93 text
93
Slide 94
Slide 94 text
94 !?!?!?!?
Slide 95
Slide 95 text
95 無限ループからの脱出なので...
Slide 96
Slide 96 text
96 無限ループからの脱出なので...
Slide 97
Slide 97 text
97
Slide 98
Slide 98 text
98 💪
Slide 99
Slide 99 text
まとめ ● Rakulang普通にプログラミングできる ● RubyVMはまずは文字列から攻めるとわかり やすい ● 気楽にやっていこう 99