嵌套的子程序定义 如 PASCAL,子程序定乂在主程序中作为声明出现,子 程序本身又可含有其他子程序定义。 其目标是强调结构化的语句,但事实上产生了不同用途 结构化语句的引入主要是为算法结构的常见的层次划分 提供一种自然的注记方式,但嵌套子程序定义为编译时 定义的子程序提供了非局部的作用环境。从而允许静态 类型检查,和有效的可执行代码的生成。 没有子程序定义的嵌套,则必须为每个在子程序定义中 的非局部变量提供声明,或将所有非局部引用的类型检 查推迟到运行时, 嵌套的另一好处是作用域管理。允许子程序名具有较少 的作用域
•嵌套的子程序定义 如PASCAL,子程序定义在主程序中作为声明出现,子 程序本身又可含有其他子程序定义。 其目标是强调结构化的语句,但事实上产生了不同用途。 结构化语句的引入主要是为算法结构的常见的层次划分 提供一种自然的注记方式,但嵌套子程序定义为编译时 定义的子程序提供了非局部的作用环境。从而允许静态 类型检查,和有效的可执行代码的生成。 没有子程序定义的嵌套,则必须为每个在子程序定义中 的非局部变量提供声明,或将所有非局部引用的类型检 查推迟到运行时。 嵌套的另一好处是作用域管理。允许子程序名具有较少 的作用域
分开的接口定义 FORTRAN的结构允许分开子程序的非常容易的编译,但 缺点是不同子程序共享的数据可能有不同的定义,而这 种不同是编译器在编译时无法检测到的。 PASCAL允许编译器访问所有这样的定义以帮助发现错 误,缺点是全部程序,即使其有上千条语句,必须在每 次修改后重新编译。 结合上面的技术可以改善编译行为。 程序实现由几个相互交互的子程序构成,这些部件称为 模块,将被连接在一起以创建可执行程序,但每次只有 修改的模块被重编译。而在一个部件中的过程间传送的 数据必须具有公共声明,从而允许编译器的高效检査。 为了在分开的编译模块间传递数据,引入了规约部件, 如C中h文件。Ada中的 Package(接口定义规约+实现 体)
• 分开的接口定义 FORTRAN的结构允许分开子程序的非常容易的编译,但 缺点是不同子程序共享的数据可能有不同的定义,而这 种不同是编译器在编译时无法检测到的。 PASCAL允许编译器访问所有这样的定义以帮助发现错 误,缺点是全部程序,即使其有上千条语句,必须在每 次修改后重新编译。 结合上面的技术可以改善编译行为。 程序实现由几个相互交互的子程序构成,这些部件称为 模块,将被连接在一起以创建可执行程序,但每次只有 修改的模块被重编译。而在一个部件中的过程间传送的 数据必须具有公共声明,从而允许编译器的高效检查。 为了在分开的编译模块间传递数据,引入了规约部件, 如C中.h文件。Ada中的Package(接口定义规约+实现 体)
数据描述和可执行语句分离 COBOL包含了早期的部件结构形式。在 COBOL中,所 有子程序的数据声明和可执行语句被分入不同的程序中 即数据段和过程段,而用环境段包含关于外部操作环境 的声明 个程序的过程段被组织为子单元,以对应子程序体, 但所有数据对所有子程序均是全局的,没有东西对应于 通常子程序中的局部数据 中心化数据段的优点是:强迫形成数据格式和过程段中 算法的逻辑独立性,数据结构的细小修改可只修改数据 段而不需修改过程段。同时将数据描述搜集到一个地方, 而不是散布在子程序中也是方便的方式。 这适合于大量数据的处理。在某种意义是,数据库应用 是这种形式的扩展
•数据描述和可执行语句分离 COBOL包含了早期的部件结构形式。在COBOL中,所 有子程序的数据声明和可执行语句被分入不同的程序中, 即数据段和过程段,而用环境段包含关于外部操作环境 的声明。 一个程序的过程段被组织为子单元,以对应子程序体, 但所有数据对所有子程序均是全局的,没有东西对应于 通常子程序中的局部数据。 中心化数据段的优点是:强迫形成数据格式和过程段中 算法的逻辑独立性,数据结构的细小修改可只修改数据 段而不需修改过程段。同时将数据描述搜集到一个地方, 而不是散布在子程序中也是方便的方式。 这适合于大量数据的处理。在某种意义是,数据库应用 是这种形式的扩展
未分离的子程序定义 不分开主程序和子程序语句,如 SNOBOL4中,程序是 个语句表。 子程序间没有语法分隔,函数调用开始新的子程序执行, 返回语句结束该子程序。 程序作为是动态的。事实上,任意语句可以同时是主程 序的一部分,也可以是子程序的一部分。这体现在该语 句可在主程序的执行中某点被执行,而后又在某子程序 的执行中某点被执行。这种混沌结构仅仅对允许运行时 翻译和相对简单的新语句和子程序执行机制具有价值 Basic 简单的语法,和前述设计目标均有冲突。 主要面向非科学家用户
•未分离的子程序定义 不分开主程序和子程序语句,如SNOBOL4中,程序是 一个语句表。 子程序间没有语法分隔,函数调用开始新的子程序执行, 返回语句结束该子程序。 程序作为是动态的。事实上,任意语句可以同时是主程 序的一部分,也可以是子程序的一部分。这体现在该语 句可在主程序的执行中某点被执行,而后又在某子程序 的执行中某点被执行。这种混沌结构仅仅对允许运行时 翻译和相对简单的新语句和子程序执行机制具有价值。 •BASIC 简单的语法,和前述设计目标均有冲突。 主要面向非科学家用户
32翻译的阶段 ν逻辑上,翻译可分为两个主要部分(输入源程序的分析,可执 行目标程序的综合),两个阶段又可细分。 大多数翻译器的中这些逻辑阶段不是可以明确划分开的,而是 混合在一起使得分析和综合交替进行(通常逐条语句进行)。 编译器通常对源程序扫描两遍 第一遍将程序分解为部件并从程序中导出信息。 第二遍根据这些收集的信息生成目标程序。 如果编译速度是重要的考虑(如教学用编译器),一遍扫描是 用方式,在程序被分析时,立即被翻译为目标代码。 如果执行速度是重要考虑,三遍甚至更多遍扫描也是可能的。 第一遍分析源程序 第二遍使用各种定义好的优化算法将源程序重写为更多效 的形式 第三遍生成目标代码
3.2 翻译的阶段 •逻辑上,翻译可分为两个主要部分(输入源程序的分析,可执 行目标程序的综合),两个阶段又可细分。 •大多数翻译器的中这些逻辑阶段不是可以明确划分开的,而是 混合在一起使得分析和综合交替进行(通常逐条语句进行)。 • 编译器通常对源程序扫描两遍 第一遍将程序分解为部件并从程序中导出信息。 第二遍根据这些收集的信息生成目标程序。 •如果编译速度是重要的考虑(如教学用编译器),一遍扫描是 常用方式,在程序被分析时,立即被翻译为目标代码。 •如果执行速度是重要考虑,三遍甚至更多遍扫描也是可能的。 第一遍分析源程序。 第二遍使用各种定义好的优化算法将源程序重写为更多效 的形式。 第三遍生成目标代码