Modula-2

Modula-2，是一种通用的结构化过程式编程语言，由尼克劳斯·维尔特在1978年至1985年间于苏黎世联邦理工学院开发。它具有充分的灵活性用于系统编程，和更加广阔应用领域。特别是，它被设计为以一种直接的方式支持分离编译和数据抽象。它的很多语法基于了维尔特早先的周知语言Pascal。
历史.
在1976年至1977年年间，维尔特在Xerox Palo Alto研究中心，与一群设计Alto电脑的工作伙伴一同工作。1978年，维尔特在瑞士联邦理工学院资讯研究所，根据其早期对Pascal程式语言、Modula模组程式语言、及Alto电脑的经验，定义了Modula-2语言，他还开始了一个个人电脑计划。
Modula-2语言本身与Lilith结构之设计，都以优雅及简单为原则，是以Modula-2为Lilith的系统程式语言，而不需用到组译器，并且以Lilith为Modula-2的组织架构。为此，Modula-2语言不仅要适用于编写高阶的应用程式，也要应适用于编写低阶的与机器相关的编码程式，用于装置的操控与储存体的配置。
Modula-2提供了一些标准程式库模组，如异常处置、字串处理、输入/输出及并行程式设计等，通过重复使用它们来降低语言本身的复杂度。在Lilith计划从1978年到1988年的整个生命期中，作业系统、绘图套装软体、资料库系统、网路协议、档案伺服器，及许多其他系统和应用模组，都是藉著Modula-2发展出来的。
描述.
Modula-2被设计为显著的类似于Pascal，移除了一些元素和语法歧义，增补了“模块”这个重要概念，并且对多道程序有直接的语言支持。维尔特将Modula-2看作他早期的编程语言Pascal和Modula的后继者。主要的概念是：
Modula-2提供了（有限的）单处理器并发（监视器、协程和显式控制转移）和硬件访问（绝对地址、位操纵和中断）。它使用了。Modula-2语言允许使用。和维尔特的这种编译器大致上比早前的要快上四倍。
Modula-2有两种主要方言：PIM和ISO/IEC 10514-1:1996，PIM得名于Niklaus Wirth的著作《Programming in Modula-2》，这本书一共有四个版本，成为方言的是PIM2（1983年）、PIM3（1985年）和PIM4（1988年）。
例子代码.
下面是"Hello world"程序的Modula-2源代码例子：
<syntaxhighlight lang="modula2">
MODULE Hello;
BEGIN
END Hello.
</syntaxhighlight>
语言元素.
保留字.
PIM版本2、3、4定义了40个保留字：
内建标识符.
PIM版本3、4定义了29个内建标识符：
模块.
Modula-2的模块（module），可以用来封装一组有关的子程序和数据结构，并限制它们对程序其他部份的可见性。模块设计以清晰的方式，实现了Modula-2的数据抽象特征。语言有严格的作用域控制。模块的作用域，可以被当作是不可逾越的墙：除了标准标识符之外，来自外部的对象在模块内是不可见的，除非显式的导入它；内部的模块对象在外部是不可见的，除非显式的导出它。
Modula-2程序是由模块组成，其中“程序模块”包含一个Modula-2程序的主程序。所有Modula-2程序，必须有定义了执行开始之处的一个主程序。在一个单一的程序中，不能有链接在一起的两个程序模块。“局部模块”是在其他模块内声明的模块。程序模块和局部模块的起始关键字，就是单独的。
定义模块与实现模块.
除了程序模块之外的“全局模块”，都构成自两个部份：作为接口部份的“定义模块”，它只包含“导出”（对其他模块可见）的那部份子系统，和同名的“实现模块”，它包含模块内部的工作代码：
<syntaxhighlight lang="modula2">
DEFINITION MODULE GM;
IMPLEMENTATION MODULE GM;
</syntaxhighlight>
定义模块中可以包含声明，它有如下形式：
<syntaxhighlight lang="modula2">
TYPE name;
</syntaxhighlight>
它对应的实际类型，对于这个模块的用户是不可见的。这个类型名字，可以用在定义模块内的其他声明之中。对于在定义模块中声明的任何不透明类型，在对应的实现模块中，必须包含它的完全类型声明。完全类型声明，必须定义一个指针类型。
导出.
假定局部模块codice_1导出对象codice_2、codice_3、codice_4和codice_5，可将它们的标识符列举于显式codice_6导出列表之中：
<syntaxhighlight lang="modula2">
MODULE M1;
</syntaxhighlight>
如果加上了可选的关键字codice_7，它们以一种有限制的方式给导出至外部，必须将导出的这个模块名字用作限定符，并跟随着对象的名字。这里的来自模块codice_1的对象codice_2、codice_3、codice_4和codice_5，在模块codice_1外部就叫做codice_14、codice_15、codice_16和codice_17。
PIM2在定义模块中要求显式的codice_6子句；PIM3从定义模块中删除了codice_6子句，因为发现了它是多余的。
导入.
假定模块codice_20包含下列codice_21声明：
<syntaxhighlight lang="modula2">
MODULE M2;
</syntaxhighlight>
然后这意味着模块codice_1导出至它所包围的程序的外部的对象，现在可以用在模块codice_20内部。它们以一种限定方式来引用，也就是codice_14、codice_15、codice_16和codice_17。例如：
<syntaxhighlight lang="modula2">
</syntaxhighlight>
限定导出避免了名字冲突：例如，如果另一个模块codice_28也导出了一个对象叫做codice_5，那么我们仍可以区分这两个对象，因为codice_17不同于codice_31。凭借限定导出，两个对象在它们的导出模块codice_1和codice_28中都叫做codice_5是不碍事的。
存在一种可作为替代的方式，它在Modula-2编程者中广泛采用。假定模块codice_28是公式化为如下：
<syntaxhighlight lang="modula2">
MODULE M3;
</syntaxhighlight>
然后这意味着模块codice_1导出至外部的对象，可以用在模块codice_28内部，但可以用无限定方式来引用导出的标识符，也就是codice_2、codice_3、codice_4和codice_5。例如：
<syntaxhighlight lang="modula2">
</syntaxhighlight>
这种无限定导入的方法，允许在其导出模块之外，以同在它们的导出模块之内一样简单的方式，来使用这些变量和其他对象。对于所有这些已经被显式允许的对象，包围所有模块的墙变得与它们无关了。当然无限定导入只在没有名字冲突时是可用的。
这些导出和导入规则，看起来可能是没有必要的限制和冗余的。但是它们不只是守卫对象免于不希望的访问，而且还有一个让人愉悦的副作用，提供了在程序中定义的所有标识符的自动交叉引用：如果标识符被一个模块名字所限定，那么它的定义位于那个模块。否则如果它是无限定的出现的，简单的回溯查找，将会要么遇到这个标识符的声明，要么遇到它出现在一个codice_21语句中，指出了它所来自的模块的名字。这个性质在尝试理解包含很多模块的大型程序时是非常有用的。