节省编程时间,也要节省机时
20世纪50年代,科学计算的困难不仅在计算速度。使用者还要把数学过程拆成机器指令,安排存储地址、循环和输入输出。编程与排错往往耗费大量人力,而昂贵的计算机又不能接受明显低效的执行程序。自动翻译若只让代码好写,却使计算大幅变慢,就很难获得用户信任。
约翰·巴克斯领导的国际商业机器公司(IBM)团队在纽约开展FORTRAN工作,目标机器是具备浮点运算和变址寄存器的IBM 704。1954年的初步规格提出公式翻译设想;1956年10月的参考手册让用户提前学习;1957年编译器交付,才把语言说明变成可在用户机器上反复使用的系统。
公式写在卡片上
使用者仍须先决定算法。比如要计算一个圆的面积,可以写出AREA = 3.14159 * R * R,让系统计算右侧表达式,再把结果存入AREA对应的位置。这个等号表示赋值,不是要求机器证明一个代数等式。编译器据此生成取数、乘法和存数等704指令,计算机最终执行的仍是机器代码。
数组和DO语句让成组数据的重复处理更简洁;IF语句可依据数值的正、负或零选择路径。程序员把语句写入规定栏位的穿孔卡片,并另外规定输入输出格式。语言接近公式,却保留明确限制:整数、浮点数和数组下标不能随意混用,源程序也必须遵守卡片的语句与续行布局。
参考:[2]
翻译还包括重新安排计算
FORTRAN编译器不是把每个词替换成固定指令。它先分析公式与控制语句,再安排数组循环、程序流程和寄存器,最后产生目标程序。1957年的论文用求根公式说明,重复出现的子表达式可以只算一次,平方可以用一次乘法实现。这类处理让简洁写法不必付出同等数量的重复运算。
更棘手的是704只有三个变址寄存器,而程序可能同时涉及许多数组和循环。团队先采用符号化的变址位置,再分析程序中哪些路径经常经过,把实际寄存器优先用于有益的位置,减少装入和保存开销。洛伊丝·海布特负责流程分析,谢尔登·贝斯特负责其后的变址寄存器处理;优化依靠多个阶段协作,而非一项孤立技巧。
从实验室结果到用户现场
1957年2月,团队在洛杉矶的西部联合计算机会议发表系统论文。论文报告了用少量FORTRAN语句生成大量机器指令的实例,但开发者自己的示范还不是所有用户工作的保证。巴克斯后来回忆,会议前后他们仍借用北美航空公司的704夜间调试,到4月才认为系统已足够稳定,可以向用户分发。
交付本身也是工程问题。复制成千张二进制卡片容易出错,团队转而用磁带及配套编辑、装入程序传播系统。用户遇到的源程序错误和编译器故障,需要不同处理;交付后仍持续发布修补。1957年的节点因此应理解为可用编译系统的发放,而非从此不再需要调试。
让编译器承担更多工作
首版FORTRAN主要面向数值计算,程序规模扩大后,整套重新编译和含混的诊断信息逐渐成为负担。1958年发放的FORTRAN II加入独立编译子程序等能力,帮助用户拆分工作、重复利用已有代码。它属于后续发展,不能放进1957年首版的功能清单。
弗朗西丝·艾伦的技术评述指出,早期FORTRAN在流程分析、循环处理和寄存器分配上的组织,成为后来编译器的重要基础。它证明高级表达和高效执行可以通过复杂的翻译程序结合起来。代价也清楚可见:优化本身需要时间,短程序或频繁修改时未必划算。用户与机器之间由此多出一个承担大量工程判断的软件层,语言的推广也有赖于可靠实现、手册和维护的共同支持。