From 1b262941cafb906da0aa814cea6b3dbdc15b1663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Sun, 27 May 2018 12:46:47 +0300 Subject: [PATCH] Implement a readMemory() in runVM() that returns 0 on reads to nonexistent memory --- README.md | 2 -- gir.js | 49 ++++++++++++++++++++++++++----------------------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 54ee23b..d715710 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,6 @@ Gir supports following optimizations: TODO ---- ### gir.js -* Make VM and transformMultiplyLoops use a Proxied object that gives out 0 - for nonexistent elements for tape and allows using [] interface * Support for other types of EOF? ### gir.html diff --git a/gir.js b/gir.js index 1532938..addf9e8 100644 --- a/gir.js +++ b/gir.js @@ -588,7 +588,7 @@ function newVM(program, input) { }; } -// (girVMState, int) → {state: girVMState, complete: bool, cycles: int, +// (girVMState, int/null) → {state: girVMState, complete: bool, cycles: int, // intParseFailed: bool, breakPointReached: bool, // lastIndex: int/null} // complete is set to true is the program completed its execution @@ -598,6 +598,16 @@ function newVM(program, input) { // lastIndex tells the last memory index accessed by the VM // If maxCycles is null, the program runs until completion function runVM(state, maxCycles = null) { + // (int) → int + function readMemory(index) { + // Return 0 if index doesn't exist + if(memory.has(index)) { + return memory.get(index); + } else { + return 0; + } + } + let program = state.program; let ip = state.ip; @@ -630,8 +640,7 @@ function runVM(state, maxCycles = null) { let command = program[ip]; - // See if we need to make sure the cell we're on exists and - // calculate the index into the array of the cell we're + // Calculate the index into the array of the cell we're // accessing let index = tapeHead; switch(command.type) { @@ -643,21 +652,13 @@ function runVM(state, maxCycles = null) { case readInt: // These have an offset property, add it index += command.offset; - // Fall through - case multiply: - case jumpIfZero: - case jumpIfNonZero: - // Ensure the cell exists - if(!memory.has(index)) { - memory.set(index, 0); - } - lastIndex = index; } + lastIndex = index; // Run the command switch(command.type) { case add: - let old = memory.get(index); + let old = readMemory(index); memory.set(index, (command.value + old) & 0xFF); ip++; @@ -665,12 +666,18 @@ function runVM(state, maxCycles = null) { case moveHead: tapeHead += command.value; + // Set lastIndex to the new tape head + // position. Technically we do not access + // the cell, but otherwise it will point + // to the cell we were in previously, so + // this allows better debugging + lastIndex = tapeHead; ip++; break; case writeByte: - output.push(memory.get(index)); + output.push(readMemory(index)); ip++; break; @@ -697,14 +704,11 @@ function runVM(state, maxCycles = null) { `multiply where change for 0 is ${command.changes.get(0)}`); } - let multiplier = memory.get(index); + let multiplier = readMemory(index); for(let [offset, change] of command.changes.entries()) { let index = tapeHead + offset; - if(!memory.has(index)) { - memory.set(index, 0); - } - let old = memory.get(index); + let old = readMemory(index); let value = old + multiplier * change; memory.set(index, value & 0xff); } @@ -713,7 +717,7 @@ function runVM(state, maxCycles = null) { break; case jumpIfZero: - if(memory.get(index) == 0) { + if(readMemory(index) == 0) { ip = command.target; } else { ip++; @@ -721,7 +725,7 @@ function runVM(state, maxCycles = null) { break; case jumpIfNonZero: - if(memory.get(index) != 0) { + if(readMemory(index) != 0) { ip = command.target; } else { ip++; @@ -729,7 +733,7 @@ function runVM(state, maxCycles = null) { break; case writeInt: - let outputStr = memory.get(index).toString(); + let outputStr = readMemory(index).toString(); output = output.concat(encodeUTF8(outputStr)); ip++; break; @@ -984,7 +988,6 @@ function cachedCompile(program, enableExtensions = true) { // (string, string, int) → string function ircbotRun(program, input, maxCycles = 400000) { - // TODO; Cache programs let compiled = cachedCompile(program); let vm = newVM(compiled, encodeUTF8(input));