[ The tape looks like this: [0, 0, 0, -1, 0, 0, , , 0, 0, ] Where commands are in the format [..., instruction pointer, command, command copy, ...] unpacking is for setting up an easy branch statement within the program: [0, 0, 0, 0, 0, 0, 0, 0, 0] and the emulated tape is in the format [..., tape head pointer, tape cell, ...] The instruction pointer marks [ with 1 and ] with 2 while not being a pointer. Otherwise it is 0 at the current instruction and -1 everywhere else. The tape head pointer is 0 at the current cell and -1 everywhere else. The commands are encoded like so: + = 1 , = 2 - = 3 . = 4 < = 5 > = 6 [ = 7 ] = 8 Behavior for malformed programs: < at beginning of tape : does not move unmatched [, on non-zero : continues execution unmatched [, on zero : halts program unmatched ], on non-zero : halts program unmatched ], on zero : continues execution Any other oddities are your top-level interpreter's fault. Tape is theoretically infinite but is constrained by the top-level interpreter. ] =========================== READ PROGRAM >>>->>> write beginning of tape as 0 0 0_1 0 0 ,---------- take input and subtract 10 (return = done) [>>+++++[<<------->>-]<<++ subtract 33 [>+<- inc c and subtract 1 [>+<- inc c and subtract 1 [>+<- inc c and subtract 1 [>+<-------------- inc c and subtract 14 [>+<-- inc c and subtract 2 [>+>+++++[<<------>>-]<<+ inc c and subtract 29 [>+<-- inc c and subtract 2 [>>+++++++++[<<++++++++++ add 94 and zero results (c = _1 for now) >>-]<<++++>>---<[-]-<[-] also set c2 to _3 to nullify jump header additions ]>>+<<]>>++<<]]]]]] end clauses and save 1 in c2 for loop start and 2 for loop end >>[-<<+>>] move the loop indicator to the header cell <+[<->>>>]< inc c set header _1 and move to next entry (move back if c = _1) ,----------] take input and subtract 10 (return = done) <<<[<<<]>>>>>>+[-]> go back and set the command pointer to the first command as 0 =========================== RUN PROGRAM [ begin processing [->+>[>>>]>+<<<<[<<<]>] move the current command to unpacking then move back >[-<+>]>[>>>]- fix the current command (recopy) and move to unpacking >-[[->+<]>-]++[-<+] unpack the command (unary expansion) >[ ADD code >>>>>>>>>>[>>]> move to tape location + ADD <<<[<<]<<<<<<<<-] move back >[ IN code >>>>>>>>>[>>]> move to tape location , IN <<<[<<]<<<<<<<-] move back >[ SUB code >>>>>>>>[>>]> move to tape location - SUB <<<[<<]<<<<<<-] move back >[ OUT code >>>>>>>[>>]> move to tape location . OUT <<<[<<]<<<<<-] move back >[ DEC code >>>>>>[>>] move to tape location <<[>>-<<+] DEC (with bounds check) <<[<<]-[+<-]] move back >[ INC code >>>>>[>>] move to tape location ->>[+] INC <<[<<]<<<-] move back >[ JUMP code >>>>[>>]> move to tape location [<<<[<<]<<- clear marker if nonzero <<<<<<<<<<[<<<]>>++ also fix command buffer (preserves loop marker) >[>>>]>>>>>>>] and move back to marker <<<[<<]<< go back to marker (move back 5 if already there) [>>+<<<<<<<<<<<<[<<<] set breakout point and move to command if jumping +[>>> set loop marker and move forward +[>>++<< if header ~= _1 then set buffer = 2 --[>>+<< if header ~= 1 then set buffer = 3 -[>>---<<++ if ~= 2 then must be out of bounds so set it and buffer to 0 <<<+[-]>>[-] then go back and do the same for the previous command >[>>>]>>>>>>>[-]+ go to loop marker and set to 1 (becomes 0) <<<<<<<<<<[<<<]] go back to instruction >>>[>>>]>>>>>>>-- closing bracket: go to loop marker and decrease by 2 (becomes _1) <<<<<<<<<<[<<<]] go back to instruction >>>[>>>]>>>>>>>+ opening bracket: go to loop marker and increase by 1 [<<<<<<<<<<[<<<]]] if still looping go back to instruction >>[-<<+>>]<<-] copy buffer into header and subtract 1 (causes breakpoint) <<<<<]>>>>>] move back and forth (fixes branching fudge at beginning) >[ LOOP code >>>[>>]> move to tape location [<<<[<<]>+< move back and set breakpoint if nonzero <<<<<<<<<<<<[<<<] move to command ++[<<< set loop marker and move backward +[>>+++<< if header ~= _1 then set buffer = 3 ---[>>-<< if header ~= 2 then set buffer = 2 +[+>>- if ~= 1 then must be 0 (out of bounds) and buffer = 1 >[>>>]>>>>>>>>[-]+ go to loop marker and set to 1 (becomes 0) <<<<<<<<<<<[<<<]] go back to instruction >>>[>>>]>>>>>>>>-- opening bracket: go to loop marker and decrease by 2 (becomes _1) <<<<<<<<<<<[<<<]] go back to instruction >>>[>>>]>>>>>>>>+ closing bracket: go to loop marker and increase by 1 [<<<<<<<<<<<[<<<]]] if still looping go back to instruction >>[-<<+>>]<<-] copy buffer into header and subtract 1 (causes breakpoint) <<<<<<<<<<<[<<<]>>--- decrease current command buffer by 3 >[>>>]>>>>>>>> gets reversed momentarily (also set branch fudge mark) ]<<<[<<]<[-<<<<] move back and synchronize with nonloop branch <<<<<<<[<<<]>>+++ also inc current command buffer by 3 >[>>>]>>>>>>>>] important for preserving loop marker on nonloop <<<<<<<<<<<[<<<] return to the command pointer ->>[-<<+>>]>--[+]> and move it ] end processing (repeat)