【问题标题】:How does an interpreter translate a for loop?解释器如何翻译 for 循环?
【发布时间】:2017-07-31 06:18:16
【问题描述】:

我了解解释器将您的源代码逐行翻译成机器代码,并在遇到错误时停止。

我想知道,当你给它 for 循环时,解释器会做什么。

例如我有以下(MATLAB)代码:

for i = 1:10000

pi*pi

end

它真的会遍历并逐行翻译 for 循环 10000 次吗?

使用编译器,机器代码更短,仅由一组语句组成,其中包括对 10000 次迭代有效的 go to control 语句。

如果这没有意义,我很抱歉,我对编程的基本细节不是很了解,但我想快速理解。

【问题讨论】:

    标签: compilation compiler-construction interpreter


    【解决方案1】:

    我了解解释器将您的源代码逐行翻译成机器代码,并在遇到错误时停止。

    这是错误的。有许多不同类型的解释器,但很少有逐行执行代码的解释器(主要是 shell)根本不会生成机器代码。

    一般来说,解释代码有四种或多或少的常见方式:

    • 逐语句执行

      这大概就是你所说的逐行的意思,除了通常分号可以用作换行符的替代品。正如我所说,这几乎只能由 shell 完成。

      它的工作原理是一次解析一个语句。那就是解析器读取标记,直到语句完成。对于直到到达语句终止符的简单语句,例如行尾或分号。对于其他语句(例如 if 语句、for 循环或 while 循环),直到找到相应的终止符(endif、fi 等)。无论哪种方式,解析器都会返回语句的某种表示形式(通常是某种类型的 AST),然后执行。任何时候都不会生成机器代码。

      这种方法有一个不寻常的特性,即文件末尾的语法错误不会阻止文件开头的执行。但是,所有内容仍最多解析一次,即使条件为假,if 语句等的主体仍将被解析(因此if false 中的语法错误仍将中止脚本)。

    • AST-walking 解释

      这里一次性解析整个文件并从中生成一个 AST。然后解释器简单地遍历 AST 来执行程序。原则上和上面一样,只是先解析整个程序。

    • 字节码解释

      同样,整个文件被一次解析,但解析器生成的不是 AST 类型的结构,而是某种字节码格式。然后这个字节码被逐条执行。

    • JIT 编译

      这是唯一实际生成机器代码的变体。这有两种变体:

      • 在调用之前为所有函数生成机器码。这可能意味着在加载整个文件后立即翻译整个文件,或者在调用每个函数之前翻译它。代码生成后,执行。
      • 首先解释字节码,然后在执行多次后分别对特定函数或代码路径进行 JIT 编译。这使我们能够根据在解释期间收集的使用数据进行某些优化。这也意味着我们不需要为不经常调用的函数支付编译开销。一些实现(特别是一些 JavaScript 引擎)还会重新编译已经 JIT 过的代码,以根据新收集的使用数据进行优化。

    总而言之:逐行(或者更确切地说是逐语句)执行代码的实现与生成机器代码的实现之间的重叠应该非常接近于零。而那些逐语句执行的实现仍然只解析一次代码。

    【讨论】:

    • 对不起,如果没有生成机器码,如何在机器上执行指令?谢谢!
    • @mzoz 我相信这些语句被解释和执行,而不是编译成二进制指令并执行。
    猜你喜欢
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-04
    • 1970-01-01
    • 2021-02-20
    相关资源
    最近更新 更多