【问题标题】:Lua language context/scope implementationLua 语言上下文/作用域实现
【发布时间】:2014-02-08 17:40:47
【问题描述】:

我正在用 C# 实现一个 Lua 解释器,我偶然发现了一个性能问题,我认为这是由不正确的设计引起的: 在我的实现中,范围以分层方式排列,也就是说,每个范围都有一个父范围,它可能为空,也可能不为空;每次设置或请求变量时,范围都会检查指定的变量是否包含在其中。如果没有,则要求其父级执行相同的操作,或者,如果没有父级,则创建它/返回 nil。 问题是作用域在下面使用Dictionary<string, LuaObject>,而Get/Set 函数是递归的。有更好的方法吗?我一直在考虑不同的方法,我发现了这个,它不是很优雅也不是很高效(受 V8 和 C# 闭包的启发):

使用类型和字段作为变量。

  • 每次请求之前未声明的变量时,请使用继承前一个类型的反射创建一个新类型。
  • 如果声明了函数,请检查它是否使用了在外部作用域中声明的变量。如果是这样,请重新创建该类型的字段并使外部变量指向新变量。 (我知道这点解释得非常糟糕,但这只是 C# 闭包的标准实现方式。如果你不明白,你可以去阅读)

有更简单/更优雅的解决方案吗? Lua 内部是如何实现的?

【问题讨论】:

  • 关于 Lua 的内部实现,this reading order for Lua 的源代码你可能会感兴趣。
  • 谢谢,我找不到任何解释 Lua 源代码的文档,阅读它绝对不容易:)

标签: c# .net lua clr


【解决方案1】:

它的完成方式in the reference implementation,以及在许多其他类似语言的实现中:在编译时,

  • 在编译时确定哪个名称指的是哪个范围。
  • 对于每个范围(全局除外),枚举变量并为每个范围分配索引。
  • 不要在字节码中提及变量名称,而是使用上一步中的索引。

然后在执行过程中,

  • 将本地变量的值存储在一个数组中(每个激活记录)。读写操作码带有必要的索引。
  • 像 Lua 表一样实现全局变量(并免费获得 nil 以获取缺少的变量)。

这比使用动态创建的类型更简单、更容易和可移植。它甚至可能更快,但肯定不会慢很多。

闭包支持大多是正交的。所谓的 upvalues 是指 locals 数组还活着时(一个插槽),并在 locals 数组死亡时采用封闭值。您可以对原始设计做类似的事情。为了正确起见,您必须注意只为每个封闭变量创建一个上值并展平 闭包。例如,以下代码中的 g 也必须关闭 x 以便在创建 h 闭包时它仍然存在:

function f()
  local x = 1
  function g()
    function h()
      return x
    end
    return h
  end
  return g
end

print(f()()())

【讨论】:

  • 这真的很有启发性:) 我的大脑忙于思考复杂的解决方案,我无法看到简单的解决方案。谢谢。
猜你喜欢
  • 1970-01-01
  • 2010-09-19
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多