Skip to content

Instantly share code, notes, and snippets.

@Taneb
Created July 9, 2019 10:39
Show Gist options
  • Select an option

  • Save Taneb/be9d6d5048ce6ca3c5563df223052c6b to your computer and use it in GitHub Desktop.

Select an option

Save Taneb/be9d6d5048ce6ca3c5563df223052c6b to your computer and use it in GitHub Desktop.
brainfuck interpreter in jq
# invoke as jq -f bf.jq -rS --arg program [PROGRAM] -
# interactivity is not supported
# try:
# $ echo "" | jq -f bf.jq -RrS --arg program '++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.'
def increment: .tape.head+=1;
def decrement: .tape.head-=1;
def shiftleft:
.tape.left=[.tape.head]+.tape.left |
.tape.head=(.tape.right[0]//0) |
.tape.right|=.[1:];
def shiftright:
.tape.right=[.tape.head]+.tape.right |
.tape.head=(.tape.left[0]//0) |
.tape.left|=.[1:];
def loop(f):
until(.tape.head == 0; f);
def bfin:
.tape.head=(.in[0]//0) |
.in|=.[1:];
def bfout:
.out=.out+[.tape.head];
def setup:
{"tape":
{"left":[]
,"head":0
,"right":[]
}
,"in":explode
,"out":[]
};
def finalize: .out|implode;
def instrs:
{"+": increment
,"-": decrement
,"<": shiftleft
,">": shiftright
,",": bfin
,".": bfout
};
# find the index of closing bracket
def findmatch(prog;d;n):
if prog[n:n+1] == "["
then findmatch(prog;d+1;n+1)
elif prog[n:n+1] == "]"
then if d == 0
then n
else findmatch(prog;d-1;n+1)
end
else findmatch(prog;d;n+1)
end;
def interpret(prog):
if prog == ""
then .
elif prog[0:1] == "["
then findmatch(prog;0;1) as $loopend | loop(interpret(prog[1:$loopend])) | interpret(prog[$loopend+1:])
else (instrs[(prog[0:1])//.])|interpret(prog[1:])
end;
setup|interpret($program)|finalize
@tst2005

tst2005 commented Jul 9, 2019

Copy link
Copy Markdown
--- bf.jq	2019-07-09 13:14:22.761150933 +0200
+++ bf.jq.new	2019-07-09 13:13:51.473121752 +0200
@@ -30,6 +30,7 @@
                 }
         ,"in":explode
         ,"out":[]
+	,"stdin":(.)
         };
 
 def finalize: .out|implode;
@@ -63,4 +64,4 @@
         else (instrs[(prog[0:1])//.])|interpret(prog[1:])
         end;
 
-setup|interpret($program)|finalize
+setup|interpret(.stdin)|finalize

To be able to use
cat helloworld.bf | jq -f bf.jq -RrS

@Taneb

Taneb commented Jul 9, 2019

Copy link
Copy Markdown
Author

@tst2005 I talked to you about this on IRC but for people reading here: your suggestion breaks brainfuck programs which take input, for example ,[.,] (which just emits its input with no further processing).

@tst2005

tst2005 commented Jul 10, 2019

Copy link
Copy Markdown

@Taneb you are right I just forgot that BrainFuck is able to be use as a real program to process data, no just to obfuscate a secret string like "hello world". ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment