backend/js の設計

設計の目標

仕様は 2 つ目の実現経路を記述しています。JavaScript にコンパイルされた MoonBit コードが型付き配列のバッファを Node.js アドオンに渡し、アドオンがネイティブバックエンドと同じ C ランタイムを呼び出すというものです。backend/js はその経路のためにパッケージを確保して識別子を固定し、モジュールのほかの部分がポリシー、ケイパビリティの表、投入ですでに JavaScript ターゲットを指定できるようにしています。

数学的背景

このパッケージは何も計算しません。関わる構造はバックエンドの直和型だけです。

B={ Native,JavaScript },B = \{\, \mathrm{Native}, \mathrm{JavaScript} \,\},

各バックエンドパッケージは、自分を指す定数 backend_target∈B\texttt{backend\_target} \in B を提供します。JavaScript パッケージではこの定数は JavaScript\mathrm{JavaScript} で、shared の設計ページで述べる v1 のポリシー部分集合 P1P_1 はこれを除外しています。そのため、このバックエンドを指定するポリシーや投入は、どのランタイムにも届く前に拒否されます。

設計上の決定

バックエンドより先にパッケージを

今パッケージを宣言しておくと、仕様のモジュール構成(backend/native と backend/js が並ぶ形)を保てるうえ、コードは shared のコンストラクタではなく @js.backend_target() に依存できます。バックエンドが実装されたら、その外部宣言とラッパーは新しいインポートパスなしにここへ入ります。

外部宣言はまだない

js/ のアドオンは runtimeName しかエクスポートせず、C ランタイムもリンクしていないので、宣言するものがありません。実装のない関数を宣言するとコンパイルは通っても実行時に失敗し、提供しないよりも悪い結果になります。

正しさ / 不変条件

  • backend_target() は JavaScript を、default_plan_kind() は Map を、package_name() は "backend/js" を返します。このパッケージは状態を持ちません。
  • このパッケージは js を含むすべてのターゲットでビルドできます。

採用しなかった案

  • バックエンドができるまでパッケージを省く。 そうすると、下流のコードが JavaScript バックエンドを参照する安定した場所がなくなります。
  • JavaScript ターゲットで MoonBit によりカーネルを実行するスタブ。 C ランタイムと仕様の所有権規則を迂回してしまい、本物のバックエンドでは再現できないかもしれない結果を生みます。

境界

このパッケージはプランやワークフローを実行せず、外部関数を宣言せず、Node.js アドオンを読み込まず、JavaScript の境界を越えてデータを移動しません。