javascript

时间:2015-06-23 12:33:38

标签: javascript simulation

作为一个有趣的小项目,并获得更多经验,我目前正在尝试创建类似于TIS-100的东西,但使用HTML和Javascript。 TIS-100基本上是一个非常简单,非常有限的汇编解释器,设计为编程难题。

有固定数量的节点,所有节点都模拟运行自己代码的迷你计算机。我对指令集的编程接近完成,节点通常工作。也就是说,只要每个人都保持独立。这意味着所有逻辑都已实现并且可以使用,只要没有读取或写入其中一个连接。

每个节点都有两个连接到它的直接邻居,包括垂直和水平。其中一个是输出(写入邻居),另一个是输入(从邻居读取)。

+----+    +----+    +----+
| No | -> | No | -> | No |
| 1  | <- | 2  | <- | 3  |
+----+    +----+    +----+
 ^  |      ^  |      ^  |
 |  v      |  v      |  v
+----+    +----+    +----+
| No | -> | No | -> | No |
| 4  | <- | 5  | <- | 6  |
+----+    +----+    +----+

连接类似于unix中的命名管道。节点的执行停止,直到连接另一端的程序从中读取。

目前,用户必须按一个按钮才能运行下一条指令。所有节点同时运行,我只需在单击按钮时调用每个节点的runNextInstruction()方法。

当获得读或写指令时,它会调用readFromConnection(direction)writeToConnection(direction)。这是我到目前为止所得到的:

TIS_Node.prototype.readFromConnection = function(direction) {
    this.ioMode = TIS_ioMode.READ;
    this.lastDirection = direction;
    var connection = this._connections[direction];
    console.log(connection.ioMode);
};

现在所做的就是将节点的状态从IDLE设置为READ,这将阻止executeNextInstruction()方法执行任何其他指令。确切地说,readFromConnection被调用如下:

// Gets called when a MOV instruction is called.
// Syntax: MOV SOURCE, DEST
TIS_Node.prototype.action_MOV = function(command) {
    var components = command.split(",");
    var source = components[0].trim();
    var destination = components[1].trim();

    source = this.getValue(source);

    switch (destination) {
        case "ACC":
            this.acc = source;
            break;
        case "NIL":
            // Discard
            break;
        // ...
    }
};

TIS_Node.prototype.getValue = function(address) {
    switch (address.trim().toUpperCase()) {
        case "LEFT":
            return this.readFromConnection(TIS_Direction.LEFT);
        case "RIGHT":
            return this.readFromConnection(TIS_Direction.RIGHT);
        // ...
        default:
            return address;
    }
};

我遇到的问题是如何解决这个问题。我的第一个天真的想法就是在javascript中等待,直到连接的ioMode更改为WRITE,但这可能无效,我甚至无法想象如何。

我的第二个想法是将自己的ioMode设置为READ,然后在执行写入指令时从另一个节点调用receiveInputValue(direction, value)等方法。不过,我无法考虑如何实现这一点并仍然写入正确的目标(一个值可以写入节点的累加器ACC,通过NIL丢弃或者只是传递给另一个连接)。

另一方面说明:
虽然一切都足够快,似乎节点同时运行,但实际上并非如此。在Node的方法之前,节点1的runNextInstruction在forEach循环中被调用一步。这也会毁了我的结果。想象一下:节点1想要从节点2读取。在完全相同的时间(理论上),节点2从IDLE变为WRITE并且想要将节点1的值传递给节点1。因为节点1事实上在节点2之前执行,所以当它尝试读取值时,节点2仍然处于IDLE状态,因此开始等待。

有解决这些问题的简单方法吗?你能给我一些关于如何从这里继续下去的线索吗?

0 个答案:

没有答案