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 */
23 var disp_pointer
= "<div id=disp_pointer>⇒</div>"; /* data pointer displayed in memory block */
25 /* highlight current instruction running on machine */
26 function code_highlight(inputEl
, selStart
, selEnd
) {
27 if (inputEl
.setSelectionRange
) {
29 inputEl
.setSelectionRange(selStart
, selEnd
);
30 } else if (inputEl
.createTextRange
) {
31 var range
= inputEl
.createTextRange();
33 range
.moveEnd('character', selEnd
);
34 range
.moveStart('character', selStart
);
39 /* turns breakpoints on and off */
40 function debug_toggle_breakpoints()
42 var button
= document
.getElementById("dbg_status");
45 button
.innerHTML
='<img src="http://opentextbook.info/icons/32x32/bug_delete.png">';
48 button
.innerHTML
='<img src="http://opentextbook.info/icons/32x32/bug_add.png">';
52 /* removes all breakpoints in source code */
53 function debug_remove_breakpoints()
55 /* ask user for permission first */
56 var ans
= confirm("Permanently remove all breakpoints from code?");
57 var code
= document
.getElementById("code");
58 if(ans
) { code
.value
= code
.value
.replace( /\*/g , '' ); }
61 /* test current code character - return true if it is an instruction */
62 /* tried to use regex on this and could not get it to work :( */
65 if(ins
== '+' || ins
== '-' || ins
== '>' || ins
== '<' ||
66 ins
== '*' || ins
== '.' || ins
== '[' || ins
== ']' || ins
== ',') {
72 /* find next instruction in code and move instruction pointer to it */
73 function fnd_nxt_inst()
76 if(ins_pointer
> disp_code
.value
.length
) { break; } /* must stop at end of code */
77 update_ins_pointer(1);
78 ins
= disp_code
.value
.substring(ins_pointer
-1,ins_pointer
); /* get data at ins_pointer location */
80 if(ins_pointer
> disp_code
.value
.length
) {
81 alert("HALT: Program is Complete");
86 /* highlight code currently executing on screen */
87 code_highlight(disp_code
, ins_pointer
-1, ins_pointer
);
90 /* find previous instruction in code and move instruction pointer to it */
91 function fnd_prv_inst()
94 while(ins_pointer
>= 0)
96 ins
= disp_code
.value
.substring(ins_pointer
-1, ins_pointer
); /* get data at ins_pointer location */
97 if(tst_inst()) { return; }
100 if(ins_pointer
== 0) {
101 alert("SEGFAULT: Program could not find corresponding jump instruction");
107 /* execute next instruction from input */
108 function exe_nxt_inst()
115 ram_modify(dat_pointer
, 1);
118 ram_modify(dat_pointer
, -1);
124 dat_point_modify(-1);
126 case '*': /* these are comments - a break from the standard language */
127 if(breakpoints
) { stop(); }
141 /* must be a comment :) */
145 /* if byte at data pointer is = 0, jump forward to instruction after matching ']' command */
148 if(ram
[dat_pointer
] != 0) { return; }
149 /* add this jump to stack */
151 /* loop through code, pushing and popping stack until stack is empty */
152 while(jmp
.length
> 0) {
154 if(ins
== ']') { jmp
.pop();
155 } else if (ins
== '[') { jmp
.push(']'); }
159 /* if byte at data pointer is != 0, jump back to instruction after matching '[' command */
162 if(ram
[dat_pointer
] == 0) { return; }
163 /* add this jump to stack */
165 /* loop through code, pushing and popping stack until stack is empty */
166 while(jmp
.length
> 0 && ins_pointer
> 0) {
168 if(ins
== '[') { jmp
.pop();
169 } else if (ins
== ']') { jmp
.push(']'); }
174 rewind code to beginning reset all memory locations
175 this simulates rebooting the computer
179 update_ins_pointer(0);
182 ram_highlight_clear();
183 dat_point_highlight();
184 document
.getElementById("output_disp").innerHTML
= '';
185 document
.getElementById("addr_0").innerHTML
= "0" + disp_pointer
;
186 dat_point_highlight_clear();
189 /* stop stepping through code on timer if breakpoints enabled */
195 /* run through program on timer, stopping at breakpoints if enabled */
198 var total_steps
= document
.getElementById("code").value
.length
;
199 while(ins_pointer
<= total_steps
&& halt
== false) { step_next(); }
202 /* step forward one instruction */
205 //update_ins_pointer(1);
207 dat_point_highlight();
210 /* more back one instruction - undoes work of previous instruction */
213 update_ins_pointer(-1);
214 dat_point_highlight();
217 /* update instruction pointer
220 1 increment pointer by one
222 -1 decrement pointer by one
224 function update_ins_pointer(direction
)
226 if(direction
< 0 && ins_pointer
!= 0 ) { ins_pointer
--; }
227 else if (direction
== 0 ) { ins_pointer
= 0; }
228 else { ins_pointer
++; }
229 disp_ins_pointer
.value
= ins_pointer
;
232 /* update instruction pointer and set to new value */
233 function ins_point_modify_by_address(val
)
235 /* instruction pointer can never be less than 0 */
237 alert("Instruction Pointer cannot be set less than Zero.");
238 disp_ins_pointer
.value
= ins_pointer
; /* reset val to previous */
241 if(val
> disp_code
.value
.length
) {
242 alert("Instruction Pointer cannot be set beyond end of code.\n Current length of code: " + disp_code
.value
.length
);
243 disp_ins_pointer
.value
= ins_pointer
; /* reset val to previous */
246 ins_pointer
= disp_ins_pointer
.value
;
249 /* setup virtual machine - must be called on page load */
252 disp_code
= document
.getElementById("code");
253 disp_ins_pointer
= document
.getElementById("ins_pointer_disp");
254 disp_dat_pointer
= document
.getElementById("dat_pointer_disp");
255 disp_ram
= document
.getElementById("ram_disp");
258 document
.getElementById("addr_0").innerHTML
= "0" + disp_pointer
;
259 disp_docs
= document
.getElementById("docs");
260 /* reset_output(); */
263 /* reset all RAM to 0 */
267 for(i
=0; i
< 64; i
++) { ram
[i
] = 0; }
270 /* update highlight of one memory address and release other highlight if needed */
271 function ram_highlight(address
)
273 var disp_last_address
= document
.getElementById("ram_"+ram_last_address
);
274 /* highlight background of current address */
275 document
.getElementById("ram_"+address
).style
.backgroundColor
= "#ff0";
277 /* remove highlight from last address modified */
278 if(ram_last_address
!= address
){
279 if(ram_last_address
%2==0) {
280 disp_last_address
.style
.backgroundColor
= "#fff";
282 disp_last_address
.style
.backgroundColor
= "#def";
287 /* remove highlight from all memory cells regardless of current status */
288 function ram_highlight_clear()
291 for(i
=0; i
< 64; i
++)
294 document
.getElementById("ram_"+i
).style
.backgroundColor
= "#fff";
296 document
.getElementById("ram_"+i
).style
.backgroundColor
= "#def";
298 document
.getElementById("ram_"+i
).innerHTML
= ram
[i
];
302 /* define RAM on screen */
306 var table
= "<table id=memory_table>\n";
307 for(i
=0; i
< 16; i
++){
309 table
+= "\t<tr class=even>";
311 table
+= "\t<tr class=odd>";
313 table
+= "<td width='35' class=addr id=addr_"+i
+">"+i
+"</td><td width='35' class=ram id=ram_"+i
+">"+ram
[i
]+"</td>";
314 table
+= "<td width='35' class=addr id=addr_"+(i
+16)+">"+(i
+16)+"</td><td class=ram id=ram_"+(i
+16)+">"+ram
[i
+16]+"</td>\n";
315 table
+= "<td class=addr id=addr_"+(i
+32)+">"+(i
+32)+"</td><td width='35' class=ram id=ram_"+(i
+32)+">"+ram
[i
+32]+"</td>\n";
316 table
+= "<td class=addr id=addr_"+(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(ram
[dat_pointer
]);
425 document
.getElementById("output_disp").innerHTML
+= x
;
428 /* documentation stored inside invisible div. This shows its contents. */
429 function display_docs()
431 disp_docs
.style
.visibility
= "visible";
432 docs_select("docs_main");
435 /* hide documentation from user */
438 disp_docs
.style
.visibility
= "hidden";
441 function docs_select(page
)
443 if(page
== "basic") {
444 document
.getElementById("docs_content").innerHTML
= document
.getElementById("docs_basic").innerHTML
;
445 } else if(page
== "features") {
446 document
.getElementById("docs_content").innerHTML
= document
.getElementById("docs_features").innerHTML
;
447 } else if(page
== "examples") {
448 document
.getElementById("docs_content").innerHTML
= document
.getElementById("docs_examples").innerHTML
;
449 } else if(page
== "examples2") {
450 document
.getElementById("docs_content").innerHTML
= document
.getElementById("docs_examples2").innerHTML
;
452 document
.getElementById("docs_content").innerHTML
= document
.getElementById("docs_main").innerHTML
;
458 <style type=
"text/css">
461 font-family: Tahoma
, Arial
, Helvetica
, sans-serif
;
524 border:1px solid
#000;
525 border-collapse: collapse
;
530 border-bottom:1px solid
#000;
535 background-color: #def;
536 border-bottom: 1px solid
#000;
544 border-right:1px solid
#000;
554 border:1px solid
#000;
555 background-color: #dfd;
566 background-color: #88f;
567 border-bottom:1px solid
#000;
578 background-color: #f00;
579 border:3px solid
#000;
588 border:2px solid
#000;
589 background-color: #faa;
608 background-color: #faa;
614 background-color: #fff;
615 border: 1px solid
#ddd;
643 <body onLoad=
"init_form();">
645 <center><h2>Turing Tarpit Simulator
</h2></center>
648 <button onClick='reset();'
><img src=
"http://opentextbook.info/icons/32x32/resultset_first.png"></button>
650 <button onClick='step_back();'
><img src=
"http://opentextbook.info/icons/32x32/resultset_previous.png"></button>
652 <button onClick='step_next();'
><img src=
"http://opentextbook.info/icons/32x32/resultset_next.png"></button>
654 <button onClick='run();'
><img src=
"http://opentextbook.info/icons/32x32/resultset_last.png"></button>
656 <button onClick='halt();'
><img src=
"http://opentextbook.info/icons/32x32/cancel.png"></button>
658 <button disabled
><img src=
"http://opentextbook.info/icons/32x32/disk.png"></button>
660 <button onClick='display_docs();'
><img src=
"http://opentextbook.info/icons/32x32/book_open.png"></button>
663 <div id=
"code_buttons">
664 <button id=
"dbg_status" onClick='debug_toggle_breakpoints();'
>
665 <img src=
"http://opentextbook.info/icons/32x32/bug_add.png">
668 <button id=
"dbg_status" onClick='debug_remove_breakpoints();'
>
669 <img src=
"http://opentextbook.info/icons/32x32/bin.png">
673 <div id=
"input_banner">INPUT
</div>
674 <div id=
"input"><textarea id=
"code" rows=
"27" cols=
"38"></textarea></div>
676 <div id=
"ip_banner">INSTRUCTION POINTER
</div>
677 <div id=
"instruction"><input onBlur=
"ins_point_modify_by_address(disp_ins_pointer.value);" id=
"ins_pointer_disp" type=
"text" diabled value=
0></div>
679 <div id=
"da_banner">DATA POINTER
</div>
680 <div id=
"data"><input onBlur=
"dat_point_modify_by_address(disp_dat_pointer.value);" id=
"dat_pointer_disp" type=
"text" diabled value=
0></div>
682 <div id=
"ref_banner">INSTRUCTION REFERENCE
</div>
683 <table id=
"reference">
684 <tr><td>+
</td><td>increment byte at data pointer
</td></tr>
685 <tr><td>-
</td><td>decrement byte at data pointer
</td></tr>
686 <tr><td>></td><td>increment data pointer
</td></tr>
687 <tr><td><
</td><td>decrement data pointer
</td></tr>
688 <tr><td>.
</td><td>print byte at data pointer
</td></tr>
689 <tr><td>,
</td><td>accept one byte of input
</td></tr>
690 <tr><td>*
</td><td>set breakpoint
</td></tr>
693 <div id=
"memory_banner">MEMORY
</div>
694 <div id=
"ram_disp"></div>
695 <div id=
"output_banner">OUTPUT
</div>
697 <textarea name=code id=output_disp
rows=
"10" cols=
"38" disabled
></textarea>
700 <div id=
"docs_top_banner">
701 Turing Tarpit Simulator Documentation
702 <div id=
"docs_mnu_btn" onClick=
"docs_select('main');">Main Menu
</div>
703 <div id=
"docs_close_btn" onClick=
"hide_docs();">X
</div></div>
705 <div id=
"docs_content"></div>
708 <div id=
"docs_main" class=
"docs_hidden">
709 <div id=
"docs_link" onClick=
"docs_select('basic');">Basic Operation
</div>
710 <div id=
"docs_link" onClick=
"docs_select('features');">Features and Hints
</div>
711 <div id=
"docs_link" onClick=
"docs_select('examples');">Example Code
1</div>
712 <div id=
"docs_link" onClick=
"docs_select('examples2');">Example Code
2</div>
716 <div id=
"docs_basic" class=
"docs_hidden">
720 <p>This program is completely self contained in one HTML document. You are free do use it how you wish, subject to the terms and conditions of the GNU GPL license (version
3).
722 <p>Although it has not been tested in all browsers, it should work well under most any modern web browser that supports Dynamic HTML and JavaScript. You must have JavaScript enabled for this application to work properly.
724 <p>No server interaction or outside service is needed for this program to operate.
728 <div id=
"docs_features" class=
"docs_hidden">
732 <p>All characters outside the Instruction Set are considered comments and will be skipped over during runtime.
734 <p>While program executes, the Input cursor is moved over the current instruction.
736 <p>User can change the address of the Data Pointer and Instruction Pointer at any time.
737 Memory and pointers that have been modified are highlighted in yellow until the next step.
739 <p>The Data Pointer can point to any location. If you de-reference a pointer out of memory range, a segfault error will occur. This causes the computer to reboot without warning.
741 <p>The Instruction Pointer can point to a location range of
1 to the number of characters in the input.
743 <p>Restarting the machine will reset all Memory, Data and Instruction Pointers to zero.
745 <p>The output of the program cannot be edited.
747 <p>A user can add a break instruction in the code using an asterisk '*'. This will cause the machine to pause when in Run Mode. Breaks can be disabled and enabled with the debug button, and can be permanently deleted with the delete button.
749 <p>In this version the programs you type in are not saved to your computer. This must be done as a manual operation.
751 <p>As this program is reliant on the speed and efficiency of your browsers JavaScript implementation some computers will be able to execute programs faster than others.
755 <div id=
"docs_examples" class=
"docs_hidden">
756 These are some examples of programs and snippets to get you started. Click the
"Load" button to apply these to the Input of the simulator. (Please Note: You will erase the current program stored there.) Many of these examples can be found at Wikipedia.
758 <p><b>Clear Byte:
</b>
759 Sets value at current Data Pointer to Zero.
760 <div class=docs_code_ex
>
763 <p><b>Clear Previous Cells:
</b>
764 Sets value of all previous bytes including current byte to Zero.
765 <div class=docs_code_ex
>
769 Goes back to byte Zero.
770 <div class=docs_code_ex
>
773 <p><b>Fast-forward:
</b>
774 Increments the data pointer until a
0 is found then decrements if until the current cell is non-zero.
775 <div class=docs_code_ex
>
778 <p><b>Simple Loop:
</b>
779 Accepts input from the user and echos it to the screen, similar to the UNIX cat program.
780 <div class=docs_code_ex
>
783 <p><b>Moving the Data Pointer:
</b>
784 Accepts input from the user and saves all input in the memory for future use.
785 <div class=docs_code_ex
>
791 <div id=
"docs_examples2" class=
"docs_hidden">
792 <p><b>Add Two Bytes:
</b>
793 Adds current location to the next location and leaves behind a Zero for the first value.
794 <div class=docs_code_ex
>
797 <p><b>Lower To Upper:
</b>
798 Accepts lower case input from the user and makes it uppercase. Stops when user presses the enter key.
799 <div class=docs_code_ex
>
800 ,----------[----------------------.,----------]
802 <p><b>Copy Value:
</b>
803 Copy value of byte Zero to byte One.
804 <div class=docs_code_ex
>
805 >[-]
>[-]<<[-
>+
>+<<]
>>[-<<+
>>]<<
808 Move Data Pointer forward until it lands on a byte with a value of
1, preserving all bytes it passes.
809 <div class=docs_code_ex
>
812 <p><b>Single Digit Add:
</b>
813 Adds two single digit numbers and display result. Works on one-digit results only.
814 <div class=docs_code_ex
>
815 ,
>++++++[<-------->-],[<+
>-]<.
817 <p><b>Single Digit Multiplication:
</b>
818 Multiply two single digit numbers and display result. Works on one-digit results only.
819 <div class=docs_code_ex
>
820 ,
>,
>++++++++[<------<------>
>-]
821 <<[
>[
>+
>+<
<-]
>>[<<+
>>-]<<
<-]
822 >>>++++++[<++++++++
>-]<.
>.
824 <p><b>Single Digit Division:
</b>
825 Accepts two single-digit numbers from the user, divides them and displays the truncated quotient. Dividend is stored in byte Zero and Divisor is stored in byte One.
826 <div class=docs_code_ex
>
827 ,
>,
>++++++[-<--------<-------->
>]<<[
>[-
>+
>+<<]
>[-<
<-[
>]
>>>[<[
>>>-<<<[-]]
>>]<<]
>>>+<<[-<<+
>>]<<<]
>[-]
>>>>[-<<<<<+
>>>>>]<<<<++++++[-<++++++++
>]<.