mie パッケージ配布 (third-party モジュール) v1
本書は v1 の third-party パッケージ配布 を定義する。@import "pkg:<alias>" の解決規則の言語側は language-spec.md §13.4、CLI は mie-command.md を参照。本書中の §N は本書内の節を指す。language-spec.md の節は明示する。
標準ライブラリ (std/index.md) が「host が同梱するモジュール」を std: で取得するのに対し、本書は「他者が配布する mie パッケージ」を pkg: で取得する仕組みを担う。中核思想:
- 使う側は別名のみ — import 文には短い別名を書き、取得元・バージョンは マニフェスト 1 箇所に集中させる。
- 分散・中央レジストリなし — 取得は git。誰でも持つ VCS をバージョン源とし、レジストリ運用を負わない。
- 解決器なし — 各マニフェストが exact pin。バージョン範囲も衝突解消も持たず、別バージョンは共存させる。
- すべて mie — マニフェストも lockfile も mie 自身のオブジェクト値で書く。
1. 概念
| 用語 | 意味 |
|---|---|
| パッケージ | マニフェスト (package.mie) を root に持つ .mie ソース木。1 つの 入口 (entry) を公開する |
| マニフェスト | パッケージの依存 (deps) と入口 (entry) を宣言する mie ファイル |
| 別名 (alias) | pkg:<alias> でパッケージを指す論理名。マニフェスト・ローカル (各マニフェスト内で独立) |
| 取得元 (source) | 別名が解決する実体。git source (host/path@<tag>) または path dep (./ ../ /) |
| lockfile | 全推移依存を tag → commit で固定した自動生成ファイル (package-lock.mie) |
| キャッシュ | 取得済みパッケージのグローバル格納先 ($MIE_CACHE) |
消費側の最小例:
[get, post] := @import "pkg:http" # 別名 http の入口を引く get "https://example.com"
http がどこの何バージョンかは、この .mie を含むパッケージのマニフェストが決める。
2. マニフェスト (package.mie)
パッケージ root に置く。#[mie] ライブラリ形 (ファイル全体がスロットリスト、top-level の {} ラッパは不要)。
#[mie] deps := [ http := "github.com/u/mie-http@1.4.0" log := "../my-log" # ローカル path dep ] entry := "src/main.mie" # pkg:<このパッケージ> の入口
| スロット | 形 | 意味 |
|---|---|---|
deps | [ alias := <source>, ... ] スロットリスト | 別名 → 取得元の対応。空可 (deps := []) |
entry | String | pkg:<このパッケージ> を import した側が着地する入口ファイル (パッケージ root からの相対) |
host は mie 評価器でこのファイルを評価し、deps / entry スロットを読む (既存 lexer / parser / evaluator を再利用)。マニフェストはデータ宣言であり、評価時に I/O や副作用を行ってはならない (実行はリテラル相当の評価に留める)。
2.1 取得元 (source) の記法と判別
deps の各値 (String) は先頭で 2 種に判別する:
- path dep: 先頭が
.(./../) または/。マニフェスト root 基準の相対 (または絶対) ローカルパスで、取得しない。開発中パッケージの参照に使う。 - git source: それ以外。
host/path@<tag>形で@<tag>必須。 host/pathを canonical source と呼ぶ (例github.com/u/mie-http)。<tag>は git のタグ参照名としてそのまま使う (例1.4.0/v1.4.0— リポジトリのタグ命名に合わせる)。バージョン範囲・semver 比較は行わない (exact)。
@<tag> を欠いた git source、解決不能な path dep は静的エラー (§6)。
2.2 どのマニフェストが効くか
@import "pkg:<alias>" を含むファイル F の別名は、F から上方向に探索して最初に見つかるマニフェスト (package.mie) の deps で解決する。
- entry プロジェクトはプロジェクト root にマニフェストを持つ。
- 取得した依存は、キャッシュ内の自身の root にマニフェスト (配布物に同梱) を持つ。依存内部の
pkg:は その依存のマニフェストで解決する (推移依存)。 - マニフェストが見つからないファイルからの
pkg:import は静的エラー (§6)。単発スクリプトはpkg:を使えない。
別名がマニフェスト・ローカルなので、別々のパッケージが同じ別名 http を別バージョンに割り当てても干渉しない。
3. 解決と推移依存 (解決器なし・複数共存)
- 別名を効くマニフェストの
depsで引き、取得元を得る。 - git source は lockfile (§4) で
(canonical source, tag)→ commit を確定し、キャッシュ (§5) の実体ディレクトリを得る。path dep はローカルパスをそのまま実体とする。 - 実体パッケージのマニフェストの
entryを入口モジュールとして評価し、その値を返す (@importの戻り値)。 - 入口パッケージ内部の
pkg:import は実体マニフェスト基準で再帰的に 1〜3 を繰り返す。
複数共存: キャッシュは (canonical source, version) をキーにする (commit は lockfile (§4) が固定する真実源で、キャッシュのキーには含めない)。同一パッケージでも別バージョンは別実体として共存し、互いに別オブジェクトになる。バージョンを 1 つに平らげる解決器・semver range は持たない。
トレードオフ (受容): 同一パッケージの複数バージョンがキャッシュに重複し、異バージョン間でインスタンス同一性は成立しない (別実体)。
4. lockfile (package-lock.mie)
entry プロジェクト root に置く自動生成ファイル。mie add / mie update (mie-command.md) が書き、全推移依存をフラットに記録する。再現ビルドの真実源。
#[mie] # 自動生成。手で編集しない。 packages := [ [source := "github.com/u/mie-http", version := "1.4.0", commit := "a1b2c3d4e5f6...", entry := "src/main.mie"] [source := "github.com/u/mie-log", version := "0.9.2", commit := "d4e5f6a7b8c9...", entry := "log.mie"] ]
| スロット (各レコード) | 意味 |
|---|---|
source | canonical source (host/path、@tag を除く) |
version | マニフェストで指定された tag |
commit | version を解決した時点の commit SHA (固定) |
entry | 実体マニフェストの入口 (再評価せず参照できるよう記録) |
mie-native だが機械生成であり手編集しない (冒頭コメントで明示)。path dep は commit 固定を持たないため lockfile に記録せず、解決のたびにローカルツリーを直接参照する。
5. キャッシュ
- 場所: 環境変数
MIE_CACHE。未設定時の既定は XDG に従い$XDG_CACHE_HOME/mie(XDG_CACHE_HOME未設定なら~/.cache/mie)。 - キー (ディレクトリ):
(canonical source, version)($MIE_CACHE/<host>/<path>@<version>)。実体は lockfile (§4) が固定した commit をチェックアウトした読み取り専用ツリー。commit はキャッシュのディレクトリ名には含めず、lockfile を真実源とする。 mie get(mie-command.md) は lockfile / マニフェストを見てキャッシュへ復元する (CI・新規 clone 用)。lockfile があれば commit を信頼し、tag の再解決はしない。
6. 静的検査との関係 (static-analysis.md §1)
mie check / mie build / LSP 診断の前段検査は、pkg: について次を静的エラーとする (回復可能エラーにはしない):
- マニフェスト不在:
pkg:を使うファイルから上方にマニフェストが見つからない。 - 未知の別名:
<alias>が効くマニフェストのdepsに無い。 - 未取得: lockfile で解決済みだが実体がキャッシュに無い。取得 (
mie get) の実行を案内する。 - 不正なマニフェスト: マニフェストが評価できない /
depsentryのスキーマ不一致 /@<tag>欠落 / path dep 解決不能。
到達可能な pkg: 依存のソースも構文検査の対象に含める (キャッシュ内の .mie)。循環 import の扱いは相対 import と同じく実行時検出 (language-spec.md §13.4)。
エラーメッセージには未取得時の mie get 案内などを載せるが、spec 章番号・バージョン等のメタ参照は埋め込まない。
7. mie build (embed) との統合
mie build (mie-command.md §4) は package.mie がある場合 manifest dir を embed ルートとし、entry ツリー・package.mie・package-lock.mie・依存グラフの .mie を 1 つの embed FS にまとめる。pkg: の解決は埋め込んだ manifest + lockfile + 名前空間レイアウトそのものが解決表となり、ランタイムは embed FS を (source, version) キャッシュとみなして解決する。
レイアウト:
- git dep: lockfile で解決した全推移依存を
pkg/<source>@<version>/...(= キャッシュと同じ(source, version)レイアウト) に配置する。 - path dep: build 時点のローカルツリーを embed ルート相対の元位置に embed する。embed ルート外 (
../...) を指す path dep は embed 不可としてエラーで停止する (git dep 化を案内)。commit 固定が無いため再現性はローカルツリー依存で、mie buildが stderr に警告する。 - 各依存ディレクトリには
package.mieを含め、依存内のpkg:も各自の manifest から解決できるようにする。 std:モジュールは従来どおり host コンパイル同梱 (embed FS とは独立、language-spec.md §13.4)。
8. CLI
依存の追加・取得・更新・削除は mie コマンドが行う。構文と挙動は mie-command.md:
| コマンド | 役割 |
|---|---|
mie add <host/path@tag> [--as <alias>] | マニフェスト deps 追記 + 取得 + lockfile 更新 |
mie get | マニフェスト / lockfile からキャッシュへ復元 |
mie update [alias] | tag を再解決して lockfile 更新 |
mie remove <alias> | マニフェスト deps から削除 |
9. 意図的に入れない (v1 スコープ外)
以下は language-spec-future.md に持ち越す:
- semver range とバージョン自動解決器 (exact pin + 複数共存で代替)
- 中央レジストリ・検索 (git 分散のみ)
- HTTPS tarball / zip 直取得 (git のみ)
- ファイル単位の
pkg:<alias>/<path>.mie(パッケージ入口 1 点のみ) - パッケージの publish / yank / 署名・改ざん検証 (commit 固定のみ)
- bare 名 import (リテラル限定の維持、language-spec.md §13.4)