编译器 vs 解释器(基于构建和设计的比较)

8

在看了很多编译器和解释器之间的区别的文章之后,我仍然无法理解它们的构造和内部机制的区别。

我读到的最常见的区别是,编译器产生一个目标程序,该程序可以在系统上运行并接受输入。而解释器只是逐行运行输入,并产生输出。

我的主要疑问是:

1)编译器由词法分析器、解析器、中间代码生成器和代码生成器组成,但解释器的组成部分是什么?

2)谁给解释语言提供运行时支持,我的意思是谁管理递归函数的堆栈?

3)这是针对Python语言的:
Python包括编译器阶段和解释器阶段 编译器会产生一些字节码,然后这些字节码会被其虚拟机解释执行。
如果我只设计Python(Python -> bytecode)的编译器

a)我需要管理内存吗?

b)这个编译器与传统的编译器或解释器有什么不同?

我知道这里要问很多问题,但我真的想理解这些细节。

我参考了Alfred V. Aho的《编译器书籍》。


根据反馈和进一步研究,我认为我应该修改我的问题

编译器不必只产生机器代码作为输出

但是还有一个问题在困扰着我,假设我想设计一个(Python -> bytecode)编译器,然后字节码将由虚拟机解释执行(如果我错了,请纠正我)。
那么我需要为Python编写词法分析器,然后是生成某种抽象语法树的解析器...之后,我是否需要生成一些中间代码(如“龙书”中提到的3地址代码)或直接生成字节码指令(我想这些指令会在VM的文档中给出)?

我是否还需要编写处理堆栈的代码来支持递归和作用域?


你在一个帖子中问了太多问题,但是关于(2)“谁为解释型语言提供运行时支持”,答案通常是libc,即C运行时库被许多解释器使用,如果不是大多数。 - John Zwinck
“逐行” - 我认为并非所有解释器都是如此。有些解释器可能会将形成逻辑单个语句的多行编译成字节码,然后执行。而其他一些则实际上解释原始文本并立即执行它,就像 bash - Johannes Schaub - litb
抱歉 @john Zwinck,我在 (2) 方面的意思是,谁负责解释语言的内存管理。 - ajish
编译器将一种语言转换成另一种语言。大多数解释器由一个编译器和一个执行该字节码的虚拟机组成。 - Cat Plus Plus
2
@CatPlusPlus:后一点(很重要)可能更清晰地表述为:许多称为解释器的语言实现实际上是针对虚拟机和该虚拟机指令集的编译器以及解释器。 - user395760
https://dev59.com/b3A75IYBdhLWcg3wfpKr#69371092 - Buddhika Chathuranga
1个回答

5
首先,“编译器”并不意味着“输出机器代码”。你可以从任何语言编译到任何其他语言,无论是高级编程语言、某些中间格式、虚拟机(字节码)的代码还是物理机器(机器码)的代码。
像编译器一样,解释器需要读取和理解它实现的语言。因此,你有相同的前端代码(尽管今天的解释器通常只实现更简单的语言 - 只有字节码;因此这些解释器只需要非常简单的前端)。与编译器不同,解释器的后端不生成代码,而是执行它。显然,这是一个完全不同的问题,因此解释器看起来与编译器非常不同。它模拟计算机(通常比现实生活中的机器更高级),而不是产生等效程序的表示形式。
假设使用了今天的某种相对高级的虚拟机,这就是解释器的工作——其中专门有用于调用函数和创建对象的指令,并且垃圾回收已经内置在虚拟机中。当你针对较低级别的机器(例如x86指令集)时,许多这样的细节需要被编入生成的代码中,直接编写(系统调用或其他方式)或通过调用C标准库实现。
a) 可能不需要,因为专门针对Python的虚拟机不需要它。这将非常容易出错,不必要,而且可以说与Python语义不兼容,因为它允许手动内存管理。另一方面,如果你要针对像LLVM这样的低级别目标,就必须特别小心——具体细节取决于目标语言。这就是为什么没有人这样做的原因之一。
b) 这将是一个完全正常的编译器,显然不是解释器。你可能会有比针对机器代码的编译器更简单的后端,并且由于输入语言的性质,你不需要做太多的分析和优化,但是没有根本的区别。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接