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
アセンブリ言語のみで 言語処理系を作った話 (原題: ブートストラッピングで言語処理系を作った話) 第11回 カーネル/VM探検隊 中村 晃一
Slide 2
Slide 2 text
本日の資料・コード •https://speakerdeck.com/nineties/bootstrap •https://github.com/nineties/amber
Slide 3
Slide 3 text
自己紹介 • 中村晃一(@9_ties) • IoTデバイスを作っています • idein.jp • 課外活動 • 圏論勉強会、パターン認識・機械学習勉強会などの講師
Slide 4
Slide 4 text
処理系作りが趣味でした • 学生実験でコンパイラ係に • O’CamlでminCamlコンパイラを作ったり • Haskellでも作りました github.com/nineties/Choco • 大学院では最適化コンパイラの研究をしました • 特殊なプロセッサの為のコンパイラを書いたり • 型推論器を書いたり
Slide 5
Slide 5 text
自分の言語を作ろうと思いました • 言語名: 最初はrowl ⇒ 後にamber • ただ作るだけでなくその過程を楽しみたい • どうやったら楽しめるだろうか?
Slide 6
Slide 6 text
縛りを入れて作ろう • ルール 1. 実装言語はアセンブリ言語のみ 2. 既存ライブラリは使ってはならない 3. コード生成ツールは使ってはならない libcなど Cなどの高級言語 flex/bisonなど
Slide 7
Slide 7 text
作戦:ブートストラッピング アセンブリ言語でちょっと高級な言語1の処理系を書く 言語1でもうちょっと高級な言語2の処理系を書く 言語kでamberの処理系を書く amberでamberの処理系を書く 今ココ(暫らく放置中)
Slide 8
Slide 8 text
何の意味があるの? • 純粋に楽しみとして • 知識・技術・ノウハウを磨くのに役に立つかも • 効率の良い学習方法ではありませんが・・・ • ツール群を作った先人への尊敬と感謝が芽生える
Slide 9
Slide 9 text
以下ダイジェストでお見せします
Slide 10
Slide 10 text
1.アセンブリで言語「rowl0」を実装
Slide 11
Slide 11 text
アセンブリより少し高級な言語を作ります • 言語名: rowl0 • コンパイラ名: rlc
Slide 12
Slide 12 text
トークンの正規表現から
Slide 13
Slide 13 text
状態遷移図を書いて
Slide 14
Slide 14 text
状態遷移表にして
Slide 15
Slide 15 text
レキサを作ります
Slide 16
Slide 16 text
文法をBNFで書いたら
Slide 17
Slide 17 text
再帰降下法でパーサを作ります
Slide 18
Slide 18 text
コード生成はパースと同時にやりました • この時点でメモリ管理を実装 するのは面倒 ⇒ 構文木作るの面倒 コード生成
Slide 19
Slide 19 text
最初の言語「rowl0」が完成! • 変数管理が出来ない • 関数引数はp0,p1,p2,... • ローカル変数はallocate(n)でスタックメモ リを確保し x0,x1,x2,...で参照
Slide 20
Slide 20 text
2.「rowl0」でLISP系言語「rowl-core」を実装
Slide 21
Slide 21 text
一旦LISPを作る事にしました • 言語名: rowl-core • インタプリタ名: rlci • 実装が容易 • メタプログラミングによる生産性向上
Slide 22
Slide 22 text
さっきと同じ感じでレキサ・パーサを作る
Slide 23
Slide 23 text
アセンブリよりかなり記述が楽
Slide 24
Slide 24 text
evalも作っていきます。
Slide 25
Slide 25 text
メモリ管理はまだしません • mmapしか使えないので負担が大きい 1. 不要になったメモリは回収しない 2. 足りなくなったら新たに確保 3. 動かし続けるといつか死ぬ • 次の世代のコンパイルだけ出来ればあと不要なので良しとした malloc, free
Slide 26
Slide 26 text
LISP系言語「rowl-core」が完成! • lambdaやmapが使えたり • マクロが使える!
Slide 27
Slide 27 text
3.「rowl-core」で「VM記述言語」を作る
Slide 28
Slide 28 text
次の世代では仮想マシンを導入します。 • その為の「VM記述用言語」を作成。 • LISPの強みを生かして、言語内DSLとして作成 • レキサ・パーサの実装は不要!
Slide 29
Slide 29 text
こんな感じでVM用コンパイラを書きます
Slide 30
Slide 30 text
今回は高階関数とかも使えます • 生産性がぐっと向上!
Slide 31
Slide 31 text
4.「VM記述言語」で仮想マシン「rlvm」を実装
Slide 32
Slide 32 text
言語内DSLでVMのコードを書いていきます
Slide 33
Slide 33 text
ガベコレもようやく実装します • コピーGCにしました
Slide 34
Slide 34 text
組み込み関数も作っていきます
Slide 35
Slide 35 text
ここでメタプログラミングの活用例を紹介します • 以下は、VMの命令セットのテーブル
Slide 36
Slide 36 text
命令テーブルから色々自動生成します • 命令の追加・削除を自 動的に反映 • LISPだとこういう仕組み 作るのが楽な気がする vm_instructions VMのevalループ リンカ ディスアセンブラ アセンブラ amber内部で使うアセンブラ
Slide 37
Slide 37 text
命令セットを作っていきます
Slide 38
Slide 38 text
浮動小数点数演算や
Slide 39
Slide 39 text
多倍長整数演算なども用意しました
Slide 40
Slide 40 text
例外機構なども作ります
Slide 41
Slide 41 text
継続も作ってみました
Slide 42
Slide 42 text
仮想マシン「rlvm」が完成! • 186命令 • スタックマシン • コピーGC • 例外機構 • shift/reset限定継続 • 浮動小数点数演算、多倍長整数演算
Slide 43
Slide 43 text
5.VM用ツールチェインを作る
Slide 44
Slide 44 text
VMは出来たがプログラミング環境がない • VM上のツールチェインを作る • VM用中級言語「rowl1」 • アセンブラ • コンパイラ • リンカ • ディスアセンブラ
Slide 45
Slide 45 text
言語・アセンブラ・コンパイラを作ります • これらは次世代で捨てるので「rowl-core」の言語内DSLにします
Slide 46
Slide 46 text
リンカ、ディスアセンブラを作ります • 「rowl1」で記述し、これら自身もVM上で動くように実装 • リンカはメモリを食うのでGCのある環境でやりたかった
Slide 47
Slide 47 text
ディスアセンブラの出力はこんな感じ
Slide 48
Slide 48 text
VM上でプログラミングが可能に! • 分割コンパイルが出来る • デバッグもしやすい • メモリも潤沢に使える • 例外とかも使える • 普通の事が出来るようになっただけ・・・でも達成感がとても大きい!
Slide 49
Slide 49 text
6.「rowl1」で「amber」を実装
Slide 50
Slide 50 text
いよいよamberの実装に入ります • 動的スクリプティング言語として作る • インスタンスベースオブジェクト指向 • 先ほど作った「rlvm」上で動作
Slide 51
Slide 51 text
アセンブラを作ります • さっき作ったアセンブラは プログラム実行前にコンパイル • これは、プログラム実行時に その場でコンパイル • アドレスはバックパッチ
Slide 52
Slide 52 text
オブジェクトシステムを作ります • スロット、メッセージ、 ペアレントへの委譲
Slide 53
Slide 53 text
オブジェクトシステム上に中核機能を作っていきます • 動的パターンマッチングエンジンと • 部分関数関数の融合メカニズム
Slide 54
Slide 54 text
この上にコンパイラを作ります • コンパイラ自体を通常のオブジェクトとして実装 VM オブジェクトシステム パターンマッチングエンジン コンパイラ amberのコアシステム 構文木のマッチング リソース管理
Slide 55
Slide 55 text
クロージャ変換も実装しました
Slide 56
Slide 56 text
この上にパーサを作ります • 実行時にパーサをコンパイル • 各パーサは通常のオブジェクト(クロージャ) VM オブジェクトシステム パターンマッチングエンジン コンパイラ amberのコアシステム コンパイル パーサ
Slide 57
Slide 57 text
とてもシンプルな文法 1. リテラルは式である 2. hがシンボル、e1,..,en (n>=0) が式の時h{e1, ..., en}も式である 3. 以上で定まるもののみがamberの式である • これと、あるトリックを後で組み合わせる
Slide 58
Slide 58 text
Packrat法で実装します • 後のトリックのため • 従ってレキサ不要
Slide 59
Slide 59 text
浮動小数点数のエンコード・デコードは苦労します • libcが無いので自分で作ります • 先ほど作った多倍長整数演算が必要になります “3.14” 0x40091eb851eb851f stortod, sprintf
Slide 60
Slide 60 text
amberが完成! • 動的スクリプティング言語 • VM上で動作 • インスタンスベースオブジェクト指向 • 動的パターンマッチングエンジンと部分関数融合が中核機能 • レキシカルクロージャ • すごく高級になってきた!
Slide 61
Slide 61 text
7. 「amber」の標準ライブラリを作る
Slide 62
Slide 62 text
amberのテーマは自己拡張性 • amberの文法は標準ライブラリで定義されている • amber/lib/syntax/parse.ab • 起動時に自身の文法を構築する
Slide 63
Slide 63 text
起動時はリテラルとh{e1,..,en}という文法だけ
Slide 64
Slide 64 text
amberの文法を定義する為の文法を定義する
Slide 65
Slide 65 text
今定義された文法でamberの文法を定義する
Slide 66
Slide 66 text
続いてマクロシステムを作る
Slide 67
Slide 67 text
マクロで更に文法を増強
Slide 68
Slide 68 text
リッチな構文が使えるようになりました
Slide 69
Slide 69 text
オブジェクトシステムも増強します
Slide 70
Slide 70 text
継承などが使えるようになりました
Slide 71
Slide 71 text
ここで開発停止です • 更新予定はありません • 以下でインタプリタが起動(Linuxのみ) • makeのログで以上のブートストラッピングの過程を見てみましょう % git clone https://github.com/nineties/amber.git % cd amber % make; sudo make install % amber
Slide 72
Slide 72 text
まとめ rowl0 rlc rlci rowl-core as VM記述言語 rlvm rowl1 リンカ ディスアセン ブラ コンパイラ コンパイラ amber インタプリタ 実装 実装 実行 言語 ツール • 大分高級な所まで到達出来たので満足
Slide 73
Slide 73 text
No content