Compiler construction 编译和解释有什么区别?

Compiler construction 编译和解释有什么区别?,compiler-construction,compilation,interpreter,interpretation,Compiler Construction,Compilation,Interpreter,Interpretation,我刚刚与一位同事进行了一次对话,我们正在讨论V8 JavaScript引擎。根据维基百科 V8在执行之前将JavaScript编译为本机机器代码[…],而不是更传统的技术,如解释字节码或将整个程序编译为机器代码并从文件系统执行 (如果我错了),“解释字节码”是java的工作方式,“编译整个程序”将适用于C语言或C++语言。现在,我们对差异、相似性进行了猜测、辩论和假想。为此,我建议请专家们这样做 那么,谁能做到呢 命名、解释和/或引用所有主要方法(例如预编译与运行时解释) 设想或提供一个关于资料

我刚刚与一位同事进行了一次对话,我们正在讨论V8 JavaScript引擎。根据维基百科

V8在执行之前将JavaScript编译为本机机器代码[…],而不是更传统的技术,如解释字节码或将整个程序编译为机器代码并从文件系统执行

(如果我错了),“解释字节码”是java的工作方式,“编译整个程序”将适用于C语言或C++语言。现在,我们对差异、相似性进行了猜测、辩论和假想。为此,我建议请专家们这样做

那么,谁能做到呢

  • 命名、解释和/或引用所有主要方法(例如预编译与运行时解释)
  • 设想或提供一个关于资料来源、汇编和解释之间关系的方案
  • 给出#1的主要方法的示例(命名编程语言)

  • 注:

    • 我不是在寻找一篇关于不同范式的冗长平淡的文章,而是一篇视觉支持的快速概述
    • 我知道Stackoverflow并不是程序员的百科全书(而是更具体问题的问答平台)。但是,由于我可以找到很多流行的问题,这些问题为某些主题提供了百科全书式的观点(例如,,),我开始了这个问题
    • 如果此问题更适合任何其他StackExchange网站(例如),请让我知道或标记此问题以供审核

    如今,许多执行环境使用字节码(或类似的东西)作为代码的中间表示形式。因此,源代码首先被编译成一种中间语言,然后由虚拟机(对字节码指令集进行解码)解释,或者进一步编译成机器代码,并由硬件执行

    很少有生产语言不经过预编译就被解释成某种中间形式。然而,这样的解释器很容易概念化:只需考虑一个类层次结构,它包含每种类型的语言元素的子类(
    if
    语句,
    for
    ,等等),并且每个类都有一个计算给定节点的
    Evaluate
    方法。这也通常被称为

    作为一个例子,考虑下面的代码片段在一个假设的解释器中实现< <代码>如果语句(在C中实现):

    class-IfStatement:AstNode{
    私有只读节点条件、truePart、falsePart;
    公共IfStatement(AstNode条件、AstNode truePart、AstNode falsePart){
    这个条件=条件;
    this.truePart=truePart;
    this.falsePart=falsePart;
    }
    公共覆盖值求值(EvaluationContext){
    bool yes=condition.Evaluate(context.IsTrue();
    如果(是)
    评价(上下文);
    其他的
    错误部分。评估(上下文);
    返回值.None;/`if`语句没有值。
    }
    }
    

    这是一个非常简单但功能齐全的解释器。

    回答您的问题几乎是不可能的,原因很简单:没有几种方法,它们是一个连续体。这个连续体中涉及的实际代码也相当相同,唯一的区别在于事情发生的时间,以及中间步骤是否以某种方式保存。这个连续体中的各个点(不是一条直线、一个级数,而是一个具有不同角点的矩形,您可以靠近它)是:

  • 读取源代码
  • 理解代码
  • 执行你所理解的
  • 缓存沿途的各种中间数据,甚至持久地将它们保存到磁盘
  • 例如,一种纯粹的解释的编程语言几乎不执行#4和#2在1和3之间隐式发生,因此您几乎不会注意到它。它只读取代码的部分,并立即对它们作出反应。这意味着实际开始执行的开销较低,但在循环中,相同的文本行会被读取并再次读取

    在矩形的另一个角落,有传统的编译的语言,其中#4项通常包括将实际机器代码永久保存到文件中,然后可以在以后运行。这意味着您在开始时要等待相当长的时间,直到整个程序被翻译(即使您只调用其中的一个函数),但是OTOH循环更快,因为不需要再次读取源代码

    还有一些介于两者之间的东西,例如一个虚拟机:为了便于移植,许多编程语言不编译成实际的机器代码,而是编译成字节码。然后是一个生成字节码的编译器和一个接受字节码并实际运行它的解释器(有效地“将其转换为机器码”)。虽然这通常比编译和直接转到机器代码要慢,但将这种语言移植到另一个平台更容易,因为您只需移植字节码解释器,它通常是用高级语言编写的,这意味着您可以使用现有的编译器来执行“有效的机器代码翻译”,而且不必为每个要运行的平台创建和维护后端。此外,如果您可以对字节码执行一次编译,然后只分发编译后的字节码,这样其他人就不必花费CPU周期(例如,在您的代码上运行优化器),只需支付字节码到本机的转换费用,这一点在您的用例中可以忽略不计。而且,您没有分发源代码

    中间还有一件事