将 Swift 语言移植至 Apple II 复古计算机
速览
这项工程展示了现代编程语言在极受限硬件环境下的可行性。通过将 Swift 编译器或解释器适配到 Apple II 的架构,开发者突破了该复古平台的传统编程限制。此举不仅具有技术挑战意义,也为怀旧计算和编程语言教育提供了新视角。
AI 深度解读
将 Swift 带回 Apple II:复古计算与现代编程语言的跨界实验
背景
Swift 是支撑现代 Apple 平台众多应用程序的现代编程语言。作者产生了一个想法:能否将 Swift 的一小部分“味道”带回 Apple 的早期时代,即 Apple II 系列计算机?Apple II 是 Apple 推出的首款面向大众市场的机器系列,最初于 1977 年发布,搭载 1 MHz 的 MOS 6502 CPU。
作者构建了 SwiftII,这是一个专为原始 Apple II 至 Apple IIe 及更高版本设计的、带有 Swift 风味的微型开发环境。作者坦诚地表示,这个项目是在业余时间利用大量 AI 辅助完成的。对于作者而言,这种工作流本身与复古计算的工作一样有趣。
需要明确的是,这并非现代意义上的 Swift,也永远不会是。完整的 Swift 标准库无法容纳在这台机器上。SwiftII 是一个刻意设计的子集,其精神内核更接近 Embedded Swift(嵌入式 Swift),而非为 iOS 或 macOS 等现代平台设计的 SDK。
作者的目标是尽可能多地将 Swift 的特性塞入 Apple II,同时保持代码的可读性。如果你熟悉 Swift,你应该能够一眼读懂 SwiftII 兼容的程序并立即理解其逻辑。除了解释器,为了弥补 Apple II 在用户/开发者体验上的不足,作者还不得不构建启动器、文件选择器和文本编辑器。
核心内容
应用程序与功能
启动相应的磁盘后,用户会进入一个启动器界面。用户可以在此选择交互式 REPL(读取-求值-输出循环)、直接运行磁盘上 .swift 程序的文件浏览器,或者使用全屏幕编辑器。所有这些功能都自包含在一个可启动的软盘中。
演示视频展示了在原始 Apple II Plus 上的运行情况,包括系统启动、运行示例程序以及使用文件选择器、编辑器、REPL 和编译器。编译器位于与 REPL 不同的磁盘上。
由于原始 Apple II Plus 键盘没有小写字母且缺少 \ 键,程序输入需使用双字符(digraphs)。例如,??/ 会被转换为 \,SwiftII 会将其解释为标准的 Swift 语法。
动机与灵感
作者最近修复了一台捐赠的 Apple II Plus,并思考能让这台现代能力受限的机器做什么。几年前,作者曾为 Windows 3.1 编写过 DOS ChatGPT 客户端和 Slack 客户端,旨在将现代网络服务压缩进复古机器中。这次,作者想尝试将现代编程语言(特别是 Apple 自家的语言)移植到复古硬件上。
灵感来源于 Apple Pascal。1979 年,Apple Pascal 将 UCSD p-System 带到了 Apple II。它没有将 Pascal 编译为原生的 6502 机器码,而是编译为字节码,由类似 Java 的虚拟机(VM)执行。作者希望为 Swift 做同样的事情:编译器生成字节码,虚拟机执行它。尽管相隔近半个世纪,这两种语言都通过避免生成原生 6502 代码,转而使用虚拟机来适应 6502 处理器。
此外,作者希望提供一个 REPL 工具,以便用户以交互方式测试代码,这与现代 Swift SDK 的功能一致。
目标硬件
基准目标是经过适当硬件升级的 1977 年原始 Apple II。如果 SwiftII 能在此运行,它就能在几乎所有后续的 Apple II 机型上运行。
作者使用的测试机是 1979 年的 Apple II Plus,其规格如下:
- CPU: MOS 6502, 1 MHz
- 内存: 48 KB 主 RAM + Clone Saturn 128K RAM 卡(向后兼容为 16K Language Card),总计 64 KB
- 显示: Clone Videx Videoterm 80 列卡
- 存储: Yellowstone 通用磁盘控制器卡(可模拟原始 Disk II 模式)+ Floppy Emu 模拟 Disk II 驱动器
- 操作系统: ProDOS 2.4.3
原始 1977 年 Apple II 只要升级到 48 KB RAM 加上 16 KB 语言卡(总计 64 KB)即可支持。对于非 Autostart ROM 的机器,需手动通过 C600G 或 PR#6 启动 Disk II。
Apple IIe 是更友好的使用环境,因为它支持小写字母、更好的显示 ROM 和标准的 ASCII 键盘,使得输入 SwiftII 源代码更加自然。
语言特性与限制
SwiftII 的核心语法与现代 Swift 高度相似,但存在关键差异:
支持的语法(核心 Lite 磁盘):
let和var及类型推断if/else if/else条件语句while和for-in循环(支持范围)- 短路逻辑运算符
&&/||和前缀! - 带有
return的顶层函数 - 可选类型(Optionals):
if let、??和强制解包! - 数组:支持
append、count、isEmpty和下标访问 - 字符串:支持
+连接、\(...)插值和String(n)转换
扩展功能(Extras/Compiler 磁盘):
- Extras 磁盘:增加整数解析
Int(s)、字节/字符串辅助函数(asc,chr)、更多数组方法(removeLast,removeAll,contains)、内存读写peek/poke、光标/文本控制以及低分辨率图形(gr,color,plot,hlin,vlin)。 - Family B 编译器磁盘:进一步支持
switch、直接遍历数组的for-in、random(in:)、扬声器音调speakertone和文件 I/O。
类型与实现的差异:
- Int:由于 cc65 编译器的限制,
Int是 16 位有符号整数(范围 -32768 到 32767),而非现代 Swift 的 64 位。它是唯一的数值类型,没有Double或Float。 - String:SwiftII 中的字符串仅是字节序列(ASCII),而非 Unicode 字符集合。这更接近 C 风格的字符串数组。
- 数组:数组项必须具有相同的类型。
- 标识符:长度限制为 11 个字符以节省空间。超过此长度的名称会导致编译错误,而非静默截断。
- 缺失功能:不支持闭包、字典、错误处理(
throws)、并发(async/await)、宏以及调用站点参数标签。
主要约束:40,704 字节
这是该项目面临的最大挑战。SwiftII 必须极其精简,以适应有限的内存和存储资源。
开发设置与构建
作者使用了 AI 辅助开发。项目分为两个家族的二进制文件:
- 解释器/REPL:用于交互式编程。
- 编译器:用于将 Swift 代码编译为字节码。
由于 Apple II 的内存银行(Memory Banking)问题,开发过程充满挑战。最终,项目以 9 英寸软盘的形式发布,以解决存储和测试多个机器变体的复杂性。
关键要点
- 项目本质:SwiftII 是一个为 Apple II 系列计算机设计的 Swift 子集开发环境,包含解释器、编译器、文件管理器和编辑器,全部集成在软盘中。
- 技术架构:采用虚拟机(VM)架构,编译器生成字节码而非原生 6502 机器码,类似于 Java 或 Apple Pascal 的实现方式,以规避原生代码生成的复杂性。
- 硬件要求:基准配置为 64 KB RAM(48 KB 主存 + 16 KB 语言卡)和 ProDOS 操作系统。Apple IIe 因键盘和显示优势体验更佳。
- 语言限制: *
