2 <title>Turing Tarpit Simulator
</title>
5 /* internal values for simulated computer */
6 var ins_pointer
= 0; /* instruction pointer */
7 var dat_pointer
= 0; /* data pointer */
8 var dat_pointer_changed
= 0; /* bool set to 1 if data pointer has changed in the last step */
9 var dat_pointer_last_address
= 0; /* address of data pointer in last step */
10 var ram_last_address
= 0; /* address of RAM updated in last step */
11 var breakpoints
= 1; /* bool set to 0 to ignore breakpoints */
12 var ram
= new Array(); /* memory of virtual machine */
13 var jmp
= new Array(); /* used as a stack to jump from one command to another */
14 var ins
= null; /* current instruction from code */
15 var halt
= false; /* halts program ASAP */
17 /* objects that display data to the user */
22 var disp_pointer
= "<div id=disp_pointer>⇒</div>"; /* data pointer displayed in memory block */
24 /* highlight current instruction running on machine */
25 function code_highlight(inputEl
, selStart
, selEnd
) {
26 if (inputEl
.setSelectionRange
) {
28 inputEl
.setSelectionRange(selStart
, selEnd
);
29 } else if (inputEl
.createTextRange
) {
30 var range
= inputEl
.createTextRange();
32 range
.moveEnd('character', selEnd
);
33 range
.moveStart('character', selStart
);
38 /* turns breakpoints on and off */
39 function debug_toggle_breakpoints()
41 var button
= document
.getElementById("dbg_status");
44 button
.innerHTML
='<img src="http://opentextbook.info/icons/32x32/bug_delete.png">';
47 button
.innerHTML
='<img src="http://opentextbook.info/icons/32x32/bug_add.png">';
51 /* removes all breakpoints in source code */
52 function debug_remove_breakpoints()
54 /* ask user for permission first */
55 var ans
= confirm("Permanently remove all breakpoints from code?");
56 var code
= document
.getElementById("code");
57 if(ans
) { code
.value
= code
.value
.replace( /\*/g , '' ); }
60 /* test current code character - return true if it is an instruction */
61 /* tried to use regex on this and could not get it to work :( */
64 if(ins
== '+' || ins
== '-' || ins
== '>' || ins
== '<' ||
65 ins
== '*' || ins
== '.' || ins
== '[' || ins
== ']' || ins
== ',') {
71 /* find next instruction in code and move instruction pointer to it */
72 function fnd_nxt_inst()
75 if(ins_pointer
> disp_code
.value
.length
) { break; } /* must stop at end of code */
76 update_ins_pointer(1);
77 ins
= disp_code
.value
.substring(ins_pointer
-1,ins_pointer
); /* get data at ins_pointer location */
79 if(ins_pointer
> disp_code
.value
.length
) {
80 alert("HALT: Program is Complete");
85 /* highlight code currently executing on screen */
86 code_highlight(disp_code
, ins_pointer
-1, ins_pointer
);
89 /* find previous instruction in code and move instruction pointer to it */
90 function fnd_prv_inst()
93 while(ins_pointer
>= 0)
95 ins
= disp_code
.value
.substring(ins_pointer
-1, ins_pointer
); /* get data at ins_pointer location */
96 if(tst_inst()) { return; }
99 if(ins_pointer
== 0) {
100 alert("SEGFAULT: Program could not find corresponding jump instruction");
106 /* execute next instruction from input */
107 function exe_nxt_inst()
114 ram_modify(dat_pointer
, 1);
117 ram_modify(dat_pointer
, -1);
123 dat_point_modify(-1);
125 case '*': /* these are comments - a break from the standard language */
126 if(breakpoints
) { stop(); }
140 /* must be a comment :) */
144 /* if byte at data pointer is = 0, jump forward to instruction after matching ']' command */
147 if(ram
[dat_pointer
] != 0) { return; }
148 /* add this jump to stack */
150 /* loop through code, pushing and popping stack until stack is empty */
151 while(jmp
.length
> 0) {
153 if(ins
== ']') { jmp
.pop();
154 } else if (ins
== '[') { jmp
.push(']'); }
158 /* if byte at data pointer is != 0, jump back to instruction after matching '[' command */
161 if(ram
[dat_pointer
] == 0) { return; }
162 /* add this jump to stack */
164 /* loop through code, pushing and popping stack until stack is empty */
165 while(jmp
.length
> 0 && ins_pointer
> 0) {
167 if(ins
== '[') { jmp
.pop();
168 } else if (ins
== ']') { jmp
.push(']'); }
173 rewind code to beginning reset all memory locations
174 this simulates rebooting the computer
178 update_ins_pointer(0);
181 ram_highlight_clear();
182 dat_point_highlight();
183 document
.getElementById("output_disp").innerHTML
= '';
184 document
.getElementById("addr_0").innerHTML
= "0" + disp_pointer
;
185 dat_point_highlight_clear();
188 /* stop stepping through code on timer if breakpoints enabled */
194 /* run through program on timer, stopping at breakpoints if enabled */
197 var total_steps
= document
.getElementById("code").value
.length
;
198 while(ins_pointer
<= total_steps
&& halt
== false) { step_next(); }
201 /* step forward one instruction */
204 //update_ins_pointer(1);
206 dat_point_highlight();
209 /* more back one instruction - undoes work of previous instruction */
212 update_ins_pointer(-1);
213 dat_point_highlight();
216 /* update instruction pointer
219 1 increment pointer by one
221 -1 decrement pointer by one
223 function update_ins_pointer(direction
)
225 if(direction
< 0 && ins_pointer
!= 0 ) { ins_pointer
--; }
226 else if (direction
== 0 ) { ins_pointer
= 0; }
227 else { ins_pointer
++; }
228 disp_ins_pointer
.value
= ins_pointer
;
231 /* update instruction pointer and set to new value */
232 function ins_point_modify_by_address(val
)
234 /* instruction pointer can never be less than 0 */
236 alert("Instruction Pointer cannot be set less than Zero.");
237 disp_ins_pointer
.value
= ins_pointer
; /* reset val to previous */
240 if(val
> disp_code
.value
.length
) {
241 alert("Instruction Pointer cannot be set beyond end of code.\n Current length of code: " + disp_code
.value
.length
);
242 disp_ins_pointer
.value
= ins_pointer
; /* reset val to previous */
245 ins_pointer
= disp_ins_pointer
.value
;
248 /* setup virtual machine - must be called on page load */
251 disp_code
= document
.getElementById("code");
252 disp_ins_pointer
= document
.getElementById("ins_pointer_disp");
253 disp_dat_pointer
= document
.getElementById("dat_pointer_disp");
254 disp_ram
= document
.getElementById("ram_disp");
257 document
.getElementById("addr_0").innerHTML
= "0" + disp_pointer
;
258 /* reset_output(); */
261 /* reset all RAM to 0 */
265 for(i
=0; i
< 64; i
++) { ram
[i
] = 0; }
268 /* update highlight of one memory address and release other highlight if needed */
269 function ram_highlight(address
)
271 var disp_last_address
= document
.getElementById("ram_"+ram_last_address
);
272 /* highlight background of current address */
273 document
.getElementById("ram_"+address
).style
.backgroundColor
= "#ff0";
275 /* remove highlight from last address modified */
276 if(ram_last_address
!= address
){
277 if(ram_last_address
%2==0) {
278 disp_last_address
.style
.backgroundColor
= "#fff";
280 disp_last_address
.style
.backgroundColor
= "#def";
285 /* remove highlight from all memory cells regardless of current status */
286 function ram_highlight_clear()
289 for(i
=0; i
< 64; i
++)
292 document
.getElementById("ram_"+i
).style
.backgroundColor
= "#fff";
294 document
.getElementById("ram_"+i
).style
.backgroundColor
= "#def";
296 document
.getElementById("ram_"+i
).innerHTML
= ram
[i
];
300 /* define RAM on screen */
304 var table
= "<table id=memory_table>\n";
305 for(i
=0; i
< 16; i
++){
309 table
+= "\t<tr class=odd>";
311 table
+= "<td width='35' class=addr id=addr_"+i
+">"+i
+"</td><td width='35' class=ram id=ram_"+i
+">";
312 table
+= ram
[i
]+"</td><td width='35' class=addr id=addr_"+(i
+16)+">";
313 table
+= (i
+16)+"</td><td class=ram id=ram_"+(i
+16)+">"+ram
[i
+16]+"</td>\n";
314 table
+= "<td class=addr id=addr_"+(i
+32)+">"+(i
+32)+"</td><td width='35' class=ram id=ram_";
315 table
+= (i
+32)+">"+ram
[i
+32]+"</td><td class=addr id=addr_";
316 table
+= (i
+48)+">"+(i
+48)+"</td><td width='35' class=ram id=ram_"+(i
+48)+">"+ram
[i
+48]+"</td></tr>\n";
318 table
+= "</table>\n";
319 disp_ram
.innerHTML
= table
;
323 modify the value at this address - reset RAM highlights for all addresses
324 1 increment RAM by one
326 -1 decrement RAM by one
328 function ram_modify(address
, change
)
330 if(address
< 0 || address
> 63) {
331 alert("SEGFAULT: Cannot Modify Data Outside of Memory Range");
339 } else if(change
< 0 ) {
344 ram_highlight(address
);
345 document
.getElementById("ram_"+address
).innerHTML
= ram
[address
];
346 ram_last_address
= address
;
350 modify state of data pointer
351 1 increment data pointer by one
352 0 set data pointer to 0
353 -1 decrement data pointer by one
356 function dat_point_modify(change
)
358 dat_pointer_last_address
= dat_pointer
;
361 } else if(change
< 0 ) {
362 /* could put SEGFAULT here, but C does not have a check for this, so neither will I ;) */
368 /* place '>' char next to memory address in table */
369 if(dat_pointer
>= 0 && dat_pointer
< 64) {
370 document
.getElementById("addr_"+dat_pointer
).innerHTML
= dat_pointer
+ disp_pointer
;
373 /* remove '>' char next to memory address in table */
374 if(dat_pointer_last_address
>= 0 && dat_pointer_last_address
< 64) {
375 document
.getElementById("addr_"+dat_pointer_last_address
).innerHTML
= dat_pointer_last_address
;
378 disp_dat_pointer
.value
= dat_pointer
;
379 dat_pointer_changed
= 1;
382 function dat_point_modify_by_address(val
)
384 dat_pointer_last_address
= dat_pointer
;
385 dat_pointer
= disp_dat_pointer
.value
;
386 /* place '>' char next to memory address in table */
387 if(dat_pointer
>= 0 && dat_pointer
< 64) {
388 document
.getElementById("addr_"+dat_pointer
).innerHTML
= dat_pointer
+ disp_pointer
;
391 /* remove '>' char next to memory address in table */
392 if(dat_pointer_last_address
>= 0 && dat_pointer_last_address
< 64) {
393 document
.getElementById("addr_"+dat_pointer_last_address
).innerHTML
= dat_pointer_last_address
;
395 dat_pointer_changed
= 1;
396 dat_point_highlight();
399 /* turns on and off data pointer highlight if it has changed this step */
400 function dat_point_highlight()
402 if(dat_pointer_changed
) {
403 disp_dat_pointer
.style
.backgroundColor
= "#ff0";
404 dat_pointer_changed
= 0;
406 disp_dat_pointer
.style
.backgroundColor
= "#fff";
409 /* as a convenience to the user, set to red if pointer is out of memory range */
410 if(dat_pointer
< 0 || dat_pointer
> 63) {
411 disp_dat_pointer
.style
.backgroundColor
= "#f00";
415 /* remove highlight from data pointer */
416 function dat_point_highlight_clear()
418 disp_dat_pointer
.style
.backgroundColor
= "#fff";
421 /* print ASCII representation of memory at data pointer */
424 var x
= String
.fromCharCode(63+ram
[dat_pointer
]);
425 document
.getElementById("output_disp").innerHTML
+= x
;
430 <style type=
"text/css">
433 font-family: Tahoma
, Arial
, Helvetica
, sans-serif
;
490 border:1px solid
#000;
491 border-collapse: collapse
;
496 border-bottom:1px solid
#000;
500 background-color: #def;
503 border-bottom: 1px solid
#000;
511 border-right:1px solid
#000;
534 <body onLoad=
"init_form();">
536 <center><h2>Turing Tarpit Simulator
</h2></center>
539 <button onClick='reset();'
><img src=
"http://opentextbook.info/icons/32x32/resultset_first.png"></button>
541 <button onClick='step_back();'
><img src=
"http://opentextbook.info/icons/32x32/resultset_previous.png"></button>
543 <button onClick='step_next();'
><img src=
"http://opentextbook.info/icons/32x32/resultset_next.png"></button>
545 <button onClick='run();'
><img src=
"http://opentextbook.info/icons/32x32/resultset_last.png"></button>
547 <button onClick='halt();'
><img src=
"http://opentextbook.info/icons/32x32/cancel.png"></button>
549 <button disabled
><img src=
"http://opentextbook.info/icons/32x32/disk.png"></button>
552 <div id=
"code_buttons">
553 <button id=
"dbg_status" onClick='debug_toggle_breakpoints();'
>
554 <img src=
"http://opentextbook.info/icons/32x32/bug_add.png">
557 <button id=
"dbg_status" onClick='debug_remove_breakpoints();'
>
558 <img src=
"http://opentextbook.info/icons/32x32/bin.png">
562 <div id=
"input_banner">INPUT
</div>
563 <div id=
"input"><textarea id=
"code" rows=
"27" cols=
"38"></textarea></div>
565 <div id=
"ip_banner">INSTRUCTION POINTER
</div>
566 <div id=
"instruction"><input onBlur=
"ins_point_modify_by_address(disp_ins_pointer.value);" id=
"ins_pointer_disp" type=
"text" diabled value=
0></div>
568 <div id=
"da_banner">DATA POINTER
</div>
569 <div id=
"data"><input onBlur=
"dat_point_modify_by_address(disp_dat_pointer.value);" id=
"dat_pointer_disp" type=
"text" diabled value=
0></div>
571 <div id=
"memory_banner">MEMORY
</div>
572 <div id=
"ram_disp"></div>
573 <div id=
"output_banner">OUTPUT
</div>
575 <textarea name=code id=output_disp
rows=
"15" cols=
"38" disabled
></textarea>