2023 03 15 - qnighy/umo GitHub Wiki
Umoを作り始めてみる
既存のプログラミング言語に対する不満が色々溜まってきたので、それらが解決可能かどうかを知るためにプログラミング言語を作ってみたい。
元々2022年2月にも同じようなことを思っていたのだが、このときはうまくいかなかったのでもう一度挑戦してみる。
名前とリポジトリはそのままで、最初からやり直すことにした。
プロジェクトポリシー
今回は以下のように取り組んでみる。
- なるべく考えたことをメモに残す。これは日本語でよい。
- 英語で書こうとするとアウトプットが減ってしまうので無理に英語にしない。
- まだ実装できない未確定の事項もできるだけ書く。
- 不確実性が強い部分に関してもなるべく計画を立ててから進むようにする。
どんな言語を作りたいか
自分の趣味に一番近い言語はRustなので、Rustをベースに考えたい。
- Rustの強みのひとつはmutable XOR sharedをはじめとする様々な機構によってライブラリの責任境界がより明確になっている点にある。
しかしRustは低レイヤプログラミングを想定しているためにleaky abstractionが起きやすい部分が残されてしまっている。
- たとえばRustでは他の類似の言語に比べるとシグネチャから副作用が比較的明確だが、グローバル副作用を禁止しているわけではないので完全ではない。
- よくある例として楽観的並行性制御を抽象化するにはユーザーが副作用を書けないようにする機構があると望ましいが、そういうことがRustではできない。
- なので、mutable XOR sharedで担保されている契約をさらに強化して、グローバル副作用も利用者の制御下に起きたい。
- たとえばRustでは他の類似の言語に比べるとシグネチャから副作用が比較的明確だが、グローバル副作用を禁止しているわけではないので完全ではない。
- またRustにおいて
&mut T
/&T
の区別やMutex<T>
などにはアプリケーションロジックにも食い込んだ本質的な意味がある一方、Box<T>
やRc<T>
vs.Arc<T>
などは低レイヤの事情が露出しているに過ぎない。低レイヤ部分のニーズをある程度諦めることで、現在のRustよりは手をつけやすくなる可能性がある。 - Rustの名前解決、型推論、トレイトシステム、パッケージシステムなどはよく出来ているものの、言語のコアの設計に比べると考慮漏れが目立つ。これらは実用性のために妥協された面も大きいが、実際に問題が発生するケースも散見される以上、もう少し厳密にやることに価値がある可能性も残されている。
- Rustは部分型付けをほぼ持たない(正確にはライフタイムに対してしか部分型を持たない)。部分型付けは言語の複雑性を大きく引き上げてしまうためこれは致し方ない面もあるが、TypeScriptなどと比べると逸失しているユースケースも多い。うまく工夫して適正な複雑度の部分型付けが導入できないか考えてみたい。
- メタプログラミングとツーリングの相性問題をより優れた形で解決したい。
- メタプログラミングが適切に行えることはRubyやJavaScriptに挑戦するにあたっては重要度が高い。
大雑把なロードマップ
当面は以下のゴールを目指す。
- Rustでインタプリタを作る。
- WASIターゲットのセルフホストコンパイラを作る。
- セルフホストに移行する。
なので、まずはセルフホストコンパイラに必要な機能を作っていくことになる。以下は必要そうなものを雑多にリストしていったもの。
- 基本機能
- パーサー
- VMまたはツリーベースインタプリタ
- 関数適用
- 再帰
- 変数
- 木構造 -- ASTやwasmのために必要
- ADT
- 直和
- 直積
- ADT
- 入出力
- 文字列・バイト列
- 配列
- 文字列処理のための基本的な計算プリミティブ
- 加減乗除・比較くらいは最低必要
- 文字列・バイト列
初期の構文をどうするかは悩みどころで、S式から始めてしまってもいいかもしれない。