Class: BfRb::Interpreter

Inherits:
Object
  • Object
show all
Defined in:
lib/bfrb/interpreter.rb

Overview

interprets brainfuck code

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeInterpreter

initialize the interpreter



11
12
13
14
15
16
# File 'lib/bfrb/interpreter.rb', line 11

def initialize
	@memory = Memory.new
	initialize_environment
	@input_stream = $stdin
	@output_stream = $stdout
end

Instance Attribute Details

#input_streamObject

Returns the value of attribute input_stream.



8
9
10
# File 'lib/bfrb/interpreter.rb', line 8

def input_stream
  @input_stream
end

#memory_counterObject (readonly)

Returns the value of attribute memory_counter.



7
8
9
# File 'lib/bfrb/interpreter.rb', line 7

def memory_counter
  @memory_counter
end

#output_streamObject

Returns the value of attribute output_stream.



8
9
10
# File 'lib/bfrb/interpreter.rb', line 8

def output_stream
  @output_stream
end

#program_counterObject (readonly)

Returns the value of attribute program_counter.



7
8
9
# File 'lib/bfrb/interpreter.rb', line 7

def program_counter
  @program_counter
end

Instance Method Details

#check_for_matching_bracesObject

checks the code to be run to make sure all braces match



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/bfrb/interpreter.rb', line 38

def check_for_matching_braces
	brace_counter = 0
	@code.each_char do |char|
		if char == "["
			brace_counter += 1
		elsif char == "]"
			brace_counter -= 1
			if brace_counter < 0
				@output_stream.puts "Unmatched ]"
				return false
			end
		end
	end
	if brace_counter > 0
		@output_stream.puts "Unmatched ["
		return false
	end
	return true
end

#current_memoryObject

returns the value in the current memory cell



123
124
125
# File 'lib/bfrb/interpreter.rb', line 123

def current_memory
	return @memory.get(@memory_counter)
end

#evaluate_codeObject

evaluate each instruction in the current code



59
60
61
62
63
# File 'lib/bfrb/interpreter.rb', line 59

def evaluate_code
	while ((0 <= @program_counter) and (@program_counter < @code.length))
		evaluate_instruction(@code[@program_counter])
	end
end

#evaluate_instruction(instruction) ⇒ Object

evaluate an individual instruction



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/bfrb/interpreter.rb', line 66

def evaluate_instruction(instruction)
	case instruction
	# shift right in memory
	when ">"
		@memory_counter += 1
	# shift left in memory, unless we're at the beginning
	when "<"
		if @memory_counter > 1
			@memory_counter -= 1
		else
			@memory_counter = 0
		end
	# increment value in memory
	when "+"
		@memory.set(@memory_counter, current_memory + 1)
	# decrement value in memory
	when "-"
		unless current_memory == 0
			@memory.set(@memory_counter, current_memory - 1)
		end
	# print value in memory
	when "."
		@output_stream.print current_memory.chr
	# input a character into memory
	when ","
		@output_stream.puts
		input = @input_stream.gets.getbyte(0)
		if input == 24
			throw :quit
		end
		@memory.set(@memory_counter, input)
	# jump to the closing bracket if memory is 0
	when "["
		if current_memory != 0
			@loop_stack.push @program_counter
		else
			bracket_counter = 1
			while ((bracket_counter != 0) and (@program_counter < @code.length - 1))
				@program_counter += 1
				if @code[@program_counter] == "["
					bracket_counter += 1
				elsif @code[@program_counter] == "]"
					bracket_counter -= 1
				end
			end
		end
	# return to the opening bracket if memory is not zero
	when "]"
		matching_bracket = @loop_stack.pop
		if current_memory != 0
			@program_counter = matching_bracket - 1
		end
	end
	@program_counter += 1
end

#initialize_environmentObject

cleans the memory and initializes member variables



19
20
21
22
23
24
25
# File 'lib/bfrb/interpreter.rb', line 19

def initialize_environment
	@memory.clear
	@program_counter = 0
	@memory_counter = 0
	@code = ""
	@loop_stack = []
end

#run(code) ⇒ Object

run a given piece of code



28
29
30
31
32
33
34
35
# File 'lib/bfrb/interpreter.rb', line 28

def run(code)
	@code += code.delete "^[]<>.,+-"
	if check_for_matching_braces
		catch :quit do
			evaluate_code
		end
	end
end