module Comfpile class ContextTag attr_reader :tag, :taglist def self.form_context(tag) @known_tags ||= {} case tag when Symbol tag_instance = @known_tags[tag] return tag_instance unless tag_instance.nil? tag_instance = ContextTag.new(tag) tag_instance = (@known_tags[tag_instance] ||= tag_instance) @known_tags[tag] ||= tag_instance @known_tags[tag_instance.tag] ||= tag_instance end end def initialize(tag) process_tag(tag) end private def process_tag(tag) case tag when Symbol, String @taglist = tag.to_s.split('_').uniq.sort when Array @taglist = tag.map(&:to_s).uniq.sort end @tag = @taglist.join('_').to_sym @taghash = {} @taglist.each do |tag| @taghash[tag] = true end end def include?(*tags) tags = tags - @tag_array tags.empy? end alias include_all? include? def include_any?(*tags) tags = tags & @tag_array tags.empty? end def hash @tag.hash end def eql?(other) if(other.is_a? Symbol) @tag.eql? other elsif(other.is_a? ContextTag) @tag.eql? other.tag end end end # # This class represents the configuration of a specific context. # It has two main jobs: # To provide functions to set up and merge configuration options # from the various tags given to it, and # to give reader options for the various config options. # # Most importantly, it contains mechanisms for safely setting up # configurations and flagging issues. # class ContextConfig attr_reader :context_tag attr_reader :config_options def initialize(context_tag, parent) @context_tag = context_tag @seeder_blocks = [] @config_options = nil end def add_seeder_block(priority, &block) @seeder_blocks << { priority: priority, block: block } end def resolve_key(key) if key.is_a? Array return key.map {|k| k.to_sym } elsif key.is_a? String return key.split('.').map {|k| k.to_sym } elsif key.is_a? Symbol return resolve_key(key.to_s) end end def [](key) @config_options&.dig(*resolve_key(key)) end def []=(key, value) key = resolve_key(key) current_hash = (@config_options ||= {}) key[0..-2].each do |key| current_hash = (current_hash[key] ||= {}) next if current_hash.is_a? Hash raise ArgumentError, "Attempted to set child-parameter of another parameter!" end current_hash[key[-1]] = value value end alias set []= def set_flag(key, value) set resolve_key(key).append(value), true end def get_flags(key) (@config_options&.dig(*resolve_key(key)) || {}).keys end def dig(arg0, *args) @config_options&.dig(arg0, *args) end def append(key, value) key = resolve_key key array = @config_options&.dig(*key) if array.nil? array = set key, [] end raise ArgumentError, "Attempted to append to a non-list parameter!" unless array.is_a? Array array << value end alias append_to append def assert(orig_key, value) key = resolve_key orig_key current_value = @config_options&.dig(*key) if current_value.nil? set key, value elsif current_value != value raise ArgumentError, "Config key assertion failed! #{orig_key} should be #{value}, is #{current_value}!" end end def build_config @config_options = nil @seeder_blocks.sort { |block| block[:priority] }.each do |block| self.instance_exec(block, &block[:block]) end self.freeze end end class ContextConfigContainer def initialize @context_configs_seeds = [] end def find_seeds_for(context_tag) out = [] @context_configs_seeds.each do |seed| seed_tags = seed[:context_tags] seed_tags.each do |tag| end end end def add_to_config(context_config) raise ArgumentError, "No context supplied!" unless context_config.is_a? ContextConfig end end end