热门问题
时间线
聊天
视角

ALGOL 60

来自维基百科,自由的百科全书

Remove ads

ALGOL 60(源自ALGOrithmic Language 1960的縮寫),是在1960年創建的称为“算法语言”的一種程式語言。它是以后来称为ALGOL 58的“国际代数语言”为基礎,其官方後繼者是ALGOL 68,它们一起并称为ALGOL語言家族。Algol 60引进了许多新的概念如:词法作用域递归[2]巴科斯-诺尔范式(BNF),它在程式語言设计和发展演化中有著巨大的影響力。

事实速览 编程范型, 语言家族 ...
Remove ads

歷史

1960年,在巴黎举行的讨论会上,来自欧洲的诺尔Bauer英语Friedrich L. BauerRutishauser英语Heinz RutishauserSamelson英语Klaus Samelson范·韦恩加登Vauquois英语Bernard VauquoisWoodger英语Michael Woodger,与来自美国的佩利巴科斯麦卡锡Katz英语Charles KatzWegstein英语Joseph Henry Wegstein和J. Green,共同发表了《算法语言ALGOL 60报告》[3]戴克斯特拉实现了ALGOL 60语言的第一个编译器。在1962年罗马会议上,ALGOL 60报告得到了修订,并于1963年出版[4]

ALGOL 60是程序设计语言发展史上的一个里程碑,影響到其後的SimulaCPLALGOL WISWIMBCPLBPascalCScheme等。它标志着程序设计语言成为一门独立的科学学科,并为后来软件自动化及软件可靠性的发展奠定了基础。

Remove ads

標準

ALGOL 60以及COBOL,是最初的企圖標準化的程式語言。ALGOL60曾經提出兩項ISO標準:

  • ISO 1538: 1984年,编程语言ALGOL 60[5],它已稳固化。
  • ISO 1672: 1977年,ALGOL基本符号的ISO 7位编码字符集硬件表示[6],它已撤消。

实现时间线

ALGOL 60在语言报告中没有I/O设施;诸多实现以少有相互兼容的方式定义了自己的设施。迄今ALGOL 60已经有了至少70个扩充、扩展、派生和子语言[7]

更多信息 名字, 年份 ...
Remove ads

词法

简单符号

除了字母数字之外,ALGOL定义了运算符

更多信息 优先级, 运算符 ...

分界符英语Delimiter:

, . : ;
( ) [ ]

在ISO 1672标准中,用:=表示(U+2254),用*表示×;用%表示÷,用**^表示;用>=表示,用<=表示,用<>表示;用@表示科学记数法指数运算的底数10所用符号(U+23E8),用{表示,并且用}表示,用空格 表示在字符串中的空白字符(U+2423)。

关键字

ALGOL 60有24个关键字

  • array
  • begin
  • Boolean
  • comment
  • do
  • else
  • end
  • false
  • for
  • go to
  • if
  • integer
  • label
  • own
  • procedure
  • real
  • step
  • string
  • switch
  • then
  • true
  • until
  • value
  • while

ALGOL 60不采用保留字的概念,但包括了标准函数名字作为限制标识符:

  • abs
  • sign
  • sqrt
  • sin
  • cos
  • arctan
  • ln
  • exp
  • entier

关键字写法依赖于实现,常见的是一种叫做索绕英语Stropping (syntax)(stropping)的方法,即将关键字大写并包围在两个'之间,例如将go to写为'GOTO'。在ISO 1672标准中关键字还包括对特定符号的某种文字转写:

更多信息 符号, 转写 ...
Remove ads

语义

块与作用域

在ALGOL 60中,“复合语句”被定义为:包围在语句括号beginend之间的成序列的语句,形成一个复合语句。被定义为:成序列的声明,跟随着成序列的语句,并被包围在beginend之间,形成一个块;所有声明以这种方式出现在一个块中,并只在这个块中有效。[25]

一个程序是特定的一个块或复合语句,它不包含在另一个语句之中,并且不使用不包含在它之中的其他语句。在1976年的修改版语言报告中,程序只能包含在叫做“环境块”的假定总是存在的一个虚构块之中,除了可以使用在环境块中声明的过程标识符和函数指定符之外,不使用不包含在它之中的其他语句。

(quantity)被区分出如下种类:简单变量、数组、标签、接转(switch列表由标签组成[26])和过程。声明负担定义在程序中用到的量的特定属性,并给它们关联上标识符。声明包括:类型声明、数组声明、接转(switch)声明和过程声明。量的作用域是语句和表达式的集合,在其中关联于这个量的标识符的声明是有效的。所有的块,自动地介入名称目录英语Nomenclature(nomenclature)的一个新的层级:

  • 在这个块内出现的标识符,可以通过合适的声明,而被指定为局部于所论及的这个块。这个标识符在这个块里面的所表示的实体,不存在于它的外面。这个标识符在这个块外面的所表示的任何实体,在这个块里面是不可见的。
  • 除了表示标签的标识符之外,一个标识符,如果出现在一个块中,而且并非声明于这个块中,则它非局部英语Non-local variable于这个块[27],就是说它在这个块里面和在紧邻其外的层级中所表示的是同一个实体。
  • 因为块中的语句自身可以是一个块,局部和非局部于一个块的概念,必须递归地去理解,就是说非局部于一个块A的一个标识符,可是亦可否地,非局部于A是其中语句的块B

这动态的蕴涵了:在通过begin进入一个块的时候,所有为这个块声明的标识符,假定了这个给定声明的本性英语Nature (philosophy)所蕴涵的意义英语Meaning (philosophy)(significance);如果这些标识符已经被外面的其他声明所定义,这时它们被给予新的意义;在另一方面,并非为这个块声明的标识符,保持它们旧有的含义。在通过endgo to语句退出一个块的时候,为这个块声明的标识符失去它们的局部意义。声明可以标记上额外的声明符own,其效果为:在重新进入一个块的时候,自有的这些量的值将不变更而仍是上次退出时的值,然而声明的没有标记上own的变量的值是未定义的。

Remove ads

表达式和语句

在描述算法处理的程序中,主要构成者是算术表达式、布尔表达式,和得到语句标签的指定(designational)表达式。除了特定的分界符之外,表达式的构成者包括:逻辑值、数值、变量、函数指定式,和基本的算术、关系、逻辑运算符(operator)及顺序运算符。用以形成语句的关键字,在ALGOL 60中被归入顺序运算符和分隔符之中。

变量是对一个单一的指名(designation英语Designation (law))。加下标(subscripted)变量指定(designate)多维数组的元素的值,这里将数组元素称为“组成元件”(component)[28]。函数指定式(designator)定义单一的数量值或逻辑值,它们是将给定的由过程声明定义的规则集合,应用于固定的实际参数集合的结果。

现在通常将变量定义为抽象的存储位置,它含有了被称为一个的某种已知或未知的信息,并且配对了关联的符号英语Symbol (programming)名字。在ALGOL 60中,某些语法单位,比如表达式及其构成者和数组标识符,被称为拥有值。各种“类型”即integerrealBoolean指称(denote)的基本的属性。

在左圆括号和匹配的右圆括号之间的表达式(parenthesized expression)自行求值,而这个值被用于后续的计算之中;因此通过适当的圆括号放置,总是可以在表达式之内安排出想要的运算次序

ALGOL 60将语句分为三类:无条件语句、条件语句和for语句。赋值语句担负将表达式的值,指派(assign)到一个或多个变量,或者在定义函数指定式的值的过程主体中指派到过程标识符;在作为指派目标的下标变量中出现的任何下标表达式,先于得出所指派之值的表达式,而按从左至右顺序求值。空无的虚设(dummy)语句不执行任何运算。过程语句负担实施调用一个过程主体的执行。

控制流程语句包括:go to跳转语句、条件语句、for循环语句。go to语句结合了无条件go to和计算go to二者,go to语句不能从块外跳转到块内的标签,但可以跳转进入复合语句。条件语句包括if语句(即if <布尔表达式> then <无条件语句>),和if语句经由关键字else与随后的语句联合在一起的形式(即<if语句> else <语句>)。ALGOL 60在if语句和for语句中介入了子句概念,算术表达式、布尔表达式和指定表达式,可以是条件表达式(即if ~ then ~ else ~[29]

由于变量和函数指定式二者的语法定义都包含表达式,表达式及其构成者的定义必须是递归的。由于成序列的语句,可以被组织成复合语句和块,语句的定义必需是递归的。ALGOL 60采用了左递归巴科斯范式(BNF)。

过程

在ALGOL 60中,过程声明担负定义过程标识符所关联的过程,其主要构成者是过程主体,它是一个语句或一段代码。过程主体总是表现得如同一个块,不管它是否有着块的形式;故而标记了在过程主体内语句或者主体自身的标签的作用域,永远不能延伸超出这个过程主体[30]

过程主体关联着一个头部,它规定了出现在过程主体内的代表形式参数的特定标识符。过程参数传递有两种求值策略传名调用传值调用。在过程声明中,通过对形式参数名字前导value来指定传值调用,缺省为传名调用。在过程主体是用ALGOL语言写的语句的情况下,过程语句执行它的效果,等价于在程序上进行下列操作的效果:

  • 声明为传值调用的形式参数,都要被赋值即指派上对应的实际参数的值,这些指派被认为是在进入过程主体之前显式进行的。其效果如同创建了包围着这个过程主体的一个额外的块,在其中所做的这些指派针对的是局部于这个虚构(fictitious)块的变量,它们具有在相应规定中给出的类型。作为结论,传值调用的变量,被认为非局部英语Non-local variable于过程主体,但是局部于这个虚构块。
  • 声明为传名调用的形式参数,在整个过程主体内,要被替代为对应的实际参数,并且只要语法上可能就对这些实际参数包围上圆括号。在通过这个名字替代处理而插入的标识符,和已经存在于过程主体之内的其他标识符,二者之间的可能冲突,将凭借对涉及到的(这个过程主体的)形式标识符或局部标识符的适合的系统性变更来避免[31]
  • 最终经过上述修改后的过程主体,被插入到过程语句的位置上并被执行。如果调用这个过程的位置,处在这个过程主体的任何非局部量[32]作用域的外面,在通过这个过程主体替代处理而插入的标识符,和在这个过程语句或函数指定式所在位置上其声明有效的标识符,二者之间的可能冲突,将通过(在发起调用的这个层级上)对后者标识符的适合的系统性变更来避免[33]

对于定义函数指定式的值的过程声明,在其过程主体中,必须出现具有过程标识符在其左侧部份中的一个或多个赋值语句,其中至少有一个必须被执行;并且这个过程标识符所关联的类型,必须通过以类型声明符作为其过程声明的最先符号的样貌来声明。最后那个这样指派的值,被用来继续此函数指定式在其中出现的表达式的求值。在这个过程主体中,这个过程标识符的不在赋值语句左侧部份中的任何出现,指示了这个过程的激活(activation)。

两个传名调用形式参数,其对应的实际参数之间可能存在依赖关系,比如第一个是整数变量i,而第二个是下标变量A[i],从而导致后者形式参数也依赖于前者形式参数,利用传名调用和这种副作用可以实现Jensen设备英语Jensen's Device[34];它典型的用于定义对应于级数过程Sum(k, l, u, ak),它有两个传名调用的形式参数:索引变量k和通项(general)表达式ak

对于交换两个参数的值的swap(x, y)过程,其过程主体定义为:t:=x; x:=y; y:=t,这种依赖性副作用会导致可能出现异常行为,由于名字替代机制相当于展开(expansion),过程语句swap(i, A[i])中下标变量A[i]的下标i未经求值,对应的过程主体就转换成为:t:=i; i:=A[i]; A[i]:=t。1964年IFIP英语International Federation for Information Processing工作组2.1英语IFIP Working Group 2.1制定了《SUBSET ALGOL 60报告》,在这个子集语言中对“完全的名字概念”(full name-concept)增加了一项限制:在名字替代(传名调用)中,实际参数只能是一个标识符或字符串。

在过程的参数列表( … <参数分界符> … )中,有可选的“) <字母串>: (”样式的参数分界符英语Delimiter[35]。众所周知的传名调用实现采用了thunk英语Thunk[a][37]Donald Knuth设计了“男人抑或男孩测试”,来区分编译器是否正确的实现了“递归和非局部引用”,这个测试用到了传名调用。

Remove ads

例子

下面是语言报告中过程声明的一个例子[b]

procedure Absmax(a) Size:(n, m) Result:(y) Subscripts:(i, k);
    value n, m; array a; integer n, m, i, k; real y;
    comment 矩阵a,其大小为nm,其绝对值最大的元素
            被传送到y,并且这个元素的下标是ik;
begin
    integer p, q;
    y := 0; i := k := 1;
    for p := 1 step 1 until n do
        for q := 1 step 1 until m do
            if abs(a[p, q]) > y then
            begin
                y := abs(a[p, q]);
                i := p; k := q
            end
end Absmax

在1976年修改版语言报告的环境块中,定义了输入输出过程:incharoutcharlengthoutstringoutterminatorinintegeroutintegerinrealoutreal,下面以其中的outinteger作为演示例子:

procedure outinteger(channel, int);
    value channel, int;
    integer channel, int;
    comment 将表示int的值的那些字符
            加上尾随的终结符传递到channel;
begin
    procedure digits(int);
        value int; integer int;
    begin
        integer j;
        comment 使用递归从右至左求值数字 
                但从左至右打印它们;
        j := int ÷ 10;
        int := int - 10 × j;
        if j  0 then
            digits(j);
        outchar(channel, 0123456789, int + 1)
    end digits;
    if int < 0 then
    begin
        outchar(channel, -, 1);
        int := -int
    end;
    digits(int); outterminator(channel)
end outinteger

这里调用到的outchar(channel, str, int),将在字符串str中对应整数int的值的那个字符,传递到通道channeloutterminator(channel),用于输出在数值之后的终结符(即空格、换行或分号)。此外,IFIP英语International Federation for Information Processing工作组2.1英语IFIP Working Group 2.1在1964年曾制定《ALGOL 60输入输出过程报告》,其中定义了insymboloutsymbollengthinrealoutrealinarrayoutarray,这里的多维数组採用了横行为主英语Row- and column-major order(Row major)次序[38]

参见

注释与引用

外部链接

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads