diff --git a/src/go-slang/goroutine.ts b/src/go-slang/goroutine.ts index 6d70fbde3..984e52d84 100644 --- a/src/go-slang/goroutine.ts +++ b/src/go-slang/goroutine.ts @@ -309,26 +309,25 @@ const Interpreter: { }, ChanRecvOp: (_inst, { C, S, H }) => { - const chanAddr = S.pop() + const chanAddr = S.peek() const chan = H.resolve(chanAddr) as BufferedChannel - const chanValue = chan.recv() - if (chanValue !== null) { return S.push(H.alloc(chanValue)) } // prettier-ignore + // if the channel is empty, we retry the receive operation + if (chan.isBufferEmpty()) { return C.push(ChanRecv) } // prettier-ignore - // retry receiving from the channel - S.push(chanAddr) - C.push(ChanRecv) + S.pop() + S.push(H.alloc(chan.recv())) }, ChanSendOp: (_inst, { C, S, H }) => { - const addrs = S.popN(2) - const [channel, value] = H.resolveM(addrs) as [BufferedChannel, any] + const chanAddr = S.peek() + const chan = H.resolve(chanAddr) as BufferedChannel - if (channel.send(value)) { return } // prettier-ignore + // if the channel is full, we retry the send operation + if (chan.isBufferFull()) { return C.push(ChanSend) } // prettier-ignore - // retry sending to the channel - S.pushR(...addrs) - C.push(ChanSend) + const [_, valueAddr] = S.popN(2) + chan.send(H.resolve(valueAddr)) }, BranchOp: ({ cons, alt }: BranchOp, { S, C, H }) => diff --git a/src/go-slang/lib/channel.ts b/src/go-slang/lib/channel.ts index 2ed18d58b..93e3f8951 100644 --- a/src/go-slang/lib/channel.ts +++ b/src/go-slang/lib/channel.ts @@ -42,6 +42,14 @@ export class BufferedChannel extends Channel { return value } + public isBufferFull(): boolean { + return this.bufSize === this.maxBufSize + } + + public isBufferEmpty(): boolean { + return this.bufSize === 0 + } + private get readIdx(): number { return this.memory.getUint8(BufferedChannel.READ_IDX_OFFSET) } @@ -65,12 +73,4 @@ export class BufferedChannel extends Channel { private set bufSize(newBufSize: number) { this.memory.setUint8(BufferedChannel.BUF_SIZE_OFFSET, newBufSize) } - - private isBufferFull(): boolean { - return this.bufSize === this.maxBufSize - } - - private isBufferEmpty(): boolean { - return this.bufSize === 0 - } }