Implement a readMemory() in runVM() that returns 0 on reads to nonexistent memory

This commit is contained in:
Juhani Krekelä 2018-05-27 12:46:47 +03:00
parent 00eb264cb4
commit 1b262941ca
2 changed files with 26 additions and 25 deletions

View File

@ -21,8 +21,6 @@ Gir supports following optimizations:
TODO TODO
---- ----
### gir.js ### 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? * Support for other types of EOF?
### gir.html ### gir.html

49
gir.js
View File

@ -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, // intParseFailed: bool, breakPointReached: bool,
// lastIndex: int/null} // lastIndex: int/null}
// complete is set to true is the program completed its execution // 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 // lastIndex tells the last memory index accessed by the VM
// If maxCycles is null, the program runs until completion // If maxCycles is null, the program runs until completion
function runVM(state, maxCycles = null) { 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 program = state.program;
let ip = state.ip; let ip = state.ip;
@ -630,8 +640,7 @@ function runVM(state, maxCycles = null) {
let command = program[ip]; 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 // accessing
let index = tapeHead; let index = tapeHead;
switch(command.type) { switch(command.type) {
@ -643,21 +652,13 @@ function runVM(state, maxCycles = null) {
case readInt: case readInt:
// These have an offset property, add it // These have an offset property, add it
index += command.offset; 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 // Run the command
switch(command.type) { switch(command.type) {
case add: case add:
let old = memory.get(index); let old = readMemory(index);
memory.set(index, (command.value + old) & 0xFF); memory.set(index, (command.value + old) & 0xFF);
ip++; ip++;
@ -665,12 +666,18 @@ function runVM(state, maxCycles = null) {
case moveHead: case moveHead:
tapeHead += command.value; 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++; ip++;
break; break;
case writeByte: case writeByte:
output.push(memory.get(index)); output.push(readMemory(index));
ip++; ip++;
break; break;
@ -697,14 +704,11 @@ function runVM(state, maxCycles = null) {
`multiply where change for 0 is ${command.changes.get(0)}`); `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()) { for(let [offset, change] of command.changes.entries()) {
let index = tapeHead + offset; let index = tapeHead + offset;
if(!memory.has(index)) { let old = readMemory(index);
memory.set(index, 0);
}
let old = memory.get(index);
let value = old + multiplier * change; let value = old + multiplier * change;
memory.set(index, value & 0xff); memory.set(index, value & 0xff);
} }
@ -713,7 +717,7 @@ function runVM(state, maxCycles = null) {
break; break;
case jumpIfZero: case jumpIfZero:
if(memory.get(index) == 0) { if(readMemory(index) == 0) {
ip = command.target; ip = command.target;
} else { } else {
ip++; ip++;
@ -721,7 +725,7 @@ function runVM(state, maxCycles = null) {
break; break;
case jumpIfNonZero: case jumpIfNonZero:
if(memory.get(index) != 0) { if(readMemory(index) != 0) {
ip = command.target; ip = command.target;
} else { } else {
ip++; ip++;
@ -729,7 +733,7 @@ function runVM(state, maxCycles = null) {
break; break;
case writeInt: case writeInt:
let outputStr = memory.get(index).toString(); let outputStr = readMemory(index).toString();
output = output.concat(encodeUTF8(outputStr)); output = output.concat(encodeUTF8(outputStr));
ip++; ip++;
break; break;
@ -984,7 +988,6 @@ function cachedCompile(program, enableExtensions = true) {
// (string, string, int) → string // (string, string, int) → string
function ircbotRun(program, input, maxCycles = 400000) { function ircbotRun(program, input, maxCycles = 400000) {
// TODO; Cache programs
let compiled = cachedCompile(program); let compiled = cachedCompile(program);
let vm = newVM(compiled, encodeUTF8(input)); let vm = newVM(compiled, encodeUTF8(input));