Created
March 1, 2021 16:58
-
-
Save Rangi42/7b29621e7eba81680e7d2f2f1e8cf34c to your computer and use it in GitHub Desktop.
BF interpreter in RGBASM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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