2012-07-20 62 views
4

我有一个自定义的基于堆栈的语言,我试图编译为CIL,因此它可以被JITed。语言本身非常简单,因为它只有整数和布尔值。但是,每种数据类型都有一个专用堆栈。语言本身是一个命令流,每个命令都可以从任一堆栈中窥视,推送和/或弹出值。由命令推送/放置的整数或布尔值的数量不会改变(因此命令具有固定的义数)。还有一个扁平的整型数组,语言读取和写入数值,代表外部存储器。堆栈本身可以是任意深的。编译基于堆栈的语言CIL

对于简单的命令如“add”,“subtract”等,将整数堆栈命令转换为CIL几乎很简单:CIL堆栈可以批量替换整数堆栈(尽管我有一个问题:是否存在在规范或实践中,CIL堆栈的深度有多大?)但是也有类似StoreIfTrue的命令,它只会在某个索引处存储一个值(从整数堆栈)到平坦整数数组(索引也是来自整数堆栈)如果布尔堆栈的最高值为真。所以我需要同时访问一些命令的布尔堆栈和整数堆栈。

现在我要保持System.Collections.Generic.Stack表示布尔堆栈。但是我想知道是否有一种已知的算法或方法可以将我的自定义语言的两个堆栈模型“拼合”成一个与CIL更直接兼容的堆栈模型。

+0

的CIL堆栈是类型更小,它可以处理和混合整数和布尔变量。应该有一种方法可以将多堆栈执行模型转换为无类型的单堆栈,但从您的问题中不清楚应该如何实现。 – 2012-07-21 10:34:08

回答

0

你是否知道如何生成,例如,C#CIL代码我无法从你的问题推断。要做到这一点,您可以使用ReflectionCecil

对于虚拟执行系统(VES,将执行该指令CIL的虚拟系统的模型)在栈上的值(和在寄存器中)没有关联的复杂类型。只有简单的类型(int32,int64,托管对象引用,托管指针和浮点数)由VES跟踪。因此,VES无法看到堆栈中布尔值和整数之间的差异(在内部,VES将布尔值视为32位整数),因此无法使用执行堆栈来模拟布尔堆栈和整数堆栈。你可以做同样的事情:将布尔值视为整数和非零整数作为布尔值true。所以两个整数的比较会导致另一个整数。然而,那么你只有一个堆栈而不是两个。


编辑

啊,我明白了。您的语言旨在成为一种通用编程语言,因此必须具有高度的可靠性,并对所有可能的输入(包括无效输入)具有一些预定义(或不​​具有)行为。通过为每种可能的类型分别设置堆栈,更有可能使用兼容操作数而不是随机操作数。因为不可能使用单个堆栈来模拟多个堆栈,我会为每个类型使用一个真实的Stack<T>对象,而不是尝试使用CIL堆栈。这有几个优点:

  • 更容易在未来
  • 添加新类型允许栈的边界检查(例如,使操作无操作)
  • 更容易比混合类型的任何自定义方案来管理在一个堆栈上
  • 随机访问,如果你需要它
  • 不需要知道CIL内部,所以可以运行在单声道和。净
  • CIL堆栈则仅用于临时操作数栈帧和返回地址
+0

我可以生成CIL,是的。我不介意把布尔变成整数。但我没有看到将两个逻辑堆栈合并到一个物理执行堆栈的方法。这真是我问题的核心。 – 2012-07-20 23:06:34

+0

或更改:我的语言使用两台堆栈机器。我如何处理它(作为我的编译步骤的一部分)才能有效地使用单个堆栈机器? – 2012-07-20 23:09:35

+0

通常不可能使用一个堆栈模拟两个堆栈。为什么你首先有两个逻辑堆栈?对我来说更有意义(除非我完全误解了你)只有一个堆栈,并将所有布尔值和整数值混合在一起。一个'add'指令可能会弹出两个值(不管它们的类型如何),然后添加它们并将结果返回。然后,将采取的布尔随后'if'指令只是获取堆栈(一个由'add'推动)的顶部整数,假装它是一个布尔值。另一种方式。 – Virtlink 2012-07-21 15:06:24

1

我想在一个堆叠存储两个独立的堆栈是不可能的(至少在没有外部临时存储,但你会得到可怕的表现)。这是因为无论如何将堆栈的顶部始终靠近实际堆栈的顶部,无论使用哪种表示形式,都无法实现。

但是CIL不只是有栈和堆,它也有局部变量。但是你只能通过一个不变的索引访问局部变量。因此,如果您在编译时总是知道堆栈顶部的索引,并且您也知道堆栈的最大大小,则可以使用局部变量来表示它。但我认为这两个条件不适用于你的情况。

正因为如此,我认为使用Stack<T>一个或两个你堆的是你的最佳选择。

+0

处理堆栈的深度可能会非常棘手,但因为每个命令有固定的参数数量,我认为找出一个恒定的指标正在抬头将是可能的。我将不得不测试它,看看它是否比使用Stack 快得多。 – 2012-07-23 17:00:40