module Comfpile class ContextTag def initialize(tag) @@known_tags ||= {} case tag when Symbol, String precompiled = @@known_tags[tag.to_sym] if not precompiled.nil? @tag = precompiled[:tag] @tag_array = precompiled[:array] else @tag_array = tag.to_s.split('_').uniq.sort end when Array @tag_array = tag.map(&:to_s).uniq.sort @tag = @tag_array end @tag ||= @tag_array.join('_').to_sym tag_data = { tag: @tag, array: @ŧag_array } @@known_tags[@tag] ||= tag_data @@known_tags[tag] ||= tag_data end def self.tagify(tag) @known_tags ||= {} 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