3 ポイント 投稿者 GN⁺ 2023-07-19 | 1件のコメント | WhatsAppで共有
  • 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 で試せるリンクを提供している

値セマンティクスと言語研究

コンパイラと標準ライブラリ

  • コンパイラ作業は、LLVMベースのコンパイル、ジェネリクス、状態保存、C相互運用性にまたがっている
  • 標準ライブラリ側では、現在実装ドキュメントとコレクションアルゴリズム関連の作業を公開している

開発者体験とビルド環境

  • エディタ、ドキュメント、言語サーバー向けのツールがあわせて提供されている
  • ビルドおよび開発環境は、複数のOSとコンテナベースのフローをサポートする
    • Development Containers のサポートで開始手順を簡素化
    • SPM/CMake、Ninja/Xcode、Windows/Linux/macOSをサポート
    • テスト生成コンパイラプラグイン
    • 事前ビルド済みの Hylo development toolchain Dockerイメージ
    • コンパイラはSwift 6.2で書かれている

Hylo関連の研究と発表資料

コード例: 安全なprojectionと明示的な解放

  • Subscripts - A Safe Projection Mechanism サンプルは、Angle 型が radians 値を保存し、degrees プロパティを letinout ブロックで提供する構造を示している
    • degreeslet は radians を degrees に変換して返す
    • inout は一時的な degree 値 dyield &d で公開した後、変更された値を再び radians に変換して self.radians に反映する
    • maininout d = &a.degrees でprojectionを取得し、d0.0 に変更した後 a.radians == 0.0 を確認する
  • Sink Methods - Capability for Deinitializing サンプルは、Computer 型が shutdown() をsink methodとして提供する構造である
    • shutdown() はメモリ内容を出力した後、self.ram をsink処理する
    • test1Computer を作成してshutdownしないため、Cannot deinit computer が発生する
    • test2if random_bool() の中でのみshutdownするため、if に入らない経路で Cannot deinit computer が発生する
    • test3while の中でshutdownを呼ぶと、最初の反復以降にconsumed objectの使用問題が生じ、whileに入らない経路ではdeinit不可が残る
  • 追加サンプルは compiler test suite で確認できる

1件のコメント

 
GN⁺ 2023-07-19
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/

    • Sean ParentがValを扱った ADSP Podcast の最近の2エピソードを聴くとよい。Adobe Research Labs がかなり本腰を入れて支援している
      https://adspthepodcast.com/
    • 「C++と相互運用」は疑わしい。他の言語がC++ときちんと相互運用できるとは信じがたく、C++コンパイラ 同士ですらバイナリ互換性が壊れるし、同じコンパイラでもバージョンが違えばそうなることがある
    • コンパイラを信頼しすぎる設計に聞こえる。小さな変更ひとつで離れた場所のコードの 最適化 が壊れ、性能が台無しになる可能性があるのではと心配だ
    • 「一日中値渡しして値返しする」なら、構造体の中で参照を効率よく変更したり保持したりするのが難しくなる。プログラムに少しでも非標準的または複雑な データ構造 が必要なら、致命的な制約に見える。もちろん、そうしたデータ構造を正しく実装するのが難しいことを考えると、むしろ利点かもしれない
    • PHPプログラムを何年も実際にこういう書き方で作ってきて、配列を気にせず渡し続けてきた
      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 などにさらに細かく分裂してほしくないし、システム言語戦争が早く終わってほしい

    • もしかすると、あまりに早く1つを選んでしまったせいで、この分野の革新が長いあいだ不足していたのかもしれない。戦争は歓迎だ
    • 現時点では Rust が勝者だと思う。LinuxとWindowsカーネルに実際に採用されるという巨大な障壁をすでに越えたからだ。そういう意味では、新しいシステム言語がさらに入り込む余地はあまりなさそうだ
    • そうはならない気がする。だからこそ、wasm + wasi のサポートをどこでも広げる理由がますます大きくなる
  • 今日初めて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

    • David Abrahams はAppleに入る前から Boost への非常に重要な貢献者であり、C++委員会のメンバーで、Stepanov流のジェネリックプログラミングの強い支持者だった。Valプロジェクトに加わったのは驚くことではない
  • コンパイラ開発者として、以下のイシューを見て衝撃を受けた。
    https://github.com/val-lang/val/issues/758
    https://github.com/val-lang/val/issues/711
    実装状態があまり良くない気配がある。できるだけ早く セルフホスティングすべきで、そうすればこうした基本的なバグももっと見つかるはずだ。それなのにスターは500を超えている

    • 別のコンパイラ開発者として見ると、早すぎる セルフホスティングほど有害な失敗も珍しい。言語が小・中規模のプログラムでは十分な利益をもたらしても、コンパイラのような大規模プロジェクトに適し、さらにツール群まで整うにはずっと長い時間がかかる。急いでいないのはむしろ良いことだ
    • そういうバグが本番運用中のコンパイラにあるなら心配だが、まだ定義中の言語のコンパイラなら、そこまで大きな問題ではない。Rust 1.0と1.71を比べれば、「最初の安定版リリース」と「実運用の多い安定言語のコンパイラ」の間にどれほど大きな隔たりがあるか分かる。
      セルフホスティングも全てではない。何より象徴的なマイルストーンに近く、達成できれば祝うべきことだが、開発サイクルのかなり後の段階までは、その言語の弱点として扱うべきものではないと思う
    • Swift自体もまだ セルフホスティングしておらず、バージョン6のリリースを控えている。私はコンパイラ開発者ではないが、Swiftコミュニティでこの話題を巡って出た結論は、まだその価値はないというものだった
  • 以前から「Valで遊ぶ」のを先延ばしにしていて、今日ようやく試してみたのだが、コミットが4,000件を超えていても、まだ使える状態にはほど遠い。言語ツアーの例の大半がコンパイルできず、見た目には単純な例でも失敗する。
    Carbonはまだまともなものを出しておらず、Sean BaxterはCircleコンパイラで大きく前進しつつ、Carbonの良い部分もいくつも実装している。まだ言語と呼ぶのが難しいなら、後継になるのも難しい

  • いまや V、Val、Vala、Vale がある。私が忘れている別の言語もあるだろうか?

    • VALもある。80年代の言語のひとつで、SISALを通じてHaskellに影響を与えた。ただ、並列言語コミュニティの外でそのVALを知っている人は多くない気がする
    • 似た名前はむしろ有利に働くかもしれない。こういう言語を学ぶ人は「新しくてホットなもの」を探している可能性が高く、似た名前の別の言語も知って調べるかもしれない。JavaScriptもそうだったが、結果は悪くなかった
    • これが本当に Vale だと思っていた。名前の衝突はかなり残念だ
    • おまけに V は Vlang とも呼ばれ、Vale も以前は Vlang と呼ばれていた
  • 毎回出てくる話だが、Valで唯一気に入らないのは、ValeV も新しいシステム言語だという点だ。名前のせいでこの3つはあまりにも簡単に混同してしまう

    • Vala もある。領域は少し違うが、似た名前の言語がもうひとつある
    • これが projection 言語なのか region 言語なのか確認するために、リンクまで開いてみる必要があった
    • VAL: Variable Assembly Language もある https://en.m.wikipedia.org/wiki/Variable_Assembly_Language
  • 関連記事がある。ほかにもある?
    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 の新しいコピーなしに可能なのかわからない。誰かが追加する場合に備えて、文字列の末尾に余分なパディングを置いておくのだろうか? もしそうなら、どのくらいパディングを置くのか、そしてなぜ全体としてより非効率にならないのか?

    • 4スペースの接頭辞は引用ではなく、コード/等幅ブロック用。HN では普通 > の慣習で引用するが、パーサーが特別扱いしなくても問題なく機能する
    • 不変値だからといって、必ずしもスタック上にある必要はない。
      ただ、似たような疑問はある。1GB の文字列を変更するとどうなるのか? コピーオンライトなのか?
      99% のケースでは最適化で消せるとしても、残り 1% で非常に見つけにくい性能低下が起きそうな気がする
    • 数日後に自分なりに答えるなら、変更された変数名をより長い新しい値でスタック上でひそかに shadowing するなら可能そうだ。おそらくこれが "projection" の意味かもしれない。この場合、スタックはすでに割り当て済みなので、新たな割り当ては発生しない。言語やコンパイラの専門家ではないので、この用語がその分野ではよく知られているのかもしれない
    • 下のほうにさらに説明がある。longer_of は関数ではなく subscript で、subscript は値を返すのではなく値を projection して、呼び出し側に一時的な読み取り/書き込みアクセス権を与えるという。
      これがどうして移動に当たらないのかはよくわからない。文字列の場合、Rust のように可変長を許すためにヒープに置くこともできそうだ