高级程序设计语言原理
梅 宏
课程目的,
1.了解高级程序设计语言发展历史及现状
2.了解高级程序设计语言的基本概念和原理
3.了解高级程序设计语言实现技术及原理
4.了解若干主要的高级程序设计语言
授课方式,
课堂讲授和研究分析论文相结合
教材与参考书,
1,Terrence W,Pratt & Marvin V,Zelkowitz,Programming
Languages,Design and Implementation,3rd Edition,
Prentice Hall,Englewood Cliffs,New Jersey,1996
2,招兆铿,朱洪,程序设计语言原理,上海科技文献出
版社,1998
3,徐家福,吕建,软件语言及其实现,科学出版社,
2000
考核方法,
研究分析报告占 30%,期末考试占 70%
第一章
程序设计语言研究
什么是语言,
语言是信息交流工具。有如下几种定义,
1,Webster字典定义
An artificially constructed primarily formal system of signs
and symbols (as symbolic logic) including rules for the
formation of admissible expressions and for their
transformation
基于一组记号与符号由人工构造的(基本上是)形式化
的系统(如符号逻辑),包括合法表达式的形成规则和
转换规则。
2,Longman字典定义
Any system of signs,movements,etc.,used to express
meanings or feelings
任何表情达意的记号系统。
3、英汉双解计算机辞典定义(清华大学出版社)
A set of characters,conventions and rules,that is used for
conveying information,The three aspects of language are
pragmatics,semantics and syntax
一种用于传递信息之字符、约定和规则的集合。语言的
三个方面是语用、语义和语法。
4、中国大百科全书,电子学与计算机卷
语言的基础是一组记号和一组规则,根据规则由记号构
成之记号串的总体就是语言。
5、徐家福:软件语言及其实现
语言是基于一组记号与一组规则、根据规则由记号构成
之记号串的总体。任何语言均包括语法、语义和语用三
个方面。
?语言的作用
描述作用、交流作用和标志作用(软件语言可作为计算
技术发展的里程碑标志)
?语言是人类生活的必要工具,不同的语言被使用于不同的领
域和方面
?在计算领域,也存在不同层次的语言,本书所论及的是实现
层次的语言,即程序设计语言。
?程序设计语言 =字符集 +规则集(用于组合字符)
?任何用于描述算法和数据结构的一套符号系统均可称为程序
设计语言
本课程研究的对象,
主要考虑那些在计算机上实现的程序设计语言
术语所界定的范围,
术语“程序设计语言”并没有一个公认的范围定义
通常这个术语是指高级语言
计算机上语言的层次,
纯二进制
机器码或符号机器码
符号汇编语言
宏汇编语言
高级语言
甚高级语言
Byte或 word,指令、数据不分
用一些符号来代表指令,如 sub代表减,
Add代表加等,机器地址用十进制。有
时汇编语言等同于符号机器码。
变量名用符号,地址也可用符号而非数字。
编制的程序称为汇编程序。
用户可以定义新指令及子程序
源程序编译为目标程序,或解释执行
高级程序语言的高层规约语言,提供比高级
程序语言更高级的语言设施。又称为“可执行
的规约语言”。有时也不区别于高级语言。
程序设计语言的四个基本特征,
1、用户不需要具有机器代码的知识,只需学习特定的程序
设计语言,并独立于任何特定的机器代码而使用。这并不
意味着用户可以完全忽略实际的计算机,如:需知道浮点
数的表示或使用某些机器资源。
2、程序设计语言必须有较大程度的机器独立性(完全的机
器独立性)。这意味着必须有较大潜力,使得源程序可运
行在具有不同机器代码的两台计算机上,不需要完全重写。
3、当源程序翻译成机器代码时,通常对每个执行单元有多
个机器指令,如,A=A+B需多个机器指令来实现
4、程序设计语言的记号比机器语言更接近于被求解的问题。
如,A=A+B比其机器翻译更易于理解。
1.1 为什么研究程序设计语言
两个基本观察,
1、已有数百种语言被设计和实现。在 1969年,Sammet就
列出了当时 120种相当广泛使用的语言,在此以后,又有
很多语言被开发。在早期,为一个项目的进行而开发一
种语言是常有的事。
2、大多数程序员通常不会同时使用多种语言,一般限制
到 1~2种。事实上,都是直接使用计算机上已有的语言如
C,Ada,Fortran等。
既然如此,为什么要去研究各种不同的语言,
有的语言甚至永远不可能再被使用?
学习、研究程序设计语言的理由
不仅仅是停留于肤浅的对语言特性的了解和考虑
深入了解根本性的语言设计概念及它们对语言实现的影响
1、提高开发有效算法的能力
?很多语言提供的特性如果被合适地使用,会给程序员带来
益处,但如被不合适地使用,将可能导致大量计算机时间
浪费或使程序员出现耗时的逻辑错误。
?有可能一个长期使用某一语言的程序员也并不理解该语言
的所有特性。
?如递归特性:是一个非常便利的程序设计语言特性
如正确、合适使用,可得到优美和高效算法的直接实现。
如不正确使用, 将可能导致执行时间的天文数字增长 。
如果程序员不知道递归蕴含的设计问题和实现困难,将
难于使用这种结构;对递归原理和实现技术的了解可使
程序员了解在特定语言中的递归的相对代价并通过其理
解确定其使用是否合适。
?新的程序设计方法不断在文献中引入,如 OO程序设计,逻
辑程序设计和并发程序设计的使用均需要对实现这些概念
的语言的详细了解和掌握。
2、改善对现行程序设计语言的使用
?通过对语言特性的实现细节的了解,可大大增加书写高效的
程序的能力。
如,
对数据结构,诸如数组、串、表、记录等,如何被创建
和操作的了解
对递归的实现细节 的了解
以及对对象类如何被创建的了解
将对书写高效程序有很大帮助
3、增加可使用的有用的程序设计结构的词汇量
?语言对思维既有帮助,也有限制
人们使用语言去表达思想,但语言也控制人如何思维,
用字句中没有直接表达的方式来思维是十分困难的。
?在解决一个问题时,要寻找合适的数据和程序结构,通常人
们首先考虑他熟悉的语言中可直接表达的结构。
?研究各种语言提供的结构和这些结构被实现的方式,程序员
可增加其编程词汇。
?对实现技术的了解非常重要。如要使用一个结构,该结构在
语言中没有直接提供,程序员必须提供自己的实现(使用语
言提供的基本结构)。
如子程序控制结构、协同例程( coroutine)在很多程序中
有用,但很少有语言直接提供协同例程特性。
C或 Fortran程序员可以设计程序来使用协同例程结构,然
后将它们实现为 C或 Fortran程序(如果熟悉相关概念及实
现)从而可以提供大型程序的正确控制结构。
4、允许更好地选择语言
?对程序设计语言知识的掌握可以允许程序员针对特定的项
目,恰当地选取合适的语言,从而减少编码工作量。如,C、
Fortran,Ada可用于数值运算,Lisp,ML,Prolog可用于人
工智能应用。对每种语言的特性的长处和弱点的了解和掌
握有利于程序员做出广泛而正确的选择。
5、更易于学习新语言
?对自然语言语法结构的学习和了解可使对新语言的学习更
容易
?对程序设计语言各种结构和实现技术的了解,也可使程序
员能够在需要时更容易地学习新语言
6、更易于设计新语言
?很少有程序员把自己考虑为语言设计者,然而,任何程序都
有一个用户界面,这事实上也是某种形式的程序设计语言,
用户界面包括提供给用户用于和程序通讯的命令和数据格式。
?大型程序,如文本编辑器、操作系统、图形包的用户界面的
设计者,必须考虑很多存在于通用程序设计语言设计中的相
同问题。
?如果程序员熟悉一般程序设计语言中的结构和实现方法,则
程序设计将可以大为简化。
总之,程序设计语言的研究十分重要,包括语言特性和实现技
术(特别是不同结构的运行时表示技术)等主要研究内容。
程序设计语言的优点
?比机器或汇编语言更易于学习。
这涉及很多方面的问题,如一个极端强大的程序设计语
言可能比一个只有十几条指令的机器的汇编语言更难学。
但给定基本相同的复杂度,程序设计语言更易学(记号
更接近问题域;更少关心物理硬件)
?程序设计语言书写的程序更易于调试 debug(程序更为短小;
记号本身更自然,因此更多注意力可放在程序逻辑而非语法
细节上)。
?程序更易于理解
?程序设计语言的记号自然起到了文档的作用
?上述原因导致解决问题的时间和代价减少。
程序设计语言的缺点
?编译过程需要机器时间,
它可能超过易于调试所节省的时间
?编译器可能产生低效的代码
?如果用户不知道机器代码或编译器未提供合适的调试工具,
则程序调试可能非常困难。
程序设计语言的分类
这是一个非常困难的问题,并没有公认的定义。这里给出一
些术语,有些是相互交迭的,一个语言可能归属于两个类别。
?面向过程的语言( procedure-oriented)
用户刻划一个可执行操作集合,它将以某种顺序完成,
从而刻划了一个过程。关键因素是这些明确可执行的操
作,执行顺序由用户确定。
?非过程型语言( nonprocedural)
这只是一个相对的术语,没有人定义过,也不可能定义。
意指用户指定的顺序步骤的减少程度,越接近于用户只
陈述问题而不指定求解步骤,语言就越是非过程的。
更进一步,可以有一个有序的步骤序列,其中每一步是
某种程度上非过程性的,或是一个可执行操作的集合,
其顺序用户并没有指定。两种情形均导致更多的非过程
性。
在 Fortran出现前,
语句 Y=A+B*C- D/E被认为是非过程性的 。
因为它不能写成一个可执行单元和被任何系统翻译 。
随着编译系统的发展, 过去非过程的今天变成过程的,
而今天非过程的, 明天可能是过程的 。
当今非过程系统的例子如,
RPG( 报告生成器 ) 或排序生成器,
只需给定输入和希望的输出即可,过程将被自动完成。
?说明型语言( Declarative Language) —— 完全非过程的
程序只定义做什么,不需指定如何做,如函数式(归
约)、逻辑式(归结、合一)语言及其它甚高级语言。
?面向问题的语言( problem-oriented)
该术语有不同解释和用法,最常见用法是强调一个语言
易于对特定问题求解(相对汇编语言),很多人将其用
于针对非常特殊的应用领域。
?面向应用的语言( Application-oriented)
这是极易误解的, 但广为使用的术语 。 实际上, 所有语
言均是面向应用的, 只是领域大小不同罢了 。
如,Fortran适合数值科学计算, Cobol适合商业数据处理
PL/1则二者均适合, 领域更广, 又称通用 ( general
purpose) 语言, 实际上很少有真正通用的语言
一般考虑:数值科学应用, 非数值应用 ( 如形式代数 ),
商业数值处理, 串, 表处理等
更特殊的领域:网形, 仿真, 数控, 设备检查等
?专用语言( special purpose)
用于满足单一的目标(指定领域;对特殊应用易用;提高
效率等)
?问题定义或规约语言( problem-defining,specification)
文字地定义问题,或特别定义输入、输出,但不定义变换
方法
?问题求解语言( problem-solving)
可以完整地刻划一个问题的求解,这也是一个相对的术语
?标注语言( reference)
是一个确定的字符集, 具有语言的格式 。 通常用唯一字
符表示某概念或语言中的字符, 不一定要适合计算机输
入 。 通常包含英文单词 ( 作为多单个字符 ), 也可能提
供固定符号集 。 不需要易读 。
?出版语言 ( publication)
标注语言的变种, 如 A↑2变成 A2。
?硬件语言 ( hardware)
又称 hardware representation,是标注语言直接映射到合适
的格式以利于计算机直接输入 。
硬件语言本身和标注语言必须有很好映射, 如 **作为 ↑的
硬件表示, begin用 ‘ BEGIN’表示等
1.2 程序设计语言简史
程序设计的历史很复杂,至今已很难于拟出一条全面清晰的发
展轨迹。已有各种不同的总结方式。 1978年,ACM Special
Interest Group on Programming Language (SIGPLAN)召开了一个
会议,HOPL( History of Programming Language),专门研讨
语言发展历史。
程序语言的早期发展
?语言发展可追溯到 1945年,德国的 Konrad Zuse设计了
,Plankalkul”,未实现。
?1954年,Laning和 Zierler开发了一个用于数学计算的高级
语言,运行于 M.I.T的 Whirlwind上,这大概是第一个运行
的编译器。它可以书写数学表达式(具有上、下标)、赋
值、分叉、输入 /输出、子程序,并处理微分方程。
?第一个广泛使用的高级语言是 Fortran。
IBM的 John Backus领头在 50年代中期完成,初衷是解决科
学及工程计算,但后也用于更多领域,甚至写编译器。该
语言证明了高级语言的可行性,奠定了后来语言研究的基
础。
?1958年,ACM和欧洲的 GAMM联合开发用于算法处理的语
言 IAL( International Algebraic Language),最终修改变成了
Algol60(早点的版本是 Algol58),Algol58和 Algol60导致了
很多相关的程序设计语言研究和编译技术开发的发展。在实
践方面 Fortran有很大影响,但 Algol带动了语言的理论研究热
潮。
?50年代中期,Remington Rand Univac的 Grace Hopper及其同
事设计了 Flow-Matic,该语言面向商业数据处理,这是第一
个面向英语的语言,并成为 Cobol的主要源泉。
?1959年,在 DoD赞助下,组织了一批计算机制造商和用户开
发了 Cobol( Common Business Oriented Language),该语言
在商业数据处理领域的影响甚至大于 Fortran在科学计算领域
的影响。
?1958,1959可能是语言历史上生产率最大的两年。
M.I.T的 Victor Yngve开发了 Comit,这是串处理语言,用
于翻译自然语言。 M.I.T的 John McCarthy和其学生开发了
人工智能语言 Lisp。 Lisp至今仍在使用,Comit后来变成
了 Snobol( Bell电话实验室于 60年代中期开发)
?科学计算和数据处理是计算机早期的主要应用,语言也是如
此,向跨两个领域的通用性发展。
?1959-1960,System Development Corporation和 Jules Schwartz
在 Algol58基础上开发了 Jovial,这是第一次通用性尝试。
?1963-1964,IBM和 SHARE的一个联系计划开发了第一个通
用语言(跨两个领域) PL/I。
?Algol68是随后的一个大的语言计划,这是一个全新的开发,
而不仅仅是升版,其主要特性是正交性,它定义了少量的基
本特征和组合它们的系统规则,允许程序员定义新的数据类
型及操作。
?下一个大的语言计划是,1975年开始的 DOD项目,目标是
开发适合于嵌入式计算机系统的语言,此即 Ada。 1979年开
始发布,1980年定稿,成为后期开发、实现和标准化的基础,
Ada不仅仅是适合嵌入系统,可有更广用途。
?随着交互计算系统的出版,适合交互环境的语言开始出现。
1963年,Rand Corporation的 J,Cliff Shaw开发了 Joss.。
1964年,Dartmouth College的 John Kemeny和 Thomas
Kurtz开发了广为流传的 Basic。
?针对非数值数学计算(如形式代数操作)的需要。
IBM的 Jean Sammet于 1962-1964开发了 Formac。
MIT的 Joel Moses于 1970年代早期开发了 Macsyma。
?专用领域语言开发。
1956年,MIT的 Douglas Ross为机床控制开发了 APT。
其他有,civil engineeriy,Cogo
computer-assisted instruction,Coursewriter
equipment checkout,Atlas。
?1967~1977,在美国,在给定年度内使用的语言数大概是
170种,同时,每年或每两年有 25— 30的增减。
?1978年 HOPL会议,讨论的语言满足如下标准,
a.1967年时已出版并被使用。
b.1977年仍在使用。
c.在计算领域有很大影响。
选出的语言有,
Algol,Apl,APT,Basic,Cobol,Fortran,GPSS,Joss,
Jovial,Lisp,PL/I,Simula,Snobol。
80年代的两个重要语言 PASCAL( Niklaus Wirth,1968)
和 Ada未列入。 PASCAL在 70年代后期成为非常重要的
语言,特别是在计算机教学方面。
E.Sammet在,Programming Language,History and Future”,
Communications of the ACM中列出了若干代表性语言,
?APT( Automatically Programmed Tools)
1956,第一个专用领域语言。
?Fortran( FORmula TRANslation)
1956,第一个广泛使用的高级语言,为大量的科学和工
程人员打开了使用计算机的大门。
?Flow-Matic
1956,第一个商业数据处理语言,第一次强调“类英文”
的语法。
?IPL-V(Information Processing Language V)
1958,第一个表处理语言。
?Comit
1957,第一个实用的串处理和模式匹配语言。
?Cobol( Common Business-Oriented Language)
1960,最广泛使用的数据处理语言。具有类英文的语法
和机器独立性。
?Algol60( ALGOrithmic Language)
1960,用于刻划算法。形式化语法定义,带动了语言的
理论和实现技术研究。
?Lisp( LISt Processing)
1960,引入了函数程序设计概念,基于表处理。
?Jovial( Jules Own Version of IAL)
1960,第一次包含了科学计算,I/O信息的逻辑操作、数
据存贮和处理等能力。大多数 Jovial编译器用 Jovial书写。
?GPSS( General-Purpose System Simulator)
1961,第一个仿真语言。
?Joss( JOHNNIAC Open-Shop System)
1964,第一个交互式语言。
?Formac( FORmula Manipulation Compiler)
1964,第一个广泛使用的形式代数操作语言。
?APL/360( A Programming Language)
1967,引入了许多高级操作子,允许很短的算法,产生
了看问题的新方式。
?Pascal
1971,在一个小语言中引入了如赋类型的新概念,并以
优美方式组合了各种著名结构。
程序设计语言的角色
早期,计算机非常昂贵,而程序员年薪不高,关键资源是
计算机。因此,语言设计是为了更高效地执行程序,高级
语言需和汇编语言竞争。
Fortran的主要设计者 Backus在 Fortran面世十年后曾说,
坦率地讲,我们当时未曾有过任何最模糊的关于 FORTRAN
及其编译器将如何工作的想法。我们只是简单地努力优化
目标程序,运行时间,因为当时大多数人不相信你可以真
正完成这样的事。他们认为机器编码的程序将是极端低效
的,对很多应用都是不实用的。
我们未曾想到的一个结果是:有这样一个系统,它被设计
为完全独立于程序将最终运行于其上的机器。这后来证明
是非常有价值的能力,但当时我们肯定未曾想到。
我们的活动没有任何组织。程序的每个部分由一到二人完
成,除了极少数例外,他们完全负责他们所做的事情。事
情无序地发展,当 FORTRAN发布时,我们面临这样一个事
实,25000条指令将并不是全正确的,存在着大量将在大量
使用后才会显示出来的问题。
?60年代中期,程序设计发生了变化,机器价格下降,程序
设计价格上升。程序移植的需求越来越多,软件的维护占用
了大量的计算资源。此时的目标不再是编译程序后使其高效
地运行,高级语言的任务变成使其易于开发正确的程序以解
决某给定应用领域中的问题。
?编译技术成熟于 60,70年代,语言技术以解决特定领域问
题为中心,如,Fortran用于科学计算,COBOL用于商业应
用,JOVIAL用于军事应用,LISP用于人工智能应用,以及
Ada用于嵌入式军事应用等。
?程序设计语言也会进化和消亡,如,Algol已不再使用,
Cobol使用正在下降,Pascal的很多结构仍在 Ada中存在,但
其黄金时代已过去。
?仍在使用的旧语言也经历了不断的修订以反应来自其他计
算领域的影响,Fortran和 Cobol已有多个标准化标本。 Ada有
1995年新标准。 Lisp修订后有 Scheme和 Common Lisp。 C++
和 ML则反应了人们在设计和使用语言中获得的经验的混合。
?对语言的主要影响源自如下几个方面,
1、计算机能力
计算机经历了数代的巨大变化,操作系统成为语言基于的平
台(不再仅依靠硬件)。这些因素影响了高级语言的结构和
使用语言特性的代价。
2、应用
应用领域有了很大变化,计算机应用已渗透到几乎所有领域,
新应用的需求影响了新语言的设计和旧语言的修订。特别是
近几年,INTERNET的发展进一步拓广的应用范围。
3、程序设计方法
人们对书写大型复杂系统的方法的深入研究和程序设计环境
的变化也影响语言的发展。
4、实现方法
更好的实现方法影响到新语言中特性的选择。
5、理论研究
使用形式化的数学方法,对语言设计和实现的概念基础的研
究加深了我们对语言特性的优势和弱点的理解,从而影响语
言中特性的选取,如“继承”,因语义复杂,而被有的语言
放弃。
6、标准化
标准化语言需要易于在不同计算机上实现,使程序易于移植,
这对语言的设计影响是保守的,即轻易不引入新特性。
一些重要的语言和技术影响,
1951- 55,
硬件:电子管计算机,水银延迟线内存
方法:汇编语言,基础概念:子程序,数据结构
语言:表达式编译器的实验性使用
1956- 60,
硬件:磁带存储器,磁芯内存,晶体管电路
方法:早期编译技术,BNF文法,代码优化,解释器,
动态存储方法和表处理
语言,FORTRAN,ALGOL 58,ALGOL 60,COBOL,
LISP
1961- 65
硬件:可兼容的体系结构家族,磁盘存储器
方法:多道程序设计操作系统,语法制导的编译器
语言,COBOL 61,ALGOL 60(修订),SNOBOL,
JOVIAL,APL符号体系
1966- 1970
硬件:增加尺寸和速度并降低成本,小型计算机,微程
序设计,集成电路
方法:分时和交互式系统,优化编译器,翻译器书写系

语言,APL,FORTRAN 66,COBOL 65,ALGOL 68,
SNOBOL 4,BASIC,PL/1,SIMULA 67,ALGOL- W
1971- 75
硬件:微型计算机,小型计算机时代,小型大规模存储
系统,磁性内存的衰落和半导体内存的兴起
方法:程序验证,结构化程序设计,软件工程作为一门
学科的早期发展
语言,PASCAL,COBOL 74,PL/1(标准),C,
Scheme,Prolog
1976-80
硬件:商用质量的微机,大型大规模存储系统,分布式
计算
方法:数据抽象,形式化语义,并发、嵌入式、和实时
程序设计技术
语言,Smalltalk,Ada,FORTRAN 77,ML
1981- 85
硬件:个人计算机,第一代工作站,视频游戏,局域网,
Arpanet
方法:面向对象程序设计,交互式环境,语法制导编辑器
语言,Turbo Pascal,Smalltalk 80,Prolog的发展,Ada 83,
Postscript
1986- 90
硬件:微机时代,工程工作站的上升,RISC体系结构,
全域网,Internet
方法:客户 /服务器计算
语言,FORTRAN 90,C++,SML(标准 ML)
1991- 95
硬件:非常快的廉价工作站和微机,大规模并行体系结
构,语音,视频,传真,多媒体
方法:开放系统,环境框架,国家信息基础设施(信息
高速公路)
语言,Ada 95,过程语言( TCL,PERL)
1996- 2000
硬件:二代 Internet,机群,网络计算机( NC)
方法:软件构件技术,Agent,中间件,浏览器 /服务器计
算,Internet计算
语言,JAVA,XML,IDL(后两种一个意义上不能算为
程序设计语言)
1.3 程序设计语言的评价
好语言的属性
1、清晰、简单、一致(协调)
程序设计语言既是思考算法的概念框架,又是表达算法
的工具。语言对程序的帮助不仅在编码阶段,还会在此
阶段前较长一段时间,均有帮助。语言应该是提供清晰、
简单、一致的概念,用作算法开发的基本原语。因此,
希望有最少数量的不同概念及其尽可能简单和规则的组
合规则,称为概念完整性。
语言的语法对程序的书写、测试、理解和修改有较大影
响,因此,可读性是一个中心问题。特别精简或隐义的
语言使程序易于书写(对有经验的程序员),但难于读
(当要修改时),如 APL,甚至程序员本人过一段间后
也难读懂。有的语言几乎相同的语句实际上代表了完全
不同的事。因此,一条基本原则是,语义不同应在语法
中完全反映出来。
2、正交性
意味着可以以所有可能的方式来组合语言特性以得到有
意义的组合结果,如条件语句和任意表达式的组合。
正交性使语言易学,程序易写,因为不需记住太多的例
外和特殊情况,缺点是:逻辑上不协调或极端低效的组
合可能会被编译器忽略。
正交性在语言设计中是一个有争议的属性。
3、应用自然性
语言的语法应使得正确的使用可以允许程序结构反映出
算法的逻辑结构。理想地:直接将程序的设计翻译为合
适的反映算法结构的程序语句。顺序算法、并发算法、
逻辑算法等各有不同的自然结构。
语言应提供合适的数据结构、操作、控制结构和面向问
题的自然语法。语言流行的主要原因之一便是对自然性
的需要。
特别适合某类应用的语言将大大简化该领域程序的创建,
如 Prolog适合于推导,C++适合于 OO设计。
4、对抽象的支持
即使对最自然的语言,在刻划问题求解的抽象数据结构
和操作与语言固有的特别的基本数据结构和操作间总是
存在着差距。
如 C可能是一个合适的用于构造大学课程调度应用的语言,
但抽象的数据结构如“学生”、“课程”、“授课老
师”、“教室”等以及抽象操作“分配某学生到某课
程”,“安排某课在某教室”等并不在 C语言中提供,而
它们对应用本身是非常自然的。
程序员的任务之一便是为问题求解设计合适的抽象,然
后用实际语言提供的更基本的特性来实现这些抽象。
理想地:语言应允许数据结构、数据类型和操作作为自
包含的抽象而定义,程序员可以将它们用在程序的其他
部分(只需了解其抽象性质,而无需知道实现细节)。
5、程序易于验证
程序的可靠性总是一个中心的问题,有很多技术验证一
个程序是否正确地完成所需功能。
程序可以用形式化方法证明是正确的,
也可以用桌面检查方式非形式地证明正确性(读程序
文本)
也可以用测试的方法,用测试数据输入,检查输出结
果是否满足规约,
对大型程序,可能需要这些方法的组合
语言应该对程序验证提供支持,其支持力度是选择语言
的主要标准之一。
语义和语法结构的简单性是简化程序验证的主要因素。
6、编程环境
语言的技术结构仅仅是影响其使用的一个方面,而合适
的编程环境可以弥补语言技术上的弱点。
编程环境包含很多因素,
可靠的、有效的、有良好文档的语言实现自然是首要
因素。
特殊的编辑器和测试包可以加速程序的创建和测试。
维护和修改程序的多个版本的机制有利于大型程序的
开发。
7、程序的易移植性
程序的易移植性是很多项目的重要目标。
广泛使用的和独立于机器特性而定义的语言是易移植性
的有用的基础,如,Ada,Fortran,C,Pascal等有标准化
定义的语言书写的程序易移植性较好。
8、使用代价
代价是评价语言的主要元素,但具有不同的代价度量。
a,程序执行代价
在早期,代价主要是程序执行代价。因此,优化编译器
的实现、高效的寄存器的分配和高效的运行时支持机制
的设计是非常重要的。
程序执行代价对语言设计是重要的,但主要对将重复执
行的大程序更为重要。
目前,对很多应用、执行速度不再是主要考虑。
对程序开发的更好诊断和更容易的用户控制以及程序的
维护也需要考虑,在此情况下,执行时间增加 10%— 20%,
也是可容忍的。
b,程序翻译代价
当 Fortran或 C等用于教学时,高效的翻译(编译)比高效
执行更为重要。通常学生程序会多次编译,而执行次数
不多,需要快速、高效的编译器。
c,程序生成、测试和使用的代价
对某类问题,求解应该在程序员最少投入的情形下被设
计、编码、测试、修改和使用。如,Smalltalk是价格有效
的,求解一个问题的时间和努力均较少。
对使用语言的总代价的考虑在很多情况下变得和传统的
代价同等重要。
d,程序维护的代价
研究表明,对较长时间运行的程序的代价不是初始设计、
编码、测试的代价而是整过生命周期代价(涉及开发和
维护)。
维护包括发现错误的修改、平台的变化所需的修改、程
序的扩展和加强。语言对维护的支持是非常重要的(长
期运行的程序由多个人员维护,语言应有支持)
语言的应用领域
语言的使用依赖于所求解问题的应用领域,过去 30年各种应
用领域的语言已有很大变化。
1,60年代的应用
60年代的程序设计可分为四个基本类:商业处理、科学计算、
系统程序设计、人工智能应用。
?商业处理
这类应用大多是大的数据处理系统,运行在大型机上,
其基本特征是:读大量在多个磁带设备上的历史数据,
读少量的当前事务集,写出一个新的历史数据集。
COBOL是这类应用的代表语言。
商业应用还包括商业计划、风险分析和,What if,方案
( 60年代,这样一个应用通常需几个月)。
?科学计算
主要用于各种数学方程的求解,包括数值分析、微积分
求解、统计,这是计算机的第一个应用领域,Fortran是
最流行语言,其语法接近数学。
?系统
操作系统和编译器
这类应用要求能够访问硬件的全部功能和资源,当时没
有有效的语言存在。汇编语言是主要的选择。
Jovial( Algol的变体)曾用于美国 DoD的一些项目,60年
代末,PL/I可用于此目的。
一个相关的应用领域是过程控制,由于当时计算机的庞
大和昂贵,大多数过程控制应用是非常大的,如电站控
制和自动装配线控制。 Forth语言专为此而设计,汇编语
言也常被使用。
?人工智能
其特征是对大的数据空间的搜索算法。
LISP是主要语言。
2,90年代的应用
当前的情况远较过去复杂,有更多的应用领域,可选语言也
更多。
?商业处理
COBOL仍然是主要语言,C和 PL/1也时常被使用
然而,What if”方案已完全改变,spreadsheet已完全改革
该领域
过去对典型的商业计划程序需化一个程序员几个月,现
在可在几小时内泡制出很多。
第四代语言也开始进入此市场。 4GL提供了基于窗口的程
序员界面,易于访问数据库记录,易于产生填空式的输
入表和优美的输出报告,有时 4GL编译器产生 COBOL程
序作为输出。
?科学计算
Fortran仍有较大市场,C开始进入该领域。
Fortran 90加入了许多 Ada和其他语言的特征。
?系统软件
60年代末的 C和后来的 C++占据了这个领域。
C提供了非常高效的执行,允许程序员对操作系统和硬
件的完全访问,其他语言如,Modula,Pascal、现代
BASIC也可用于此。
Ada以支持系统软件开发为目标,但从未达到其成为此
领域主要语言的目标。
汇编语言的使用已成为过去。
实时语言的需求也在增加,C,Ada,Pascal常用于此。
?AI
LISP仍在使用,只是改为 Scheme和 Common Lisp。 Prolog
是此领域的新军。
?出版
字处理系统有自己的输入命令和输出文件语法。 TEX是
常用的语言,它产生 Postscript页面描述语言(直接使用
已不多见)。
?Process(处理)
60年代,程序员通过命令操作计算机,现在常用程序来
控制其他程序,如:每天半夜备份文件,自动回答电子
邮件等。这样的活动称为处理,这需要专用的处理语言,
例如有,UNIX中的 Shell,DOS中的 BAT等。
?新范型
新的应用模型仍在研究中,ML用于类型理论研究,其用
户正在增长。 Smalltalk是另一重要语言,它是 OO语言的
起源。 JAVA的应用域也在逐步扩大。
语言的标准化
?一个例子,int i; i=(1&&2)+3;这是一条 C语言语句,该语
句是否有效? i的值是什么?要回答这个问题,三个方法是常
用的。
1.通过阅读语言参考手册以决定语句的含义
2.在自己的计算机上写一段程序查看其结果
3.阅读语言标准中的定义
?选择 2是常用的方法 —— 简单易行,因为语言概念和其特殊
实现相关。
?直接查用户参考手册也是常用的。但选择 3较少用,因为很
少有人看语言标准。
?选择 1,2意味着一个语言的概念是和其特殊实现相关的。
但实现是否正确?如:移植一个程序到另一计算机上,仍能
正确编译吗?
?通常语言设计涉及一些复杂的细节,各个厂商有不同的解
释,从而产生细微的执行行为上的差异。
?厂商也可能决定加入新的特性到语言中以增强其有用性,
但新加入是否“合法”是一个问题,它有可能导致移植的困
难。
?为解决这些问题,大多数语言有标准定义,所有实现应该
符合标准,通常有两种标准,
1.业主标准( Proprietary)。开发并拥有语言的公司所给
定的定义。这类标准通常不适合已广泛使用的语言。实
现上的变体会随着很多增强和不兼容而出现。
2.合议标准( Consensus)。基于相关参与者的同意而由
一个组织产生的标准。合议标准是保证语言实现一致性
的主要方法。
?每个国家都有自己的标准化组织
美国,American National Standard Institute,ANSI
负责程序设计语言标准的是,
Computer Business Equipment Manufacture
Association(CBEMA)的 X3委员会。
IEEE( Institute of Electrical and Electronic Engineers)
也开发相应标准。
英国,BSI( British Standards Institute)
国际,ISO( International Standards Organization),在瑞
士、日内瓦。
?标准开发遵循类似的过程
在某一时间,一组人认为一个语言需要一个标准定义了,
标准化组织将组织一批志愿者来开发标准,当工作组提
出标准后,让更大范围的人进行投票,不能达成共识的
部分去掉,然后产生语言标准。
从理论上说,这是一个好过程,然而,实际上标准制订
技术和政治因素参半,如:编译器的制造商在标准化过
程中均有财力投入,都希望标准按自己的思路走,从而
避免改变自己的实现以及失去用户群。
标准的制定是一个合议的过程,不是每一个人按自己的
方式办,而是希望最终的语言能为所有人所接受。在意
见不同时,有时不得不将有的特性排除在标准外。
?为了更好地使用标准,有三个值得强调的问题,
1.时限:什么时候开始标准化一个语言?
Fortran于 1966年开始标准化,当时已有很多不兼容版本,
从而导致了很多问题。
另一个极端,Ada于 1983年在有任何实现前即开始标准
化,因此,并不清楚标准产生时是否有语言可以使用。
第一批的 Ada编译器在 87或 88年才出现。
人们应该尽早开始一个语言的标准化,只要有足够的语
言使用经验即可,太晚则会导致很多不兼容的实现。
2.相符性 —— 什么意味着程序和编译器符合标准
程序符合标准 —— 如果该程序只使用标准定义的特性
编译器符合标准 —— 对一个给定的符合标准的程序,可
以生成能够产生正确输出的可执行码。
这里并未涉及对标准的扩充,如编译器加了附加特性,
则使用这些特性的程序将不合标准。标准通常强调符合
标准的程度,大多数编译器都加入了自己的特性。
3.废弃
新的计算机结构需要新的语言特性。
一旦我们标准化一个语言,几年以后它可能会变得古怪。
如,Fortran 66标准就已过时,它没有类型、嵌套控制结
构、封装、块结构和其他现代特征。
一般每五年应复审标准,或者重新修订或者丢弃。
所有标准的一个问题是:遵循旧标准书写的程序怎么办?
重写程序代价非常大,因此大多数标准需要向后兼容。
这样也存在一些问题:具有废弃结构的语言可能变得
难以控制,更危险的是这些结构可能会对好的程序设
计有害。
目前,存在两个相关概念:废弃和反对( deprecate)
废弃 —— 一个特性被废弃是指:它是一个可能在下一个
标准版本中丢弃的特性,这意味着,该特性仍然可用,
但在 5— 10年内会被丢弃,这样提前可为重写作好准备。
反对 —— 反对特性将在下一个标准版本中变成废弃的,
新编写的程序不应再使用此类特性。
?符合标准的编译器允许有扩展,只要能正确地编译符合标
准的程序即可。
大多数编译器均有扩展,厂商加入特性以力争扩大市场
份额。这是导致语言发展的重要因素之一。
学术界,人们并不关心这样的标准,总是根据自己的研
究扩展和修改语言。这也是语言发展的重要源泉。
1.4 环境对语言的影响
?语言的发展不能在真空中进行,支持语言的硬件对语言有很大
影响。
?支持程序执行的外部环境称为操作或目标环境。
?程序被设计、编码、测试和调试的环境称为宿主环境。
?通常可分为四类目标环境,
批处理环境
交互式环境
嵌入式系统环境
程序设计环境--交互式环境的特例
批处理环境
?最早和最简单的操作环境只含有外部数据文件
数据文件 → 程序处理 → 数据文件
称为批处理:因为输入数据聚集成批并成批处理。
Fortran,C、和 Pascal均是为批处理而设计的,当然也可
用于交互式嵌入式环境。
?对语言设计的影响
环境的影响可分为四个方面,I/O特性、错误和例外处理、
时间设施和程序结构。
批处理语言中,文件是大多数 I/O特性的基础。虽然文件
可用作到终端的交互式 I/O,但对交互 I/O的特殊需要并不
涉及。文件通常存贮定长记录,而终端需要键盘上每输
入一个字符就读入一次。嵌入系统需访问特殊的 I/O设备,
批处理器则不作此考虑。
批处理中,终止程序执行的错误是可接受的,但代价昂
贵,因为错误纠正后,必须重复全部运行。同时,来自
用户的立即处理和纠正错误的帮助是不可能的。这样语
言的错误或例外处理机制强调在程序中进行错误 /例外处
理,使得程序可从大多数错误恢复,无终止地继续执行
码。
批处理的第三特征是程序时间限制的缺乏。语言通常不
提供监控或直接影响执行速度的设施。语言特性的实现
也通常反映出时间限制的缺乏。
程序结构通常包含一个主程序和一个子程序集合,如,C、
Fortran,Pascal等。子程序完全由编译器处理,编译器在
工作时间内很少和程序员交流。
交互式环境
?当前的 PC机和工作站大多如此使用,程序在执行过程中直
接和用户交互,从键盘或 mouse接收数据并送到显示器显示。
如字处理、游戏、数据管理,CAI等。
?影响,
交互式 I/O完全不同于一般的文件操作,
错误处理方式不同,一旦错误输入,程序可能显示错误
消息并请求纠正,在程序中处理错误的设施并不重要,
错误时终止程序通常是不可接受的。
必须经常使用某种时间限制,至少必须有可以忍受的时
间反应。有时,长时间不输入会导致其他操作的调用。
主程序的概念通常不存在。程序由一系列子程序构成,
用户在终端输入“主程序”作为命令序列。和用户的交
互形式为:请求命令,按命令执行,请求另一命令。
嵌入式系统环境
?一个用于控制一个大系统的部分的计算机系统称为嵌入式系
统(成为大系统的有机集成部分,其失误将导致整个大系统的
失败)。可靠性和正确性是这类系统程序的主要属性。
?影响,
嵌入式系统的程序通常没有操作系统的支持,也没有通常
的文件和 I/O设备环境,程序必须和非标准的 I/O设备直接
交互,通常使用特殊的过程。因此,语言通常不考虑文件
和面向文件的 I/O操作。特殊设备的访问能力是必须提供的:
通过访问特殊的硬件寄存器、存储位置中断处理器或以汇
编或其他低级语言书写的子程序。
错误处理是十分重要的。每个程序应准备好处理所有错误,
采取适当的动作去恢复和继续。程序终止是不可接受的,
除非灾难性的系统失误。通常也无用户提供交互帮助。错
误处理还必须处理系统部件的失败(除了一般的错误外)。
嵌入系统总是涉及实时操作,即能对输入作出及时反应
并同时产生输出,语言必须具有时间设施。
嵌入式计算机系统通常是分布系统,涉及多个计算机。
这样,运行的程序通常是一个并发执行的任务集,每个
任务控制或监控一个局部。如果有主程序,也仅仅是为
了初始化任务的执行,一旦初始化后,任务通常并发运
行,且无限地运行,除非整个系统失败或关闭。
程序设计环境
?这是程序创建和测试的环境,和操作环境相比,它对程序
设计影响稍小,然而,普遍的认识是:好的程序设计环境对
程序生产有较大影响,程序设计环境通常包含一个支持工具
的集合和调用它们的命令集(编辑器、调试器、验证器、测
试数据生成器、美化打印器等)。
?对语言的影响主要体现在两个方面:分开编译和部件装配,
程序测试和调试
?分开编译 —— 这对大型程序的实现非常重要
分开编译的困难在于:编译一个子程序时,编译器可能
需要其他子程序或共享数据对象的信息。
所需指导的信息包括,
1、被调用子程序的参数的数量、类型、顺序等的规约,
允许编译器检查外部子程序的调用是否有效。其他子程
序的书写语言也是需要知道的,编译器可以据此设置适
当调用顺序,以传送数据和控制信息。
2、被引用变量的类型声明是需要的,允许编译器确定外
部变量的存储表示,使得引用可以用适合的访问格式来
编译。
3、外部定义而在内部声明使用的数据类型的定义是需要
的,允许编译器分配存储和计算局部数据格式。
为了提供关于分开编译的子程序、共享数据对象和类型
定义的信息,通常有三个方法,
1、语言可能需要信息在子程序中重新申明(如 Fortran)。
2、指定特殊的编译顺序,先编译所需的外部信息(如
Ada,Pascal)
3、需要在编译过程中包含相关规约的库的存在,使得编
译器可随时查询( Ada,C++)
方法一又可称为独立编译
每个子程序可不需外部信息而独立编译,子程序是完
全自包含的。
缺点是:没有办法检查内外信息的一致性。这种不一
致错误只能在装配阶段才可能知道。
方法二、三需要工具将子程序、类型定义和公共环境的
规约放到库中。
通常子程序的体( body,含局部变量和语句)可以略
去,只需规约。体部分可在以后分开编译。
如 Ada中,每个子程序、任务或包分成两个部分(可
以分开编译):规约和体。
一个对尚未编译的子程序的调用称为 Stub,包含 Stub
的子程序可以执行。但当到达 Stub点时,该调用产生
一个系统诊断信息而不进行实际调用,从而可达到单
独测试目的。
分开编译影响语言设计的另一面是共享名(不同开发者
可能对子程序类型定义、公共变量使用相同的名)的使
用。
通常解决共享名的方法有三,
1、每个共享名必须是唯一的(由程序员来保证),如 C
中 extern中的变量名。命名约定用于每个小组使用不同的
子程序名(如固定的名字前缀),如 C中的 _缀。
2、语言常使用作用域( Scope)(在嵌套情况下,只有
最外层子程序中的名对外可知)规则来隐藏名字。
3、通过显式地加入来自外部的定义而使名字可用,
OOPL的继承即为这种机制,通过包含外部定义的类在一
个子程序中,该类定义的其他对象也就自然可知。 Ada
中,名字可以重载,n个对象可有相同名字,需编译器来
指定实际的引用。
?测试和调试
大多数语言会有辅助程序测试和调试的特性。
1、执行追踪。 Prolog,LISP和很多其它交互语言提供了
允许特殊语句和变量被标志为执行时“追踪”。当标记
的语句被执行或标记的变量被赋新值时,程序的执行中
断,指定的追踪子程序被调用。
2、断点( Breakpoint)。在交互式编程环境中,语言常
提供断点设施,当达到断点,执行中止,控制权交给程
序员,他可检查或修改变量值并且开始程序执行。
3、断言( Assertion)。断言是一个条件表达式,插入在
程序中。
例,assert( x>0 and A=1) or ( x=0 and A>B+10)
断言陈述了在指定点变量值间应有的关系。当断言被
“使能”,编译器插入相应的代码来测试被陈述的条件,
条件不成立,则执行终止,调用例外处理。程序正确后,
可将断言设置掉重编译,此时,它只作为注释用。
环境框架
在过去十年,支撑环境的概念已得到较大发展。
一个支撑环境包含了称为环境框架的基础设施服务。
框架提供的服务有:数据仓库、图形用户界面、安全和通讯
服务等。
程序将使用这些服务,程序员需能容易地使用这些服务作为
程序设计的一部分,对应地,语言应设计为可以容易地访问
这些服务。
如,60年代,程序需用特定的 I/O例程处理和用户的通讯。
现在窗口系统已变成标准的输出模式,框架环境应包括基本
的窗口管理器,如,Motif(基于 X-Window),程序只需调
用 Motif函数。