Skip to content

Instantly share code, notes, and snippets.

@franklindyer
Last active September 14, 2023 21:52
Show Gist options
  • Save franklindyer/2f07091081d70ecc6153646e93237351 to your computer and use it in GitHub Desktop.
Save franklindyer/2f07091081d70ecc6153646e93237351 to your computer and use it in GitHub Desktop.
Brainfuck memory-management macro expander
# Some useful macros for readable Brainfuck coding.
# Usage: ./memorymacros mycode.bf mau-size bus-size
cat $1 > $1.tmp1
echo 'Beginning macro expansion. Initial code size:'
wc -c $1
# Following pointers
perl -pe 's/PTRGO/[NEXTCHUNK PREVCHUNK -RMOVE(CHUNK) NEXTCHUNK]/g' $1.tmp1 > $1.tmp2
cat $1.tmp2 > $1.tmp1
# Memory chunk management
perl -pe 's/INITMEM/SREPEAT(>;CHUNK)TODATA<<+<+>>>TOBUS SREPEAT(<;CHUNK)/g;
s/MOVBUSR/SREPEAT([-NEXTCHUNK+PREVCHUNK]>;BUS)SREPEAT(<;BUS)/g;
s/MOVBUSL/SREPEAT([-PREVCHUNK+NEXTCHUNK]>;BUS)SREPEAT(<;BUS)/g;
s/NEXTCHUNK/SREPEAT(>;CHUNK)TODATA<<[-SREPEAT(>;CHUNK)+SREPEAT(<;CHUNK)PREVCHUNK<LDUP(2;1)<RMOVE(CHUNK)SREPEAT(>;CHUNK)RMOVE(1)+>>]>>TOBUS/g;
s/PREVCHUNK/SREPEAT(<;CHUNK)/g;
s/TODATA/SREPEAT(>;BUS)/g;
s/TOBUS/SREPEAT(<;BUS)/g;' $1.tmp1 > $1.tmp2
cat $1.tmp2 > $1.tmp1
# Minimum addressible unit and bus size
MAU=$2;
BUS=$3;
CHUNK=$[$MAU+$BUS];
parammac=$(echo "s/MAU/${MAU}/g; s/BUS/${BUS}/g; s/CHUNK/${CHUNK}/g");
paramcmd=$(echo "perl -pe '$parammac' $1.tmp1 > $1.tmp2")
eval $paramcmd
cat $1.tmp2 > $1.tmp1
# Copying and moving values
perl -pe 's/LMOVE\((\d+)\)/[-SREPEAT(<;$1)+SREPEAT(>;$1)]/g;
s/RMOVE\((\d+)\)/[-SREPEAT(>;$1)+SREPEAT(<;$1)]/g;
s/LDUP\((\d+);(\d+)\)/[-SREPEAT(<;$1)+SREPEAT(>;$1)SREPEAT(<;$2)+SREPEAT(>;$2)]SREPEAT(<;$1)[-SREPEAT(>;$1)+SREPEAT(<;$1)]SREPEAT(>;$1)/g;
s/RDUP\((\d+);(\d+)\)/[-SREPEAT(>;$1)+SREPEAT(<;$1)SREPEAT(>;$2)+SREPEAT(<;$2)]SREPEAT(>;$1)[-]SREPEAT(<;$1)/g' $1.tmp1 > $1.tmp2
cat $1.tmp2 > $1.tmp1
# Lossless compression
perl -pe 's/COMPRESS4/[->+>>+<<<]>[[->+<<+>]>-[-<+>]<]>>[-<<<+>>>]<<</g;
s/DECOMPRESS4//g' $1.tmp1 > $1.tmp2
cat $1.tmp2 > $1.tmp1
# Simple static repetition macro
# Do-while loop permits nested repeat macros
while
cat $1.tmp2 > $1.tmp1
perl -pe 's/SREPEAT\(([^\(;]+);(\d+)\)/"$1"x$2/ge' $1.tmp1 > $1.tmp2
! cmp $1.tmp1 $1.tmp2 > /dev/null
do true; done
echo 'Macros expanded. Intermediate code size:'
wc -c $1.tmp1
# Clean up whitespace and redundant code
while
cat $1.tmp2 > $1.tmp1
perl -pe 's/ //g;
s/\n//g;
s/><//g;
s/<>//g;
s/\+-//g;
s/-\+//g;' $1.tmp1 > $1.tmp2
! cmp $1.tmp1 $1.tmp2 > /dev/null
do true; done
cat $1.tmp1 > $1out
echo 'Code cleanup finished. Final code size:'
wc -c $1out
rm $1.tmp1
rm $1.tmp2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment