HN 日本語サマリー

← 一覧へ戻る
プログラミング

Clamiga: AmigaのためのCommon Lisp

Clamiga: Common Lisp for the Amiga (nnamgreb.de)

119 pointsby emptybits21 コメント

要約

Clamigaは、クラシックAmigaOS 3、MorphOS、AROS、AmigaOS 4などのAmigaファミリー向けに構築されたCommon Lispの実装です。macOSやLinuxでも動作し、Amigaのメモリ制約を考慮した設計が特徴です。バイトコードVMとJITコンパイラにより、Amiga上でのLisp開発を可能にします。

全文翻訳

Manfred Bergmann [ブログ] | [プロジェクト] | [自己紹介] | [インプリント] Clamiga - AmigaのためのCommon Lisp 31 July 2026 Clamiga -- AmigaのためのCommon Lisp 過去数ヶ月のACE BASICに関する投稿に続き、今回はここ半年ほど取り組んできた別のプロジェクト、CL-Amiga、略してClamigaについてです。これはAmigaファミリー向けに構築されたCommon Lispの実装です -- 68k上のクラシックAmigaOS 3と、完全にネイティブなPPCビルドとしてのMorphOS、AROSとAmigaOS 4も今後登場するかもしれません -- しかし、macOS(ここで開発の大部分が行われており、私のメインのCommon Lisp実装として使用しています)やLinuxでも動作します。 名前はシンプルです:AmigaのためのCommon LispはCL-Amigaとなり、それを声に出して言うと「クラミガ」となります。そして、Amigaはスペイン語/ポルトガル語で(女性の)友達を意味する言葉(Amigaユーザーなら知っているはず)なので、この名前は二重の意味を持っています:あなたのAmigaで動くLisp、そしてあなたの友達であるLispです ;)。(プロジェクトリンクは下部にあります) Common Lispについての簡単な言葉 Common Lispは、現在もアクティブに使用されている最も古いプログラミング言語の一つです。はい、産業界や多くの他の分野で使用されています。ANSI標準は1994年のもので、それ以来変更されていません -- それでもこの言語は驚くほどモダンに感じられます(通常、ANSI準拠の古いCommon Lispプログラムはモダンなコンパイラでもコンパイルできます)。フルオブジェクトシステム(CLOS)を持ち、例外を超える条件システム、言語自体を拡張できるマクロ、そしてライブ実行中のシステムで関数をコンパイル・再定義できる、信じられないほどインタラクティブなイメージベースの開発スタイルを備えています。過去数十年の多くの「新しい」言語機能は、Common Lispにはずっと以前から存在していました。ここではそのすべてを繰り返しません。適切な入門書が必要な場合は、数年前に私が書いた primer: Common Lisp - Oldie but goldie を参照してください。Common Lispでの関数型プログラミングに関する投稿もありますので、興味があればご覧ください。 なぜ別のCommon Lisp実装なのか? SBCL、CCL、ECL、Clasp、CLISP(数十年間メンテナンスされていない)、あるいはLispWorksやAllegroのような商用実装など、優れたCommon Lisp実装はすでに存在します。しかし、それらのどれもAmiga上では動作しません。高性能な実装(SBCL、CCL)は、モダンなアーキテクチャ(x86-64、ARM、PPC)に紐づいたネイティブコードコンパイラであり、68kバックエンドがなく、メモリフットプリントは数10メガバイトで測定されます。ClaspはLLVM上に構築されています。CLISPは、精神的には最も近い存在 -- Cで書かれたコンパクトなバイトコードインタプリタ -- ですが、長年メンテナンスされておらず、AmigaOSのビルドは数十年間ありません。 Clamigaはm68k Amigaで動作するように構築されています。ポータブルC言語で自己完結型のバイトコードVMを備えており、実行時に外部ランタイム依存関係はありません -- libffi、LLVM、実行時にCコンパイラは不要です。完全なCommon Lisp実装、その言語とランタイム機能は、Amiga上でのCやアセンブラプログラムと比較してパフォーマンスレコードを破ることはないでしょう。そのため、スーパーファストスクロールなどを必要とするゲームをこれでコーディングするようには設計されていません。m68k-JITは、より多くのパフォーマンスを引き出そうとしますが、限界があります。ビット(bitvector)から比率や複素数、ビッグ整数まで、フル数値タワーなどの他の機能もすぐに利用できます。インタラクティブな開発のためのREPL、デバッガ、インスペクタを備えています。条件システム、リスタートなどを使用した回復力(上記のOldie but Goldie記事を参照)。ソケット、スレッド、ファイルシステムアクセス、AmigaOS APIにネイティブ実装されたストリームを備えているため、Common Lispコードは互換性を保ち、他のシステムへのポートが不要な場合が多いです。CLOS(Common Lisp Object System)は、私が遭遇した中で最も高度なオブジェクトシステムです。必要であれば関数型プログラミングも可能です。しかし、もう少し技術的なことを見てみましょう。 以下で言及されるいくつかの用語集 ASDF: Another System Definition Facility。Common Lispの事実上の標準ビルド機能です。Javaの世界の'make'やGradleのようなものです。依存関係グラフ、バージョン管理などを管理できます。今日メンテナンスされているほとんどのCommon Lisp 'ライブラリ'(ASDFでは'システム'と呼ばれる)はASDFでビルドされています。事実上、今日メンテナンスされているすべてのCommon Lisp実装にはASDFが付属しており、Clamigaも同様です。 FASL: FASt Load。Lispソースコードをコンパイルする際(例: (compile-file "foo.lisp"))にFASLファイルが生成されます。FASLファイルは、シリアライズされた形式にすでにコンパイルされているため、Lispソースコードファイルよりも高速にロードできます。すべてのCommon LispバリアントがFASLを実装しており、Clamigaも同様です。m68kまたはPPCで生成されたClamigaのFASLファイルは、これらの2つのアーキテクチャ間で交換可能です。 Quicklispは、1,500以上のライブラリを含むCommon Lispのライブラリマネージャーです。Clamigaには互換性シムが付属しているため、(理論的には)Quicklispで利用可能な多くのライブラリを使用できます。ただし、多くはより多くの計算能力を必要とし、m68020ではおそらく手の届かないものです。 仕組み Clamigaは、S式からバイトコードへの単一パスコンパイラであり、スタックベースのVMによって実行されます。いくつかの設計上の決定は、Amigaの制約から直接導かれています: タグ付き32ビット値。すべてのLisp値は32ビットワードです。ヒープポインタはアリーナ相対オフセットであり、オブジェクトモデル全体を32ビットクリーンかつコンパクトに保ちます(パック配列については後述)。 コンパクションGC。小さなヒープはすぐに断片化します。マークアンドスイープコレクタは、断片化が割り当てをブロックした場合にヒープをスライドコンパクションできるため、4MBまたは8MBでの長時間実行セッションがゆっくりと終了することはありません。 アーキテクチャに依存しないバイトコード。実行はバイトコードであるため、同じコンパイル済みLispは68kとPowerPCで変更なく実行されます。コンパイル済みのFASLファイルは、AmigaOS 3とMorphOS間でバイト互換性があります。ポータブルCコアの便利な副作用:まったく同じシステムがmacOSとLinuxでビルドおよび実行されます。開発、デバッグ、およびほとんどのテストは高速なホストで行われ、結果は(ほとんどの場合)Amiga上で同様に動作します。 クラシックAmiga上:4MBでの生活、まあ、それ以下でも動作します アクセラレータがより多くのRAMを提供しても、68k Amigaではメモリが制約となることが多く、それを尊重するために多くの作業が行われました。完全なCommon Lispコア -- CLOS、条件、数値タワー、format、loop -- は、約0.5MBのヒープで起動します。簡単なプログラムを書くには、clamiga --heap 1M で十分です。デフォルトはそこからスケールアップします: ユースケース | ヒープ | スタック ---|---|--- 簡単なプログラム(Quicklisp/ASDFなし) | --heap 1M | 64K (デフォルト) 小~中規模プログラム | 4M (デフォルト) | 64K (デフォルト) ASDFのロード | --heap 11M | 64K (デフォルト) Quicklisp + quickloadライブラリ | --heap 24M | stack 128000 小さなヒープを実用的にするいくつかの要因: パックバイトベクトル:(make-array n :element-type '(unsigned-byte 8)) は、4バイトのタグ付き値ではなく、要素ごとに1バイトを格納し、GCは内容をスキャンしません。8MBのマシンでは、I/Oバッファ、グラフィックスプレーンデータ、オーディオサンプルが4倍小さくなり、実質的に無料で収集できます。16ビット値用のパックバイトベクトルもあります。 バルクシーケンスI/O:byte vectorに対するread-sequenceとwrite-sequenceは、バイトごとのVMラウンドトリップではなく、OSコールごとにチャンク全体を移動します。14MHzの68020では、20KBのアセットファイルをロードするのに、数秒からファイルI/O速度になります。 プリコンパイル済みブートFASL:標準ライブラリとCLOSはプリコンパイルされて出荷されます。ローエンドの020ベースラインでは、コールドブートが約92秒から約9秒に短縮されます。 スタックがネストの深いフォームに対して小さすぎる場合、ClamigaはクリーンなCスタックがほぼ使い果たされたというエラーを通知し、スタックを上げるように指示します -- セッションを破損しません。 m68k JIT AmigaOSビルド(68020+)では、Clamigaは定義時にバイトコード関数をネイティブm68kマシンコードに変換します。VMディスパッチャは、バイトコードを解釈する代わりに、ネイティブボディに直接ジャンプします。トランスレータは、命令セットの広範なコアをカバーしています:整数演算、分岐、リスト操作、構造体スロットアクセス、関数呼び出しと自己再帰テール呼び出し、クロージャ、複数値、非ローカル終了、動的バインディング、およびAmigaOS FFI。まだ処理できないものは、透過的にインタプリタにフォールバックします -- あなたは決して気づかず、物事はただ実行されます。いくつかのA/B番号