1.1概述(Overview)
Ada 语言最初设计是为了构建长周期的、高度可靠的软件系统。它提供了一系列功能来定义相关的数据类型(type)、对象(object)和操作(operation)的程序包(package)。程序包可以被参数化,数据类型可以被扩展以支持可重用库的构建。操作既可以使用方便的顺序控制结构,通过子程序(subprogram)来实现,也可以通过包含并发线程同步控制的入口(entry)来实现。Ada 也支持单独编译(separate compilation),在物理层上支持模块性。
Ada 包含了很复杂的功能以支持实时(real-time),并发程序设计(concurrent programming)。错误可以作为异常(exception)来标示,并可以被明确地处理。Ada 也覆盖了系统编程(system programming);这需要对数据表示和系统特性访问的精确控制。最后,提供了预定义的标准程序包,包括输入输出、字符串处理、数值计算的基本函数和随机数生成。
——译自《Ada Reference Manual》Section1:General
在本章里,我们将会初步介绍一下 Ada,以给读者留下大致的印象。
1.2 Ada 的历史(The History of Ada)
为了更好的理解 Ada,它的历史有必要简要地了解一下。
1974 年时,美国国防部(DoD)意识到开发和维护嵌入式系统(固化在硬件中的系统,如导弹弹导系统)耗费了过多的时间,精力和资金。
当时,在使用的计算机语言有 450 多种,这增加了开发新系统以及培训程序员使熟悉现有系统的时间和成本。维护工作也由于没有标准化的工具(编辑器,编译器等)而受阻。所有这些因素使 DoD 意识到它需要一门强大的语言,能被所有嵌入式电脑供应商使用。
开发工作始于 1975 年,当时 DoD 列举了一系列的语言需求;但没有一门现有语言指定了这些特性,因此在 1977 年,DoD 起草了一份建议,开发一门新的语言。不像COBOL 这些语言由专门的委员会制定,新语言是一场竞争的主题,在产业界和学术界的评估中产生。
在众多竞争者当中,有 4 家被选中以完成进一步的工作。最终只剩下 Cii-Honeywell Bull 公司。这门语言被命名为 Ada。设计小组由 Jean Ichbiah 领导,对语言全权负责。
在 1983,Ada 成为了一个 ANSI 标准 ANSI/MIL-STD-1815A。此年成为一个 ISO 标准。在参考手册中定义的语言通常称为 LRM 或 ARM(Ada Reference Manual)。在 Ada 的相关书籍和编译器的报错信息中经常出现手册内容的引用。对于任何 Ada 站点,参考手册都是推荐的;虽然很难阅读,但它是所有 Ada 问题的最权威解释(一个小组正在澄清语言定义中已发现的语义不清的内容)。
Ada 也经过了一次修正,即 1995 的新的 ISO 标准。新标准修正了 Ada83 的很多缺陷,并进一步扩展了它的功能(在修正工作中,有个临时的标准,即 Ada9x,不少 Ada 文章是在 这段时间写的,因此有些内容在细节上可能与 Ada95 有所区别,但主要原理差不多)。
为了防止 Ada 编译器的不兼容版本的扩散,Ada Joint Program Office (控制 Ada 语言的执行部门,于 1998 年 10 月 1 日关闭,见 Ada Joint Program Office closed) 采取了不寻常的做法 - 他们注册 Ada 商标。除非通过他们的兼容性测试,编译器厂商不允许出售 ‘Ada’ 编译器。这在不久以后放松了,保护协议变成了 `Validated Ada’。因而产生的 Ada 确认证书被限制在一定的时间内并有一个期满时间。当时间过期后,该编译器不能再被标记为`Validated Ada’ 编译器。通过这种方式,AJPO 确保当前市场上的编译器与当前标准相一致。
目标是使所有的 Ada 程序能在所有系统上被编译-在这点上,AJPO 比其它语言小组做得好。
1.3 与 C 和 C++ 的比较(Contrast:Ada and C,C++)
由于 Ada 出生年月迟了一点,而且目前的操作系统基本上由 C,C++ 写成,导致 Ada 在“平民层”的推广比较糟糕,至今还不是很流行,Why Ada isn’t Popular 一文对此有比较详细的解释。而 Ada 爱好者们为了显示 Ada 的优越性(这种心情相当能理解),将 Ada 与 C,C++ 做了一系列比较,其结果反正综和指数都是 Ada 高,这方面文章有不少,如 Comparing Development Costs of C and Ada,Contrasts: Ada 95 & C++。在这里,我们只初略地了解一下 Ada 的优势即可,在读者朋友接下去的学习中,应该是能从心里感受到 Ada 的优点。
- 更高的安全性、可靠性。Ada 中对于访问内存、数值计算等很多方面有一些严格的规定,而没有 C 和 C++ 那么自由;程序的错误绝大部份能在编译和运行时检测到,以至于可以不需要编译器,另外,语言也包含异常特性,能方便地处理错误。
- 更高的移植性。在 Unix 和 Windows 下有 C 编程经验的朋友应该对于兼容性深有体会,很多代码纯粹是为了适应不同的系统增添的,对于实际工作没多大用处。但 Ada 的初始语言环境中就有了异常(约等于 Unix 下的 Signal)、任务(线程)、分布式计算、随机数产生、宽字符集很多特性的支持,而在现在的具体操作系统中,这些特性往往随系统而异。即使 Ada95 里缺少一些功能,也可以通过额外标准和函数库来弥补:GDI 库,可以用 GtkAda,在 Windows 和 X 下通用;Ada 也有一个 Posix 接口的标准,可以使用函数库 Florist 来调用 Posix 的函数…… 用户层是大大省力—只要自己的操作系统上有所需的编译器和函数库即可。
- 语法明确,基本上没有令人混淆的地方。Ada 程序的源代码远远比 C 或 C++ 的代码易懂。看程序的人是减轻了不少脑负担。
- ……
……
总之,C 和 C++ 能做的 Ada 肯定能做,但 Ada 要省时方便的多。读者在学习 Ada之后,无需多说也就明白了,笔者在初学 Ada 时就有耳目一新的感觉,唯一的遗憾是 Ada 不流行。
1.4 网络资源(Internet Resources)
Ada 虽然在国内不流行,但在国外还是有不少网站,下面是只列举一小部份,至于更多的资源,读者可至 VenusIC 查找:
- Home of the Brave Ada Programmers (HBAP),即 Ada Home,由 Magnus Kempe 维护,里面包含了不少 Ada 相关的文档、软件
- Public Ada Library (PAL)。PAL 是 Ada 软件、文档的图书馆。主站点在 wuarchive.wustl.edu (WUARCHIVE), 以及法国的一个映像站点mirror site,PAL 目前由 Richard Conn 维护。
- AdaIC,由 AJPO 发起的一个站点,也包含了不少相关信息 。
- SIGAda ,是 ACM 的一个 Special Interest Group。
- AdaPower,很不错的一个站点,有相关教材、文档、Faq、Linux 等链接。
- Ada Core Technology,Gnat,Glade 等软件的老家。
- 新闻组 comp.lang.ada ,不用多介绍了
1.5 第一个程序(The First Program)
为了了解 Ada 程序的大致结构,举一个例子是难免的。大部份书籍一般都是用"hello world"程序来开始,我们下面就见识一个在终端屏幕上输出 "Hello World!"的简例。
000 -- filename:hello.adb;
001 with Ada.Text_IO;
002 procedure Hello is
003 begin
004 Ada.Text_IO.Put ("Hello World!");
005 Ada.Text_IO.New_Line;
006 end Hello;
先介绍一下在本教材中代码的一些问题:每行代码前的 000,001 等数字表示该代码是第几行,只为了讲解方便,在实际源代码中是不存在的;with,procedure 等保留字(reserved word)都用粗体表示,以示区别;有些字是用斜体表示,表示该字是用其它有效字符替换。
现在让我们分析上述的简单程序:
- [000]标示该程序文件名为 hello.adb,在程序中并不需要;-- 是注释符,表示从其所在位置至行尾都是注释,对程序没有什么影响,与 C 的 /* */类似。
- [001] Ada.Text_IO 是预定义的一个程序包(package);with package_name和 C 的 include 功能差不多。
- [002]-[006]是程序的主体部份。与 C 下的 main 函数类似,Ada 也需要一个主过程(main procedure),在这个例子中是过程 Hello。过程的用法和上例一样,都是
procedure procedure_name is
statements1;
begin
statements2;
end procedure_name;
statement1 可以是变量、常量、函数、过程等的声明;statements2 是过程 procedure_name 要执行的语句,对象的声明不能在这部份;end 后的 procedure_name 不是必需的,但为了程序的可读性,应加上。
-
[003],[004] 分别输出"Hello World!" 和新行符。Put 和 New_Line 都是 Ada.Text_IO 里的过程。
但上7例调用过程 Put 和 New_Line 的方法比较罗嗦,因此我们也可以使用 use 语句:
000 -- filename:hello.adb;
001 with Ada.Text_IO; use Ada.Text_IO;
002 procedure Hello is
003 begin
004 Put ("Hello World!");
005 New_Line;
006 end Hello;
这样 Ada 编译器就能在程序包 Ada.Text_IO 中自动搜寻 Put,New_Line,而无需用户指定它们所在的准确位置。
我们在将上例略微改动以下,以使读者了解一下声明部份:
000 -- filename:hello.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 procedure Hello is
003 Str:String := "Hello World!";
004 begin
005 Put(Str);
006 New_Line;
007 end Hello;
在 is 和 begin 之间,声明了一个字符串变量 Str,它的初始值为"Hello World"。String 是预定义的字符串类型。上述的声明方式和 Pascal 差不多。
现在我们对 Ada 程序长的什么样已有了基本的认识,下面需要了解几个术语。一个 Ada 程序是由一个或多个程序单元组成(program unit)。一个程序单元可以为:
- List item
- 子程序(subprogram),定义一些可执行运算。过程(procedure)和函数(function)都是子程序。
- 程序包(package),定义一些实体(entity)。程序包是 Ada 中的主要分组机制,类似于 C 的函数库,Modula 的"module"。
- 任务单元(task unit),与线程类似,定义一些计算,然后并发执行。
- 保护单元(protected unit),在并发计算中协调数据共享,这在 Ada 83 中不存在。
- 类属单元(generic unit),帮助构建可重用组建,和 C++ 的模板类似。
后3类属于高级话题,在后面的章节中我们会依次介绍。程序单元又可为两部份:
- 声明部份(declaration)。定义对其它程序的接口,有些可用资源可以被用户使用,与 C 下的’.h’文件相似。
- 主体部份(body)。是声明部份的具体实现,等价与 C 的’.c’文件。
其中程序包(package)和子程序(subprogram)是用的最广泛的2个程序单元。大部份 Ada 程序基于一堆程序包,在以一个主过程(main proceudre) 来开始 Ada 程序 。