Module: Operations
- Included in:
- BefungeInterpreter
- Defined in:
- lib/operations.rb
Overview
This module is responsible for performing operations. It keeps all logic based on opertaions encapsulated. It is meant to be included with the top-level BefungeInterpreter.
Constant Summary collapse
- MATH_OPS =
Bunch of Constants here. Important thing: %i() defines array of symbols while %w() defines array of strings. The Hash pattern I’ve chosen to employ here simply maps the string/symbol single character representation of the operation to it’s actual method name here. For instance: OPERATORS_MAP => :logical_not We can just #send that symbol in our #operate! method.
%i(+ - * / %)
- DIRECTION_OPS =
%i(^ < > v)
- DIRECTIONS =
%i(n w e s)
- DIRECTIONS_MAP =
Hash[DIRECTION_OPS.zip(DIRECTIONS)]
- OPERATORS =
%w(! ` ? _ | : \\ $ . , # p g & ~ @)
- OPERATORS_MAP =
Hash[OPERATORS.zip([ :logical_not, :greater_than, :rand_direction, :left_right, :up_down, :duplicate_stack_top, :swap_stack_top, :pop_and_discard, :pop_and_display_int, :pop_and_display_char, :trampoline, :put_call, :get_call, :get_user_input_int, :get_user_input_char, :end_program ]
Instance Method Summary collapse
-
#change_dir(op) ⇒ Object
I call this method two different ways - one with directional operational arguments < > ^ v and one with actual directions :n :e :s :w.
- #duplicate_stack_top ⇒ Object
- #end_program ⇒ Object
- #get_call ⇒ Object
- #get_user_input_char ⇒ Object
- #get_user_input_int ⇒ Object
- #greater_than ⇒ Object
- #left_right ⇒ Object
- #logical_not ⇒ Object
- #operate!(op) ⇒ Object
- #pop_and_discard ⇒ Object
- #pop_and_display_char ⇒ Object
- #pop_and_display_int ⇒ Object
- #push_ascii_value(op) ⇒ Object
- #push_num(num) ⇒ Object
- #put_call ⇒ Object
- #rand_direction ⇒ Object
- #string_mode ⇒ Object
- #swap_stack_top ⇒ Object
- #trampoline ⇒ Object
- #up_down ⇒ Object
Instance Method Details
#change_dir(op) ⇒ Object
I call this method two different ways - one with directional operational arguments < > ^ v and one with actual directions :n :e :s :w. This is the reason for the unless statement here.
53 54 55 56 |
# File 'lib/operations.rb', line 53 def change_dir(op) op = DIRECTIONS_MAP[op] unless DIRECTIONS.include?(op) @code_map.pointer.direction = op end |
#duplicate_stack_top ⇒ Object
85 86 87 88 |
# File 'lib/operations.rb', line 85 def duplicate_stack_top @stack.push(0) and return if @stack.empty? @stack.push(@stack.last) end |
#end_program ⇒ Object
140 141 142 |
# File 'lib/operations.rb', line 140 def end_program @computing = false end |
#get_call ⇒ Object
122 123 124 125 126 |
# File 'lib/operations.rb', line 122 def get_call y = @stack.pop x = @stack.pop @stack.push(@code_map.get_operation_at(y, x).ord) end |
#get_user_input_char ⇒ Object
133 134 135 136 137 138 |
# File 'lib/operations.rb', line 133 def get_user_input_char puts 'Befunge needs your input for char!' input = $stdin.gets.chomp raise 'Must be a single character' unless input.length == 1 @stack.push(input.ord) end |
#get_user_input_int ⇒ Object
128 129 130 131 |
# File 'lib/operations.rb', line 128 def get_user_input_int puts 'Befunge needs your input for int!' @stack.push(Integer($stdin.gets.chomp)) end |
#greater_than ⇒ Object
62 63 64 65 66 |
# File 'lib/operations.rb', line 62 def greater_than a = @stack.pop b = @stack.pop b > a ? @stack.push(1) : @stack.push(0) end |
#left_right ⇒ Object
72 73 74 |
# File 'lib/operations.rb', line 72 def left_right @stack.pop == 0 ? change_dir(:e) : change_dir(:w) end |
#logical_not ⇒ Object
58 59 60 |
# File 'lib/operations.rb', line 58 def logical_not @stack.pop == 0 ? @stack.push(1) : @stack.push(0) end |
#operate!(op) ⇒ Object
26 27 28 29 30 31 32 33 34 |
# File 'lib/operations.rb', line 26 def operate!(op) string_mode and return if op == '"' push_ascii_value(op) and return if @string_mode return if op == ' ' send(op) and return if MATH_OPS.include?(op.to_sym) push_num(op) and return if Integer(op) rescue false change_dir(op.to_sym) and return if DIRECTION_OPS.include?(op.to_sym) send(OPERATORS_MAP[op]) end |
#pop_and_discard ⇒ Object
95 96 97 |
# File 'lib/operations.rb', line 95 def pop_and_discard @stack.pop end |
#pop_and_display_char ⇒ Object
105 106 107 108 109 |
# File 'lib/operations.rb', line 105 def pop_and_display_char display_char = @stack.pop.chr @return_string << display_char print display_char end |
#pop_and_display_int ⇒ Object
99 100 101 102 103 |
# File 'lib/operations.rb', line 99 def pop_and_display_int display_int = @stack.pop @return_string << display_int.to_s print display_int end |
#push_ascii_value(op) ⇒ Object
144 145 146 |
# File 'lib/operations.rb', line 144 def push_ascii_value(op) @stack.push(op.ord) end |
#push_num(num) ⇒ Object
46 47 48 |
# File 'lib/operations.rb', line 46 def push_num(num) @stack.push(num.to_i) end |
#put_call ⇒ Object
115 116 117 118 119 120 |
# File 'lib/operations.rb', line 115 def put_call y = @stack.pop x = @stack.pop v = @stack.pop @code_map.set_operation(y, x, v.chr) end |
#rand_direction ⇒ Object
68 69 70 |
# File 'lib/operations.rb', line 68 def rand_direction @code_map.pointer.direction = DIRECTIONS.sample end |
#string_mode ⇒ Object
80 81 82 83 |
# File 'lib/operations.rb', line 80 def string_mode @string_mode = !@string_mode true end |
#swap_stack_top ⇒ Object
90 91 92 93 |
# File 'lib/operations.rb', line 90 def swap_stack_top return if @stack.length < 2 @stack[-1], @stack[-2] = @stack[-2], @stack[-1] end |
#trampoline ⇒ Object
111 112 113 |
# File 'lib/operations.rb', line 111 def trampoline @code_map.pointer.trampoline = true end |
#up_down ⇒ Object
76 77 78 |
# File 'lib/operations.rb', line 76 def up_down @stack.pop == 0 ? change_dir(:s) : change_dir(:n) end |