【问题标题】:What's an efficient way to store variables? (Home-Built Virtual Machine)什么是存储变量的有效方法? (自制虚拟机)
【发布时间】:2013-08-23 18:45:40
【问题描述】:

我和我的一个朋友正在考虑使用即时编译来编写我们自己的编程语言。我们同意我们将要使用的程序集,但我们不太确定的一件事是如何存储变量。我们确实同意的是这些的结构。

变量将被键替换(在编译期间)。每个键都是一个 2 字节整数,范围从 1 到 65535。例如,当您在命名空间中有一个变量时,该键将首先存在一个包含命名空间键的 2 字节整数,然后是一个包含实际变量的键。

例如,如果我有命名空间 foo 并且我在其中有一个变量 test,我们说命名空间 foo 将被分配键 1,而 1 内的变量 test 将被分配键 1->1。 (第一个命名空间中的第一个变量)。在程序集本身中,我们用 NULL 字节终止这些键。 (请记住,这是编译后的程序集,而不是编译前的真实代码)

GETV 1 1 0 SET 5 RET

此程序集将从命名空间 foo 中获取变量 test,并将其设置为 5。然后它将返回该变量。

GETV 1 2 1 0 SETV 1 1 0 RET

此程序集可以匹配以下(虚构)代码:

foo::testClass::test = foo::test;
return foo::test;

提供以下结构。

namespace foo { // 1 First Global Variable
    byte test = 1; // 1 1 - First Variable Inside First Global Variable
    class testClass { // 1 2 - Second Variable Inside First Global Variable
        static byte test = 0; // 1 2 1 - First Variable Inside Second Variable Inside First Global Variable
    }
}

我将如何访问这些变量?我目前的计划是使用键作为字符串作为哈希将它们存储在哈希图中。我不知道该怎么做,因为我怎么知道当前键中存储了哪种类型的变量,它有多长以及如何用它进行计算。我确实明白,编译器可以处理诸如将无符号整数添加到有符号整数之类的疯狂计算,但这仍然给我们留下了问题,该变量有多长以及如何处理它。 (添加 2 个浮点数与添加 2 个整数的处理方式不同,对吧?)

【问题讨论】:

  • 你到底为什么要这样做?
  • 写一门语言很有趣。为什么要使用这种奇怪的变量命名方法? 这个命名约定(某种索引)有趣吗?
  • 这些是用其他东西替换变量名的原因。这些不是用您选择的奇怪索引约定替换变量名称的理由,它混淆较少,具有更多无意义的字节,并且比普通的旧 uid(无论是否为数字)更难被虚拟机解释。我的建议是拿起紫龙或红龙编译器的书,阅读并吸收其中的建议。
  • 你的方法有很多问题,我什至不知道从哪里开始。 O_o 不要试图重新发明一个方形轮子,只需像其他人一样使用一个圆形轮子并将变量名称映射到它们的内存地址......(或至少映射到一个唯一的全局标识符)不要忘记命名空间, 类等对于我们大脑有限的人类来说只是语法糖,绝对没有必要(实际上这是一件坏事)在代码结构和编译后的实现之间进行 1-1 映射。
  • @Binero 如果您使用size_tvoid*(通常大小相同)作为您的uid,您根本无法达到限制:您总是会用完记忆第一。现在,您当前对每个命名空间 64k 个对象的限制完全是另一回事,它更容易饱和。

标签: c++ memory assembly memory-management vm-implementation


【解决方案1】:

这里最好的方法不是为变量保留一些奇怪的标识符,而是使用直接指针。编译程序后,您将不再需要以人为中心的名称。

更重要的是,您需要考虑变量的结构。根据您的语言语法,除了保留变量值的内存之外,您可能还需要存储一些元数据 - 例如变量的类型。仅当您想要支持自动类型转换时才需要此信息。如果您的语言是严格类型化的,您将能够在编译时解决所有类型冲突,然后在运行时就不需要类型信息。

此外,根据语法,您可能需要保留一个索引,将变量的人类可读名称映射到实际地址。仅当您的语言具有类似以下功能时才需要此索引:

var_by_name(s:string):pointer

【讨论】:

  • 不确定指针是什么意思。我理解 C 和 C++ 中的概念指针,但我认为您在这里谈论的不是同一类。
  • 是的,但是我在编译时如何使用它们呢?如果一个函数被调用两次(并发)怎么办?我需要重新编译以更新地址。
  • @Binero - 有几种方法可以为变量分配内存。局部变量通常是从堆栈中分配的。您绝对必须清理您对虚拟机内存管理的想法。
  • 所以你是说我应该在调用函数之前为函数分配内存? :o
  • 我还是不太明白。如果我要使用指向内存的指针,那是不是意味着我必须在内存中设置一个等于所有变量在 RAM 中相互添加的部分?
猜你喜欢
  • 2019-03-05
  • 2020-09-07
  • 2017-12-08
  • 2020-02-11
  • 2013-01-05
  • 2011-02-08
  • 2017-11-07
  • 2015-06-20
  • 2011-02-22
相关资源
最近更新 更多