pocketlang/tests/examples/brainfuck.pk
Thakee Nathees 8c039b5d77 fn, cls moved to constants buffer
functions and classes are moved to constant buffer, and forward
names are resolved for globals.
2022-04-11 00:02:21 +05:30

121 lines
4.2 KiB
Plaintext

from lang import write
###############################################################################
## BRAINFUCK IMPLEMENTATION IN POCKETLANG ##
###############################################################################
## Reference: https://en.wikipedia.org/wiki/Brainfuck
## Note that this interpreter implementation is just to test pocketlang and is
## not an efficient one. This could be optimized by evaluating the expressions
## at "compile time" (AOT) to avoid re-evaluating those expressions at runtime
## and also we can pre compile the loop jump offsets.
## Source: https://en.wikipedia.org/wiki/Brainfuck
hello_world = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]
>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
## Source: https://github.com/fabianishere/brainfuck/blob/master/examples/asciiart/triangle.bf
## Madeby: Nyyrikki(2002)
triangle = ">++++[<++++++++>-]>++++++++[>++++<-]>>++>>>+>>>+<<<<<<<<<<[-[->+<]>
[-<+>>>.<<]>>>[[->++++++++[>++++<-]>.<<[->+<]+>[->++++++++++<<+>]>.
[-]>]]+<<<[-[->+<]+>[-<+>>>-[->+<]++>[-<->]<<<]<<<<]++++++++++.+++.
[-]<]+++++"
## Source: https://github.com/fabianishere/brainfuck/blob/master/examples/math/fib.bf
fibonacci = ">++++++++++>+>+[[+++++[>++++++++<-]>.<++++++[>--------<-]+<<<]>.
>>[[-]<[>+<-]>>[<<+>+>-]<[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+
<-[>+<-[>[-]>+>+<<<-[>+<-]]]]]]]]]]]+>>>]<<<]"
def main()
execute(hello_world)
execute(triangle)
##execute(fibonacci) This will run endlessly (cannot run test).
end
###############################################################################
## INTERNAL ##
###############################################################################
def execute(expr)
ptr = 0 ## Data pointer.
mem = [0] ## Data / Memory
i = 0 ## Instruction pointer
while true
c = expr[i] ## Current char.
## Increment the data pointer (to point to the next cell to the right).
if c == '>'
ptr += 1
if ptr >= mem.length then list_append(mem, 0) end
## Decrement the data pointer (to point to the next cell to the left).
elsif c == '<'
ptr -= 1
if ptr < 0 then assert(false, "ip < 0") end
## Increment (increase by one) the byte at the data pointer.
elsif c == '+'
if mem[ptr] == 255 then mem[ptr] = 0
else mem[ptr] += 1 end
## Decrement (decrease by one) the byte at the data pointer.
elsif c == '-'
if mem[ptr] == 0 then mem[ptr] = 255
else mem[ptr] -= 1 end
## output the byte at the data pointer.
elsif c == '.'
write(str_chr(mem[ptr]))
elsif c == ','
assert(false, "Currently input isn't supported in pocketlang.")
## if the byte at the data pointer is zero, then instead of moving the
## instruction pointer forward to the next command, jump it forward to
## the command after the matching ] command.
elsif c == '[' and mem[ptr] == 0
open = 0
while true
i += 1
if expr[i] == ']' and open == 0 then break end
if expr[i] == '[' then open += 1
elsif expr[i] == ']' then open -= 1
end assert(open >= 0)
end
## if the byte at the data pointer is nonzero, then instead of moving the
## instruction pointer forward to the next command, jump it back to the
## command after the matching [ command
elsif c == ']' and mem[ptr] != 0
open = 0
while true
i -= 1
if expr[i] == '[' and open == 0 then break end
if expr[i] == ']' then open -= 1
elsif expr[i] == '[' then open += 1
end assert(open <= 0)
end
else
## Any other characters are ignored in brainfuck interpreter.
end
## Increment the instruction pointer by one.
## If we reached the end terminate.
i += 1
if i == expr.length then break end
end
end
###############################################################################
## MAIN ##
###############################################################################
main()