【问题标题】:How to implement dynamic types in a bytecode interpreter?如何在字节码解释器中实现动态类型?
【发布时间】:2015-07-23 08:58:04
【问题描述】:

我正在为动态类型语言制作字节码解释器。例如这个表达式:

2 + 3

将创建以下类似汇编的输出(稍后编译为字节码):

iconst reg1, 2 ; Put integer 2 to register 1
iconst reg2, 3 ; Put integer 3 to register 2
iadd reg3, reg1, reg2 ; Add the 2 as integers from reg1 and 2 and put it into reg3

另一个例子是:

1 + 3.2

输出:

iconst reg1, 1
itof reg2, reg1 ; Convert integer to float and put it into reg2
fconst reg3, reg2
fadd reg4, reg2, reg3

所以每种类型都有自己的运算符(fadd、iadd、也许是sadd...)。这意味着我需要知道编译类型的类型。在我有例如函数调用之前,这不是问题:

function foo(x, y):
    return x + y

foo() 可以用整数、浮点数,甚至混合调用。所以我不能在编译时为它生成正确的字节码。最好做什么,所以它不会真正影响速度。使用所使用的参数类型生成函数是一个好策略吗?所以如果这被调用:

foo(2, 3.2)

它会生成类似 foo@int,float() 的东西。还是在运行时解决它更好?我可以在不影响性能的情况下这样做吗?如何? lua是怎么做到的?

对不起,如果这是重复的,也许我需要提高我的谷歌搜索技能。

【问题讨论】:

    标签: interpreter dynamic-typing


    【解决方案1】:

    我可以想出几种方法来处理这个问题:

    1 - 跟踪 foo(x, y) 的调用方式,并记录不同的函数签名。这可能会变得复杂,因为 foo(x, y) 可能会从 bar(a, b) 调用,而 bar(a, b) 可能会从 baz(c, d) 调用,等等。

    在您解析整个程序、构建您的 AST 并遍历它以记录对 foo(x, y) 的调用的所有唯一签名后,为调用它的不同方式生成代码。

    你可能有:

    foo(int, int)
    foo(float, int)
    

    这告诉你你需要两个独特的 foo(x, y) 函数。

    2 - 将您的操作码集更改为具有通用的 add、sub、mul 等操作码。然后通用操作码必须在运行时确定其操作数的类型并正确执行。这会慢一些,因为操作码现在必须检查操作数的类型,并基于此进行分支。

    3 - 如您所料,在实际调用函数之前不要生成函数代码。这会慢一点,但仅在第一次调用所述函数时。与 (1) 一样,您仍然需要支持多个唯一的函数签名,因此仍然需要进行一些记账。

    我希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2016-11-16
      • 2018-10-08
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 2012-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多