Skip to content

Instantly share code, notes, and snippets.

@soya-daizu
Created August 25, 2022 17:57
Show Gist options
  • Save soya-daizu/16eed302d7d4d55181f5f5243ef08a50 to your computer and use it in GitHub Desktop.
Save soya-daizu/16eed302d7d4d55181f5f5243ef08a50 to your computer and use it in GitHub Desktop.
Patched version of brainfuck interpreter found in the official Crystal examples
# 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
@soya-daizu
Copy link
Author

Major changes:

  • Use UInt8 instead of Int32 in Tape
  • Use wrapping addition &+ instead of normal addition + for manipulating tape data
  • Support , command to accept input while running program

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment