编译器与编程语言发展历程

参考互联网上的相关资料,编译器与编程语言几乎是同步发展起来的,发展过程可以分为几个阶段:

  • 第一阶段是20世纪50年代,出现了第一个编译程序,将算术公式翻译成机器代码,为高级语言的发展奠定了基础。
  • 第二阶段是20世纪60年代,出现了多种高级语言和相应的编译器,如FORTRAN、COBOL、LISP、ALGOL等,编译技术也逐渐成熟和规范化。
  • 第三阶段是20世纪70年代,出现了结构化程序设计方法和模块化编程思想,以及面向对象的语言和编译器,如Pascal、C、Simula等,编译技术也开始注重- 的可读性和可维护性。
  • 第四阶段是20世纪80年代,出现了并行计算机和分布式系统,以及支持并行和分布式的语言和编译器,如Ada、Prolog、ML等,编译技术也开始考虑程序的- 性和分布性。
  • 第五阶段是20世纪90年代至今,出现了互联网和移动设备等新兴平台,以及支持跨平台和动态特性的语言和编译器,如Java、C#、Python等,编译技术也开始关注程序的安全性和效率。
    在发展过程中也伴随着编译理论体系的逐步成熟,一些关键也成为了实现编译器必不可少的部分,如:有限状态自动机、上下文无关文法、属性文法等。

现代的编译体系与编程语言

在 21 世纪后仍然有许多新兴的编程语言,如函数式编程语言Haskell,优秀的内存安全性与性能的Rust,用于微服务的 Go,基于JVM 平台的Android 官方开发语言 Kotlin,Apple平台的Swift等。这些新的编程语言设计之初都有着不同的侧重点,并且相比老牌编程语言拥有着更加优秀的表达能力,伴随着也拥有着完善的编译体系,比如有强大的lint静态分析工具,以及更出色的编译期优化。优秀的语言与编译套件固然能大大提升软件开发效率。

基础设施

不过新兴编程语言的快速发展少不了基础设施的逐步完善。LLVM (原Low Level Virtual Machine)的出现,可以让任意编程语言前端编译到一个LLVM中间表示(IR),再由LLVM 中的后端编译至任意平台(指LLVM 所支持的大多数主流平台),并且可以在多个阶段中实现优化。LLVM 极大地简化了编程语言编译器的开发过程,不同语言只需要实现语言到LLVM IR的前端编译程序,再调用LLVM后端编译器,就可以得到编译至任意平台的能力,而无需为不同的平台实现不同的编译器。如Rust和Swift 的编译器就使用了 LLVM 作为后端。不过随着时代发展,其他语言也能通过 GCC(GNU Compiler Collection)的 IR来实现最终编译阶段,目前 Rust社区也在积极尝试使用GCC作为后端的编译器,以使用 GCC 的优化和平台支持。
值得一提的是,正如如上文所述,LLVM和 GCC(原GNU C-Compiler) 如今已不再是某个具体的工具,而已然成为了一套编译基础设施。LLVM 和 GCC 不仅提供了一系列编译器,也主要提供了一些C/C++语言相关工具,如 LLVM 的Clang工具链(包含clang-tidy、clang-format)。
一些语言的分析工具:

  • 代码格式化工具:自动格式化代码,使代码符合固定格式,提高代码可读性。
  • 静态代码分析工具:一般在编译期间运行,来检测出代码中的问题和漏洞。如clang-tidyrust-clippyclangd(LSP)rust-analyzer(LSP)
  • 动态代码分析工具:在运行时分析,一般比静态分析更能发现一些潜在的漏洞,诸如一些C/C++的内存检测工具,用于检查内存泄露以及异常内存使用并能返回问题代码位置。

虚拟机与优化

一些语言(如 Java、Python、JavaScript)的运行依赖于运行时(Runtime)并常常带有虚拟机(VM)和解释器。这些语言有是脚本语言不需要编译,或者是可编译为跨平台的字节码。不过这些语言性能通常较静态且直接编译为机器码的语言低许多,原因也是很明显的,因为其需要在运行时先解释代码再执行。
不过如今也有许多技术手段能够提升这些语言的性能。下文将主要以 JVM平台调优举例说明。

  • JIT(Just In Time):即时编译,在程序运行时将源代码或字节码编译成机器码,提高执行效率。使用 JIT 可以避免热点代码的重复解释,虚拟机可以在运行时实施动态优化,检测并将热点代码编译成机器码。缺点是会增加启动时间和内存占用。
  • AOT(Ahead Of Time):预编译,运行前将代码编译成机器码,获得更少的启动时间和内存占用以及更接近原生的性能,甚至不再需要依赖于虚拟机。但是随之 来缺陷的就是失去了“一次编译,处处使用”的跨平台特性,以及一些语言的动态特性。
  • 虚拟机优化:OpenJDK 有许多不同的实现,不同的实现也有着不同的性能,其中比如Oracle 的HotSpot JVM(with GraalVM’s advanced JIT optimizing compiler)对 JIT 有额外的优化编译器。

未来编译器与语言发展趋势

根据现代语言发展的情况来看,跨越不同编程语言之间的鸿沟变得越来越小,语言也逐渐在一些方面趋同。比如如今在 JVM 平台上可以运行多种语言,甚至可以通过使用GraalVM Compiler对接 LLVM,使得C/C++、Rust 代码得以在 JVM 上运行,实现多语言之间无缝调用。反之,在底层平台逐步扩大的同时,上层的语言也变得能够扩张到任何平台,比如 Java、Kotlin 最初在JVM 上运行,到可以编译为原生机器码或者WASM在WebAssembly平台上运行。
不过,在另外的一个方面,迅速发展的 AI领域,AI 编程也变得不再遥远。如今,AI 能够帮助人们编写一些代码,再到未来 AI 拥有完全的编程能力,AI 能自主完成任意项目的编程工作,迅速编写一套操作系统或是大型软件都不在是问题。如果到了那个时候,任何的编程语言都不再是编译的关键。再往大胆一点的构想,AI 自身是如今的这个编译器,输入的自然语言(或抽象需求,下同)也就是今天的编程语言。如果今天的编程、编译过程可以看做自然语言到编程语言再到机器码的两阶段过程。此时,AI 就实现了自然语言直接到机器码的一步转换,那必然是编程、编译效率的极大提升。