所以,让我看看我是否明白这一点。
当我们说编译器和解释器之间的区别时,解释器将高级指令翻译成中间形式,然后执行。[我认为编译器也将高级指令转换为中间形式,但此时它生成目标代码而不是执行它,对吗?]
解释器一次读取一条指令或一行的源代码,将这一行转换为机器代码并执行它。 [解释器本身不会将代码转换为机器代码,它使用自己的预编译函数来评估指令(在解析之后)。例如,高级语言中的 Add 表达式将使用先前编译的解释器 add 函数进行评估,对吗?]
所以,让我看看我是否明白这一点。
当我们说编译器和解释器之间的区别时,解释器将高级指令翻译成中间形式,然后执行。[我认为编译器也将高级指令转换为中间形式,但此时它生成目标代码而不是执行它,对吗?]
解释器一次读取一条指令或一行的源代码,将这一行转换为机器代码并执行它。 [解释器本身不会将代码转换为机器代码,它使用自己的预编译函数来评估指令(在解析之后)。例如,高级语言中的 Add 表达式将使用先前编译的解释器 add 函数进行评估,对吗?]
关键区别在于:解释器在运行源代码时对其进行处理。它不会将源代码转换为机器代码,它只是使用自己的代码来完成源代码的指示。编译器将源代码转换为可以直接运行的机器代码。
并非所有编译器都与执行过程分开。例如,大多数 Java 运行时都包含一个“JIT 编译器”,它根据需要在 Java 代码运行时对其进行编译。
你可以有一些介于两者之间的东西。本质上,可以首先使用类似于编译的过程将源代码转换为更小且更易于解释的东西。然后可以解释这个编译的输出。(例如,第一遍可以转换,比如 'if' 到 53,'else' 到 54,'for' 到 55,等等 - 这将使解释器不必处理代码中的可变长度字符串实际上并不处理字符串。)
我同意第一个,尽管解释器一次只处理一行并不一定是真的(它可以根据对整个代码的了解进行优化)。
我认为第二个有点偏离:编译器确实创建了“机器代码”(对于 JVM,它可能是字节码)。解释器根据输入执行自己程序的一部分(到目前为止与编译器相同),这些执行的部分正在执行输入中描述的计算(而不是执行计算以计算所需的机器代码)。
可能会模糊两者之间的界限,因为编译器可以生成将在执行时解释的代码(根据编译时不可用的因素提供运行时优化)
你是对的(1)。
广告(2),解释器不需要一次读取一条指令的源代码,因为在解释包含循环的代码时这太昂贵了。更有可能的是,它读取整个表达式、语句、函数甚至源文件,将它们转换为中间格式并对其进行评估。
请注意,编译器和解释器都不需要在任何时候生成机器代码;许多编程语言,包括 Java、Python,以及像 Prolog 这样的旧语言,通常都被编译为虚拟机字节码。在 Python 和 Prolog 中,“解释器”通常是字节码编译器/字节码解释器的组合。
我所知道的关于编译和解释的最好的介绍是SICP的第 4 章和第 5 章,它们从讨论一个非常简单的解释器开始,然后迭代地改进它,直到它成为一个成熟的编译器。
S -> T 翻译器接受以源语言 S 表达的代码,并将其翻译成以另一种(目标)语言 T 表达的等效代码。
翻译示例:
S 解释器接受用语言 S 表达的代码,并立即执行该代码。它通过一次获取、分析和执行一条指令来工作。
当用户以交互方式输入指令(想想 Python)并希望在输入下一条指令之前获得输出时非常棒。当程序只执行一次或需要可移植时也很有用。
行为
表现
解释性编译器
解释性编译器是编译器和解释器之间的一个很好的折衷。它将源程序翻译成虚拟机代码,然后进行解释。
解释性编译器将快速翻译与适度快速执行相结合,前提是:
示例:JDK 为 Java 提供了一个解释性编译器