4

给定的是以下(缩短的)线程代码解释器(有限状态机)。它有一个操作栈和一个操作数栈。执行时,从操作堆栈中弹出下一个操作并执行。

有三个指令:

  • 加法指令从操作数堆栈中弹出两个操作数,将它们相加并将结果压入操作数堆栈
  • 打印指令,从操作数栈中弹出一个操作数并打印出来
  • 特殊调用指令,尝试手动调用加法指令(从指令内),需要得到计算结果

现在的问题是,在 specialcall 方法中,需要计算结果,但是在指令循环中调用了加法运算之后,进一步的执行只会在最初的 specialcall 之后继续执行。

一种方法是创建一个操作结构,其中包含 a) 操作和 b) 跳转回的地址 - 如有必要。然后在指令循环中,当弹出指令结构并设置地址时,将在实际指令执行后立即跳转到该地址。

有没有其他方法可以解决这个问题?

#include <stdint.h>
#include <iostream>
#include <deque>

const uint32_t operation_addition = 1;
const uint32_t operation_print = 2;
const uint32_t operation_specialcall = 3;

std::deque<uint32_t> operations;
std::deque<uint32_t> stack;

void specialcall() {
    std::cout << "specialcall" << std::endl;

    // Manually create the call
    stack.push_back(52);
    stack.push_back(25);
    operations.push_back(operation_addition);

    // "place to jump back"

    // Need result of calculation here!
    ...
}

void addition() {
    std::cout << "addition" << std::endl;

    uint32_t operandA = stack.back();
    stack.pop_back();
    uint32_t operandB = stack.back();
    stack.pop_back();

    uint32_t result = operandA + operandB;
    stack.push_back(result);
}

void print() {
    std::cout << "print" << std::endl;

    uint32_t result = stack.back();
    stack.pop_back();

    std::cout << result << std::endl;
}

void start() {
    while (!operations.empty()) {
        uint32_t op = operations.back();
        operations.pop_back();

        switch (op) {
        case operation_specialcall:
            specialcall();
            break;
        case operation_print:
            print();
            break;
        case operation_addition:
            addition();
            break;
        }
    }
}

int main() {
    stack.push_front(25);
    stack.push_front(53);
    operations.push_front(operation_addition);
    operations.push_front(operation_print);
    operations.push_front(operation_specialcall);
    start();

    std::cout << "execution finished" << std::endl;
}
4

1 回答 1

2

你已经有了结果,它在堆栈的顶部。代码执行后。所以只需检索它:

int main() {
    stack.push_front(25);
    stack.push_front(53);
    operations.push_front(operation_addition);
    operations.push_front(operation_print);
    operations.push_front(operation_specialcall);
    start();

    uint32_t result = stack.back();
    stack.pop_back();
    std::cout << result << std::endl;
}

如果您需要 operation_specialcall() 函数中的结果,那么您需要深入考虑该函数将如何使用结果。任意地,您可以打印它:

void specialcall() {
    stack.push_back(52);
    stack.push_back(25);
    operations.push_back(operation_addition);
    operations.push_back(operation_print);
}

两种方法都完成了完全相同的事情。这里的关键是区分编译时和运行时。避免将它们混淆,这需要对您的解释器进行重大改进。您必须实现等效于 eval() 函数。这需要能够管理多个指令流,您没有适当的管道。换句话说,您不能再将操作堆栈变量作为全局变量。

于 2013-10-05T12:37:45.980 回答