class CompileToC
Attributes
allow_unknown_functions[RW]
gettable[RW]
settable[RW]
variable_set_counter[RW]
Public Class Methods
rewrite(*args)
click to toggle source
# File src/compile/c/compile_to_c.rb, line 10 def self.rewrite(*args) self.new.rewrite(*args) end
Public Instance Methods
rewrite(formulae, sheet_names, output)
click to toggle source
# File src/compile/c/compile_to_c.rb, line 14 def rewrite(formulae, sheet_names, output) self.settable ||= lambda { |ref| false } self.gettable ||= lambda { |ref| true } @variable_set_counter ||= 0 mapper = MapFormulaeToC.new mapper.allow_unknown_functions = self.allow_unknown_functions mapper.sheet_names = sheet_names formulae.each do |ref, ast| begin worksheet = ref.first cell = ref.last mapper.worksheet = worksheet worksheet_c_name = mapper.sheet_names[worksheet.to_s] || worksheet.to_s calculation = mapper.map(ast) name = worksheet_c_name.length > 0 ? "#{worksheet_c_name}_#{cell.downcase}" : cell.downcase # Declare function as static so it can be inlined where possible static_or_not = gettable.call(ref) ? "" : "static " # Settable functions need a default value and then a function for getting and setting if settable.call(ref) output.puts "ExcelValue #{name}_default() {" mapper.initializers.each do |i| output.puts " #{i}" end output.puts " return #{calculation};" output.puts "}" output.puts "static ExcelValue #{name}_variable;" output.puts "ExcelValue #{name}() { if(variable_set[#{@variable_set_counter}] == 1) { return #{name}_variable; } else { return #{name}_default(); } }" output.puts "void set_#{name}(ExcelValue newValue) { variable_set[#{@variable_set_counter}] = 1; #{name}_variable = newValue; }" output.puts # Other functions just have a getter else # In simple cases, don't bother memoizing the result simple = (ast[0] == :constant) || (ast[0] == :cell && ast[1] =~ /common\d+/) || (ast[0] == :blank) || (ast[0] == :error) if simple output.puts "#{static_or_not}ExcelValue #{name}() { return #{calculation}; }" else output.puts "#{static_or_not}ExcelValue #{name}() {" output.puts " static ExcelValue result;" output.puts " if(variable_set[#{@variable_set_counter}] == 1) { return result;}" mapper.initializers.each do |i| output.puts " #{i}" end output.puts " result = #{calculation};" output.puts " variable_set[#{@variable_set_counter}] = 1;" output.puts " return result;" output.puts "}" output.puts end end @variable_set_counter += 1 mapper.reset rescue Exception => e puts "Exception at #{ref} #{ast}" if ref.first == "" # Then it is a common method, helpful to indicate where it comes from s = /#{ref.last}/io formulae.each do |r, a| puts "Referenced in #{r}" if a.to_s =~ s end end raise end end end