class Computable
Constants
- Unknown
This is a special value to mark a variable to be computed.
- VERSION
Public Class Methods
calc_value(name, format=nil, freeze: true, &block)
click to toggle source
# File lib/computable.rb, line 285 def self.calc_value name, format=nil, freeze: true, &block calc_method_id = "calc_#{name}".intern define_method(calc_method_id, &block) calc_method2_id = "calc_#{name}_with_tracking".intern define_method(calc_method2_id) do |v| old_caller = Thread.current.thread_variable_get("Computable #{object_id}") Thread.current.thread_variable_set("Computable #{self.object_id}", v) begin puts "do calc #{v.inspect}" if @computable_debug begin res = send(calc_method_id) rescue Exception => err improve_backtrace(err, block, name) end Computable.verify_format(name, res, format) res.freeze if freeze res ensure Thread.current.thread_variable_set("Computable #{self.object_id}", old_caller) end end define_method("#{name}=") do |value| Computable.verify_format(name, value, format) @computable_mutex.synchronize do v = @computable_variables[name] puts "set #{name}: #{value.inspect} #{v.inspect}" if @computable_debug v = @computable_variables[name] = Variable.new(name, method(calc_method2_id), self, @computable_mutex) unless v value.freeze if freeze v.assign_value(value) end end define_method(name) do @computable_mutex.synchronize do v = @computable_variables[name] puts "called #{name} #{v.inspect}" if @computable_debug v = @computable_variables[name] = Variable.new(name, method(calc_method2_id), self, @computable_mutex) unless v kaller = Thread.current.thread_variable_get("Computable #{object_id}") v.query_value(kaller) end end end
input_value(name, format=nil, **kwargs)
click to toggle source
# File lib/computable.rb, line 332 def self.input_value name, format=nil, **kwargs calc_value name, format, **kwargs do raise UndefinedValue, "input variable '#{name}' is not assigned" end end
new()
click to toggle source
# File lib/computable.rb, line 261 def initialize @computable_debug = false @computable_max_threads = 0 @computable_variables = {} @computable_caller = nil @computable_mutex = Mutex.new end
verify_format(name, value, format)
click to toggle source
# File lib/computable.rb, line 270 def self.verify_format(name, value, format) if format && !(Unknown==value) && !(format === value) raise InvalidFormat, "variable '#{name}': value #{value.inspect} is not in format #{format.inspect}" end end
Public Instance Methods
computable_debug()
click to toggle source
# File lib/computable.rb, line 222 def computable_debug @computable_debug end
computable_debug=(v)
click to toggle source
# File lib/computable.rb, line 219 def computable_debug=(v) @computable_debug = v end
computable_display_dot(**kwargs)
click to toggle source
# File lib/computable.rb, line 233 def computable_display_dot(**kwargs) IO.popen("dot -Tpng | display -", "w") do |fd| fd.puts computable_to_dot(**kwargs) end end
computable_max_threads()
click to toggle source
# File lib/computable.rb, line 229 def computable_max_threads @computable_max_threads end
computable_max_threads=(v)
click to toggle source
# File lib/computable.rb, line 226 def computable_max_threads=(v) @computable_max_threads = v end
computable_to_dot(rankdir: "TB", multiline: true)
click to toggle source
# File lib/computable.rb, line 239 def computable_to_dot(rankdir: "TB", multiline: true) dot = "digraph #{self.class.name.inspect} {\n" dot << "graph [ dpi = 45, rankdir=#{rankdir} ];\n" @computable_variables.each do |name, v| col = case when !v.value_calced then "color = red," when !v.used_for.empty? then "color = green," else "color = blue," end label = if multiline "#{name.to_s.gsub("_","\n")}\n(#{v.count})" else "#{name.to_s} (#{v.count})" end dot << "#{name.to_s.inspect} [#{col} label=#{label.inspect}];\n" v.used_for.each do |name2, v2| dot << "#{name.to_s.inspect} -> #{name2.to_s.inspect};\n" end end dot << "}\n" end
Private Instance Methods
improve_backtrace(err, block, text)
click to toggle source
# File lib/computable.rb, line 276 def improve_backtrace(err, block, text) fpath, lineno = block.source_location bt = err.backtrace myloc = err.backtrace_locations.select.with_index{|loc, i| loc.path == fpath && loc.lineno >= lineno && !bt[i].include?("#") }.min{|a,b| a.lineno <=> b.lineno } idx = err.backtrace_locations.index(myloc) bt[idx] += " ##{text}" raise err end