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
|
||||
----
|
||||
### 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
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,
|
||||
// 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));
|
||||
|
||||
|
|
Loading…
Reference in New Issue