diff --git a/lib/comfpile/context.rb b/lib/comfpile/context.rb new file mode 100644 index 0000000..6d1d957 --- /dev/null +++ b/lib/comfpile/context.rb @@ -0,0 +1,165 @@ + + +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 + + + 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 \ No newline at end of file