Skip to content

Instantly share code, notes, and snippets.

@p7g
Last active April 2, 2020 01:58
Show Gist options
  • Save p7g/bd61e0531d1b89e77cae8a88a6960a1b to your computer and use it in GitHub Desktop.
Save p7g/bd61e0531d1b89e77cae8a88a6960a1b to your computer and use it in GitHub Desktop.
BF interpreter in bash
#!/bin/bash
tape=(0)
tape_index=0
tape_get() {
echo ${tape[$tape_index]}
}
tape_inc() {
local -i amount=$1
local -i value=tape[$tape_index]
((value+=amount))
tape[$tape_index]=$value
}
tape_move() {
local -i amount=$1
((tape_index+=amount))
while [ $tape_index -ge ${#tape[@]} ]; do
tape+=(0)
((tape_length++))
done
}
OP_INC=0
OP_MOVE=1
OP_LOOP=2
OP_PRINT=3
declare -i loop_var_count=0
declare -i string_index=0
filename=$1
contents=$(cat "$filename")
parse() {
local ops_name=$1
local op_values_name=$1_values
declare -ga $ops_name
declare -ga $op_values_name
local -n __ops=$ops_name
local -n __op_values=$op_values_name
for ((; string_index < ${#contents}; string_index++)); do
local char=${contents:string_index:1}
case $char in
+)
__ops+=($OP_INC)
__op_values+=(1)
;;
-)
__ops+=($OP_INC)
__op_values+=(-1)
;;
\>)
__ops+=($OP_MOVE)
__op_values+=(1)
;;
\<)
__ops+=($OP_MOVE)
__op_values+=(-1)
;;
.)
__ops+=($OP_PRINT)
__op_values+=(0)
;;
\[)
__ops+=($OP_LOOP)
loop_var_name="__loop_ops_$((loop_var_count++))"
__op_values+=($loop_var_name)
((string_index++))
parse $loop_var_name
;;
\])
break
;;
esac
done
}
run() {
local -n __ops=$1
local -n __op_values=$1_values
local ops=("${__ops[@]}")
local op_values=("${__op_values[@]}")
local value=
for op in ${ops[@]}; do
value="${op_values[0]}"
op_values=("${op_values[@]:1}")
case $op in
$OP_INC)
tape_inc $value
;;
$OP_MOVE)
tape_move $value
;;
$OP_PRINT)
printf "\x$(printf %x $(tape_get))"
;;
$OP_LOOP)
while [ $(tape_get) -ne 0 ]; do
run $value
done
;;
esac
done
}
parse ops
run ops
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment