-
-
Save soya-daizu/16eed302d7d4d55181f5f5243ef08a50 to your computer and use it in GitHub Desktop.
Patched version of brainfuck interpreter found in the official Crystal examples
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
# Brainf*ck interpreter | |
struct Tape | |
def initialize | |
@tape = [0_u8] | |
@pos = 0 | |
end | |
def get | |
@tape[@pos] | |
end | |
def put(value : UInt8) | |
@tape[@pos] = value | |
end | |
def inc | |
@tape[@pos] &+= 1 | |
end | |
def dec | |
@tape[@pos] &-= 1 | |
end | |
def advance | |
@pos += 1 | |
@tape << 0 if @tape.size <= @pos | |
end | |
def devance | |
@pos -= 1 | |
raise "pos should be > 0" if @pos < 0 | |
end | |
end | |
class Program | |
def initialize(@chars : Array(Char), @bracket_map : Hash(Int32, Int32)) | |
end | |
def run | |
tape = Tape.new | |
pc = 0 | |
while pc < @chars.size | |
case @chars[pc] | |
when '>'; tape.advance | |
when '<'; tape.devance | |
when '+'; tape.inc | |
when '-'; tape.dec | |
when ','; tape.put(gets(1).try(&.byte_at?(0)) || 0_u8) | |
when '.'; print tape.get.chr | |
when '['; pc = @bracket_map[pc] if tape.get == 0 | |
when ']'; pc = @bracket_map[pc] if tape.get != 0 | |
else # skip | |
end | |
pc += 1 | |
end | |
end | |
def self.parse(text) | |
parsed = [] of Char | |
bracket_map = {} of Int32 => Int32 | |
leftstack = [] of Int32 | |
pc = 0 | |
text.each_char do |char| | |
if "[]<>+-,.".includes?(char) | |
parsed << char | |
if char == '[' | |
leftstack << pc | |
elsif char == ']' && !leftstack.empty? | |
left = leftstack.pop | |
right = pc | |
bracket_map[left] = right | |
bracket_map[right] = left | |
end | |
pc += 1 | |
end | |
end | |
Program.new(parsed, bracket_map) | |
end | |
end | |
text = if ARGV.size > 0 | |
File.read(ARGV[0]) | |
else | |
<<-PROGRAM | |
Benchmark brainf*ck program | |
>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++ | |
[>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++ | |
++++++++[>++++++++++[>++++++++++[>++++++++++[>+ | |
+++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++. | |
PROGRAM | |
end | |
Program.parse(text).run |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Major changes:
UInt8
instead ofInt32
inTape
&+
instead of normal addition+
for manipulating tape data,
command to accept input while running program