我读过一些关于编译程序和解释器之间差异的答案。他们中的大多数人在解释口译员的工作方式时会说:
它每次执行一行程序,并在运行它之前翻译每一行:它翻译第一行并运行它,然后翻译第二行并运行它,等等。
(来自解释器/编译器的工作原理)
这就是让我困惑的地方——从高级语言到机器代码的翻译被称为编译。根据定义(https://en.wikipedia.org/wiki/Compiler).
那么,说高级语言的解释器由编译器而不仅仅是翻译器组成,对吗?
事实上,编译器和解释器的区别在于输入和输出的类型,而不是它们的工作方式。简而言之,解释器接受一些程序和输入,并产生一些输出,而编译器接受一些程序,并产生一个程序,给定的输入产生一些输出。
你的问题很有趣,简短的回答是“它可以但不一定要,反之亦然,但不一定要”,但为了达到目的,我们需要建立一些概念。
编程语言L是理解它的程序的某种方法,即把程序P解释为“从输入到输出的函数”。让我们为这个函数写[[P]]_L,即[[P]]_L(In)=Out。(把这个 [[.]] _L想象成“L中的意义”函数,即对L的解释)。
现在假设你有两种语言,L1和L2(让L1不同于L2,尽管通常情况下不需要这样)。
如果你只有解释L1程序的手段(例如L1是你的计算机的机器语言),有[除其他外?]这两种可能性来计算任何L2程序的[[P]]_L2,即为任何L2程序和任何输入计算[[P]]_L2(In):
(1) 你确实有一个L1程序INT,比如[[INT(P,In)]][uL1=Out=[P]][uL2(In)],或者
(2) 你确实有一个L1程序COMP,这样[[COMP(P)]]L1=P',这样[[P']L1=[[P]]L2,也就是说,[P']L1(In)=[[P]]L2(In)对于任何输入。
这种想法的主要简化是,L1和L2都使用相同的数据类型,但情况可能并非如此(但引入在其他数据类型中解释一种数据类型会让事情变得更加扭曲)。还要注意的是,输出可能包含副作用(比如I/O,或者一些db更新/删除,等等)——但这在现在并不重要。
那么INT是L1中L2的解释器,而COMP是从L2到L1的编译器,我相信这是总体上唯一有意义的区别。
INT这样工作没有问题:取P和In,用COMP编译P,在In上执行结果,然后返回它的值。这就是JIT编译口译员的工作方式。INT也可以将P编译成另一种语言L3,然后用一些L3解释器执行它——这就是基于VM的解释器的工作方式。
现在,令人兴奋的部分是:您可以通过部分求值的方式生成一个编译器COMP(从L2到L1),其中包含一个解释器INT(对于L1中的L2),如注释中提到的SK逻辑。非常简单(读:谎言!),注意,从In到Out所需的L1“操作”存在于INT的代码中。想象一下某种机制,它不是只执行INT的这些部分,而是“写下它们”。最后一个“写下的操作堆”是一个L1程序P’,它给出了In,并给出了Out,就像最初的L2程序P一样。换言之,“编辑推迟解释”。这就是Futamura的预测。你可以在这里找到很多论文(其中很多是免费提供的)http://readscheme.org/partial-eval/index.html
简而言之,你可以从编译器中生成一个解释器(例如通过jit编译和执行),也可以从解释器中生成一个编译器(例如通过IInd Futamura投影)。
再一次:区别只在于口译员/编译器消耗了什么,以及他们产生了什么。他们的工作方式是“他们自己的事”。
不,解释器不是编译器,尤其不是“根据定义”。本质上,解释器在编译器翻译时执行。解释器读取代码,然后根据代码改变解释器的状态。它调用解释器所用语言的库来执行网络事务等副作用。另一方面,编译器输出一组指令,这些指令执行代码用另一种“语言”描述的内容,例如x86机器代码。它会插入预先编写的机器代码位,以执行正在编译的代码中的副作用。
然而,在实践中,这些想法有很大的重叠,尤其是在Python、Java和Java等较新的语言中。网通常,代码会被编译成字节码,然后由字节码解释器执行,或者JIT再次编译成机器码。例如,在Python中,解释器包含所有这些内容,使其成为一个将编译工作记录在内存中的解释器。pyc文件。
问题内容: 我对JVM有一个非常基本的问题:它是编译器还是解释器? 如果它是解释器,那么JVM内部存在的JIT编译器怎么办? 如果两者都不是,那么JVM到底是什么?(我不希望将字节码转换为机器特定的代码等jVM的基本定义。) 问题答案: 首先,让我们对以下术语有一个清晰的认识 是Java编译器-将Java代码编译为 Bytecode 是Java虚拟机-运行/解释/将字节码转换为本 机代码 是即时编
问题内容: 为什么我们说Java是一种编译和解释语言? (编译和解释)这样做有什么好处? 问题答案: Java在编译时被编译为中间的“字节码”。这与像C之类的语言在编译时被编译为机器语言相反。Java字节代码无法像编译的C代码那样直接在硬件上执行。相反,字节码必须在运行时由JVM(Java虚拟机)解释才能执行。像C这样的语言的主要缺点是,当编译该二进制文件时,该二进制文件将仅在一种特定的体系结构(
那么,让我看看我是否明白了这一点。 > 当我们说编译器和解释器之间的区别时,解释器将高级指令翻译成中间形式,然后执行。[我认为编译器也将高级指令翻译成中间形式,但此刻它生成目标代码而不是执行它,对吗?] 解释器一次读取一条指令或一行的源代码,将该行转换为机器代码并执行它。[解释器本身不会将代码转换为机器代码,它会使用ist自己的预编译函数评估指令(在解析之后)。例如,高级语言中的Add表达式将使用
翻译的结果是什么?它会把高级语言变成汇编语言还是机器语言,即二进制代码? 如果是后者,这是否意味着解释语言与介绍集没有关系? 一种语言只能有一个口译员?是因为解释器不做任何优化,所以我们不需要找到更好的解释器吗?
问题内容: 我正在学习Java,以下内容对我来说有些混乱。我了解的是: Java编译器 →Java编译器仅将程序转换为文件,这意味着将我们的源代码转换为字节码(这是使Java平台独立的虚拟机(JVM)的操作码的列表)。 Java Interpreter →仅“解释”代码,而 没有 将其转换为本地机器代码。它将一条字节码的每条指令作为一条命令一一执行并执行,而不管同一条指令出现多少次。这就是为什么它
我正在学习Java,下面的事情让我有点困惑。我的理解是: > Java编译器→Java编译器只是将程序转换为文件,这意味着将我们的源代码转换为字节码(它是虚拟机(JVM)的操作代码列表,使Java平台独立)。 Java解释器→只是“解释”代码,而不是将其转换为本机机器代码。它将字节码的每一条指令作为命令逐一执行并执行,而不管同一条指令发生多少次。这就是为什么它很慢,Java引入了JIT概念。 JI