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
----
### 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

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,
// 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));