问题标签 [interpreter]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
4 回答
1608 浏览

compiler-construction - 字节码解析指令和机器语言之间的区别?

“字节码程序通常通过一次解析一条指令来执行。这种字节码解释器非常便携。一些称为动态翻译器或“即时”(JIT)编译器的系统将字节码翻译成机器语言在运行时根据需要:这使虚拟机不可移植。”

关于这一段的一个问题是:字节码被处理后,解析后的指令和机器语言(或机器码)有什么区别?

0 投票
6 回答
4466 浏览

python - 为什么python在解释之前将源代码编译为字节码?

为什么python在解释之前将源代码编译为字节码?

为什么不直接从源头解释呢?

0 投票
5 回答
1498 浏览

java - 如何在基于抽象语法树的解释器中表示类

我已阅读相关问题,但似乎都没有直接解决这个问题。我正在编写一个 PHP 脚本解释器。我让 AST 为除类之外的所有内容生成适当的节点。处理类与处理函数有点不同,所以我正在寻找如何处理独立的类以及扩展其他类的类。

我看过 ANTLR,但我负担不起开销,因为这是嵌入式平台。我正在寻找的是 AST 中的类在概念上的理论,因此它们可以由解释器的执行程序部分执行。非常感谢与此问题的具体答案的良好链接。

0 投票
4 回答
3422 浏览

performance - VM 设计:更多操作码还是更少操作码?什么是更好的?

不要感到震惊。这是很多文字,但恐怕如果不提供一些详细信息,我将无法真正展示这一切的全部内容(并且可能会得到很多并不能真正解决我的问题的答案)。这绝对不是一项任务(正如某人在他的评论中荒谬地声称的那样)。

先决条件

由于这个问题可能根本无法回答,除非至少设置了一些先决条件,所以这里是先决条件:

  • 应解释虚拟机代码。不禁止可能存在 JIT 编译器,但设计应针对解释器。
  • VM 应该是基于寄存器的,而不是基于堆栈的。
  • 答案可能既不假设有一组固定的寄存器,也不假设它们的数量是无限的,两者都可能是这种情况。

此外,我们需要更好地定义“更好”。有几个属性必须考虑:

  1. VM 代码在磁盘上的存储空间。当然,您总是可以在这里放弃所有优化并仅压缩代码,但这对(2)有负面影响。
  2. 解码速度。如果将代码转换为可以直接执行的东西需要太长时间,那么存储代码的最佳方式是无用的。
  3. 内存中的存储空间。此代码必须在有或没有进一步解码的情况下直接可执行,但如果涉及进一步解码,则在执行期间和每次执行指令时完成此编码(在加载代码时仅完成一次解码计入第 2 项)。
  4. 代码的执行速度(考虑到常见的解释器技术)。
  5. VM 的复杂性以及为其编写解释器的难度。
  6. VM 自身需要的资源量。(如果 VM 运行的代码大小为 2 KB 并且执行速度比眨眼快,这不是一个好的设计,但是它需要 150 MB 来执行此操作,并且它的启动时间远高于代码的运行时间它执行)

现在举例说明我实际上所说的或多或少的操作码。看起来实际上设置了操作码的数量,因为每次操作需要一个操作码。然而它并不那么容易。

同一操作的多个操作码

您可以进行类似的操作

将 R1 和 R2 的值相加,将结果写入 R3。现在考虑以下特殊情况:

这些是您可以在许多应用程序中找到的常见操作。您可以使用已经存在的操作码来表达它们(除非您需要不同的操作码,因为最后一个操作码具有 int 值而不是寄存器)。但是,您也可以为这些创建特殊的操作码:

和之前一样。优势在哪里?ADD2 只需要两个参数,而不是 3,INC 甚至只需要一个。因此,这可以在磁盘和/或内存中进行更紧凑的编码。由于将任何一种形式转换为另一种形式也很容易,因此解码步骤可以在两种方式之间转换以表达这些陈述。不过,我不确定这两种形式会在多大程度上影响执行速度。

将两个操作码组合成一个

现在让我们假设您有一个 ADD_RRR(R 代表寄存器)和一个 LOAD 来将数据加载到寄存器中。

您可以拥有这两个操作码并始终在整个代码中使用这样的结构......或者您可以将它们组合成一个新的操作码,名为 ADD_RMR(M 代表内存)

数据类型与操作码

假设您有 16 位整数和 32 位整数作为本机类型。寄存器是 32 位的,因此任何一种数据类型都适合。现在,当您添加两个寄存器时,您可以将数据类型设为参数:

例如,有符号和无符号整数也是如此。这样 ADD 可以是一个短操作码,一个字节,然后你有另一个字节(或者可能只是 4 位)告诉 VM 如何解释寄存器(它们是 16 位还是 32 位值)。或者您可以废弃类型编码,而使用两个操作码:

有人可能会说两者完全相同 - 只需将第一种方式解释为 16 位操作码即可。是的,但是一个非常天真的解释器可能看起来完全不同。例如,如果每个操作码有一个函数并使用 switch 语句进行调度(不是最好的方法,函数调用开销,switch 语句也可能不是最优的,我知道),两个操作码可能如下所示:

每个功能都以某种添加为中心。第二个可能看起来像这样:

将子交换机添加到主交换机或将子调度表添加到主调度表。当然,无论类型是否显式,解释器都可以做任何一种方式,但根据操作码设计,任何一种方式都会让开发人员感觉更原生。

元操作码

由于没有更好的名字,我会这样称呼他们。这些操作码本身没有任何意义,它们只是改变了后面的操作码的含义。就像著名的 WIDE 运算符:

例如,在第二种情况下,寄存器是 16 位的(因此您可以添加更多),在第一种情况下只有 8 个。或者,您不能有这样的元操作码,并且有一个 ADD 和一个 ADD_WIDE 操作码。像 WIDE 这样的元操作码避免使用 SUB_WIDE、MUL_WIDE 等,因为您始终可以在所有其他正常操作码之前添加 WIDE(始终只有一个操作码)。缺点是单独的操作码变得毫无意义,您必须始终检查它之前的操作码是否是元操作码。此外,VM 必须为每个线程存储一个额外的状态(例如,我们现在是否处于宽模式)并在下一条指令之后再次删除该状态。甚至 CPU 也有这样的操作码(例如 x86 LOCK 操作码)。

如何找到一个好的权衡???

当然,您拥有的操作码越多,开关/调度表就会变得越大,在磁盘或内存中表达这些代码所需的位数就越多(尽管您可以更有效地将它们存储在数据不存在的磁盘上必须由 VM 直接执行);此外,VM 将变得更加复杂,代码行数也更多——另一方面,操作码越强大:您越来越接近每个表达式,即使是复杂的表达式,都将在一个操作码中结束的地步。

选择小的操作码可以很容易地对 VM 进行编码,并且我猜会导致非常紧凑的操作码 - 另一方面,这意味着您可能需要大量的操作码来执行简单的任务,并且每个不经常使用的表达式都必须成为某种(本机)函数调用,因为它不能使用任何操作码。

我在 Internet 上阅读了很多关于各种 VM 的信息,但没有任何消息来源能够真正做出良好且公平的权衡。设计 VM 就像设计 CPU,有些 CPU 的操作码很少,它们速度很快,但您也需要很多这样的 CPU。并且有许多操作码的 CPU,有些非常慢,但你需要更少的操作码来表达相同的代码。看起来“越多越好”的CPU完全赢得了消费市场,而“越少越好”的CPU只能在服务器市场或超级计算机业务的某些部分生存。虚拟机呢?

0 投票
2 回答
1389 浏览

python - Eclipse 中 Python 解释器的问题

当尝试通过选择可执行文件在 Eclipse 中为 python 设置解释器时,单击确定显示“发生错误”。口译员的名字重要吗?

0 投票
1 回答
914 浏览

parsing - javacc parseException...前瞻问题?

我正在为 javacc 中的一个非常简单的语法编写一个解析器。它开始融合在一起,但目前我完全陷入了这个错误:

有问题的输入行是z = y + z + 5

给我带来问题的产生是我从 varDecl() 调用的表达式:

表达式如下所示:

我不知道为什么会出现此错误 - 任何见解都将不胜感激。

0 投票
4 回答
4903 浏览

python - Lego Mindstorm 是否有任何 Ruby 或 Python 解释器?

我想开始用 Python 或 Ruby 编码。因为我拥有乐高 Midstorms套件,所以我认为对它进行编程会很好。Mindstorms 砖有什么好的翻译/解释者吗?

0 投票
2 回答
653 浏览

java - 解释一些东西,并在 Java 中运行生成的字节码?

我正在用 Java 编写一个带有 REPL 的玩具解释器。我想从语言生成字节码并运行它,而不是解释 AST 并运行它。

由于我的 Java 有点生疏,是否可以在 JVM 上动态运行生成的字节码?

0 投票
5 回答
1537 浏览

compiler-construction - 在“真实世界”应用程序中使用机器学习

我真的很喜欢在大学学习机器学习。我发现函数式编程通常是编写某些算法的一种令人耳目一新的优雅方式。我听说过 F# 并且玩过它。尽管如此,我还是在 ML 中编写了一些有趣的函数,并希望将它们集成为可以在其他应用程序中使用的库。

通常我将我的函数粘贴到 SMLnj 解释器中。有没有办法可以将它们编译下来?

0 投票
3 回答
443 浏览

c++ - 认识新线

我有一个相当复杂的计算器,当用户输入“;”时会打印输出 (并按回车键。)我现在要做的是允许用户在按回车键时打印输出,(不使用分号。)我需要知道如何实现这一点。

旁注:计算器使用标记化来读取用户输入

这是计算器源代码的一部分,也是唯一需要更改的部分。它是 Token_stream 的成员函数,当计算器的各种其他函数调用以获取下一个令牌时调用它。

到目前为止,如果用户输入 5*5 并点击空格然后输入..没有任何反应。但是,如果他们点击空格,然后输入一个随机字符(任何字符,而不仅仅是 ;)然后按 Enter,它就会输出答案。在此之后,用户可以使用 enter 产生输出,但是它保存了用户在敲击空格后输入的额外令牌,因此操作顺序变得很混乱。

简而言之,我需要知道如何让用户最初点击空格然后输入(甚至只是输入,但现在使用空格并输入)以产生输出 - 没有任何额外的字符。

如果您想查看更多来源或对计算器本身有任何疑问以解决问题,我很乐意发布更多信息。

PS 原始程序来自我正在学习 C++ 的一本书。我一直在做一些改变它并为其添加功能的练习。