本文へ移動
mie 仕様
REPL Playground

mie コマンド仕様 v1

本書は mie CLI の起動形態と各サブコマンドの仕様を定める。言語の意味論は language-spec.md、組込関数群は prelude.md を参照。分量の大きい 3 つのモードは別冊に分離した — REPL は repl.md、LSP サーバは lsp.md、整形 (mie fmt) は format.md。本書中の §N は本書内の節を指し、別冊内の節は「repl.md「動作モード」」のように書名+節名で参照する。

1. 起動ディスパッチ

mie [SUBCOMMAND | <path>] [ARGS...]

第 1 引数によって起動モードが決まる。

第 1 引数モード
なし (または --strict のみ)REPLrepl.md
lspLSP サーバlsp.md
buildバイナリビルド§4
check静的検査のみ§6
testテスト実行§7
fmtソース整形format.md
lintスタイル検査§9
docリファレンス生成§10
add依存追加§11
get依存取得§11
update依存更新§11
remove依存削除§11
eval標準入力評価§5.6
それ以外ファイル実行§5

サブコマンド名 (lsp / build / check / test / fmt / lint / doc / add / get / update / remove / eval) は予約。同名の .mie ファイルを実行したい場合は ./lsp のようにディレクトリ付きで指定する。

1.1 終了コード

ファイル実行モード・eval モード・build モード・check モードの終了コード:

code意味
0成功
1構文エラー / 評価エラー / ビルドエラー
2I/O エラー / 引数不正 / 必須ツール不在

REPL と LSP サーバは正常終了時 0

1.2 ソース系サブコマンドの住み分け

check / fmt / lint はいずれも評価せずソースを扱うが、責務が異なる。

ツール対象動作不変条件
check (§6)正しさ(構文 + 静的エラー、到達可能グラフ全体)検出のみ
fmt (format.md)具体構文の正規形-w で書き換え抽象構文木を保存
lint (§9)スタイル/品質(パース可能前提、保守的)検出、--fix で書き換え--fix抽象構文を変えうる
  • checklint はどちらも評価せず診断するが、check は「正しさ」(エラーの有無、モジュールグラフ単位)、lint は「書き方」(エラーではないスタイル問題、ファイル単位で import 解決なし)。
  • fmtlint --fix はどちらもソースを書き換えるが、不変条件が違う。fmt抽象構文木を保存する正規化のみ(具体構文の見た目を正す。例: 1 引数 f(x)f x)。lint --fix抽象構文を変える正規化まで踏み込む(例: 制御構造 if(c, t, e)if c {t} {e}。評価結果は同じだが適用の段数=抽象構文が変わる)。よって fmt は制御構造のタプル形を保ち、並置化は lint --fix が担う。

2. REPL

REPL (mie を引数なし、または --strict のみで起動) の仕様は repl.md に分離した。

3. LSP サーバ (mie lsp)

LSP サーバ (mie lsp) の仕様は lsp.md に分離した。

4. ビルド (mie build)

エントリ .mie とその import 依存を go:embed で同梱した単体 Go バイナリを生成する。生成バイナリはホストに mie 処理系をインストールしなくても動く。

4.1 構文

mie build [-o <output>] [--target <os>/<arch>]... [--strict] <entry.mie>

引数の並びは フラグ → エントリ の順。Go の flag パッケージの規約に従い、positional 引数 (エントリ) より後ろのフラグは解釈されない。

4.2 オプション

フラグ既定値意味
-o <output>エントリの basename から .mie を除いたもの出力ファイル名のベース
--target <os>/<arch>ホストの GOOS/GOARCHビルドターゲット。複数指定可
--strictoffビルド前に strict 型検査 (§4.9) を適用する

4.3 出力名

  • ターゲットが 1 個: <output> をそのまま使う。
  • ターゲットが複数: <output>-<os>-<arch> の形に展開。
  • ターゲット OS が windows の場合は .exe を付与。

4.4 対応ターゲット

go build がサポートする任意の GOOS/GOARCH ペア。検証済みの組合せ:

  • darwin/arm64
  • darwin/amd64
  • linux/amd64
  • linux/arm64
  • windows/amd64

4.5 import の静的解決

ビルドはまず entry を起点に 静的検査 (static-analysis.md §1) を行う。構文エラー (動的 import を含む) や import 先不在があればビルドを中止し exit code 1。検査を通過した場合のみ、@import "<path>" のリテラルパスを再帰収集して embed する。embed ルート (相対 slash パスの 0 点) は、プロジェクトに package.mie (packages.md) があれば その manifest dir、無ければ エントリの所属ディレクトリ

  • 構文エラー / import 先不在 → 静的エラーで 停止 (ファイル実行 §5・mie check §6 と同一規則)。
  • embed ルートより外 (../...) に出る相対 import は エラー で停止する (embed FS の制約)。
  • pkg: 依存 (third-party、packages.md) は lockfile で解決したグラフを別名前空間 pkg/<source>@<version>/... に embed する。path dep は embed ルート相対の元位置に embed し、embed ルート外 (../...) を指す path dep は embed 不可として エラー で停止する (git dep 化を案内)。path dep は commit 固定が無いため embed 時に再現性警告を stderr に出す。std: モジュールは従来どおり host コンパイル同梱 (embed FS とは独立)。

4.6 ホスト要件

  • ホストに go ツールチェーン (Go 1.26+) が必要。exec.LookPath("go") で確認し、無ければ「go toolchain not found in PATH」を stderr に出して exit code 2
  • 内部で go mod tidy および go build -ldflags="-s -w" を実行する。
  • 生成バイナリ自体の実行には Go ツールチェーンは不要。

4.7 mie リポジトリの位置解決

生成プロジェクトは replace github.com/bluegreenhq/mie => <path> で本体ソースを参照する。<path> は次の順で決定する:

  1. 環境変数 MIE_REPO の値 (絶対化)
  2. os.Executable() の親から最大 6 階層上向きに go.mod を含むディレクトリを探索
  3. os.Getwd() から最大 6 階層上向きに go.mod を含むディレクトリを探索

いずれも見つからなければエラーで exit code 2

4.8 進捗出力

go mod tidy / go build の stdout/stderr はそのまま stderr に流す。

4.9 strict 型検査 (--strict)

mie build --strict は、§4.5 の構文層 静的検査 (static-analysis.md §1) の通過後・go build の起動前に、entry を起点とした strict 型検査 (static-analysis.md §3) を走らせる。型エラーが 1 件でもあれば診断を stderr に出してビルドを中止し exit code 1 で停止する (バイナリは生成しない)。検査がクリーンなときのみ通常どおりビルドを続行する。

  • strict 規則はファイル実行 mie <path> --strict (§5.5) と同じ (static-analysis.md §3 の 6 規則)。
  • 実効 strict はファイル単位。entry ファイルが header #{mie strict} / #[mie strict] (language-spec.md §13.1) を宣言していれば --strict 無しでもその entry は strict として検査される。実効 strict = 「CLI --strict」OR「entry header の strict 属性」。
  • フラグ無し・header に strict 無しの mie build は従来どおり構文層検査のみで、型検査は行わない (通常モードの mie <path> と揃う。実行時照合が backstop、§6.2)。

5. ファイル実行 (mie <path> [args...])

<path>.mie ソースとして読み込み、評価する。<path> より後ろのトークンは プログラム起動引数としてそのまま実行プログラムへ渡り、std:envargs() (std/env.md §3) で取得できる。

mie app.mie list --json hello     # args() は ["list", "--json", "hello"]

mie 自身のフラグ (--strict、§5.5) は位置を問わず entry に渡る前に取り除かれるため args() には現れない。その帰結として、プログラムへ literal --strict を引数として渡すことはできない。

5.1 ヘッダ要件

ファイル先頭の #{mie} ヘッダは省略できる (省略時は #{mie} 明示と同一意味、language-spec.md §1.1 / §13.1)。#[mie] ヘッダ (ライブラリ形) は省略不可。先頭の空行・行コメント・shebang #!... は許容される。

5.2 標準入出力

  • 標準入力: input(prompt) (prelude.md §1) の読み取り元。
  • 標準出力: print(s) の出力先。
  • 標準エラー: パース/評価エラーメッセージの出力先(トップレベルに達した ? の失敗 bail 診断を含む、language-spec.md §16.7)。

5.3 import の解決

@import "<rel>"caller ファイルのディレクトリ を起点に絶対化される。同じファイルを複数回 import してもパースは 1 度だけ (*module.Manager の Cache による)。循環 import は呼び出し位置のエラーで停止する (詳細は language-spec.md の import 章を参照)。

ファイル実行モードでは OS の filepath.Abs ベースの解決が使われ、ファイルシステム外への参照 (絶対パスなど) も許される。embed バイナリ (§4) では FS ルートからの slash 相対パスに限定される (runtime.Config.EmbedMode)。

std:fs の各関数 (read / write / readdir ほか、std/fs.md) は @import "std:fs" で取得するが、データファイルの読み書きはソースの @import "x.mie" とは 解決系統が別 で、embed バイナリ内でも常にホスト FS の cwd 相対で動く (embed FS にはアクセスしない)。std:fs モジュール自体は embed バイナリにも常に含まれる。

5.4 終了コード

状況code
正常終了0
パース・評価エラー1
ファイル読み取り失敗2

トップレベルに達した未処理失敗(? の失敗 bail、language-spec.md §16.7)は評価エラーとして 1。診断は stderr(§5.2)に出す。

5.5 strict 型検査 (--strict)

mie <path> --strict は、評価の 前に strict 型検査 (static-analysis.md §3) を走らせ、型エラーが 1 件でもあれば診断を stderr に出して 評価せず exit code 1 で停止する。型検査がクリーンなら通常どおり評価する。フラグは path の前後どちらに置いてもよい (mie --strict <path> / mie <path> --strict)。

  • strict モードは static-analysis.md §2 の健全・漸進検査に「名前付き関数の結果型に明示 Any を禁止 (省略は許容)」「名前付き関数のパラメータ型必須化」「宣言結果型を契約とした越境照合」を上乗せする (static-analysis.md §3)。
  • 実効 strict はファイル単位で決まる。entry ファイルが header #{mie strict} / #[mie strict] (language-spec.md §13.1) を宣言していれば、--strict を付けなくてもそのファイルは strict として検査される。実効 strict = 「CLI --strict」OR「entry header の strict 属性」。
  • フラグ無し・header に strict 無しの mie <path> は従来どおり型検査せず実行する (実行時照合が backstop)。
  • 終了コードは §5.4 と同じ (型エラーは構文/評価エラーと同じ 1)。

5.6 標準入力からの評価 (mie eval)

mie eval は標準入力から読み込んだソース全量を .mie プログラムとして評価する。エディタの選択範囲など、ファイルに無いソース断片を実行する用途を想定する。

  • 入力: 標準入力全量がソース。パス引数は取らない。
  • ヘッダ: ファイル実行 (§5.1) と同じく #{mie} は省略可。
  • 標準出力: print(s) の出力先。標準エラー: パース/評価エラーの出力先。
  • input(): 標準入力はソースとして消費されるため、input(prompt) は即座に EOF(空)を受け取る。
  • import の解決: @import "<rel>"実行時カレントディレクトリ を起点に絶対化される(§5.3 と同じ OS filepath ベース)。エラー位置のファイルラベルは <stdin> と表示する。
  • 終了コード: ファイル実行 (§5.4) と同一。
状況code
正常終了0
パース・評価エラー1
標準入力の読み取り失敗2

eval評価する 点で、評価せずソースを扱う check / fmt / lint (§1.2) とは別系統である。

6. 静的検査 (mie check)

指定した各 .mie を起点 (entry) に、評価せず 静的検査 (static-analysis.md §1) のみを実行する。entry とそこから到達可能なモジュールグラフ全体を構文検査し、結果に応じた終了コードを返す。CI や保存時フックでの利用を想定する。

6.1 構文

mie check [--strict] <path>...

引数は .mie ファイルまたはディレクトリを 1 個以上。ディレクトリは配下の .mie を再帰収集する (fmt / lint と同じパス展開、§4)。収集した各ファイルをそれぞれ entry として検査する。1 件の検査単位は到達可能なモジュールグラフ全体であり、lint の「ファイル単位・import 解決なし」とは異なる (§4)。

6.2 検査内容

ファイル実行 (§5) の開始前に走るものと同一の検査 (同じ internal/analyze)。検出対象は static-analysis.md §1 を参照。

mie check は構文・import 解決層 (§6.2 前段) に加えて、健全な静的型検査 (static-analysis.md §2) を行う。検出するのは「実行すれば確実に型不一致 panic になる」ことが静的に確定する箇所だけで (誤検出を出さない)、確定しない箇所は素通しする (漸進的型付け)。深いケース (関数結果の越境推論・演算子レベル・未定義型参照の静的化など) は将来段階。型検査は mie check と LSP 診断でのみ走り、通常モードの mie <path> / mie build には適用しない (実行時照合が backstop)。

6.3 strict 型検査 (--strict)

mie check --strict <path>... は、§6.2 の健全・漸進検査に strict 規則 (static-analysis.md §3) を上乗せして検査する。越境・契約まわりで追加検出するのは次の 3 点:

  • 名前付き関数の結果型に明示 Any を禁止 (省略は許容): 名前に束縛された関数 (body 非空) の結果型を宣言する場合 (束縛注釈 add: {Int, Int | Int} := …/内部名注釈 {self: {Int, Int | Int} | …}/body 末尾アスクリプション {x, y | x + y: Int} のいずれか。language-spec.md §17.3)、その結果型を Any にすると型エラー。結果型注釈を省略した場合は許容し Any 扱いとする (素通し)。
  • 名前付き関数のパラメータ型必須化: 名前に束縛された関数 (body 非空) の各パラメータ型が、インライン注釈・宣言関数型の対応位置 (非 Any)・推論可能なデフォルトのいずれでも確定しなければ型エラー。インライン x: Any は動的型へのオプトインとして充足する (型変数の無い mie で真に多相な関数を書く唯一の手段)。bare パラメータと関数型注釈位置の Any は充足とみなさない (static-analysis.md §3)。
  • 宣言結果型を契約とした越境照合: 完全適用 f(args) の結果型を宣言から確定し、x: T := f(args) 等の照合に用いる。

加えて、分岐の収束系診断 (static-analysis.md §3 規則 (4)-(6)) も strict で報告する: if/@match の分岐結果型が確実に割れる場合、closed variant の @match の被覆漏れ (非網羅)、および到達しえないアーム・冗長な catch-all (不要 default)。

strict は mie <path> --strict (§5.5) と同じ規則。実効 strict もファイル単位で、entry が header #{mie strict} / #[mie strict] を宣言していれば --strict 無しでもその entry は strict として検査される (実効 strict = 「CLI --strict」OR「entry header の strict 属性」)。複数 entry のときは entry ごとに独立に判定する。診断・終了コードの形式は §6.1 / §6.2 と同じ (型エラーは exit 1)。LSP は mie lsp --strict (lsp.md「起動」)、ビルドは mie build --strict (§4.9) で strict 診断に対応する。

import 解決規則はファイル実行 (§5.3) と同じ (caller ディレクトリ基準、OS filepath ベース)。各 entry は独立に検査するため、複数 entry が同じモジュールを import する場合そのモジュールは複数回検査される (診断は冪等)。

6.3 出力と終了コード

  • 全 entry の検査がクリーンな場合は 何も出力せず exit code 0
  • 静的エラーがある場合は各診断を <file>:<line>:<col>: <msg> 形式で stderr に出す。
  • 複数 entry のときは全 entry を検査し、終了コードはそれらの最大値を返す (いずれかに静的エラーがあれば 1、いずれかの読み取りに失敗すれば 2)。
状況code
静的エラーなし0
静的エラーあり1
読み取り失敗 / 引数不正 / .mie 不在2

7. テスト (mie test)

mie のテストを mie 自身で書く。*_test.mie 内に test "name" {block} を並べ、assert 名前空間でアサーションする。CI やローカル開発での回帰検査を想定する。

test / assertmie test 専用の魔法束縛ではなく、@import で取得する通常のライブラリ (std:test / std:assert) である。mie test はそれらで組んだテストを収集・実行する専用ランナーであり、REPL・playground・mie run からも同じ API を使える。

7.1 構文

mie test [path...]
  • path は 0 個以上。各 path はファイルまたはディレクトリ。
  • ディレクトリは配下を再帰し、ファイル名が _test.mie で終わるものを収集する。
  • ファイルはそのまま対象にする (名前が _test.mie で終わらなくてよい)。
  • 引数省略時は cwd を対象ディレクトリとする。
  • 収集されたファイルはパス昇順で評価する。

7.2 テストライブラリ (std:test / std:assert)

テストの語彙は 2 つの標準ライブラリモジュールとして提供する。ambient 束縛ではないため、@import すれば REPL・playground・mie run を含む任意の文脈で使える。

std:assert — アサーション (状態なし)

equal / not_equal / ok / fail を持つ純粋な名前空間。失敗時に panic (object.Error) を投げるだけで std:test に依存しない。test の外で失敗した場合は通常どおりトップレベルまで伝播する。

assert := @import "std:assert"
assert.equal(1 + 1, 2)
pass 条件失敗メッセージ例
assert.equal(actual, expected)actual == expected (language-spec.md §9.1。ユーザー定義 == スロットも尊重)assert.equal: expected 3, got 4
assert.not_equal(a, b)a == b が偽assert.not_equal: expected values to differ, both 3
assert.ok(cond)condtrue (Bool、language-spec.md §9.3)assert.ok: expected true, got false
assert.fail(message)(常に失敗)message

両辺・実値の表示は各値の Inspect を用いる。

std:test — テストの構築と実行 (collect-then-run)

test は receiver を持ち回らない純関数で、テストを構築するだけ (実行しない)。実行・集計は run が担う。

[test, run] := @import "std:test"
assert := @import "std:assert"

run [
  test "add" { assert.equal(1 + 1, 2) }
  test "less" { assert.ok ("a" < "b") }
]
返り値意味
test("name", {block}) / test "name" {block}Trialname (String) のテストを 1 件構築する。block は必須スロット 0 個の本体付きオブジェクト ({body} 形)。実行はしない
suite("name", [trials])Trial子 Trial をまとめたグループを構築する (ネスト可)。実行時に名前は 親/子 でプレフィックスする
run([trials])ReportTrial 列を記述順に実行し、集計した Report を返す。出力はしない

run の合否は各 Trial の block を呼んだ結果で決まる: panic (object.Error) なら FAIL (メッセージと位置を記録)、それ以外は PASS。1 件が失敗しても残りは継続実行する (合否境界は run にある)。group Trial は子を再帰実行する。

Report は集計値で、少なくとも次を持つ:

{
  passed := Int
  failed := Int
  failures := [{ name := String, message := String, pos := String |}]
|}

出力・整形は行わない (printer / reporter は将来課題)。mie test は返った Report を §7.5 の形式で整形出力する。REPL では run の返り値をそのまま参照・表示すればよい。

7.3 収集 (mie test の top-level Trial 収集)

mie test は各対象ファイルについて次を行う:

  1. 静的検査 (§6 / static-analysis.md §1) を通す。
  2. test / suite (std:test) と assert (std:assert) をファイルスコープに供給して評価する (ゼロボイラープレート維持。REPL・playground・mie run はこの供給を受けず @import で明示取得する — 同一意味論・入口 2 つ)。
  3. ファイルの top-level が返す値のうち Trial であるものを記述順に収集する#{mie} ブレース形式のファイル (テストファイルの通常形) では top-level の bare な式文 (test "name" {block} / suite …) が対象。#[mie] ブラケット形式や | 区切りを使うファイルでは file-root の位置スロット (language-spec.md §1.4) も同じ枠で拾う。名前束縛 (t := …) の値は収集対象にしない (ヘルパ・import は束縛として共有する)。
  4. 収集した Trial 列を run で実行し、返った Report を §7.5 形式で整形出力し、終了コードを立てる。

したがって _test.mie は従来どおり top-level に test "name" {block} を並べるだけでよい。名前束縛 (ヘルパ定義・@import した被テストコード) は従来どおり共有する。

7.4 分離 (isolation)

  • 各テストファイルは fresh な root 環境 で評価する (mie <file> 1 回相当)。ファイル間で状態は共有しない。
  • ファイル評価はまず全 top-level 文を評価して Trial (thunk) を構築し、そのあと run が各 Trial の block を実行する。したがって top-level の副作用はテスト body より前に一度だけ起こり、各テストは共有 top-level 束縛 (ヘルパ定義・@import した被テストコード) を参照する。テスト間の自動状態リセットは行わないため、共有された mutable 状態を変更すると後続テストに影響しうる。
  • 被テストコードは @import "<rel>" で取り込む (§5.3 と同じ caller ディレクトリ基準の解決)。被テストコード側も必要なら @import "std:assert" してアサートヘルパを共有できる。

7.5 出力と終了コード

mie testrun の返した Report をもとに、各ファイルについてファイル名見出しを出し、テストごとに PASS / FAIL 行 (FAIL は失敗メッセージと位置を続ける) を出力。最後に集計行 <P> passed, <F> failed を出す。出力例:

foo_test.mie
  PASS  add は和を返す
  FAIL  add は0で恒等
        assert.equal: expected 5, got 6  (foo_test.mie:8:3)

3 passed, 1 failed
状況code
全テスト pass (対象 0 件を含む)0
1 件でも FAIL / 構文・評価エラー1
I/O エラー / 引数不正2

8. 整形 (mie fmt)

整形 (mie fmt) の仕様は format.md に分離した。

9. スタイル検査 (mie lint)

パースは通るが書き方として問題のあるパターンを検出する。構文エラー (= 静的検査 mie check §6 の領域) とは別レイヤで、スタイル/品質に絞った保守的な (誤検出を避ける) 検査を行う。

9.1 構文

mie lint [--fix] [path...]

path はファイルまたはディレクトリ (ディレクトリは配下を再帰して .mie を収集)。引数省略時は cwd を対象とする。収集ファイルはパス昇順で処理する。

--fix自動修正可能なルールを修正してファイルを上書きする (現状の対象は control-juxtaposition)。修正の際ソースは整形され (mie fmt 相当 + 制御構造の並置化)、内容が変わる場合のみ書き込む。--fix 指定時は診断を出力しない。

9.2 ルール

ルール検出内容
unused値が一度も読み出されないローカル束縛。immutable 宣言 name :=、mutable local name = (auto-vivify)、分割束縛 a, b := / = / [a, b] := の各名が対象。代入先 (書き込み) は使用に数えないため write-only な mutable local も検出する。さらに body 内で一度も参照されない inner-name ({self | …} の self、§4.2) も対象 (inner-name は body 専用の自己参照で名前による外部参照が無いため、ローカル束縛と同じく安全に判定できる)。ただし型注釈付き inner-name ({self: T | …}) は名前未参照でも自身の型を表明する用途があるため対象外。破棄子 _ は対象外。オブジェクトのスロット (関数引数を含む) は対象外 (下記)
self-assign自分自身への代入 (x = x / a.b = a.b) で効果が無い
control-juxtaposition制御構造 (if / when / while) がタプル形 if(c, t, e) で書かれている。並置形 if c {t} {e} が推奨 (--fix で自動変換)
non-tail-recur@loop 関数 (language-spec.md §16.9) の反復ドライバ (lexically 内側の inner-name 自己再帰) で、self 呼び出しが末尾位置になく TCO (language-spec.md §16.10) が効かない。深い反復で呼び出しスタックを消費する (溢れうる)。@loop は「これはループ (定数スタックで回るべき)」という意図の宣言なので、その駆動再帰が非末尾なら書き方の問題として報告する

検出は保守的で、検出漏れ (false negative) は許容し誤検出 (false positive) を避ける。unused はシャドウイング等の曖昧なケースでは報告しない。

non-tail-recur@loop に限る理由: 非末尾の自己再帰は一般には正常であり (fact / fib・木の再帰・分割統治・アキュムレータなしのリスト構築)、それらに警告するのは誤検出になる。@loop 注釈だけが「この関数はループ=定数スタックで回るべき」という意図を静的に宣言するため、その反復ドライバの非末尾 self 呼び出しに限れば高信号・低誤検出で報告できる (language-spec.md §16.10 の末尾位置判定を再利用する)。@loop を使わない一般の再帰は対象外 (Scala @tailrec が注釈付き関数のみを検査するのと同じく、意図の signal がある箇所だけを見る)。

unused がオブジェクトのスロットを対象としない理由: スロット (関数引数を含む) は、束縛元のオブジェクトが関数として呼ばれて body 内で参照されるだけでなく、obj.slot で外部から参照され得る。そして mie は型情報を静的に持たないため、ある .slot 参照がどのオブジェクトのどのスロットを指すかを mie lint は静的に特定できない。とりわけ次のパターンでは、スロットの参照がそのファイルの外 (別ファイル) に現れる:

  • ファクトリ関数が構築して return するオブジェクト のメソッド/フィールド (importer が account.deposit 等で参照)
  • 引数として他の関数に渡すレコード (呼び出し先が .field を読む)
  • @type / @enum で宣言される 型のフィールド名

これらはファイル内に .slot が現れないため、スロットを未使用検出の対象に含めると誤検出になる。name := / name = / 分割束縛といった ローカル束縛は名前で外部参照されない ので安全に判定できるが、スロットは外部 API になり得る点が本質的に異なる。この区別はエスケープ解析や型情報なしには厳密化できないため、unused はスロットを一律に対象外とする (検出漏れを許容し誤検出を避ける保守的方針)。

9.3 出力と終了コード

検出は <file>:<line>:<col>: <msg> (<rule>) 形式で stdout に出す。

状況code
検出なし0
検出あり / 構文エラー1
I/O エラー / 引数不正2

構文エラーのあるファイルは lint せず、診断を stderr に出して exit code 1 に寄与する。

--fix 指定時は診断を出力せず、修正対象を並置形へ書き換えてファイルを上書きする。修正成功 (変更なしを含む) は 0、構文エラーのあるファイルは整形せずスキップして 1、I/O エラーは 2

10. リファレンス生成 (mie doc)

mie doc は prelude・std・言語構文の doc コメント(実装内 //| / #|)からユーザ向けリファレンス Markdown を docs/reference/ に生成する。ソース (internal/prelude 等の Go 実装、および言語構文の doc コメント) が真実源であり、docs/reference/ はそこから機械的に生成される派生物である。ライブラリ項目には、処理系の静的型表 (LSP hover と同じ出所) から型シグネチャ (mie 型表記) を合成し、形と同じコードブロックの 2 行目に束縛注釈と同じ「名前: 型」の形 (例 range: {Int, Int | Range}) で併記する。型表から確定しない項目 (型名の値束縛・each のように戻り型を静的に固定できないメソッドなど) は形と意味だけを出す。

10.1 構文

mie doc [--check]

引数を取らない (対象は常にリポジトリ全体の doc コメント)。

10.2 動作

  • mie doc — prelude・std 各モジュール・言語構文の doc コメントを収集し、ライブラリ項目に静的型表から型シグネチャを join した上で、docs/reference/{prelude.md, std/*.md, syntax.md} を生成して上書きする。
  • mie doc --check — 同じ生成処理を行い、結果が現在の docs/reference/ の内容と一致するか検査する。差分があれば非ゼロ終了 (CI で「生成物が最新か」を検査する用途)。

10.3 doctest

doc コメント中の >>> で始まる例は doctest として抽出され、go test 実行時に実際に評価してその出力が期待値と一致するか検証される。ドキュメント中の例が実装と乖離することを防ぐ。

10.4 出力と終了コード

状況code
生成 (--check 無し) 成功0
--check で差分なし0
--check で差分あり1
I/O エラー2

11. パッケージ管理 (add / get / update / remove)

third-party パッケージ (packages.md) の依存を、マニフェスト (package.mie) と lockfile (package-lock.mie) を介して管理する。取得元は git source とローカル path dep。別名解決・キャッシュ・推移依存・複数共存の意味論は packages.mdpkg: 解決の言語側は language-spec.md §13.4 を参照。

各コマンドは cwd を起点に上方探索で最も近いマニフェストを対象とする。マニフェストが無い場合は §11.5 のエラー。

add / remove はマニフェストの deps / entry を読み、正規形 (2 スペースインデント・末尾カンマなし) で書き戻す。deps 内に書いたコメントは保持されない。

11.1 mie add

mie add <host/path@tag> [--as <alias>]
  • <host/path@tag> の git source をキャッシュ (§12 MIE_CACHE) へ取得し、tag → commit を解決して lockfile に固定する。マニフェスト depsalias := "<host/path@tag>" を追記する。
  • --as <alias> 省略時、alias は path の末尾要素の -_ に正規化したもの (例 github.com/u/mie-httpmie_http)。alias は mie の識別子 (スロット名) になるためハイフンを含めず、正規化しても有効な識別子にならない場合 (先頭が数字など) は取得せずエラーで --as <alias> を要求する。短い別名にしたい場合も --as http を使う。
  • 既存の同名 alias があればその pin を更新する (version の差し替え)。
  • path dep の追加は mie add では扱わず、マニフェストを直接編集する (取得を伴わないため)。

11.2 mie get

mie get
  • 引数なし。マニフェストと lockfile を読み、未取得の依存をキャッシュへ復元する。lockfile があれば commit を信頼し tag の再解決はしない。CI・新規 clone 後の初期化に使う。
  • lockfile が無い場合はマニフェストから tag → commit を解決して取得し、lockfile を生成する。

11.3 mie update

mie update [alias]
  • マニフェストに記載された tag を再解決 (tag → 現在の commit) し、lockfile を書き換える。alias 指定でその 1 件、省略で全 git 依存。
  • バージョンを上げるのは tag の変更 (mie add <...@新tag> またはマニフェスト編集) であり、update は記載済み tag の commit 固定を最新化するもの (semver range の自動引き上げは持たない)。

11.4 mie remove

mie remove <alias>
  • マニフェスト deps から <alias> を削除し、どの依存からも参照されなくなった実体を lockfile から除く。キャッシュ実体は他プロジェクトと共有のため削除しない。

11.5 出力と終了コード

状況code
成功0
取得・解決失敗 (不正な tag / リポジトリ到達不可 / マニフェスト不正) / 対象 alias 不在1
引数不正 / マニフェスト読み取り失敗 / git 不在2

git ツールチェーンは exec.LookPath("git") で確認し、無ければ exit code 2

12. 環境変数

変数影響先意味
MIE_REPOmie build / mie lspmie 本体ソースの絶対パス。設定すれば自動検出 (build §4.7 / lsp の定義ジャンプ lsp.md「定義ジャンプ」) より優先
MIE_CACHEadd / get / update / ファイル実行・buildpkg: 解決third-party パッケージのグローバルキャッシュ。未設定時の既定は XDG の $XDG_CACHE_HOME/mie (既定 ~/.cache/mie) (packages.md)

13. 意図的に残す制約

  • go install github.com/bluegreenhq/mie/cmd/mie@latest でインストールしたバイナリから mie build を使うには現状 MIE_REPO が必要 (本体ソースの自動配置は未対応)。
  • Universal Binary (darwin/arm64 + darwin/amd64lipo 結合) は非対応 — 別ターゲットとして個別バイナリを並べるのみ。
  • バイナリサイズ最適化は -ldflags="-s -w" のみ。UPX 等の圧縮は行わない。
  • LSP は semantic tokens・go-to-definition・references・hover (型情報)・補完 (ドットメンバ)・整形 (全文フォーマット)・コードアクション (lint 自動修正)・シンボル一覧 (アウトライン)・リネーム・インレイヒント (推論型)・出現ハイライト・診断 (静的検査 Error + lint Warning、publishDiagnostics) を提供 (各機能は lsp.md)。hover は prelude 組込名・ユーザ定義識別子に加え、型メソッド (list.each 等) とユーザ定義オブジェクトのメンバも対象とする (lsp.md「hover」)。補完はドット (.) を trigger に、レシーバの slot・型メソッド・std メンバ・universal method を返す (lsp.md「補完」)。
  • mie fmt は AST 再構成方式のため、行内の任意改行位置やスロットの positional/named 混在順といった意味に影響しない見た目は正規形へ寄せる (原文どおりには保たない)。
  • mie lint のルールは unused / self-assign / control-juxtaposition の 3 つ。スコープ厳密解析は行わず、全体走査による保守的判定に留める (control-juxtaposition も構文上の callee 名のみで判定し、シャドーイングは見ない)。
  • third-party パッケージの取得元は git と ローカル path dep のみ (packages.md)。中央レジストリ・HTTPS tarball 直取得・semver range の自動解決は非対応 (exact pin + 複数共存)。mie add 等のパッケージ管理コマンドは git ツールチェーンを必要とする。