プログラミング
Apple ][ に Swift を導入する
Bringing Swift to the Apple ][ (yeokhengmeng.com)
要約
筆者は、現代のAppleプラットフォームで使われているプログラミング言語Swiftを、Apple初の量産機であるApple IIに移植するプロジェクト「SwiftII」を開発しました。これは、完全なSwiftではなく、Apple IIの制約に合わせたサブセットであり、組み込みSwiftに近いものです。このプロジェクトは、AIの支援を大いに受けながら、SwiftII開発環境として、インタプリタ、ファイルセレクタ、テキストエディタなどをApple II上で実現しています。
全文翻訳
Swiftは、現代のAppleプラットフォーム上で動作する多くのアプリの背後にある最新のプログラミング言語です。私は、その小さな味わいをAppleの初期の時代、Apple IIに持ち帰ることができたら素晴らしいと考えました。Apple IIはApple初の量産機シリーズで、1977年に1 MHzのMOS 6502 CPUを搭載してリリースされました。私は、オリジナルのApple IIからIIe以降に対応する、Swift風味のミニ開発環境であるSwiftIIを構築しました。正直に言うと、私は余暇にAIの多大な支援を受けてこれを構築しました。そのワークフローはレトロコンピューティング作業そのものと同じくらい私にとって興味深いものだったので、どのようにAIが役立ったかについては後で率直にお話しします。一つの大きな注意点として、これは現代のSwiftではなく、今後もそうではありません。完全なSwift標準ライブラリはこのマシンには収まりません。SwiftIIは意図的にサブセットであり、iOSやmacOSのような現代のプラットフォーム向けのSDKよりも、Embedded Swiftの精神にずっと近いです。私の目標は、見た目はSwiftのように読み取れる状態を保ちながら、できるだけ多くのSwiftをApple IIに収めることでした。Swiftを知っていれば、SwiftII互換のプログラムを読んで即座に理解できるはずです。インタプリタ以外にも、ユーザーに比較的良好なユーザー/開発者体験を提供したいと考えていました。このため、Apple IIで遭遇した制限により、ランチャー、ファイルセレクタ、テキストエディタも構築する必要がありました。
目次
この記事はかなり長いので、直接ジャンプできるようにセクションをここに示します。
アプリ
動機
ターゲットハードウェア
言語
SwiftIIがサポートする機能
型がSwiftと異なる点
主な制約:40,704バイト
64Kを超えるメモリ
開発環境のセットアップ
言語の仕組み
ソーステキストからバイトコードへ
バイトコードの実際の見た目
浮動小数点なし
2つのバイナリファミリー
REPLを終了するとマシンが再起動する理由
「入力した内容」対「表示される内容」対「保存される内容」
IIおよびII+用の1977年のキーボードでSwiftをタイプする
Apple IIでのテキスト表示
マシン上でのSwift開発
ファイルブラウザ
エディタ
メモリーバンキングの問題
このプロジェクトが9枚のディスクとして出荷される理由
ファミリーA:REPL
ファミリーB:コンパイラとランナー
あまりにも多くのマシンでテスト
AIでどのように構築されたか
基本ルール
私が担当した呼び出し
ClaudeとCodexは異なる役割を果たした
自律モードがここで常にトリップした理由
AIの記憶としてのドキュメント
試してみる
結論
アプリ
適切なディスクを起動すると、ランチャーにたどり着きます。インタラクティブなREPL、ディスクから直接.swiftプログラムを実行するファイルブラウザ、そしてブート可能なフロッピー1枚にすべてが自己完結したフルスクリーンエディタを選択できます。以下は、私のオリジナルのApple II Plusでアプリが動作しているデモビデオです。システムの起動、いくつかのサンプルプログラムの実行、ファイルセレクタ、エディタ、REPL、コンパイラの利用について説明しています。コンパイラはREPLとは別のディスクにあります。オリジナルのII Plusキーボードには小文字や\キーがないため、プログラムはダイグラフで入力されます。??/は\となり、SwiftIIはこれを正規のSwiftとして解釈します。この奇妙な点については後で詳しく説明します。以下にいくつかのサンプルスクリーンショットを示します。
ブートランチャーメニュー
フルスクリーンエディタ(IIe、80桁)
ライブコードプレビュー付きファイルブラウザ
xsnake、プレイ可能なライトサイクルゲーム
gr / color / vlinを介した全16種類の低解像度カラー
xgrdemo、5シーンの低解像度カラーグラフィックスショーケース
読み続けるのが待ちきれず、コードとディスクイメージに飛び込みたい場合は、GitHubリポジトリ https://github.com/yeokm1/swiftii をご覧ください。
動機
最近、私に惜しみなく寄贈されたApple II Plusをレストアしました。それを現代のどのような能力で使えるようになるか疑問に思いました。数年前、私はWindows 3.1用のDOS ChatGPTクライアントとSlackクライアントを作成しました。これらのプロジェクトは、現代のネットワークサービスを古いマシンに詰め込むことに関するものでした。今回は、Apple自身の現代のプログラミング言語について同じことができるかどうかを知りたかったのです!このアプリのインスピレーションはApple Pascalです。1979年、Apple PascalはUCSD p-SystemをApple IIにもたらしました。Pascalをネイティブの6502マシンコードにコンパイルするのではなく、Javaがそうするように、仮想マシン上で実行されるバイトコードにコンパイルしました。私はSwiftでも同じことをしたかったのです。コンパイラはバイトコードを生成し、仮想マシン(VM)がそれを実行します。ほぼ半世紀離れて、両方の言語はVMを介してネイティブの6502コード生成を避けることで6502に到達します。また、ユーザーが対話的にコードをテストできるRead–eval–print loop(REPL)ツールも欲しかったのです。Appleの現代のSwift SDKもこのREPL機能をサポートしているので、それも追加するのは妥当だと考えました。
ターゲットハードウェア
ベースラインターゲットは、適切なハードウェアアップグレードが適用されたオリジナルの1977年製Apple IIです。SwiftIIがここで動作すれば、事実上将来のあらゆるApple IIで動作します。上記の写真の1979年製Apple II Plusは、オリジナルのApple IIに対する漸進的な改良版で、Applesoft BASIC、より多くのRAM、ディスクのオートスタートなどの機能が追加されています。それ以外は、オリジナルのApple IIとほぼ同様です。私のII Plusには以下の高レベル仕様があります。
MOS 6502 CPU 1 MHz
48 KBメインRAM
クローン Saturn 128K RAMカード(16K言語カードとして下位互換性あり)
クローン Videx Videoterm 80桁カード
Yellowstoneユニバーサルディスクコントローラカード(オリジナルのDisk IIモードをエミュレート可能)
Floppy EmuでDisk IIドライブをエミュレート
私のApple II Plusセットアップの詳細については、こちらに文書化されています: https://github.com/yeokm1/retro-configs-apple/tree/main/apple-ii-plus。
オリジナルの1977年製Apple IIは、48 KBのRAMと16 KBの言語カードにアップグレードされて合計64 KBになっていればサポートされます。オートスタートROMのないマシンでは、C600GまたはPR#6でDisk IIを手動で起動します。Apple IIeは、小文字サポート、より良いディスプレイROM、適切なASCIIキーボードを備えているため、より快適なマシンです。IIeでは、私が後で詳しく説明するApple II Plusのダイグラフと入力変換レイヤーに頼ることなく、SwiftIIのソースをはるかに自然に入力できます。私はProDOS 2.4.3を使用しました。これは、現代でもメンテナンスされているProDOS 8のリバイバルであり、十分に文書化されており、オリジナルのApple IIでも動作するためです。単一のProDOS参照イメージを使用することで、複数のDOS/ProDOSバリアントをサポートするよりもディスクのビルドとテストがはるかに簡単になりました。ProDOSには最低16Kの言語カードが必須です。6502は8ビットCPUです。そのA、X、Yレジスタはすべて8ビット幅であり、汎用16ビットレジスタはありません。浮動小数点ユニットはなく、ハードウェアの乗算または除算命令すらありません。ハードウェアスタックはわずか256バイトで、関数呼び出しの深さを制限します。メモリに関しては、64 KBは今日の基準ではマイクロコントローラに近いほど小さすぎます。
言語
SwiftIIがどのようなものか、少しご紹介します。Swiftをご存知の方なら、非常に馴染み深いと感じるでしょう。
```swift
let answer = 42
var count = 0
let maybe: Int? = 5
if let x = maybe {
print(x)
}
let n = maybe ?? 0
while count < 10 {
count += 1
}
for i in 0..<5 {
print(i)
}
func greet(name: String) -> String {
return "Hello, \(name)!"
}
var xs = [1, 2, 3]
xs.append(4)
print("\(xs.count) items")
```
SwiftIIでサポートされている機能
コア(ライトディスク)はSwiftと全く同じように読み取れます。
letとvar、型推論あり
if / else if / else、while、範囲に対するfor-in
ショートサーキット&& / || およびプレフィックス !
returnを持つトップレベル関数
if let、??、強制アンラップ! を使用したOptional
append、count、isEmpty、添字付けを持つArray
+連結、\(...)補間、String(n)を持つString
それ以外に、追加機能は起動するディスクによって異なります。追加機能(sat/aux)ディスクは、整数解析(Int(s))、バイト/文字列ヘルパー(asc, chr)、より多くの配列メソッド(removeLast, removeAll, contains)、peek/poke、カーソル/テキスト制御、低解像度グラフィックス(gr, color, plot, hlin, vlin)を追加します。ファミリーBコンパイラディスクは、switch、配列に対する直接のfor-in、random(in:)、スピーカー音、ファイルI/Oをさらに拡張します。そのため、同じソースコードでも、どのディスクでどの機能を試すかによって、あるディスクではコンパイルエラーになり、別のディスクでは問題なく実行される可能性があります。
型がSwiftと異なる点
型は従来のSwiftとは異なる動作をします。
Intはcc65の制限により16ビットの符号付きです。範囲は-32768から32767です。(従来のSwiftは64ビット