在读者阅读本篇文章前,建议优先阅读专栏内前面的文章。
目录
前言
本文主要根据龙书来介绍关于编译原理部分的第一章,也就是一些基础的知识。
一、程序设计语言发展历程
第一台电子计算机出现在20世纪 40 年代。它使用由0、1序列组成的机器语言编程,这个序列明确地告诉计算机以什么样的顺序执行哪些运算。运算本身也是很低层的,把数据从一个位置移动到另一个位置,把两个寄存器中的值相加,比较两个值等等。不用说,这种编程速度慢且枯燥,而且容易出错。写出的程序也是难以理解和修改的。到了 50 年代,汇编语言出现,它用 LOAD、ADD、JMP 这类助记符代替二进制机器码,使程序员不用直接记忆一长串 0 和 1,同时宏指令的加入又让常用指令序列可以被封装复用,这是程序设计语言第一次明显向"人类可读"迈进。

随后高级语言开始出现,Fortran面向科学计算和数值计算,适合表达公式、循环和数组运算,Lisp面向符号处理、递归和人工智能研究,Cobol面向商业数据处理,Basic则因为语法简单被大量用于教学和个人计算机入门,这一阶段的核心变化是程序员开始不再关心每一条机器指令,而是用更抽象的语句描述计算过程。

60年代到70年代,ALGOL 58、ALGOL 60、ALGOL 68 等语言对后来的程序语言影响巨大,尤其是块结构、词法作用域、递归、形式化语法描述等思想,推动了结构化程序设计的发展,Pascal、Modula、Modula-2 等语言都继承了这一传统,强调清晰的程序结构、类型检查和模块化组织。

同一时期,CPL、BCPL、B逐渐演化出C语言,C既保留了接近硬件的能力,又具备高级语言的表达形式,因此特别适合编写操作系统、编译器、驱动程序和底层工具,Unix系统与C语言的结合让 C成为系统编程领域的核心语言,并深刻影响了后来的C++、Objective-C、Java、C#、Go、Rust 等语言。

与此同时,面向对象思想也开始形成,Simula 67最早系统性地引入类和对象的概念,Smalltalk将"一切皆对象"的思想推向极致,后来Objective-C将Smalltalk风格的消息机制与C结合,影响了苹果早期软件生态,C++则在C的基础上加入类、继承、多态、模板等机制,让面向对象和高性能系统编程结合起来,成为大型软件、游戏引擎和底层开发的重要语言。

80年代到90年代,脚本语言和胶水语言快速发展,Shell、Awk、Perl主要用于文本处理、系统管理和自动化任务,Python受到ABC等语言影响,追求简洁、易读和快速开发,Ruby强调开发者体验,PHP推动早期动态网站开发,Lua以轻量嵌入式脚本的形式广泛用于游戏和插件系统,这些语言的共同特点是编写速度快、语法灵活、适合把多个工具或系统连接起来。

90年代以后,互联网和企业级软件推动了新一代语言的发展,Java提出虚拟机和"一次编写,到处运行"的理念,适合跨平台企业应用、后端服务和Android开发,C#依托.NET生态形成完整的企业开发体系,JavaScript借助浏览器成为Web前端的核心语言,后来又通过Node.js进入后端开发,使同一种语言可以同时服务前端和服务器端。

进入2000年代和2010年代后,软件规模越来越大,语言设计开始更加重视类型安全、并发能力、内存安全、开发效率和工程维护,TypeScript在JavaScript之上加入静态类型,解决大型前端项目难维护的问题,Go由Google推出,语法简洁、编译快、并发模型清晰,适合云计算、微服务和网络服务,Rust则强调所有权、借用检查和内存安全,希望在不依赖垃圾回收的情况下避免空指针、悬垂指针和数据竞争,Kotlin在Java生态上改进语法冗余和空指针问题,成为Android开发的重要语言,Swift 作为苹果生态的新语言,试图用更现代、安全和简洁的方式替代Objective-C,Dart则依托 Flutter 进入跨平台应用开发领域。到了更近的阶段,Carbon 等新语言尝试在继承 C++ 生态优势的同时改善语言复杂度、安全性和现代工程体验。

总体来看,程序设计语言的发展不是简单的"旧语言被新语言淘汰",而是不断在不同需求之间寻找平衡:机器语言和汇编语言强调对硬件的精确控制,Fortran、Cobol、Lisp、Basic 让人们能用更高层的方式表达科学计算、商业处理、符号推理和教学程序,ALGOL、Pascal、Modula 推动了结构化和模块化思想,C 和 C++ 代表了系统性能与抽象能力的结合,Smalltalk、Java、C#、Ruby 等推动了面向对象编程,Shell、Perl、Python、PHP、JavaScript 等扩展了自动化、Web 和快速开发场景,而 Go、Rust、Kotlin、TypeScript、Swift、Dart 等现代语言则更加关注大型工程、跨平台生态、并发、安全性和开发体验;因此,程序语言的发展本质上就是计算机科学、硬件体系结构、软件工程方法和实际应用需求共同推动的结果,每一种重要语言的出现,通常都不是凭空产生,而是为了解决当时已有语言在效率、可读性、安全性、可维护性或应用场景上的某些不足。
二、对编译器的影响
因为程序设计语言的设计和编译器是紧密相关的,程序设计语言的发展向编译器的设计者提出了新的要求。他们必须设计相应的算法和表示式来翻译和支持新的语言特征。从 20 世纪 40 年代以来,计算机体系结构也有了很大的发展。编译器的设计者不仅需要跟踪新的语言特征,还需要设计出新的翻译算法,以便尽可能地利用新硬件的能力。通过降低用高级语言程序的执行开销,编译器还可以推动这些高级语言的使用。要使得高性能计算机体系结构能够高效运行用户应用,编译器也是至关重要的。实际上,计算机系统的性能是非常依赖于编译技术的,以至于在构建一个计算机之前,编译器会被用作评价一个体系结构概念的工具。编写编译器是很有挑战性的。编译器本身就是一个大程序。而且,很多现代语言处理系统在同一个框架内处理多种源语言和目标机。也就是说,这些系统可以被当做一组编译器来使用,可能包含几百万行代码。因此,好的软件工程技术对于创建和发展现代的语言处理器是非常重要的。编译器必须能够正确翻译用源语言书写的所有程序。这样的程序的集合通常是无穷的。为一个源程序生成最佳目标代码的问题一般来说是不可判定的。因此,编译器的设计者必须作出折衷处理,确定解决哪些问题,使用哪些启发式信息,以便解决普遍发生的问题我们将在之后看到,有关编译器的研究也是有关如何使用理论来解决实践问题的研究。
总结
本文基于龙书梳理了程序设计语言的发展历程及对编译器的影响。从20世纪40年代的机器语言到50年代汇编语言,再到高级语言如Fortran、Lisp等的出现,语言不断向人类可读性迈进。60-70年代结构化程序设计兴起,80-90年代面向对象和脚本语言发展,2000年后更注重类型安全、并发等现代需求。语言发展是硬件、软件工程和应用需求共同推动的结果。同时,语言演进也推动编译器技术发展,编译器需适应新语言特性并优化硬件利用,其设计涉及算法创新与工程实践平衡。编译技术对计算机性能至关重要,是现代语言处理系统的核心。