Created
February 7, 2025 11:15
-
-
Save WinslowJosiah/75dcdc22a85601c876d151b06a5e6b0a to your computer and use it in GitHub Desktop.
A brainfuck interpreter in the esolang Bespoke.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Bespoke software for brainfuck (the esolang) | |
An okay interpreter that interprets commands of program in line. | |
- end of input = nothing is changed | |
- `[]` pair isn't match = `unmatched [` / `]` | |
- 8 bits, wrapped numbers | |
- the tape infinitely extends solely forward | |
(but, go back a lot = `out of bounds`) | |
- `!` in commands = input starting | |
I confirm (if it really succeeds) Bespoke is Turing complete. Esolangs like | |
brainfuck operate Turing-machine-ish, so when a program can be made for machines | |
which simulate a program in _that_, it is _equal_ to that. | |
---- | |
A brainfuck compiler written one day by Urban Müller targeted Amiga's OS, having | |
a tiny filesize equaling only 240 bytes. However, coding Bespoke got _my_ code a | |
bit big. So let's ignore filesize (which, actually, I believe is _fine_). | |
It is often categorized "Turing tarpit" -- denoting language with small command | |
amount. Because it's so tiny, implementations can be very easy, handling eight | |
commands (`+`, `-`, `<`, `>`, `.`, `,`, `[`, `]`). A listing of bytes go on some | |
"tape", triggering commands to initiate a process of: | |
- `+` = add one to value | |
- `-` = single subtract | |
- `<` = travel back one | |
- `>` = go ahead | |
- `[` = a loop, if byte != 0 | |
- `]` = looping end | |
- `.` = do a printing | |
- `,` = entering byte input | |
(Perhaps worded weirdly, but it fits approximately.) | |
---- | |
Now to list short programs. | |
First program's a classic: it says "Hi!" | |
(It works _so_ slow -- a minor nuisance.) | |
>---[[<+>->->>>>-<<<<<]>]>.<<<.<. | |
Secondly, the "cat"; it shows inputs directly copied to output. | |
(A note: initiate inputted text with `!`.) | |
,[.[-],] | |
Finally, _highly_ amazing one is `dbfi.b`, and it's by Daniel Cristofani. | |
Requires input matching a program in BF; neatly executes programs in _itself_. | |
(Also, we do input with `!`.) | |
>>>+[[-]>>[-]++>+>+++++++[<++++>>++<-]++>>+>+>+++++[>++>++++++<<-]+>>>,<++[[>[ | |
->>]<[>>]<<-]<[<]<+>>[>]>[<+>-[[<+>-]>]<[[[-]<]++<-[<+++++++++>[<->-]>>]>>]]<< | |
]<]<[[<]>[[>]>>[>>]+[<<]<[<]<+>>-]>[>]+[->>]<<<<[[<<]<[<]+<<[+>+<<-[>-->+<<-[> | |
+<[>>+<<-]]]>[<+>-]<]++>>-->[>]>>[>>]]<<[>>+<[[<]<]>[[<<]<[<]+[-<+>>-[<<+>++>- | |
[<->[<<+>>-]]]<[>+<-]>]>[>]>]>[>>]>>]<<[>>+>>+>>]<<[->>>>>>>>]<<[>.>>>>>>>]<<[ | |
>->>>>>]<<[>,>>>]<<[>+>]<<[+<<]<] | |
Everything software is capable of, however, well-done input can do. Simple | |
puzzles for computer geniuses will interest several people (perhaps you?). | |
---- | |
In this interpreter for BF (brainfuck), I consider _these_ concerns. | |
A number's on **heap**, or on **stack**; I did storage of programs covering | |
**heap**. All of program commands utilize heap, via an address with negative | |
numbers (-1 begins program, and then -2, -3, -4, ...). I decided numbers in | |
memory belonged together on heap also, but if it's _nonnegative_ at this area. | |
(Preserving commands, my pointed-to address won't ever reach negatives. This, | |
perhaps, somehow can be made not so confining; I probably _could_ generate a | |
formula so, when I go, it controls _endless_ numbers.) | |
Execution of loop has it recording the brackets level. Whenever a program is at | |
a singular starting bracket, _increment_; at a closing/end bracket, you go | |
_down_ instead. And if a bracket's position gets invalid somehow, broken program | |
has to send a message for it (`unmatched [` / `]`) and shouldn't still continue. | |
(A bracket is good if it forms a bracket grouping: a bracket at _starting_ | |
position, then one at _closing_ position. Brackets also can be _between_ each | |
end of pairs.) | |
With brainfuck's capacity of numbers, if numbers vary past 0-255 range, | |
brainfuck wraps numbers between the ends. That's because values express one | |
byte; a typical storage of memory consists largely of this type, and an 8-bit | |
(or "byte") size altogether contains 0 to 255. Whenever a pointed-to address | |
upon plus/minus surpasses range, number's written mod 256. | |
(Unfortunately, it won't _for_ us; moduloing a specific value involves a command | |
to do a specific division, getting remainder.) | |
It will not be efficient, and probably fully deserves a rewrite. It is a | |
valuable program, however; brainfuck is a classic (old) esolang, and it will | |
roughly act as a workable argument that a regular Turing machine can evaluate | |
formulas just like Bespoke can. | |
## Message printing with number codepoints using Bespoke | |
At each nonzero stack number, remove it, then display (but as a Unicode chr). | |
---- | |
Unicode messages (not really "strings", precisely) have codepoints, but it may | |
be odd for a programmer unschooled in this. Unicode's complex if you'd ever use | |
anything more than two or three typeface elements (but not a counterintuitive | |
idea -- by no means! -- just an annoying thing). | |
This is in ASCII code, however; anything ASCII is more painless overall. All the | |
interpreter outputs are of a relatively concise, tiny word length, containing | |
ASCII numbers nearing one hundred eighteen -- some times, decidedly less! | |
Pushing numbers near the stack's topmost locations all in sequences, a simple | |
function outputs characters stating the message. | |
---- | |
Messages here aren't unusually large, stating useless junk. One output message | |
brainfuck has is `unmatched [` / `]` -- the output if bracket alignment's | |
invalid. And another function will print `out of bounds` when surpassing the far | |
limitations along the tape -- preventing a (presumably) _disastrous_ | |
self-modification while it's in a programmed-commands area. | |
Now, the interpreter message has use, undoubtedly a lot -- it describes mistakes | |
put in the BF code -- though we still need to describe that with _lots_ of words | |
(one of the, if not _the_, predominant issues for one programming Bespoke). Each | |
word in there may be a meaningful segment, each word chosen skillfully while | |
keeping meaning (remarkably closely, too!). | |
## Read characters inputted, stopping without passing input completion or `!` | |
This is very much elementary. | |
Commands up to input's end (or `!`) are put together, going wherever a negative | |
heap address is. If I stop eventually, program's ultimate ending's a -1. | |
Keeping all that as an input, I initialize integers pointing into the program | |
and at memory. I also then initialize an item as zero: brackets leveling. | |
---- | |
Finally, Bespoke program runs the brainfuck, and (perhaps) reaches end. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
COMMENTARY INITIALIZE | |
Parameters: [... 0 {c ...}] | |
c = character codepoint | |
Result: [...] | |
COMMENTARY TERMINATED | |
CONTROL FUNCTION XXXX:OUTPUT CHARACTERS WHILE NONZERO | |
DO COPY | |
CONTROL WHILE | |
OUTPUT CH | |
DO COPY | |
CONTROL END | |
DO P | |
CONTROL END | |
CONTROL FUNCTION XXX:OUTPUT NEWLINE UNMATCHED | |
COMMENTARY INITIALIZE | |
Print a newline and "unmatched ". | |
COMMENTARY TERMINATED | |
PUSH NUMBERZERO | |
PUT XX:TRI BI | |
PUT XXX:I NUMBERZERO NUMBERZERO | |
PUT XXX:I NUMBERZERO I | |
PUT XXX:I NUMBERZERO FOUR | |
PUT XX:DIGITNINE DIGITNINE | |
PUT XXX:I I SEXTET | |
PUT XX:DIGITNINE SEVENTH | |
PUT XXX:I NUMBERZERO DIGITNINE | |
PUT XXX:I I NUMBERZERO | |
PUT XXX:I I SEVENTH | |
PUT XX:I NUMBERZERO | |
CONTROL CALL XXXX:OUTPUT CHARACTERS WHILE NONZERO | |
CONTROL END | |
CONTROL FUNCTION XXXX:ERROR UNMATCHED OPEN BRACKET | |
COMMENTARY INITIALIZE | |
Print a newline and "unmatched [", | |
and end the program. | |
COMMENTARY TERMINATED | |
CONTROL CALL XXX:OUTPUT NEWLINE UNMATCHED | |
PUT XX:DIGITNINE I;OUTPUT CH | |
CONTROL ENDPROGRAM | |
CONTROL END | |
CONTROL FUNCTION XXXX:ERROR UNMATCHED CLOSE BRACKET | |
COMMENTARY INITIALIZE | |
Print a newline and "unmatched ]", | |
and end the program. | |
COMMENTARY TERMINATED | |
CONTROL CALL XXX:OUTPUT NEWLINE UNMATCHED | |
PUT XX:DIGITNINE TRI;OUTPUT CH | |
CONTROL ENDPROGRAM | |
CONTROL END | |
CONTROL FUNCTION XXXX:ERROR OUT OF BOUNDS | |
COMMENTARY INITIALIZE | |
Print a newline and "out of bounds", | |
and end the program. | |
COMMENTARY TERMINATED | |
PUSH NUMBERZERO | |
PUT XXX:I I FIFTH | |
PUT XXX:I NUMBERZERO NUMBERZERO | |
PUT XXX:I I NUMBERZERO | |
PUT XXX:I I SEVENTH | |
PUT XXX:I I I | |
PUT XX:DIGITNINE INTEIGHT | |
PUT XX:TRI BI | |
PUT XXX:I NUMBERZERO BI | |
PUT XXX:I I I | |
PUT XX:TRI BI | |
PUT XXX:I I SEXTET | |
PUT XXX:I I SEVENTH | |
PUT XXX:I I I | |
PUT XX:I NUMBERZERO | |
CONTROL CALL XXXX:OUTPUT CHARACTERS WHILE NONZERO | |
CONTROL ENDPROGRAM | |
CONTROL END | |
COMMENTARY INITIALIZE | |
Parameters: [... lvl tp ip] | |
lvl = nesting level | |
tp = tape pointer | |
ip = instruction pointer | |
Result: [... lvl_ tp_ ip_ continue] | |
lvl_ = new nesting level | |
tp_ = new tape pointer | |
ip_ = new instruction pointer pointer | |
continue = 0 if at end of program, nonzero otherwise | |
COMMENTARY TERMINATED | |
CONTROL FUNCTION XXX:INTERPRET ONE COMMAND | |
COMMENTARY INITIALIZE | |
If the instruction is less than 0 (EOF)... | |
COMMENTARY TERMINATED | |
DO COPY | |
H V | |
PUSH NUMBERZERO STACKTOP LT | |
CONTROL IF | |
COMMENTARY INITIALIZE | |
...check the nesting level. | |
If it's nonzero, there was an unmatched "[". | |
COMMENTARY TERMINATED | |
PUSH TRI DO COPYN | |
CONTROL IF | |
CONTROL CALL XXXX:ERROR UNMATCHED OPEN BRACKET | |
CONTROL END | |
COMMENTARY INITIALIZE | |
Otherwise, end this program here. | |
COMMENTARY TERMINATED | |
PUSH NUMBERZERO | |
CONTROL RETURN | |
CONTROL END | |
COMMENTARY INITIALIZE | |
If the instruction is 43 ("+")... | |
COMMENTARY TERMINATED | |
DO COPY | |
H V | |
PUT XX:FOUR TRI;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
COMMENTARY INITIALIZE | |
...replace this tape value N | |
with (N+1) % 256. | |
COMMENTARY TERMINATED | |
PUSH BI DO COPYN | |
DO COPY | |
H V | |
STACKTOP PLUSONE | |
PUT XXX:BI FIFTH SEXTET;STACKTOP MODULO | |
DO SWITCH | |
H SV | |
COMMENTARY INITIALIZE | |
Move on to the next instruction. | |
COMMENTARY TERMINATED | |
STACKTOP MINUSONE | |
PUSH I | |
CONTROL RETURN | |
CONTROL END | |
COMMENTARY INITIALIZE | |
If the instruction is 44 (",")... | |
COMMENTARY TERMINATED | |
DO COPY | |
H V | |
PUT XX:FOUR FOUR;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
COMMENTARY INITIALIZE | |
...replace this tape value | |
with an inputted character, | |
if it's not less than 0 (EOF). | |
COMMENTARY TERMINATED | |
INPUT CH | |
DO COPY | |
PUSH NUMBERZERO STACKTOP LT | |
STACKTOP F | |
CONTROL IF | |
PUT XXX:BI FIFTH SEXTET;STACKTOP MODULO | |
PUSH TRI DO COPYN | |
H SV | |
DO COPY | |
CONTROL END | |
DO P | |
COMMENTARY INITIALIZE | |
Move on to the next instruction. | |
COMMENTARY TERMINATED | |
STACKTOP MINUSONE | |
PUSH I | |
CONTROL RETURN | |
CONTROL END | |
COMMENTARY INITIALIZE | |
If the instruction is 45 ("-")... | |
COMMENTARY TERMINATED | |
DO COPY | |
H V | |
PUT XX:FOUR FIFTH;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
COMMENTARY INITIALIZE | |
...replace this tape value N | |
with (N-1) % 256. | |
COMMENTARY TERMINATED | |
PUSH BI DO COPYN | |
DO COPY | |
H V | |
STACKTOP MINUSONE | |
PUT XXX:BI FIFTH SEXTET;STACKTOP MODULO | |
DO SWITCH | |
H SV | |
COMMENTARY INITIALIZE | |
Move on to the next instruction. | |
COMMENTARY TERMINATED | |
STACKTOP MINUSONE | |
PUSH I | |
CONTROL RETURN | |
CONTROL END | |
COMMENTARY INITIALIZE | |
If the instruction is 46 (".")... | |
COMMENTARY TERMINATED | |
DO COPY | |
H V | |
PUT XX:FOUR SEXTET;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
COMMENTARY INITIALIZE | |
...output this tape value | |
as a character. | |
COMMENTARY TERMINATED | |
PUSH BI DO COPYN | |
H V | |
OUTPUT CH | |
COMMENTARY INITIALIZE | |
Move on to the next instruction. | |
COMMENTARY TERMINATED | |
STACKTOP MINUSONE | |
PUSH I | |
CONTROL RETURN | |
CONTROL END | |
COMMENTARY INITIALIZE | |
If the instruction is 60 ("<")... | |
COMMENTARY TERMINATED | |
DO COPY | |
H V | |
PUT XX:SEXTET NUMBERZERO;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
COMMENTARY INITIALIZE | |
...replace the tape pointer N | |
with N-1. | |
COMMENTARY TERMINATED | |
DO SWITCH | |
STACKTOP MINUSONE | |
DO SWITCH | |
COMMENTARY INITIALIZE | |
If the tape pointer is less than 0, | |
the tape pointer is out of bounds. | |
COMMENTARY TERMINATED | |
PUSH BI DO COPYN | |
PUSH NUMBERZERO STACKTOP LT | |
CONTROL IF | |
CONTROL CALL XXXX:ERROR OUT OF BOUNDS | |
CONTROL END | |
COMMENTARY INITIALIZE | |
Move on to the next instruction. | |
COMMENTARY TERMINATED | |
STACKTOP MINUSONE | |
PUSH I | |
CONTROL RETURN | |
CONTROL END | |
COMMENTARY INITIALIZE | |
If the instruction is 62 (">")... | |
COMMENTARY TERMINATED | |
DO COPY | |
H V | |
PUT XX:SEXTET BI;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
COMMENTARY INITIALIZE | |
...replace the tape pointer N | |
with N+1. | |
COMMENTARY TERMINATED | |
DO SWITCH | |
STACKTOP PLUSONE | |
DO SWITCH | |
COMMENTARY INITIALIZE | |
Move on to the next instruction. | |
COMMENTARY TERMINATED | |
STACKTOP MINUSONE | |
PUSH I | |
CONTROL RETURN | |
CONTROL END | |
COMMENTARY INITIALIZE | |
If the instruction is 91 ("[")... | |
COMMENTARY TERMINATED | |
DO COPY | |
H V | |
PUT XX:DIGITNINE I;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
COMMENTARY INITIALIZE | |
...check this tape value N. | |
If N is nonzero, | |
nest and move on to the next instruction. | |
COMMENTARY TERMINATED | |
PUSH BI DO COPYN | |
H V | |
CONTROL IF | |
STACKTOP MINUSONE | |
PUSH TRI DO SWITCHN | |
STACKTOP PLUSONE | |
PUSH TRI DO SWITCHN | |
PUSH I | |
CONTROL RETURN | |
CONTROL END | |
COMMENTARY INITIALIZE | |
Otherwise, start a "bracket counter" at 1, | |
trying to find a matching 93 ("]") going forwards. | |
COMMENTARY TERMINATED | |
PUSH I | |
CONTROL DOWHILE | |
DO SWITCH | |
STACKTOP MINUSONE | |
DO COPY | |
PUSH TRI DO ROT | |
H V | |
COMMENTARY INITIALIZE | |
If this instruction is less than 0 (EOF), | |
there was an unmatched "[". | |
COMMENTARY TERMINATED | |
DO COPY | |
PUSH NUMBERZERO STACKTOP LT | |
CONTROL IF | |
CONTROL CALL XXXX:ERROR UNMATCHED OPEN BRACKET | |
CONTROL END | |
COMMENTARY INITIALIZE | |
If this instruction is 91 ("["), | |
add one to the bracket counter; | |
otherwise, if this instruction is 93 ("]"), | |
subtract one from the bracket counter. | |
COMMENTARY TERMINATED | |
DO COPY | |
PUT XX:DIGITNINE I;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
DO P | |
STACKTOP PLUSONE | |
CONTROL OTHERWISE | |
DO COPY | |
PUT XX:DIGITNINE TRI;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
DO P | |
STACKTOP MINUSONE | |
CONTROL OTHERWISE | |
DO P | |
CONTROL END | |
CONTROL END | |
COMMENTARY INITIALIZE | |
Stop looping if the bracket counter is 0. | |
COMMENTARY TERMINATED | |
DO COPY | |
CONTROL END | |
COMMENTARY INITIALIZE | |
Clean up the bracket counter, | |
and move just past the bracket. | |
COMMENTARY TERMINATED | |
DO P | |
STACKTOP MINUSONE | |
PUSH I | |
CONTROL RETURN | |
CONTROL END | |
COMMENTARY INITIALIZE | |
If the instruction is 93 ("]")... | |
COMMENTARY TERMINATED | |
DO COPY | |
H V | |
PUT XX:DIGITNINE TRI;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
COMMENTARY INITIALIZE | |
...check this tape value N. | |
If N is zero, | |
denest and move on to the next instruction. | |
COMMENTARY TERMINATED | |
PUSH BI DO COPYN | |
H V | |
STACKTOP F | |
CONTROL IF | |
STACKTOP MINUSONE | |
PUSH TRI DO SWITCHN | |
STACKTOP MINUSONE | |
PUSH TRI DO SWITCHN | |
COMMENTARY INITIALIZE | |
If the nesting level is less than 0, | |
there was an unmatched "]". | |
COMMENTARY TERMINATED | |
PUSH TRI DO COPYN | |
PUSH NUMBERZERO STACKTOP LT | |
CONTROL IF | |
CONTROL CALL XXXX:ERROR UNMATCHED CLOSE BRACKET | |
CONTROL END | |
PUSH I | |
CONTROL RETURN | |
CONTROL END | |
COMMENTARY INITIALIZE | |
Otherwise, start a "bracket counter" at 1, | |
trying to find a matching 91 ("[") going backwards. | |
COMMENTARY TERMINATED | |
PUSH I | |
CONTROL DOWHILE | |
DO SWITCH | |
STACKTOP PLUSONE | |
DO COPY | |
PUSH TRI DO ROT | |
COMMENTARY INITIALIZE | |
If the instruction pointer is not less than 0, | |
there was an unmatched "]". | |
COMMENTARY TERMINATED | |
DO COPY | |
PUSH NUMBERZERO STACKTOP LT | |
STACKTOP F | |
CONTROL IF | |
CONTROL CALL XXXX:ERROR UNMATCHED CLOSE BRACKET | |
CONTROL END | |
COMMENTARY INITIALIZE | |
If this instruction is 91 ("["), | |
subtract one from the bracket counter; | |
otherwise, if this instruction is 93 ("]"), | |
add one to the bracket counter. | |
COMMENTARY TERMINATED | |
H V | |
DO COPY | |
PUT XX:DIGITNINE I;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
DO P | |
STACKTOP MINUSONE | |
CONTROL OTHERWISE | |
DO COPY | |
PUT XX:DIGITNINE TRI;STACKTOP MINUS | |
STACKTOP F | |
CONTROL IF | |
DO P | |
STACKTOP PLUSONE | |
CONTROL OTHERWISE | |
DO P | |
CONTROL END | |
CONTROL END | |
COMMENTARY INITIALIZE | |
Stop looping if the bracket counter is 0. | |
COMMENTARY TERMINATED | |
DO COPY | |
CONTROL END | |
COMMENTARY INITIALIZE | |
Clean up the bracket counter, | |
and move just past the bracket. | |
COMMENTARY TERMINATED | |
DO P | |
STACKTOP MINUSONE | |
PUSH I | |
CONTROL RETURN | |
CONTROL END | |
COMMENTARY INITIALIZE | |
If we're here, the instruction did nothing; | |
move on to the next instruction anyway. | |
COMMENTARY TERMINATED | |
STACKTOP MINUSONE | |
PUSH I | |
CONTROL END | |
COMMENTARY INITIALIZE | |
First, read the program from input, | |
and store its characters on the heap | |
from address -1 downward. | |
COMMENTARY TERMINATED | |
PUSH NUMBERZERO | |
STACKTOP MINUSONE | |
CONTROL DOWHILE | |
INPUT CH | |
COMMENTARY INITIALIZE | |
If this character is less than 0 (EOF), | |
or if this character is equal to 33 ("!")... | |
COMMENTARY TERMINATED | |
DO COPY | |
DO COPY | |
PUSH NUMBERZERO STACKTOP LT | |
DO SWITCH | |
PUT XX:TRI TRI;STACKTOP MINUS | |
STACKTOP F | |
STACKTOP PLUS | |
CONTROL IF | |
COMMENTARY INITIALIZE | |
...replace the value with -1, | |
and stop processing input. | |
COMMENTARY TERMINATED | |
DO P | |
PUSH NUMBERZERO | |
STACKTOP MINUSONE | |
CONTROL B | |
CONTROL END | |
PUSH BI DO COPYN | |
H SV | |
STACKTOP MINUSONE | |
PUSH I | |
CONTROL END | |
DO SWITCH | |
H SV | |
COMMENTARY INITIALIZE | |
Initialize the nesting level to 0, | |
the tape pointer to 0, | |
and the instruction pointer to -1. | |
COMMENTARY TERMINATED | |
PUSH NUMBERZERO | |
DO COPY | |
DO COPY | |
STACKTOP MINUSONE | |
COMMENTARY INITIALIZE | |
Finally, interpret the program | |
one instruction at a time. | |
COMMENTARY TERMINATED | |
CONTROL DOWHILE | |
CONTROL CALL XXX:INTERPRET ONE COMMAND | |
CONTROL END |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment