作为一个有趣的小项目,并获得更多经验,我目前正在尝试创建类似于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状态,因此开始等待。
有解决这些问题的简单方法吗?你能给我一些关于如何从这里继续下去的线索吗?