module RubyListComprehension
Constants
- FM_REGEX
- F_REGEX
- I_REGEX
- M_REGEX
Private Instance Methods
create_protocol(denested_array, operator_array)
click to toggle source
# File lib/ruby_list_comprehension.rb, line 61 def create_protocol(denested_array, operator_array) operator_array.each_with_object({}).with_index do |(e, o), i| case e when :filter o[i] = [e, denested_array[i].match(F_REGEX)] when :filter_map o[i] = [e, denested_array[i].match(FM_REGEX)] when :map o[i] = [e, denested_array[i].match(M_REGEX)] when :identity o[i] = [e, denested_array[i].match(I_REGEX)] end end end
denest_builder(nested_list)
click to toggle source
# File lib/ruby_list_comprehension.rb, line 44 def denest_builder(nested_list) nested_list.split('[') .delete_if{|x| x == ""} .map{|str|str[0..-1] + " end"} .join.split('],') .join.split(' end') .map{|x|"#{x} end"} end
denest_flattener(nested_list)
click to toggle source
# File lib/ruby_list_comprehension.rb, line 53 def denest_flattener(nested_list) nested_list.split(" end") .join .split(' end') .split('for')[1..-1] .map!{|x|"for#{x} end"} end
execute_comprehension(hash, flatten = true)
click to toggle source
# File lib/ruby_list_comprehension.rb, line 76 def execute_comprehension(hash, flatten = true) $process_str = '' op_array = hash.values.map{|x,|x} start_index = op_array.length - 1 nested = op_array.length > 1 match_data_array = hash.values.map{|_,x|x} i = 0 until op_array.empty? current_data = match_data_array[i] $iterable_string = fetch_capture(current_data, 'iterable') $mappable = fetch_capture(current_data, 'mappable') $parameter = fetch_capture(current_data, 'parameter') $filterable = fetch_capture(current_data, 'filterable') $identity = fetch_capture(current_data, 'identity') $iterable = Array($iterable) if $iterable.class == Set $iterable = fetch_capture(current_data, 'iterable') if i != 0 $iterable = $iterable_string if !flatten && @nested case op_array.shift when :identity flatten = @flattener if !@nested return *$iterable elsif i.zero? && !@flattener $process_str += "(#{$iterable}).map" elsif i.zero? && @flattener $process_str += "(#{$iterable}).flat_map" elsif !i.zero? && i != start_index $process_str += "{(#{$iterable}).map" elsif i == start_index $process_str += "{(#{$iterable_string}).map(&:itself)" $process_str += '}' * (start_index) elsif nested && i.zero? && !flatten $process_str += "(#{$iterable}).map" elsif i != 0 && nested $process_str += "(#{$iterable_string}).map" end when :map if i == 0 $mappable = $parameter if /\A\s*\Z/ === $mappable $process_str += "(#{$iterable}).map{|#{$parameter}|(#{$mappable})}" elsif i == 0 && flatten $mappable = $parameter if /\A\s*\Z/ === $mappable $process_str += "(#{$iterable}).flat_map{|#{$parameter}|(#{$mappable})" elsif i == 0 && !flatten $mappable = $parameter if /\A\s*\Z/ === $mappable $process_str += "(#{$iterable}).map{|#{$parameter}|(#{$mappable})" elsif i == start_index $mappable = $parameter if /\A\s*\Z/ === $mappable $process_str += "{(#{$iterable}).map{|#{$parameter}|(#{$mappable})" $process_str += '}' * (start_index+1) elsif i != start_index $process_str += "{(#{$iterable_string}).map{|#{$parameter}|(#{$mappable})" end when :filter if op_array.empty? $process_str += "(#{$iterable}).filter{|#{$parameter}|(#{$filterable})}" end when :filter_map if op_array.empty? && RUBY_VERSION >= '2.7.0' $process_str += "(#{$iterable}).filter_map{|#{$parameter}|(#{$mappable}) if (#{$filterable})}" else $process_str += "(#{$iterable}).map{|#{$parameter}|(#{$mappable}) if (#{$filterable})}.compact" end end i += 1 end begin instance_eval($process_str) rescue SyntaxError => e "List incomprehensible: #{e.backtrace_locations.to_s}" rescue Error => e "Check your assumptions, something is amiss: #{e.backtrace_locations.to_s}" end end
fetch_capture(data, name)
click to toggle source
# File lib/ruby_list_comprehension.rb, line 14 def fetch_capture(data, name) data[name.to_sym] if data.names.include?(name.to_s) && !data.nil? end
one_shot(str)
click to toggle source
# File lib/ruby_list_comprehension.rb, line 152 def one_shot(str) len = str.scan('for ').length @nested = len > 1 if @nested nest_mode = str.include?('end end') && !@nested ? :flatten : :matrix nest_array = @flattener ? denest_flattener(str) : denest_builder(str) else nest_array = [str] end op_array = nest_array.map(&method(:op_type)) hash = create_protocol(nest_array, op_array) begin execute_comprehension(hash, nest_mode==@nested) rescue SyntaxError => se puts 'RESCUED!' + se.backtrace_locations.to_s end end
op_type(str)
click to toggle source
# File lib/ruby_list_comprehension.rb, line 18 def op_type(str) match_map = str.match(M_REGEX) match_filter_map = str.match(FM_REGEX) match_filter = str.match(F_REGEX) match_identity = str.match(I_REGEX) parameter = fetch_capture(match_identity, :parameter) mappable = fetch_capture(match_map, :mappable) map_condition = mappable.split('if')[0] if match_filter_map.nil? && match_filter.nil? && (parameter.strip == mappable.strip || /\A\s*\Z/ === mappable) return :identity elsif match_filter_map.nil? && match_filter.nil? return :map end if fetch_capture(match_map, :mappable).include?('if') && !(parameter.strip == map_condition.strip || /\A\s*\Z/ === mappable) :filter_map else if match_identity[:parameter].strip == match_filter[:filterable].strip return :identity end :filter end end