C#-Lua语言上下文/范围的实现

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

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

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

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

解决方法:

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()()())
上一篇:微信小程序简单常见首页demo


下一篇:异常过滤器的好坏(CLR)