高水準システムプログラミング言語 Hylo(Val)
(val-lang.dev)- Hyloは値セマンティクスを基盤に、安全なシステム・ジェネリックプログラミングを志向しており、コンパイラと標準ライブラリは初期段階にあるものの、Compiler Explorerでサンプルを実行して試せる
- 言語研究は、Swift subscriptのinout projection拡張、method bundles、構造化並行性、値セマンティクスベースの双方向連結リストといったテーマに集中している
- コンパイラはLLVMを使用し、coherenceを備えたジェネリックコンパイル、プログラム状態のキャッシュ・シリアライズ、C相互運用性の研究も扱っている
- 開発環境はVSCode拡張、ドキュメントコンパイラ、Language Serverプロトタイプを提供し、SPM/CMake、Ninja/Xcode、Windows/Linux/macOS、Docker開発ツールチェーンイメージをサポートする
- サンプルは安全なprojectionとsink methodを通じて、所有権・解放ルールをコードレベルで明示し、システム言語がどのように安全性を強制できるかを示している
Hyloの範囲と現状
- Hyloのコンパイラと標準ライブラリはまだ初期段階にある
- 高度なHyloコードのサンプルは Compiler Explorer で実行して試せる
- トップページでもHyloを Compiler Explorer で試せるリンクを提供している
値セマンティクスと言語研究
- MVS & Theory は、値セマンティクス、安全なprojection、並行性、データ構造表現を中心に展開されている
- Swiftのsubscriptをinout projectionへ拡張
- Method bundles
- Structured concurrency made easy: thread hoppingやfunction coloringなしの構造化並行性
- 値セマンティクスで双方向連結リストを表現する方式は、reference semantics実装より安全で高速
コンパイラと標準ライブラリ
- コンパイラ作業は、LLVMベースのコンパイル、ジェネリクス、状態保存、C相互運用性にまたがっている
- LLVMを使用したコンパイル
- coherenceを備えたジェネリックコンパイルのための新しい手法
- コンパイラのプログラム状態のキャッシュ・シリアライズ
- C interop 研究
- 標準ライブラリ側では、現在実装ドキュメントとコレクションアルゴリズム関連の作業を公開している
- 現在の実装ドキュメント には基本traitとデータ構造が含まれる
- Positionless Collection Algorithms
- rs-stl: ジェネリックプログラミング改善のためのC++ STLアルゴリズムのRust移植
開発者体験とビルド環境
- エディタ、ドキュメント、言語サーバー向けのツールがあわせて提供されている
- VSCode extension: 構文ハイライトとコード実行をサポート
- Documentation compiler
- Language Server プロトタイプ
- ビルドおよび開発環境は、複数のOSとコンテナベースのフローをサポートする
- Development Containers のサポートで開始手順を簡素化
- SPM/CMake、Ninja/Xcode、Windows/Linux/macOSをサポート
- テスト生成コンパイラプラグイン
- 事前ビルド済みの Hylo development toolchain Dockerイメージ
- コンパイラはSwift 6.2で書かれている
Hylo関連の研究と発表資料
- Hylo周辺資料は、論文、発表、ポッドキャストとして整理されている
- 最近の論文・文書には次の項目が含まれる
- Who Owns the Contents of a Doubly-Linked List?, 2025-09
- High-Fidelity C Interoperability in Hylo, 2025-06
- Debugging Hylo, 2025-06
- On the State of Coherence in the Land of Type Classes, 2025-02
- Method Bundles, 2024-10
- Type Checking with Rewriting Rules, 2024-10
- Use Site Checking Considered Harmful, 2024-10
- Borrow checking Hylo, 2023-10
- The Val Object Model, 2022-10
- Implementation Strategies for Mutable Value Semantics, 2022
- 発表資料は、構造化並行性、安全なシステム・ジェネリック言語、HyloDoc、borrow checking、C++相互運用性、値セマンティクスを扱っている
- Hylo: The Safe Systems and Generic-programming Language Built on Value Semantics, C++ on Sea 2024-07
- HyloDoc: A Documentation Compiler for Hylo, C++ on Sea 2024-06
- Val: A Safe Language to Interoperate with C++, CppCon 2022-09
- Value Semantics: Safety, Independence, Projection, & Future of Programming, CppCon 2022-09
コード例: 安全なprojectionと明示的な解放
- Subscripts - A Safe Projection Mechanism サンプルは、
Angle型がradians値を保存し、degreesプロパティをletとinoutブロックで提供する構造を示しているdegreesのletは radians を degrees に変換して返すinoutは一時的な degree 値dをyield &dで公開した後、変更された値を再び radians に変換してself.radiansに反映するmainはinout d = &a.degreesでprojectionを取得し、dを0.0に変更した後a.radians == 0.0を確認する
- Sink Methods - Capability for Deinitializing サンプルは、
Computer型がshutdown()をsink methodとして提供する構造であるshutdown()はメモリ内容を出力した後、self.ramをsink処理するtest1はComputerを作成してshutdownしないため、Cannot deinit computerが発生するtest2はif random_bool()の中でのみshutdownするため、ifに入らない経路でCannot deinit computerが発生するtest3はwhileの中でshutdownを呼ぶと、最初の反復以降にconsumed objectの使用問題が生じ、whileに入らない経路ではdeinit不可が残る
- 追加サンプルは compiler test suite で確認できる
1件のコメント
Hacker Newsのコメント
C++の後継としては、Herb Sutterの優れた CppFront よりも Val のほうが期待できるかもしれない。まだ下の2つの発表しか見ていないが、静的コンパイル・静的型付け・C++相互運用・メモリ安全・型安全・データ競合なしが中核に見える
自分が説明するときは、「新しいC++プロジェクトを始めるとして、性能は気にしないことにして、ポインタや参照を使わずすべて値渡し・値返しにしたら、副作用やデータ競合を心配しなくてよくて便利ではないか」と言っている。Valが興味深いのは、言語からポインタと参照を取り除いても、コンパイラが内部的に const 参照渡しと戻り値最適化を適用して、望ましいセマンティクスと性能を同時に保てるようにしている点だ
Val: A Safe Language to Interoperate with C++ - Dimitri Racordon - CppCon 2022 https://www.youtube.com/watch?v=ws-Z8xKbP4w
https://cppcast.com/val-and-mutable-value-semantics/
https://adspthepodcast.com/
PHPインタプリタは実際には copy-on-write(書き込み時コピー) を使うだけの賢さがあると思うが、自分でプロファイリングしたことはない。それでも、かなり複雑なデータ処理、DSLの文字単位パース、動的SQL生成、結果を任意の構造に整形する処理をページロードごとにやっても、体感できる性能問題はなかった
PHP 4時代にはオブジェクトも変数に格納された値のように振る舞っていたが、その後オブジェクト変数を参照セマンティクスに変えたとき、「値、変数参照、値へのポインタ」を保存型と直交する変数属性にしなかったのは、惜しい機会損失だったと思う
$a = $b; // $bの値を$aにコピー$a = &$b; // $aと$bはこれで同じ変数$a = *$b; // $aは$bと同じオブジェクトを指すが、$a = &$b と違って変数自体は結び付かないゼロコスト抽象化 言語がこれほど多く登場するのは一方では良いことだが、システムプログラマにはそろそろ勝者を1つ選んでほしい気持ちもある。もともと小さいシステムプログラマのコミュニティが Rust、Zig、Val などにさらに細かく分裂してほしくないし、システム言語戦争が早く終わってほしい
今日初めてValを知って、感情の流れはこうだった。「お、新しいシステム言語か。大したことはないかもしれないが見てみよう。ドキュメントは悪くない。所有権まわりのアイデアもかなりよく考えられていて、構文も筋が通っている。でも、独自に存在するだけの違いはあるのか? 誰が作っているんだ?」
そこから Dave Abrahams が取り組んでいると知って興味が増した。Appleで会ったことがあり、SwiftについてのCrusty講演[1]も覚えている。強い見解がよかったが、Appleは後になって古い助言が含まれているという理由でその動画を下ろした。今はAdobeにいるのか、これはAdobeの言語なのかと思った
結論としては、注目する価値はあり、リンク先の発表を見たうえで待ってみようという感じだ
[1] Crusty講演を見つけた: "I don't do Object Oriented!" https://www.youtube.com/watch?v=p3zo4ptMBiQ
コンパイラ開発者として、以下のイシューを見て衝撃を受けた。
https://github.com/val-lang/val/issues/758
https://github.com/val-lang/val/issues/711
実装状態があまり良くない気配がある。できるだけ早く セルフホスティングすべきで、そうすればこうした基本的なバグももっと見つかるはずだ。それなのにスターは500を超えている
セルフホスティングも全てではない。何より象徴的なマイルストーンに近く、達成できれば祝うべきことだが、開発サイクルのかなり後の段階までは、その言語の弱点として扱うべきものではないと思う
以前から「Valで遊ぶ」のを先延ばしにしていて、今日ようやく試してみたのだが、コミットが4,000件を超えていても、まだ使える状態にはほど遠い。言語ツアーの例の大半がコンパイルできず、見た目には単純な例でも失敗する。
Carbonはまだまともなものを出しておらず、Sean BaxterはCircleコンパイラで大きく前進しつつ、Carbonの良い部分もいくつも実装している。まだ言語と呼ぶのが難しいなら、後継になるのも難しい
いまや V、Val、Vala、Vale がある。私が忘れている別の言語もあるだろうか?
毎回出てくる話だが、Valで唯一気に入らないのは、Vale と V も新しいシステム言語だという点だ。名前のせいでこの3つはあまりにも簡単に混同してしまう
関連記事がある。ほかにもある?
Val, a new programing language inspired by Swift and Rust - https://news.ycombinator.com/item?id=31788527 - 2022年6月、コメント19件
「mutable value semantics」論文をざっと読んだのだが、著者たちは参照とポインタを、a) ネストした構造体と
Anyを介した一部の間接化およびランタイム検査、b) 配列インデックスで置き換えようと提案している、と理解してよいのか気になった。「可変値型で二重連結リストや有向グラフのような自己参照データ構造をどう表現できるのかと問うのはもっともだ。実際、任意のグラフは隣接リストで表現できる…」という一節が目に留まった。実装の中でメモリヒープと一種のガベージコレクションを作り直さずに 二重連結リスト を妥当に実装する方法は、あまり見当たらない。
さらに https://github.com/orgs/val-lang/discussions/736 で議論を見つけたが、Rustの
unsafeのような逃げ道ができそうだ。そうなればあらゆる問題は解決するが、「Valの安全な部分集合だけで実用的なアプリケーションを作るのに十分か」という問いは、今後長く議論の的であり続けそうだこれが思ったほど愚かな方法ではない理由は、これらのインデックスが特定のデータ構造、たとえば二重連結リストやグラフに結び付いていて、プログラムの別の場所にアクセスするよう細工するのが簡単ではないからだ。コンパイラがこれを検査する場合でも、プログラムを壊そうとする試みについても同様だ
ホームページの例の説明をどう読めばいいのかわからない。『不要な割り当ては発生しない。
longer_ofの結果はより長い引数の projection なので、emphasizeが z を変更すると y の値が直接変更される。値はコピーも移動もされないが、emphasizeに参照として渡されるわけでもない』とある。文字列引数が関数に渡されて文字が追加される状況なのに、元の文字列は初期の長さとスタック上の特定の位置・サイズを持っていたはずで、どうやって y の新しいコピーなしに可能なのかわからない。誰かが追加する場合に備えて、文字列の末尾に余分なパディングを置いておくのだろうか? もしそうなら、どのくらいパディングを置くのか、そしてなぜ全体としてより非効率にならないのか?
>の慣習で引用するが、パーサーが特別扱いしなくても問題なく機能するただ、似たような疑問はある。1GB の文字列を変更するとどうなるのか? コピーオンライトなのか?
99% のケースでは最適化で消せるとしても、残り 1% で非常に見つけにくい性能低下が起きそうな気がする
longer_ofは関数ではなく subscript で、subscript は値を返すのではなく値を projection して、呼び出し側に一時的な読み取り/書き込みアクセス権を与えるという。これがどうして移動に当たらないのかはよくわからない。文字列の場合、Rust のように可変長を許すためにヒープに置くこともできそうだ