Class: Forthic::MapWord
- Inherits:
-
Object
- Object
- Forthic::MapWord
- Defined in:
- lib/forthic/words/map_word.rb
Instance Attribute Summary collapse
-
#cur_index ⇒ Object
Returns the value of attribute cur_index.
-
#depth ⇒ Object
Returns the value of attribute depth.
-
#errors ⇒ Object
Returns the value of attribute errors.
-
#flags ⇒ Object
Returns the value of attribute flags.
-
#forthic ⇒ Object
Returns the value of attribute forthic.
-
#forthic_location ⇒ Object
Returns the value of attribute forthic_location.
-
#is_debugging ⇒ Object
Returns the value of attribute is_debugging.
-
#is_done ⇒ Object
Returns the value of attribute is_done.
-
#items ⇒ Object
Returns the value of attribute items.
-
#num_interps ⇒ Object
Returns the value of attribute num_interps.
-
#processing_item ⇒ Object
Returns the value of attribute processing_item.
-
#push_error ⇒ Object
Returns the value of attribute push_error.
-
#result ⇒ Object
Returns the value of attribute result.
-
#with_key ⇒ Object
Returns the value of attribute with_key.
Instance Method Summary collapse
- #execute(interp) ⇒ Object
-
#initialize(items, forthic, forthic_location, flags) ⇒ MapWord
constructor
A new instance of MapWord.
- #map(interp, items) ⇒ Object
- #normal_execute(interp) ⇒ Object
Constructor Details
#initialize(items, forthic, forthic_location, flags) ⇒ MapWord
Returns a new instance of MapWord.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/forthic/words/map_word.rb', line 7 def initialize(items, forthic, forthic_location, flags) @forthic = forthic @forthic_location = forthic_location @items = items @flags = flags # MAP flags @depth = flags[:depth] || 0 @num_interps = flags[:interps] || 1 @push_error = flags[:push_error] @with_key = flags[:with_key] @cur_index = 0 @result = [] @errors = [] @is_debugging = false @processing_item = false @is_done = false end |
Instance Attribute Details
#cur_index ⇒ Object
Returns the value of attribute cur_index.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def cur_index @cur_index end |
#depth ⇒ Object
Returns the value of attribute depth.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def depth @depth end |
#errors ⇒ Object
Returns the value of attribute errors.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def errors @errors end |
#flags ⇒ Object
Returns the value of attribute flags.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def flags @flags end |
#forthic ⇒ Object
Returns the value of attribute forthic.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def forthic @forthic end |
#forthic_location ⇒ Object
Returns the value of attribute forthic_location.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def forthic_location @forthic_location end |
#is_debugging ⇒ Object
Returns the value of attribute is_debugging.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def is_debugging @is_debugging end |
#is_done ⇒ Object
Returns the value of attribute is_done.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def is_done @is_done end |
#items ⇒ Object
Returns the value of attribute items.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def items @items end |
#num_interps ⇒ Object
Returns the value of attribute num_interps.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def num_interps @num_interps end |
#processing_item ⇒ Object
Returns the value of attribute processing_item.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def processing_item @processing_item end |
#push_error ⇒ Object
Returns the value of attribute push_error.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def push_error @push_error end |
#result ⇒ Object
Returns the value of attribute result.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def result @result end |
#with_key ⇒ Object
Returns the value of attribute with_key.
5 6 7 |
# File 'lib/forthic/words/map_word.rb', line 5 def with_key @with_key end |
Instance Method Details
#execute(interp) ⇒ Object
27 28 29 |
# File 'lib/forthic/words/map_word.rb', line 27 def execute(interp) normal_execute(interp) end |
#map(interp, items) ⇒ Object
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 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/forthic/words/map_word.rb', line 90 def map(interp, items) forthic = @forthic forthic_location = @forthic_location self_ref = self if !items interp.stack_push(items) return end # This maps the forthic over an item, storing errors if needed map_value = lambda do |key, value, errors| interp.stack_push(key) if self_ref.with_key interp.stack_push(value) if self_ref.push_error error = nil begin # If this runs successfully, it would have pushed the result onto the stack interp.run(forthic, forthic_location) rescue => e # Since this didn't run successfully, push nil onto the stack interp.stack_push(nil) error = e end errors.push(error) else interp.run(forthic, forthic_location) end interp.stack_pop end # This recursively descends a record structure descend_record = lambda do |record, depth, accum, errors| record.each do |k, item| if depth > 0 if item.is_a?(Array) accum[k] = [] descend_list.call(item, depth - 1, accum[k], errors) else accum[k] = {} descend_record.call(item, depth - 1, accum[k], errors) end else accum[k] = map_value.call(k, item, errors) end end accum end # This recursively descends a list descend_list = lambda do |items, depth, accum, errors| items.each_with_index do |item, i| if depth > 0 if item.is_a?(Array) accum.push([]) descend_list.call(item, depth - 1, accum.last, errors) else accum.push({}) descend_record.call(item, depth - 1, accum.last, errors) end else accum.push(map_value.call(i, item, errors)) end end accum end errors = [] result = if items.is_a?(Array) descend_list.call(items, @depth, [], errors) else descend_record.call(items, @depth, {}, errors) end @result = result @errors = errors [result, errors] end |
#normal_execute(interp) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/forthic/words/map_word.rb', line 31 def normal_execute(interp) @is_debugging = false items = @items if !items || items.empty? interp.stack_push(items) return end @result = [] @errors = [] if @num_interps > 1 interp.stack_push(items) interp.run("LENGTH") num_items = interp.stack_pop group_size = (num_items.to_f / @num_interps).ceil interp.stack_push(items) interp.stack_push(group_size) interp.run("GROUPS-OF") groups = interp.stack_pop # Clone and load up interpreters interp_runs = [] groups.each do |group| new_interp = interp.dup interp_run = -> { map(new_interp, group) } interp_runs.push(interp_run) end # Run in parallel using threads threads = interp_runs.map do |interp_run| Thread.new { interp_run.call } end run_results = threads.map(&:value) # Gather results is_array = items.is_a?(Array) array_result = [] object_result = {} errors = [] run_results.each do |res| if is_array array_result.concat(res[0]) else object_result.merge!(res[0]) end errors.concat(res[1]) end @result = is_array ? array_result : object_result @errors = errors else map(interp, items) end # Return results interp.stack_push(@result) interp.stack_push(@errors) if @push_error end |