为Lilith工作站设计系统语言

Modula-2由尼克劳斯·维尔特在苏黎世联邦理工学院设计,与Lilith个人工作站的研制紧密相连。1977年访问施乐帕洛阿尔托研究中心期间,他接触到Alto工作站和Mesa语言,看到个人计算环境与明确模块接口可以怎样支持软件开发。回到瑞士后,团队决定自行建设相应的硬件和软件系统。

维尔特在后来发表的技术回顾中,把实际语言设计集中于1978至1979年。团队希望用同一种语言编写工作站所需的编译器、操作系统和应用程序,因此需要比Pascal更适合大型系统组织、又能处理设备和存储操作的工具。Modula-2继承Pascal的许多数据结构,同时沿用早期Modula的模块思想和较整齐的控制语法。

参考:[1] [2]

把接口与实现分开

1980年3月的《Modula-2》报告明确区分定义模块与实现模块。定义部分列出其他程序可以使用的名称、类型和过程接口;实现部分给出过程的完整操作,以及不必公开的内部数据。使用者通过导入声明建立依赖,模块边界使不同人员编写的部分能够按约定组合。

这种安排还服务于分别编译。编译器读取被导入模块的符号信息,在没有重新读取其全部实现代码时检查类型一致性。接口保持不变时,修改内部实现不必迫使所有使用者重新编译;接口变更则会影响依赖它的模块。模块因而同时是程序组织方式和工具链中的工作单位。

参考:[1]

磁盘空闲表的具体例子

报告第25页给出磁盘磁道预留模块:内部用位集合数组记录哪些磁道空闲,只把取得新磁道和归还磁道两个过程导出。申请时,程序寻找一个空闲位置,把相应标记清除,再返回磁道编号;找不到可用位置则返回负一。归还操作重新设置相应的空闲标记。

客户端无需直接接触空闲表的表示方式,只需遵循两个过程的接口。分配策略或内部表结构可以集中在一个地方修改,其他程序不必到处重复同一套位操作。这个例子把信息隐藏的作用落在一个具体资源管理问题上,同时表明接口必须包含失败情况的约定。

参考:[1]

在模块内处理设备与协程

系统程序还需要处理内存地址和设备。Modula-2通过SYSTEM等低层设施提供与具体机器有关的类型和操作,并把这种依赖集中在指定模块。普通算法因此可以主要使用语言的一般类型,设备相关代码则负责连接特定硬件环境。

1980年报告把这里的进程主要解释为协程:在单处理器上,每次执行一个协程,程序通过显式转移保存当前活动并恢复另一个活动。设备操作可以与处理器计算重叠,完成时再由中断促成切换。调度策略可以写成模块,而不必把一种完整的多任务操作系统方案固定在语言内部。

参考:[1]

从PDP-11编译器到日常使用

早期编译工作受PDP-11有限内存约束,因而采用多遍处理。维尔特回顾,U. Ammann设计的五遍编译器在1979年初可用,依次处理词法、语法、类型检查和代码生成。L. Geissmann与Christian Jacobi随后围绕Lilith特点发展新的编译器;Svend Erik Knudsen参与操作系统软件,语言实现与工作站相互推进。

1980年的报告保存了PDP-11工具链的具体操作:COMP编译程序,定义模块产生SYM符号文件,程序模块产生可链接代码;LINK把相关代码组合成LOD文件,再由加载器执行。工具还保留调试所需的信息,并利用版本时间标记拒绝不一致的链接组合。

1980年12月,首批20台Lilith送达苏黎世联邦理工学院,扩大了团队实际使用和改进软件的条件。编译、编辑和系统程序逐渐构成共同工作环境,应用开发中的反馈也用于检验语言接口和实现是否合适。

参考:[1] [2]

报告、教材与后续调整

1980年的语言报告定位为供程序员、实现者和手册作者共同核对的参考说明。1982年出版的《Programming in Modula-2》则面向编程学习者,以结构化方式讲授程序设计和语言使用。两类文献分别承担精确定义与教学传播的任务。

后续实现继续调整语言和工具。维尔特的回顾提到,新的编译器设计后来简化了定义模块的导出规则,使其中声明的名称自动对外提供,不再需要重复列出导出清单。这些变化发生在早期系统形成之后。Modula-2的主要贡献,是把清楚的接口、分别编译和系统编程需要结合在一套可用于实际工作站的软件方法中。

参考:[1] [2] [3]