5.8过程说明和过程调用的翻译 ·过程说明和过程调用是一种常见的语法结构,绝大多 数语言都含有这方面的定义。其形式随语言的不同而 有所不同。 ·过程说明方式有些语言过程说明由关键字(PROCEDURE, FUCTION)引1导,有些语言则可直接定义。 ·过程调用方式对于子程序过程,通常须使用过程语句 或CALL语句;对于函数过程,一般把它们作为表达式中 的一个初等量来引用。 ·尽管过程说明和过程调用的形式因不同的语言而异, 但在功能上和需做的语义处理工作上仍较类以。 ·应当指出,过程说明和过程调用的翻译,还依赖于形式 参数与实在参数结合的方式以及数据存储空间的分配 方式
5.8 过程说明和过程调用的翻译 • 过程说明和过程调用是一种常见的语法结构,绝大多 数语言都含有这方面的定义。其形式随语言的不同而 有所不同。 • 过程说明方式 有些语言过程说明由关键字(PROCEDURE, FUCTION)引导,有些语言则可直接定义。 • 过程调用方式 对于子程序过程,通常须使用过程语句 或CALL语句;对于函数过程,一般把它们作为表达式中 的一个初等量来引用。 • 尽管过程说明和过程调用的形式因不同的语言而异, 但在功能上和需做的语义处理工作上仍较类似。 • 应当指出,过程说明和过程调用的翻译,还依赖于形式 参数与实在参数结合的方式以及数据存储空间的分配 方式
5.8.1过程说明的翻译 过程说明的翻译需要做如下的 过程信息向量的内容主要是形参 工作: 的信息,并以某种方式和过程名的 1.在符号表中新登记一项,并填 登记项连接起来。 入有关的属性 为每个形式参数分配相应的存储 单元,称为形式单元,供形实结合 这些属性通常有:种属(过程或 时传递信息之用.并将形参的名字、 函数等)、是否为外部过程、数 相应形式单元的地址,以及此形 据类型(对函数而言)、形参个 参的其它一些属性记入符号表。 数、形参的信息(供语义检查用, 如种属、类型等)、过程的入口 需要指出的是,对于具有嵌套结构 地址等等。 的语言,为确保程序中全局量和局 部量都能得到正确的引用,符号表 由于每个过程的登记项所需填 及各量的数据空间是按嵌套的层 写的信息较多,所以编译程序往 次建立、分配的.有关这方面的问 往设置专门的过程名表,或者为 题将在第六章和第七章进行讨论。 过程名再建立一个附属的“过 程信息向量”(见P229)
5.8.1 过程说明的翻译 过程说明的翻译需要做如下的 工作: 1.在符号表中新登记一项,并填 入有关的属性 这些属性通常有:种属(过程或 函数等)、是否为外部过程、数 据类型(对函数而言)、形参个 数、形参的信息(供语义检查用, 如种属、类型等)、过程的入口 地址等等。 由于每个过程的登记项所需填 写的信息较多,所以编译程序往 往设置专门的过程名表,或者为 过程名再建立一个附属的“过 程信息向量”(见P229). 过程信息向量的内容主要是形参 的信息,并以某种方式和过程名的 登记项连接起来. 为每个形式参数分配相应的存储 单元,称为形式单元,供形实结合 时传递信息之用.并将形参的名字、 相应形式单元的地址,以及此形 参的其它一些属性记入符号表。 需要指出的是,对于具有嵌套结构 的语言,为确保程序中全局量和局 部量都能得到正确的引用,符号表 及各量的数据空间是按嵌套的层 次建立、分配的.有关这方面的问 题将在第六章和第七章进行讨论
过程说明的翻译(续) 2.当扫描到过程说明中的过 (②产生形实结合的代码,即 程体时,产生执行过程体的 产生将实参的信息(实参的 代码.此时需完成: 值或地址,它们在过程语句 (1)产生将返回地址推入堆栈 相应的代码序列中给出)分 的代码(因过程调用可以 别送入相应形式单元的代 嵌套和递归,所以应将各 码。接着,再产生执行过程 返回地址按调用的嵌套或 体的代码 递归层次依次压入栈保存, (3)产生有关从过程返回的 若转子指令能自动完成将 代码(对于函数,在此之前 返回地址送入堆栈,此项工 应产生将函数值送入寄存 作可省去)。 器或指定地址的代码)
过程说明的翻译(续) 2. 当扫描到过程说明中的过 程体时,产生执行过程体的 代码.此时需完成: (1)产生将返回地址推入堆栈 的代码(因过程调用可以 嵌套和递归, 所以应将各 返回地址按调用的嵌套或 递归层次依次压入栈保存, 若转子指令能自动完成将 返回地址送入堆栈,此项工 作可省去)。 (2)产生形实结合的代码,即 产生将实参的信息(实参的 值或地址,它们在过程语句 相应的代码序列中给出)分 别送入相应形式单元的代 码。接着,再产生执行过程 体的代码. (3)产生有关从过程返回的 代码(对于函数,在此之前 应产生将函数值送入寄存 器或指定地址的代码)
闭说明过程的处理 GOTO L1; ·对于某些将过程说明写成闭说明的程 序语言,在产生过程体的代码时,通常都 prog p, GOTO L2; 把它处理为一个闭子程序的形式。 proc a;- ·因此,在每一过程体的代码之前,应有一 GOTO L3; proc b; 条跳过过程体的无条件转移指令, GOTO L4; ·但是,在产生此指令时,过程体的代码尚 proc c; 未生成,故只能产生一条不完全的转移 begin (c)...end 指令,并记录此指令的位置,待以后回填 显然,对于过程说明可以嵌套的语言,为 begin (b)...end 12 了记录这些待回填位置,需使用一个指 begin a...end 令地址栈。 begin (p)...end
闭说明过程的处理 • 对于某些将过程说明写成闭说明的程 序语言,在产生过程体的代码时,通常都 把它处理为一个闭子程序的形式。 • 因此,在每一过程体的代码之前,应有一 条跳过过程体的无条件转移指令. • 但是,在产生此指令时,过程体的代码尚 未生成,故只能产生一条不完全的转移 指令,并记录此指令的位置,待以后回填. 显然,对于过程说明可以嵌套的语言,为 了记录这些待回填位置,需使用一个指 令地址栈。 prog p; proc a; proc b; proc c; begin {c} …end; begin {b} …end; begin {a} … end; begin {p}…end. L1: GOTO L1; GOTO L2; L2: L3: L4: GOTO L3; GOTO L4;
过程说明语句的文女法 ·下面,我们给出经过拆分的过程说明语句的文法,它包括函 数、有参过程和无参过程的定义.相应的属性翻译文法,可 根据上述处理方案和相应的文法自行设计. ProcDefStatement-ProcName I ProcArgMSG ProcArgMSG-ProcName iden I ProcArgMSG,iden ProcName ProcKey iden ProcKey procedure function
过程说明语句的文法 • 下面,我们给出经过拆分的过程说明语句的文法,它包括函 数、有参过程和无参过程的定义.相应的属性翻译文法,可 根据上述处理方案和相应的文法自行设计. ProcDefStatement → ProcName | ProcArgMSG ) ProcArgMSG → ProcName ( iden | ProcArgMSG , iden ProcName → ProcKey iden ProcKey → procedure | function
5.8.2实参和形参间的信息传递 ·在执行过程调用时,首先应把实在参数传送给被调过程, 以便被调过程能对实参执行相应的过程体。 ·所谓把实参传送给被调过程,就是把实参的信息(如实 参的值或地址)送入相应的形参单元之中,在执行过程 体时,就能从形参的形式单元中取得对应实参的值或地 址。 ·可采用两种不同的代码结构来传递实参的信息: 1.先结合,后调用在控制转入被调过程前,将各实参的信息送 入相应形参单元; 2.先用,后结合将实参的信息依次排列在转子指令前,当执 行转子指令而进入过程后,被调过程根据返回地址,找到存放 实参信息的单元位置,再把各实参信息送入相应形参的形式单 元,然后再执行过程的目标代码
5.8.2 实参和形参间的信息传递 • 在执行过程调用时,首先应把实在参数传送给被调过程, 以便被调过程能对实参执行相应的过程体。 • 所谓把实参传送给被调过程,就是把实参的信息(如实 参的值或地址)送入相应的形参单元之中,在执行过程 体时,就能从形参的形式单元中取得对应实参的值或地 址。 • 可采用两种不同的代码结构来传递实参的信息: 1.先结合,后调用 在控制转入被调过程前,将各实参的信息送 入相应形参单元; 2.先调用,后结合 将实参的信息依次排列在转子指令前,当执 行转子指令而进入过程后,被调过程根据返回地址,找到存放 实参信息的单元位置,再把各实参信息送入相应形参的形式单 元,然后再执行过程的目标代码
形实结合的方式 ●1.1用调用(Call by reference)控制转入被调过程 后,由被调过程将实参的地址写入相应的形式单元.过程体 中对形式参数的任何引用或赋值,都按对相应形式单元间 接访问的寻址方式为其产生代码。显然,执行过程时,对形 参的赋值将会影响相应实参之值(右值).例如, PROCEDURE SWAP(VAR X,y:INTEGER);VAR t:INTEGER; BEGIN t:=x;x:=y;y:=t;END; 若按引用调用方式,则执行过程语句SWAP(,A[i])相当于执行如下操 作:(仪、y是指针变量) X=&i;y=&A[i]:t=*X;*x=*y;*y=t; 执行上述操作之后,就交换了变量i和A[i门之值
形实结合的方式 • 1.引用调用(Call by reference) 控制转入被调过程 后,由被调过程将实参的地址写入相应的形式单元.过程体 中对形式参数的任何引用或赋值,都按对相应形式单元间 接访问的寻址方式为其产生代码。显然,执行过程时,对形 参的赋值将会影响相应实参之值(右值).例如, PROCEDURE SWAP(VAR x,y:INTEGER);VAR t:INTEGER; BEGIN t:=x; x:=y; y:=t; END; 若按引用调用方式,则执行过程语句SWAP(i,A[i])相当于执行如下操 作:(x、y是指针变量) x=&i; y=&A[i]; t=*x; *x=*y;*y=t; 执行上述操作之后,就交换了变量i和A[i]之值
2.值调用(Call by value) 值调用的处理方法是:进入过程时,送入形式单元的 是相应实参的值;过程体中对形参的任何赋值都有按 对形式单元的直接访问来产生代码。 因此,一旦把实参之值送入对应形式单元之后,在执 行过程体期间,除了以实参值作为形参的初值进行运 算之外,将不再与实参发生任何联系。 由此可见,过程执行的结果决不会改变实参之值。 例如,在(5.29)中的形参若采用值结合方式,则执行 过程语句SWAP(I,A[I])之后,对变量I和A[I]之 值毫无影响
2. 值调用(Call by value) 值调用的处理方法是:进入过程时,送入形式单元的 是相应实参的值;过程体中对形参的任何赋值都有按 对形式单元的直接访问来产生代码。 因此,一旦把实参之值送入对应形式单元之后,在执 行过程体期间,除了以实参值作为形参的初值进行运 算之外,将不再与实参发生任何联系。 由此可见,过程执行的结果决不会改变实参之值。 例如,在(5.29)中的形参若采用值结合方式,则执行 过程语句SWAP(I,A[I])之后,对变量I和A[I]之 值毫无影响
3.结果调用(Call by result)和值结果调 (Call by value-result) ·结果调用和值结果调用在某些FORTRAN语言的编译 系统中使用。 ·特点为每个形参分配两个形式单元,第一单元用于存放 实参的地址(左值),第二单元用于存放实参的(右)值(在 结果调用中,实参的值将不被传送),在执行过程体时,将 只对第二单元进行操作,但在返回时,将第二单元的内容, 按相应的第一单元中的地址传给实参。 注意在结果调用中,因实参的值未被传送,所以,在过程 体中形参的初值是不确定的,因此对形参的第一次访问 必颏是为其赋值,而不允许使用其值,否则,程序运行的 结果将不可预测。 。名字调用(Call by name)略
3.结果调用(Call by result)和值结果调 用(Call by value-result) • 结果调用和值结果调用在某些FORTRAN语言的编译 系统中使用。 • 特点 为每个形参分配两个形式单元,第一单元用于存放 实参的地址(左值),第二单元用于存放实参的(右)值(在 结果调用中,实参的值将不被传送),在执行过程体时,将 只对第二单元进行操作,但在返回时,将第二单元的内容, 按相应的第一单元中的地址传给实参。 • 注意 在结果调用中,因实参的值未被传送,所以,在过程 体中形参的初值是不确定的,因此对形参的第一次访问 必须是为其赋值,而不允许使用其值,否则,程序运行的 结果将不可预测。 • 名字调用(Call by name) 略
5.8.3过程语句的翻译 常见过程调用语句格式为P(a1va2van) (5.30) 在一些语言中,过程调用语句是由诸如CALL等关键字引导的. 我们假定,参数传递仅限于采用引用调用方式,且假定实参均 为算术表达式,对于其它种类的实参,我们将在5.8.4节讨 论。对于调用语句(5.30)所产生的代码序列有如下的结 构: (par,O, 0, A1) (par,O, 0, A2) (5.31) (par, 0, (call, 0
5.8.3 过程语句的翻译 常见过程调用语句格式为 P(a1, a2, …, an) (5.30) 在一些语言中,过程调用语句是由诸如CALL等关键字引导的. 我们假定,参数传递仅限于采用引用调用方式,且假定实参均 为算术表达式,对于其它种类的实参,我们将在5.8.4节讨 论。对于调用语句(5.30)所产生的代码序列有如下的结 构: (par, 0, 0, A1) (par, 0, 0, A2) … … … … (5.31) (par, 0, 0, An) (call, 0, 0, P )