class ReplaceArithmeticOnRangesAst
Public Instance Methods
arithmetic(ast)
click to toggle source
Format [:artithmetic, left, operator, right] should have removed arithmetic with more than one operator in an earlier transformation
# File src/simplify/replace_arithmetic_on_ranges.rb, line 85 def arithmetic(ast) left, operator, right = ast[1], ast[2], ast[3] # Three different options, array on the left, array on the right, or both # array on the left first if left.first == :array && right.first != :array ast.replace( array_map(left) do |cell| [:arithmetic, map(cell), operator, right] end ) # array on the right next elsif left.first != :array && right.first == :array ast.replace( array_map(right) do |cell| [:arithmetic, left, operator, map(cell)] end ) # now array both sides elsif left.first == :array && right.first == :array ast.replace( left.map.with_index do |row, i| if row == :array row else row.map.with_index do |cell, j| if cell == :row cell elsif i >= left.length || i >= right.length || j >= left[1].length || j >= right[1].length [:error, "#VALUE!"] else [:arithmetic, map(left[i][j]), operator, map(right[i][j])] end end end end ) end end
array_map(array) { |column| ... }
click to toggle source
# File src/simplify/replace_arithmetic_on_ranges.rb, line 138 def array_map(array) array.map do |row| if row == :array row else row.map do |column| if column == :row column else yield column end end end end end
comparison(ast)
click to toggle source
FIXME: DRY THIS UP
# File src/simplify/replace_arithmetic_on_ranges.rb, line 40 def comparison(ast) left, operator, right = ast[1], ast[2], ast[3] # Three different options, array on the left, array on the right, or both # array on the left first if left.first == :array && right.first != :array ast.replace( array_map(left) do |cell| [:comparison, map(cell), operator, right] end ) # array on the right next elsif left.first != :array && right.first == :array ast.replace( array_map(right) do |cell| [:comparison, left, operator, map(cell)] end ) # now array both sides elsif left.first == :array && right.first == :array ast.replace( left.map.with_index do |row, i| if row == :array row else row.map.with_index do |cell, j| if cell == :row cell elsif i >= left.length || i >= right.length || j >= left[1].length || j >= right[1].length [:error, "#VALUE!"] else [:comparison, map(left[i][j]), operator, map(right[i][j])] end end end end ) end end
function(ast)
click to toggle source
FIXME: Generalise this? Combine with Array
formulae?
# File src/simplify/replace_arithmetic_on_ranges.rb, line 25 def function(ast) unless [:RIGHT, :LEFT].include?(ast[1]) && ast[2][0] == :array ast.each { |a| map(a) } return end ast.replace( array_map(ast[2]) do |cell| a = ast.dup a[2] = cell a end ) end
map(ast)
click to toggle source
# File src/simplify/replace_arithmetic_on_ranges.rb, line 3 def map(ast) return ast unless ast.is_a?(Array) ast.each do |a| next unless a.is_a?(Array) case ast.first when :error, :null, :space, :boolean_true, :boolean_false, :number, :string next when :sheet_reference, :table_reference, :local_table_reference next when :function function(ast) else map(a) end end prefix(ast) if ast.first == :prefix arithmetic(ast) if ast.first == :arithmetic comparison(ast) if ast.first == :comparison ast end
prefix(ast)
click to toggle source
Format [:prefix, symbol, array]
# File src/simplify/replace_arithmetic_on_ranges.rb, line 127 def prefix(ast) symbol, array = ast[1], ast[2] # array on the right next return unless array.first == :array ast.replace( array_map(array) do |cell| [:prefix, symbol, map(cell)] end ) end