谁能给我指出解释堆栈机的 C# 代码吗?

发布于 2024-09-26 08:48:47 字数 278 浏览 6 评论 0原文

我正在寻找堆栈机的 C# 实现,最好是附带单元测试或至少有几个示例的实现。 http://en.wikipedia.org/wiki/P-code_machine 中的代码出现成为我正在寻找的那种东西。不幸的是,自从我用 Pascal 编程以来已经十多年了,并且在将其移植到 C# 时遇到了一堆问题。此外,没有使用该代码的示例。

无论如何,在这方面的任何帮助将不胜感激......

I'm looking for a C# implementation of a stack machine, preferably one with accompaning unit tests or at least couple of examples. The code at http://en.wikipedia.org/wiki/P-code_machine appears to be the sort of thing that I'm looking for. Unfortunately, it's been more than a decade since I programmed in Pascal and ran into a bunch of problems porting it to C#. Also, there was no example(s) of using the code.

Anyway, any help in this regard would be greatly appreciated....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

洋洋洒洒 2024-10-03 08:48:47

解释型堆栈机在概念上与逆波兰表示法非常相似。

该表达式

3 + (6 - 2)

用 RPN 表示为

3 6 2 - +

计算如下:

Input   Operation    Stack      Comment

3       Push value   3

6       Push value   6
                     3

2       Push value   2
                     6
                     3

-       Subtract     4          Pop two values (6, 2) and push result (4)
                     3

+       Add          7          Pop two values (3, 4) and push result (7)

从这里开始,应该很容易用 C# 构建一个简单的解释堆栈机。例如

var stack = new Stack<int>();

var program = new[] 
{ 
    OpCode.Ldc_3,
    OpCode.Ldc_6,
    OpCode.Ldc_2,
    OpCode.Sub,
    OpCode.Add,
};

for (int i = 0; i < program.Length; i++)
{
    int a, b;
    switch (program[i])
    {
    case OpCode.Add: b = stack.Pop(); a = stack.Pop(); stack.Push(a + b); break;
    case OpCode.Sub: b = stack.Pop(); a = stack.Pop(); stack.Push(a - b); break;
    case OpCode.Mul: b = stack.Pop(); a = stack.Pop(); stack.Push(a * b); break;
    case OpCode.Div: b = stack.Pop(); a = stack.Pop(); stack.Push(a / b); break;
    case OpCode.Ldc_0: stack.Push(0); break;
    case OpCode.Ldc_1: stack.Push(1); break;
    case OpCode.Ldc_2: stack.Push(2); break;
    case OpCode.Ldc_3: stack.Push(3); break;
    case OpCode.Ldc_4: stack.Push(4); break;
    case OpCode.Ldc_5: stack.Push(5); break;
    case OpCode.Ldc_6: stack.Push(6); break;
    case OpCode.Ldc_7: stack.Push(7); break;
    case OpCode.Ldc_8: stack.Push(8); break;
    }
}

var result = stack.Pop();

,对于

enum OpCode
{
    Nop,    // No operation is performed.
    Add,    // Adds two values and pushes the result onto the evaluation stack.
    Sub,    // Subtracts one value from another and pushes the result onto the
            // evaluation stack.
    Mul,    // Multiplies two values and pushes the result on the evaluation
            // stack.
    Div,    // Divides two values and pushes the result onto the evaluation
            // stack.
    Ldc_0,  // Pushes the integer value of 0 onto the evaluation stack.
    Ldc_1,  // Pushes the integer value of 1 onto the evaluation stack.
    Ldc_2,  // Pushes the integer value of 2 onto the evaluation stack.
    Ldc_3,  // Pushes the integer value of 3 onto the evaluation stack.
    Ldc_4,  // Pushes the integer value of 4 onto the evaluation stack.
    Ldc_5,  // Pushes the integer value of 5 onto the evaluation stack.
    Ldc_6,  // Pushes the integer value of 6 onto the evaluation stack.
    Ldc_7,  // Pushes the integer value of 7 onto the evaluation stack.
    Ldc_8,  // Pushes the integer value of 8 onto the evaluation stack.
}

现实世界的示例,请查看 .NET Framework 中 OpCodes 类的字段

Interpreted stack machines are very similar in concept to Reverse Polish notation.

The expression

3 + (6 - 2)

is expressed in RPN as

3 6 2 - +

This gets evaluated as follows:

Input   Operation    Stack      Comment

3       Push value   3

6       Push value   6
                     3

2       Push value   2
                     6
                     3

-       Subtract     4          Pop two values (6, 2) and push result (4)
                     3

+       Add          7          Pop two values (3, 4) and push result (7)

From there, it should be easy to build a simple interpreted stack machine in C#. E.g.

var stack = new Stack<int>();

var program = new[] 
{ 
    OpCode.Ldc_3,
    OpCode.Ldc_6,
    OpCode.Ldc_2,
    OpCode.Sub,
    OpCode.Add,
};

for (int i = 0; i < program.Length; i++)
{
    int a, b;
    switch (program[i])
    {
    case OpCode.Add: b = stack.Pop(); a = stack.Pop(); stack.Push(a + b); break;
    case OpCode.Sub: b = stack.Pop(); a = stack.Pop(); stack.Push(a - b); break;
    case OpCode.Mul: b = stack.Pop(); a = stack.Pop(); stack.Push(a * b); break;
    case OpCode.Div: b = stack.Pop(); a = stack.Pop(); stack.Push(a / b); break;
    case OpCode.Ldc_0: stack.Push(0); break;
    case OpCode.Ldc_1: stack.Push(1); break;
    case OpCode.Ldc_2: stack.Push(2); break;
    case OpCode.Ldc_3: stack.Push(3); break;
    case OpCode.Ldc_4: stack.Push(4); break;
    case OpCode.Ldc_5: stack.Push(5); break;
    case OpCode.Ldc_6: stack.Push(6); break;
    case OpCode.Ldc_7: stack.Push(7); break;
    case OpCode.Ldc_8: stack.Push(8); break;
    }
}

var result = stack.Pop();

with

enum OpCode
{
    Nop,    // No operation is performed.
    Add,    // Adds two values and pushes the result onto the evaluation stack.
    Sub,    // Subtracts one value from another and pushes the result onto the
            // evaluation stack.
    Mul,    // Multiplies two values and pushes the result on the evaluation
            // stack.
    Div,    // Divides two values and pushes the result onto the evaluation
            // stack.
    Ldc_0,  // Pushes the integer value of 0 onto the evaluation stack.
    Ldc_1,  // Pushes the integer value of 1 onto the evaluation stack.
    Ldc_2,  // Pushes the integer value of 2 onto the evaluation stack.
    Ldc_3,  // Pushes the integer value of 3 onto the evaluation stack.
    Ldc_4,  // Pushes the integer value of 4 onto the evaluation stack.
    Ldc_5,  // Pushes the integer value of 5 onto the evaluation stack.
    Ldc_6,  // Pushes the integer value of 6 onto the evaluation stack.
    Ldc_7,  // Pushes the integer value of 7 onto the evaluation stack.
    Ldc_8,  // Pushes the integer value of 8 onto the evaluation stack.
}

For a real world example, have a look at the fields of the OpCodes class in the .NET Framework.

木森分化 2024-10-03 08:48:47

原始的 Magpie 解释器是用 C# 编写的,并编译为堆栈 -基于字节码。看看 Machine.cs对于核心解释器类。将源代码转换为该字节码的编译器位于 Magpie.Compiler 中

The original Magpie interpreter was written in C# and compiled down to stack-based bytecode. Take a look at Machine.cs for the core intepreter class. The compiler that translates source code to this bytecode is in Magpie.Compiler.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文