Skip to content

Instantly share code, notes, and snippets.

@LordRatte
Created October 4, 2017 14:29
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LordRatte/c6a5694f0a13e2ec2d1798872feb5906 to your computer and use it in GitHub Desktop.
Save LordRatte/c6a5694f0a13e2ec2d1798872feb5906 to your computer and use it in GitHub Desktop.
A wrapper to give Befunge access to Python's API

Introduction

Esolangs are cool. I especially like Befunge. I like Befunge so much, in fact, that I'd like to write complex utilities and apps in it.

What? It can't be done? That's what they told me too. But I'll show them; I'll show them all!

This Gist is a proof of concept to demonstrate how to run Python commands from a Befunge programme -- opening up a world of opportunity.

Steps to run

  1. Clone and compile https://github.com/CzechsMix/FungePP
  2. Navigate to where the freshly built executable is.
  3. Put the wrap.py and python_executor.bef in that directory.
  4. Run python2 wrap.py python_executor.bef 0

The expected output is the Ascii values from 1 to Z.

Explanation

The specified Befunge programme reads a character in from stdin (in this case it will be 0) and outputs a python instruction to stdout that will look something like this: o=chr(ord('0')+1);p(). Python will read that line and execute it. If the variable o is set, it's value is written back to stdin to be read by befunge next time it gets input.

Befunge can, thus, pipe instructions to its Python environment and results get piped back. What could go wrong?

Final thoughts

One can obviously abuse this and offload the main logic of the programme into Python but the real beauty comes in when calls to Python are used purely to do things that Befunge can't e.g. read from the disk, make network requests, etc.

v >v >v
>91+")(p;)1+)'">~:|>:"Z"-|>"'(dro(rhc=o">:# ,_v
^ <
@ <
from subprocess import Popen, PIPE
from sys import argv
stream = Popen(['./F++', argv[1]], stdout=PIPE, stdin=PIPE)
if len(argv) >= 3:
stream.stdin.write(argv[2]+'\n')
while True:
o=None
def p():
print o
cmd = stream.stdout.readline()
cleaned = cmd.replace('\x00','').replace('\n', '')
if cleaned == '':
continue
try:
exec cleaned
if o != None:
stream.stdin.write(o+'\n')
except SyntaxError as e:
continue
except Exception as e:
raise e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment