Skip to content

Instantly share code, notes, and snippets.

@Rangi42
Created March 1, 2021 16:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Rangi42/7b29621e7eba81680e7d2f2f1e8cf34c to your computer and use it in GitHub Desktop.
Save Rangi42/7b29621e7eba81680e7d2f2f1e8cf34c to your computer and use it in GitHub Desktop.
BF interpreter in RGBASM
ASCII EQUS "␀\t\n \r !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz\{|}~"
err: MACRO
println "error: ", \1
; print where the error occurred
println " {src}"
print " "
rept src_i - 1
print "_"
endr
println "^"
fail "execution halted"
ENDM
bf: MACRO
; interpret a BF program
if !_NARG
fail "Usage: bf source[, input]"
endc
; point to the first program char
src_i = 1
if _NARG > 0
REDEF src EQUS "\1"
src_len = STRLEN("{src}")
else
src_len = 0
endc
; point to the first input char
in_p = 1
if _NARG > 1
REDEF in EQUS "\2"
in_len = STRLEN("{in}")
else
in_len = 0
endc
; point to the first cell
mem_p = 0
; run the program
rept $7fff_ffff
if src_i > src_len
break
endc
; get the current source code character
x = STRSUB("{src}", src_i, 1)
; increment the current cell
if x == "+"
if mem_p < 0
err "+ outside tape"
endc
if !DEF(mem{d:mem_p})
mem{d:mem_p} = 0
endc
mem{d:mem_p} = LOW(mem{d:mem_p} + 1)
; decrement the current cell
elif x == "-"
if mem_p < 0
err "- outside tape"
endc
if !DEF(mem{d:mem_p})
mem{d:mem_p} = 0
endc
mem{d:mem_p} = LOW(mem{d:mem_p} - 1)
; move to the next cell
elif x == ">"
mem_p = mem_p + 1
; move to the previous cell
elif x == "<"
mem_p = mem_p - 1
; output the current cell
elif x == "."
if mem_p < 0
err ". outside tape"
endc
if !DEF(mem{d:mem_p})
mem{d:mem_p} = 0
endc
print STRSUB("{ASCII}", mem{d:mem_p} + 1, 1)
; input the current cell
elif x == ","
if mem_p < 0
err ", outside tape"
endc
if in_p <= in_len
mem{d:mem_p} = STRSUB("\2", in_p, 1)
in_p = in_p + 1
else
mem{d:mem_p} = 0
endc
; begin while loop
elif x == "["
if mem_p < 0
err "[ outside tape"
endc
if !DEF(mem{d:mem_p})
mem{d:mem_p} = 0
endc
if mem{d:mem_p} == 0
if !DEF(pair{d:src_i})
; find the corresponding ']' after the '['
depth = 1
for i, src_i + 1, src_len + 1
y = STRSUB("{src}", i, 1)
depth = depth + (y == "[") - (y == "]")
if depth == 0
break
endc
endr
if i == src_len
err "[ without ]"
endc
pair{d:src_i} = i
endc
src_i = pair{d:src_i}
endc
; end while loop
elif x == "]"
if mem_p < 0
err "] outside tape"
endc
if !DEF(mem{d:mem_p})
mem{d:mem_p} = 0
endc
if mem{d:mem_p} != 0
if !DEF(pair{d:src_i})
; find the corresponding '[' before the ']'
depth = 1
for i, src_i - 1, 0, -1
y = STRSUB("{src}", i, 1)
depth = depth - (y == "[") + (y == "]")
if depth == 0
break
endc
endr
if i == 0
err "] without ["
endc
pair{d:src_i} = i
endc
src_i = pair{d:src_i}
endc
endc
; move to the next source code character
src_i = src_i + 1
endr
ENDM
; Usage: rgbasm bf.asm -Dsrc=... -Din=...
if DEF(src)
if DEF(in)
bf {src}, /* keep leading spaces */{in},
else
bf {src}, ,
endc
elif DEF(in)
; echo
bf >\,[>\,]<[<]>[.>]++++++++++., /* keep leading spaces */{in},
else
; hello world
bf ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
endc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment