Implement a readMemory() in runVM() that returns 0 on reads to nonexistent memory
This commit is contained in:
parent
00eb264cb4
commit
1b262941ca
|
@ -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
49
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,
|
// 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));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue