本文へ移動
mie 仕様
REPL Playground

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 := [])
entryStringpkg:<このパッケージ> を 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. 解決と推移依存 (解決器なし・複数共存)

  1. 別名を効くマニフェストの deps で引き、取得元を得る。
  2. git source は lockfile (§4) で (canonical source, tag) → commit を確定し、キャッシュ (§5) の実体ディレクトリを得る。path dep はローカルパスをそのまま実体とする。
  3. 実体パッケージのマニフェストの entry を入口モジュールとして評価し、その値を返す (@import の戻り値)。
  4. 入口パッケージ内部の 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"]
]
スロット (各レコード)意味
sourcecanonical source (host/path@tag を除く)
versionマニフェストで指定された tag
commitversion を解決した時点の 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) の実行を案内する。
  • 不正なマニフェスト: マニフェストが評価できない / deps entry のスキーマ不一致 / @<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.miepackage-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)