“没有”编译语言“或”解释语言“这样的东西。语言实现者是选择编写编译器,解释器还是其中的任何东西都是实现细节而与语言无关。 “
以上陈述是否属实?
答案 0 :(得分:14)
是的,在最严格的解释中也是如此。例如,您可以找到C++ interpreter和Javascript compiler。但是,您会发现某些类型的语言(例如静态类型)非常适合本机代码编译。其他语言(例如,动态类型)通常使用字节码编译与虚拟机执行环境相结合来实现。
答案 1 :(得分:3)
排序。通常,解释器和编译器首先需要解析源代码并将其转换为表示,称为AST(抽象语法树)。编译器然后将AST转换为可执行代码(通过各种转换),而解释器可能只是直接“解释”AST或有时编译并执行它(即时编译)。
该陈述是正确的,因为这与语言无关:理论上,您可以为任何语言编写解释器和编译器。使用哪一个确实取决于用例,场景和环境。
编译器的优势在于,无论您执行程序的频率如何,他只需要完成一次工作。解释器需要每次解析源(或进行一些缓存),因此每次执行都会产生开销,这可能比最终程序的实际执行时间长。另一方面,解释器更灵活(它可以考虑当前环境,因此不允许编译器进行优化)。但差异并不止于此,这只是两个显而易见的要点。
答案 2 :(得分:1)
语言设计与更高级别输入部分的语法和在目标上执行的更低级别输出代码有关。
两者之间有一个抽象的语法树。
传统上,如果您编写较低级别的输出代码以在特定硬件平台及其特定指令集上执行,则输出将被“编译”。
如果有人决定编写解释器作为目标,则输出代码是解释器期望的指令集或字节代码。额外的间接级别意味着解释的代码可以在任何具有解释器实现的硬件平台上运行。
因此,如果我们将“语言设计”称为语法和词法分析器/解析器片段,则该语句是正确的。
如果我们谈论代码生成器,那么这不是严格正确的。
只需通过调用不同的代码生成器来遍历AST,就可以发出特定语言,只需解释和编译。
所以也许这就是区别模糊的方式。但我认为它仍然存在。
答案 3 :(得分:0)
以上陈述属实。
然而,有人可能会认为它在现实世界中不够真实。如果语言的所有现有实现都依赖于编译,那么该语言可以合法地称为编译语言。
答案 4 :(得分:0)
仅在最终编译语言和解释语言必须生成机器代码的意义上才是真的。它确实对语言有影响,因为传统上某些范例在一个方面比另一方更容易。例如,通常,闭包或块在编译语言中比编译语言更容易实现。这是正确的,因为在解释语言中编译时间和运行时范围之间实际上没有区别。因此动态范围TENDS更易于在解释语言中实现。
答案 5 :(得分:0)
语言的给定实现将是“纯”编译器(其输出由处理器作为代码执行),“纯”解释器(每个语句首次以原始源形式检查,因为它被执行,并且没有任何关于解释的缓存),或两者之间的混合。将“纯粹”案例与混合案件区分开来很容易,但有些混合物比其他混合物“更接近”。 “编译”混合与“解释”混合之间的界限可能相当模糊。
除了汇编语言(“汇编程序”一词通常优先于“编译器”使用)之外,我认为任何语言都没有实际用途,而这种语言在混合中至少在某种程度上无法实现解释器(“纯粹”解释器的表现除了最微不足道的循环结构之外几乎都是可怕的)。但是,有些语言允许以不适合编译的方式生成动态代码。
顺便说一句,当我说“原始来源”表格时,我并不总是指文字格式。我的第一个可编程计算器有99个程序步骤,每个步骤都可以配置击键或一些特殊的排序指令。该程序本身不会以人类可读的文本形式存在,而是作为一系列关键数字存在。尽管如此,我会将其描述为纯粹解释的“语言”,因为每个程序步骤都是完全独立评估的。
答案 6 :(得分:0)
整个编译器/解释器的东西取决于你对程序的意图。已编译的程序是一个转换为机器代码的程序。解释器用于读取中间语言并在计算机上运行。例如,当您编译Java时,它将转换为Java字节码并由解释器读取并运行(与C ++相比,这也解决了速度劣势)。
我并不认为你关于它与语言无关的陈述是完全正确的。关于Java的一个主要问题是它应该可以在不同的体系结构上运行。如果编译那是不可能的。
答案 7 :(得分:0)
值得注意的是,对于(某些?)包含“eval”类型语句的语言(特别是如果在运行时无法确定给定块是代码还是数据),即使是最纯粹编译的版本必须部分解释给定的程序。对于这样的语言,不可能完全编译它们(编译后的代码必须包含该语言的解释器)。
例如,请考虑以下代码:
set s [eval {sum $a $b $c}]
对于上面的Tcl代码,直到运行时才能确定块({}内部)是否为代码。