Skip to content

Commit

Permalink
added memory sharing for the interpreter
Browse files Browse the repository at this point in the history
ui does not highlight the current memory pointer yet
  • Loading branch information
btzy committed Aug 20, 2017
1 parent 98c5b35 commit 9bd5a69
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 40 deletions.
8 changes: 8 additions & 0 deletions bf.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@
<script src="jelly-bf-processhandler.js" type="text/javascript"></script>
<script src="jelly-memoryview.js" type="text/javascript"></script>
<script src="bf.js" type="text/javascript"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create','UA-53448064-1','auto');
ga('send','pageview');
</script>
</head>
<body>
<div class="wrapper">
Expand Down
13 changes: 10 additions & 3 deletions bf.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ window.addEventListener("load",function(){

// memoryview
var memoryview=document.getElementById("memoryview");
var memoryviewmanager=new MemoryView(memoryview.getElementsByClassName("memory-cells")[0],new Uint8Array(30000),0,29999);
var memoryviewmanager=undefined;

// buttons
var openbutton=document.getElementById("openbutton");
Expand Down Expand Up @@ -349,7 +349,7 @@ window.addEventListener("load",function(){
else{
console.log("Execution paused.");
}
draw_execution_paused(options.index);
draw_execution_paused(options.index,options.memoryuint8array,options.memory_ptr);
continuehandler=options.resume;
});
show_execution_only_buttons(true);
Expand Down Expand Up @@ -460,7 +460,7 @@ window.addEventListener("load",function(){
}
});
var execution_location_marker_id=undefined,execution_location_line_id=undefined;
var draw_execution_paused=function(index){
var draw_execution_paused=function(index,memoryuint8array,memory_ptr){
undraw_execution_paused();
var Range=ace.require('ace/range').Range;
var pos=codeEditor.getSession().getDocument().indexToPosition(index);
Expand All @@ -481,6 +481,8 @@ window.addEventListener("load",function(){
execution_is_paused=true;
stepbutton.classList.remove("displaynone");
memoryview.classList.remove("displaynone");
codeEditor.resize();
memoryviewmanager=new MemoryView(memoryview.getElementsByClassName("memory-cells")[0],memoryuint8array,0,29999,memory_ptr);
};
var undraw_execution_paused=function(){
if(execution_location_marker_id!==undefined)codeEditor.getSession().removeMarker(execution_location_marker_id);
Expand All @@ -497,6 +499,11 @@ window.addEventListener("load",function(){
execution_is_paused=false;
stepbutton.classList.add("displaynone");
memoryview.classList.add("displaynone");
codeEditor.resize();
if(memoryviewmanager){
memoryviewmanager.clear();
memoryviewmanager=undefined;
}
};


Expand Down
23 changes: 13 additions & 10 deletions jelly-bf-interpreter.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
JellyBFInterpreter=function(codeString,get_input,put_output,breakpointuint8array,globalpauseuint8array){
JellyBFInterpreter=function(codeString,get_input,put_output,breakpointuint8array,globalpauseuint8array,memoryuint8array){
this.code=codeString;
this.get_input=get_input;
this.put_output=put_output;
this.breakpointuint8array=breakpointuint8array;
this.globalpauseuint8array=globalpauseuint8array;
this.memory_cells=30000;
this.memory=new Uint8Array(this.memory_cells);
this.memory=memoryuint8array||new Uint8Array(this.memory_cells);
this.memory_ptr=0;
this.next_instruction_index=[];
this.loop_pair=[];
Expand Down Expand Up @@ -56,33 +56,36 @@ JellyBFInterpreter.prototype.run=function(){
++this.memory_ptr;
}
else if(this.code[this.instruction_ptr]==="+"){
this.memory[this.memory_ptr]=(this.memory[this.memory_ptr]+1)&255;
Atomics.add(this.memory,this.memory_ptr,1);
//this.memory[this.memory_ptr]=(this.memory[this.memory_ptr]+1)&255;
}
else if(this.code[this.instruction_ptr]==="-"){
this.memory[this.memory_ptr]=(this.memory[this.memory_ptr]-1)&255;
Atomics.sub(this.memory,this.memory_ptr,1);
//this.memory[this.memory_ptr]=(this.memory[this.memory_ptr]-1)&255;
}
else if(this.code[this.instruction_ptr]==="["){
if(this.memory[this.memory_ptr]===0){
if(Atomics.load(this.memory,this.memory_ptr)===0){
this.instruction_ptr=this.loop_pair[this.instruction_ptr];
}
}
else if(this.code[this.instruction_ptr]==="]"){
if(this.memory[this.memory_ptr]!==0){
if(Atomics.load(this.memory,this.memory_ptr)!==0){
this.instruction_ptr=this.loop_pair[this.instruction_ptr];
}
}
else if(this.code[this.instruction_ptr]===","){
this.memory[this.memory_ptr]=this.get_input();
Atomics.store(this.memory,this.memory_ptr,this.get_input());
//this.memory[this.memory_ptr]=this.get_input();
}
else if(this.code[this.instruction_ptr]==="."){
this.put_output(this.memory[this.memory_ptr]);
this.put_output(Atomics.load(this.memory,this.memory_ptr));
}
else{
throw "Internal error!";
}
this.instruction_ptr=this.next_instruction_index[this.instruction_ptr];
if(this.instruction_ptr!==Number.MAX_SAFE_INTEGER&&Atomics.load(this.breakpointuint8array,this.instruction_ptr)!==0)return {type:JellyBFInterpreter.RunResult.PAUSED_AT_BREAKPOINT,index:this.instruction_ptr};
if(this.instruction_ptr!==Number.MAX_SAFE_INTEGER&&Atomics.load(this.globalpauseuint8array,0)!==0)return {type:JellyBFInterpreter.RunResult.PAUSED_WITHOUT_BREAKPOINT,index:this.instruction_ptr};
if(this.instruction_ptr!==Number.MAX_SAFE_INTEGER&&Atomics.load(this.breakpointuint8array,this.instruction_ptr)!==0)return {type:JellyBFInterpreter.RunResult.PAUSED_AT_BREAKPOINT,index:this.instruction_ptr,memory_ptr:this.memory_ptr};
if(this.instruction_ptr!==Number.MAX_SAFE_INTEGER&&Atomics.load(this.globalpauseuint8array,0)!==0)return {type:JellyBFInterpreter.RunResult.PAUSED_WITHOUT_BREAKPOINT,index:this.instruction_ptr,memory_ptr:this.memory_ptr};
}
return {type:JellyBFInterpreter.RunResult.PROGRAM_TERMINATED};
};
8 changes: 5 additions & 3 deletions jelly-bf-processhandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,18 @@ JellyBFProcessHandler.prototype.executeInteractive=function(options,inputRequest
delete options.breakpointBuffer;
delete options.globalPauseBuffer;

var memoryBuffer=new SharedArrayBuffer(30000);

var resumer=function(){
that.worker.postMessage({type:"interpret-continue"});
};

var interpretHandler=function(e){
if(e.data.type==="interpret-breakpoint"){
pausedCallback({breakpoint:true,resume:resumer,index:e.data.index});
pausedCallback({breakpoint:true,resume:resumer,index:e.data.index,memoryuint8array:new Uint8Array(memoryBuffer),memory_ptr:e.data.memory_ptr});
}
else if(e.data.type==="interpret-paused"){
pausedCallback({breakpoint:false,resume:resumer,index:e.data.index});
pausedCallback({breakpoint:false,resume:resumer,index:e.data.index,memoryuint8array:new Uint8Array(memoryBuffer),memory_ptr:e.data.memory_ptr});
}
};

Expand Down Expand Up @@ -205,7 +207,7 @@ JellyBFProcessHandler.prototype.executeInteractive=function(options,inputRequest
doneCallback({success:false});
});

this.worker.postMessage({type:"interpret-interactive",sourcecode:sourcecode,inputbuffer:inputBuffer,outputbuffer:outputBuffer,inputwaitbuffer:inputWaitBuffer,outputwaitbuffer:outputWaitBuffer,breakpointbuffer:breakpointBuffer,globalpausebuffer:globalpauseBuffer,options:options});
this.worker.postMessage({type:"interpret-interactive",sourcecode:sourcecode,inputbuffer:inputBuffer,outputbuffer:outputBuffer,inputwaitbuffer:inputWaitBuffer,outputwaitbuffer:outputWaitBuffer,breakpointbuffer:breakpointBuffer,globalpausebuffer:globalpauseBuffer,memorybuffer:memoryBuffer,options:options});
}
else{
var that=this;
Expand Down
4 changes: 2 additions & 2 deletions jelly-bf-sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ var JellyBFSync={
terminate_output();
return true;
},
interpretInteractive:function(str,inputuint8array,outputuint8array,inputwaitint32array,outputwaitint32array,breakpointuint8array,globalpauseuint8array,options,updatedOutputCallback,requestInputCallback){
interpretInteractive:function(str,inputuint8array,outputuint8array,inputwaitint32array,outputwaitint32array,breakpointuint8array,globalpauseuint8array,memoryuint8array,options,updatedOutputCallback,requestInputCallback){
var WaitArrayId={
READ_HEAD:0,
WRITE_HEAD:1,
Expand Down Expand Up @@ -132,7 +132,7 @@ var JellyBFSync={
Atomics.store(outputwaitint32array,WaitArrayId.WRITE_HEAD,output_write_head+1);
updatedOutputCallback();
};
var instance=new JellyBFInterpreter(str,get_input,put_output,breakpointuint8array,globalpauseuint8array);
var instance=new JellyBFInterpreter(str,get_input,put_output,breakpointuint8array,globalpauseuint8array,memoryuint8array);
return {
run:function(){
var res=instance.run();
Expand Down
7 changes: 4 additions & 3 deletions jelly-bf-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@
var options=message.options;
var breakpointbuffer=message.breakpointbuffer;
var globalpausebuffer=message.globalpausebuffer;
var memorybuffer=message.memorybuffer;
try{
interpretstate=JellyBFSync.interpretInteractive(sourcecode, new Uint8Array(inputbuffer), new Uint8Array(outputbuffer), new Int32Array(inputwaitbuffer), new Int32Array(outputwaitbuffer), new Uint8Array(breakpointbuffer), new Uint8Array(globalpausebuffer),options,function(){
interpretstate=JellyBFSync.interpretInteractive(sourcecode, new Uint8Array(inputbuffer), new Uint8Array(outputbuffer), new Int32Array(inputwaitbuffer), new Int32Array(outputwaitbuffer), new Uint8Array(breakpointbuffer), new Uint8Array(globalpausebuffer),memorybuffer?(new Uint8Array(memorybuffer)):undefined,options,function(){
self.postMessage({type:"output-updated"});
},function(readhead){
self.postMessage({type:"input-requested",readhead:readhead});
Expand All @@ -88,10 +89,10 @@
interpretstate=undefined;
}
else if(ret.type===JellyBFInterpreter.RunResult.PAUSED_AT_BREAKPOINT){
self.postMessage({type:"interpret-breakpoint",index:ret.index});
self.postMessage({type:"interpret-breakpoint",index:ret.index,memory_ptr:ret.memory_ptr});
}
else if(ret.type===JellyBFInterpreter.RunResult.PAUSED_WITHOUT_BREAKPOINT){
self.postMessage({type:"interpret-paused",index:ret.index});
self.postMessage({type:"interpret-paused",index:ret.index,memory_ptr:ret.memory_ptr});
}
else{
self.postMessage({type:"interpreterror"});
Expand Down
37 changes: 21 additions & 16 deletions jelly-bf-worker.max.js
Original file line number Diff line number Diff line change
Expand Up @@ -1540,14 +1540,14 @@ var JellyBF_CloseAndAttemptUnrollLoop = function(codeChunks, options) {
}
};

JellyBFInterpreter = function(codeString, get_input, put_output, breakpointuint8array, globalpauseuint8array) {
JellyBFInterpreter = function(codeString, get_input, put_output, breakpointuint8array, globalpauseuint8array, memoryuint8array) {
this.code = codeString;
this.get_input = get_input;
this.put_output = put_output;
this.breakpointuint8array = breakpointuint8array;
this.globalpauseuint8array = globalpauseuint8array;
this.memory_cells = 3e4;
this.memory = new Uint8Array(this.memory_cells);
this.memory = memoryuint8array || new Uint8Array(this.memory_cells);
this.memory_ptr = 0;
this.next_instruction_index = [];
this.loop_pair = [];
Expand Down Expand Up @@ -1589,40 +1589,42 @@ JellyBFInterpreter.RunResult = {
};

JellyBFInterpreter.prototype.run = function() {
while (this.instruction_ptr != Number.MAX_SAFE_INTEGER) {
while (this.instruction_ptr !== Number.MAX_SAFE_INTEGER) {
if (this.code[this.instruction_ptr] === "<") {
if (this.memory_ptr === 0) throw JellyBFInterpreter.RuntimeError.INVALID_MEMORY_ACCESS;
--this.memory_ptr;
} else if (this.code[this.instruction_ptr] === ">") {
if (this.memory_ptr + 1 === this.memory_cells) throw JellyBFInterpreter.RuntimeError.INVALID_MEMORY_ACCESS;
++this.memory_ptr;
} else if (this.code[this.instruction_ptr] === "+") {
this.memory[this.memory_ptr] = this.memory[this.memory_ptr] + 1 & 255;
Atomics.add(this.memory, this.memory_ptr, 1);
} else if (this.code[this.instruction_ptr] === "-") {
this.memory[this.memory_ptr] = this.memory[this.memory_ptr] - 1 & 255;
Atomics.sub(this.memory, this.memory_ptr, 1);
} else if (this.code[this.instruction_ptr] === "[") {
if (this.memory[this.memory_ptr] === 0) {
if (Atomics.load(this.memory, this.memory_ptr) === 0) {
this.instruction_ptr = this.loop_pair[this.instruction_ptr];
}
} else if (this.code[this.instruction_ptr] === "]") {
if (this.memory[this.memory_ptr] !== 0) {
if (Atomics.load(this.memory, this.memory_ptr) !== 0) {
this.instruction_ptr = this.loop_pair[this.instruction_ptr];
}
} else if (this.code[this.instruction_ptr] === ",") {
this.memory[this.memory_ptr] = this.get_input();
Atomics.store(this.memory, this.memory_ptr, this.get_input());
} else if (this.code[this.instruction_ptr] === ".") {
this.put_output(this.memory[this.memory_ptr]);
this.put_output(Atomics.load(this.memory, this.memory_ptr));
} else {
throw "Internal error!";
}
this.instruction_ptr = this.next_instruction_index[this.instruction_ptr];
if (this.instruction_ptr !== Number.MAX_SAFE_INTEGER && Atomics.load(this.breakpointuint8array, this.instruction_ptr) !== 0) return {
type: JellyBFInterpreter.RunResult.PAUSED_AT_BREAKPOINT,
index: this.instruction_ptr
index: this.instruction_ptr,
memory_ptr: this.memory_ptr
};
if (this.instruction_ptr !== Number.MAX_SAFE_INTEGER && Atomics.load(this.globalpauseuint8array, 0) !== 0) return {
type: JellyBFInterpreter.RunResult.PAUSED_WITHOUT_BREAKPOINT,
index: this.instruction_ptr
index: this.instruction_ptr,
memory_ptr: this.memory_ptr
};
}
return {
Expand Down Expand Up @@ -1712,7 +1714,7 @@ var JellyBFSync = {
terminate_output();
return true;
},
interpretInteractive: function(str, inputuint8array, outputuint8array, inputwaitint32array, outputwaitint32array, breakpointuint8array, globalpauseuint8array, options, updatedOutputCallback, requestInputCallback) {
interpretInteractive: function(str, inputuint8array, outputuint8array, inputwaitint32array, outputwaitint32array, breakpointuint8array, globalpauseuint8array, memoryuint8array, options, updatedOutputCallback, requestInputCallback) {
var WaitArrayId = {
READ_HEAD: 0,
WRITE_HEAD: 1,
Expand Down Expand Up @@ -1757,7 +1759,7 @@ var JellyBFSync = {
Atomics.store(outputwaitint32array, WaitArrayId.WRITE_HEAD, output_write_head + 1);
updatedOutputCallback();
};
var instance = new JellyBFInterpreter(str, get_input, put_output, breakpointuint8array, globalpauseuint8array);
var instance = new JellyBFInterpreter(str, get_input, put_output, breakpointuint8array, globalpauseuint8array, memoryuint8array);
return {
run: function() {
var res = instance.run();
Expand Down Expand Up @@ -1844,8 +1846,9 @@ var JellyBFSync = {
var options = message.options;
var breakpointbuffer = message.breakpointbuffer;
var globalpausebuffer = message.globalpausebuffer;
var memorybuffer = message.memorybuffer;
try {
interpretstate = JellyBFSync.interpretInteractive(sourcecode, new Uint8Array(inputbuffer), new Uint8Array(outputbuffer), new Int32Array(inputwaitbuffer), new Int32Array(outputwaitbuffer), new Uint8Array(breakpointbuffer), new Uint8Array(globalpausebuffer), options, function() {
interpretstate = JellyBFSync.interpretInteractive(sourcecode, new Uint8Array(inputbuffer), new Uint8Array(outputbuffer), new Int32Array(inputwaitbuffer), new Int32Array(outputwaitbuffer), new Uint8Array(breakpointbuffer), new Uint8Array(globalpausebuffer), memorybuffer ? new Uint8Array(memorybuffer) : undefined, options, function() {
self.postMessage({
type: "output-updated"
});
Expand Down Expand Up @@ -1887,12 +1890,14 @@ var JellyBFSync = {
} else if (ret.type === JellyBFInterpreter.RunResult.PAUSED_AT_BREAKPOINT) {
self.postMessage({
type: "interpret-breakpoint",
index: ret.index
index: ret.index,
memory_ptr: ret.memory_ptr
});
} else if (ret.type === JellyBFInterpreter.RunResult.PAUSED_WITHOUT_BREAKPOINT) {
self.postMessage({
type: "interpret-paused",
index: ret.index
index: ret.index,
memory_ptr: ret.memory_ptr
});
} else {
self.postMessage({
Expand Down
21 changes: 18 additions & 3 deletions jelly-memoryview.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
var MemoryView=function(root_el,uint8_array,min_index,max_index){
var MemoryView=function(root_el,uint8_array,min_index,max_index,memory_ptr){
this.root=root_el;
this.minIndex=min_index;
this.maxIndex=max_index;
this.currentIndex=this.minIndex;
this.viewLength=1;
this.data=uint8_array;
this.ptr=memory_ptr;
this.redraw();
var that=this;
window.addEventListener("resize",function(){
Expand All @@ -17,12 +18,16 @@ MemoryView.prototype.refresh=function(){
var labels=this.root.getElementsByClassName("labelwrapper")[0].getElementsByClassName("label");
for(var i=0;i<this.viewLength;++i){
labels[i].firstChild.nodeValue=(this.currentIndex+i).toString();
cells[i].firstChild.nodeValue=(this.data[this.currentIndex+i]).toString();
cells[i].firstChild.nodeValue=Atomics.load(this.data,this.currentIndex+i).toString();
}
};

MemoryView.prototype.redraw=function(){
MemoryView.prototype.clear=function(){
while(this.root.firstChild)this.root.removeChild(this.root.firstChild);
};

MemoryView.prototype.redraw=function(){
this.clear();
var root_width=this.root.offsetWidth;
this.viewLength=Math.floor((root_width-6-1)/29);
if(this.viewLength>this.maxIndex-this.minIndex+1)this.viewLength=this.maxIndex-this.minIndex+1;
Expand All @@ -45,6 +50,16 @@ MemoryView.prototype.redraw=function(){
this.refresh();
};

MemoryView.prototype.centerAtIndex=function(index){
if(index<this.minIndex||index>this.maxIndex)return false;
index-=(this.viewLength-1)/2;
if(index<0)index=0;
if(index+this.viewLength>this.maxIndex+1)index=this.maxIndex+1-this.viewLength;
this.currentIndex=index;
this.refresh();
return true;
};

MemoryView.prototype.goToIndex=function(index){
if(index<this.minIndex||index>this.maxIndex)return false;
if(index<this.currentIndex){
Expand Down

0 comments on commit 9bd5a69

Please sign in to comment.