rggen-core 0.19.0 → 0.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/exe/rggen +2 -2
  3. data/lib/rggen/core.rb +7 -4
  4. data/lib/rggen/core/base/component.rb +16 -7
  5. data/lib/rggen/core/base/component_factory.rb +12 -9
  6. data/lib/rggen/core/base/component_layer_extension.rb +194 -0
  7. data/lib/rggen/core/base/feature_layer_extension.rb +158 -0
  8. data/lib/rggen/core/builder/builder.rb +38 -52
  9. data/lib/rggen/core/builder/component_entry.rb +3 -2
  10. data/lib/rggen/core/builder/component_registry.rb +22 -17
  11. data/lib/rggen/core/builder/feature_registry.rb +6 -9
  12. data/lib/rggen/core/builder/input_component_registry.rb +43 -10
  13. data/lib/rggen/core/builder/layer.rb +132 -0
  14. data/lib/rggen/core/builder/loader_registry.rb +48 -0
  15. data/lib/rggen/core/builder/plugin_manager.rb +140 -0
  16. data/lib/rggen/core/configuration.rb +3 -2
  17. data/lib/rggen/core/configuration/component.rb +5 -0
  18. data/lib/rggen/core/configuration/component_factory.rb +1 -1
  19. data/lib/rggen/core/configuration/hash_loader.rb +4 -2
  20. data/lib/rggen/core/configuration/input_data.rb +15 -0
  21. data/lib/rggen/core/dsl.rb +3 -1
  22. data/lib/rggen/core/exceptions.rb +9 -4
  23. data/lib/rggen/core/generator.rb +3 -3
  24. data/lib/rggen/core/input_base/component_factory.rb +37 -6
  25. data/lib/rggen/core/input_base/feature.rb +3 -3
  26. data/lib/rggen/core/input_base/input_data.rb +13 -10
  27. data/lib/rggen/core/input_base/input_value_extractor.rb +34 -0
  28. data/lib/rggen/core/input_base/loader.rb +64 -21
  29. data/lib/rggen/core/input_base/yaml_loader.rb +5 -4
  30. data/lib/rggen/core/options.rb +18 -14
  31. data/lib/rggen/core/output_base/code_generator.rb +10 -23
  32. data/lib/rggen/core/output_base/component.rb +42 -39
  33. data/lib/rggen/core/output_base/component_factory.rb +4 -0
  34. data/lib/rggen/core/output_base/feature.rb +6 -7
  35. data/lib/rggen/core/printers.rb +11 -7
  36. data/lib/rggen/core/register_map.rb +6 -5
  37. data/lib/rggen/core/register_map/component.rb +4 -3
  38. data/lib/rggen/core/register_map/component_factory.rb +18 -1
  39. data/lib/rggen/core/register_map/feature.rb +2 -2
  40. data/lib/rggen/core/register_map/hash_loader.rb +61 -27
  41. data/lib/rggen/core/register_map/input_data.rb +30 -16
  42. data/lib/rggen/core/register_map/loader.rb +1 -1
  43. data/lib/rggen/core/register_map/ruby_loader.rb +1 -1
  44. data/lib/rggen/core/utility/attribute_setter.rb +4 -0
  45. data/lib/rggen/core/utility/code_utility.rb +8 -2
  46. data/lib/rggen/core/utility/error_utility.rb +33 -6
  47. data/lib/rggen/core/version.rb +2 -2
  48. metadata +10 -7
  49. data/lib/rggen/core/base/hierarchical_accessors.rb +0 -91
  50. data/lib/rggen/core/base/hierarchical_feature_accessors.rb +0 -83
  51. data/lib/rggen/core/builder/category.rb +0 -116
  52. data/lib/rggen/core/builder/plugins.rb +0 -77
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module InputBase
6
+ class InputValueExtractor
7
+ def initialize(target_layers, target_value)
8
+ @target_layers = Array(target_layers)
9
+ @target_value = target_value
10
+ end
11
+
12
+ class << self
13
+ attr_reader :extractor
14
+
15
+ private
16
+
17
+ def extract(&body)
18
+ @extractor = body
19
+ end
20
+ end
21
+
22
+ def target_value?(layer, value)
23
+ value == @target_value &&
24
+ (@target_layers.empty? || @target_layers.include?(layer))
25
+ end
26
+
27
+ def extract(input_data)
28
+ body = self.class.extractor
29
+ instance_exec(input_data, &body)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -4,40 +4,83 @@ module RgGen
4
4
  module Core
5
5
  module InputBase
6
6
  class Loader
7
- class << self
8
- def support_types(types)
9
- @support_types = types.map(&:to_sym)
10
- end
7
+ def self.support_types(types = nil)
8
+ types && (@support_types ||= []).concat(types.map(&:to_sym))
9
+ @support_types
10
+ end
11
11
 
12
- def support?(file)
13
- file_ext = File.ext(file).to_sym
14
- @support_types.any? { |type| type.casecmp?(file_ext) }
15
- end
12
+ def initialize(extractors, ignore_values)
13
+ @extractors = extractors
14
+ @ignore_values = ignore_values
15
+ end
16
16
 
17
- def load_file(file, input_data, valid_value_list)
18
- new(input_data, valid_value_list).load_file(file)
19
- end
17
+ def support?(file)
18
+ ext = File.ext(file).to_sym
19
+ types = self.class.support_types
20
+ types&.any? { |type| type.casecmp?(ext) } || false
20
21
  end
21
22
 
22
- def initialize(input_data, valid_value_lists)
23
+ def load_file(file, input_data, valid_value_lists)
24
+ File.readable?(file) ||
25
+ (raise Core::LoadError.new('cannot load such file', file))
23
26
  @input_data = input_data
24
27
  @valid_value_lists = valid_value_lists
28
+ format(read_file(file), input_data, input_data.layer, file)
25
29
  end
26
30
 
27
- def load_file(file)
28
- File.readable?(file) || (
29
- raise Core::LoadError.new('cannot load such file', file)
30
- )
31
- format(read_file(file), file)
31
+ private
32
+
33
+ attr_reader :input_data
34
+
35
+ def format(read_data, input_data, layer, file)
36
+ layer_data =
37
+ format_layer_data(read_data, layer, file) ||
38
+ format_layer_data_by_extractors(read_data, layer)
39
+ layer_data &&
40
+ input_data.values(filter_layer_data(layer_data, layer), file)
41
+ format_sub_layer(read_data, input_data, layer, file)
32
42
  end
33
43
 
34
- private
44
+ def format_sub_layer(read_data, input_data, layer, file)
45
+ format_sub_layer_data(read_data, layer, file)
46
+ &.flat_map { |sub_layer, data_array| [sub_layer].product(data_array) }
47
+ &.each do |(sub_layer, data)|
48
+ format(data, input_data.child(sub_layer), sub_layer, file)
49
+ end
50
+ end
35
51
 
36
- def format(_read_data, _file)
52
+ def format_layer_data(_read_data, _layer, _file)
37
53
  end
38
54
 
39
- attr_reader :input_data
40
- attr_reader :valid_value_lists
55
+ def format_layer_data_by_extractors(read_data, layer)
56
+ layer_data = {}
57
+ valid_values(layer).each do |value|
58
+ @extractors
59
+ .select { |extractor| extractor.target_value?(layer, value) }
60
+ .each do |extractor|
61
+ extract_value(read_data, extractor, layer_data, value)
62
+ end
63
+ end
64
+ layer_data.empty? ? nil : layer_data
65
+ end
66
+
67
+ def extract_value(read_data, extractor, layer_data, value)
68
+ data = extractor.extract(read_data)
69
+ data && (layer_data[value] = data)
70
+ end
71
+
72
+ def filter_layer_data(layer_data, layer)
73
+ layer_data
74
+ .select { |key, _| valid_values(layer).include?(key) }
75
+ end
76
+
77
+ def format_sub_layer_data(_read_data, _layer, _file)
78
+ end
79
+
80
+ def valid_values(layer)
81
+ @valid_value_lists[layer]
82
+ .reject { |value| @ignore_values[layer]&.include?(value) }
83
+ end
41
84
  end
42
85
  end
43
86
  end
@@ -26,13 +26,14 @@ module RgGen
26
26
 
27
27
  def symbolize_keys(result)
28
28
  if result.is_a? Hash
29
- result.keys.each do |key|
30
- result[key.to_sym] = symbolize_keys(result.delete(key))
29
+ result.each_with_object({}) do |(key, value), hash|
30
+ hash[key.to_sym] = symbolize_keys(value)
31
31
  end
32
32
  elsif result.is_a? Array
33
- result.map! { |value| symbolize_keys(value) }
33
+ result.map(&method(:symbolize_keys))
34
+ else
35
+ result
34
36
  end
35
- result
36
37
  end
37
38
  end
38
39
 
@@ -101,21 +101,19 @@ module RgGen
101
101
  end
102
102
  end
103
103
 
104
- Options.add_option(:setup) do |option|
105
- option.long_option '--setup FILE'
106
- option.default { default_steup_file }
107
- option.description 'Specify a Ruby file to set up RgGen tool'
108
-
109
- def option.default_steup_file
110
- ENV['RGGEN_DEFAULT_SETUP_FILE'] || define_setup_file_from_const
111
- end
104
+ Options.add_option(:no_default_plugins) do |option|
105
+ option.long_option '--no-default-plugins'
106
+ option.default false
107
+ option.action { |_, options| options[:no_default_plugins] = true }
108
+ option.description 'Do not load default plugins'
109
+ end
112
110
 
113
- def option.define_setup_file_from_const
114
- require 'rggen/default_setup_file'
115
- RgGen::DEFAULT_SETUP_FILE
116
- rescue ::LoadError
117
- nil
118
- end
111
+ Options.add_option(:plugins) do |option|
112
+ option.long_option '--plugin PLUGIN'
113
+ option.default { [] }
114
+ option.action { |value, options| options[:plugins] << value }
115
+ option.description 'Load a RgGen plugin ' \
116
+ "(name of plugin/path to 'setup.rb' file)"
119
117
  end
120
118
 
121
119
  Options.add_option(:configuration) do |option|
@@ -152,6 +150,12 @@ module RgGen
152
150
  end
153
151
  end
154
152
 
153
+ Options.add_option(:print_verbose_info) do |option|
154
+ option.long_option '--print-verbose-info'
155
+ option.default false
156
+ option.description 'Print verbose information when an error occurs'
157
+ end
158
+
155
159
  Options.add_option(:print_backtrace) do |option|
156
160
  option.long_option '--print-backtrace'
157
161
  option.default false
@@ -9,11 +9,10 @@ module RgGen
9
9
  code_blocks[kind] << block
10
10
  end
11
11
 
12
- def generate(context, kind, code)
13
- return code unless generatable?(kind)
14
- execute_code_blocks(
15
- context, kind, code || context.create_blank_code
16
- )
12
+ def generate(context, code, kind)
13
+ code_blocks[kind].each do |block|
14
+ execute_code_block(context, code, block)
15
+ end
17
16
  end
18
17
 
19
18
  def copy
@@ -28,30 +27,18 @@ module RgGen
28
27
  @code_blocks ||= Hash.new { |blocks, kind| blocks[kind] = [] }
29
28
  end
30
29
 
31
- def generatable?(kind)
32
- @code_blocks&.key?(kind)
33
- end
34
-
35
- def execute_code_blocks(context, kind, code)
36
- code_blocks[kind].each(&code_block_executor(context, code))
37
- code
38
- end
39
-
40
- def code_block_executor(context, code)
41
- lambda do |block|
42
- if block.arity.zero?
43
- code << context.instance_exec(&block)
44
- else
45
- context.instance_exec(code, &block)
46
- end
30
+ def execute_code_block(context, code, block)
31
+ if block.arity.zero?
32
+ code << context.instance_exec(&block)
33
+ else
34
+ context .instance_exec(code, &block)
47
35
  end
48
36
  end
49
37
 
50
38
  protected
51
39
 
52
40
  def copy_code_blocks(original_blocks)
53
- original_blocks
54
- .each { |kind, blocks| code_blocks[kind] = blocks.dup }
41
+ original_blocks.each { |kind, blocks| code_blocks[kind] = blocks.dup }
55
42
  end
56
43
  end
57
44
  end
@@ -4,22 +4,21 @@ module RgGen
4
4
  module Core
5
5
  module OutputBase
6
6
  class Component < Base::Component
7
- include Base::HierarchicalAccessors
7
+ include Base::ComponentLayerExtension
8
8
 
9
9
  attr_reader :configuration
10
- attr_reader :source
10
+ attr_reader :register_map
11
11
 
12
- def post_initialize(_paren, configuration, source)
12
+ def post_initialize(configuration, register_map)
13
13
  @configuration = configuration
14
- @source = source
15
- @need_children = source.need_children?
16
- define_hierarchical_accessors
17
- define_children_presense_indicator
18
- define_proxy_calls(@source, @source.properties)
14
+ @register_map = register_map
15
+ @need_children = register_map.need_children?
16
+ define_layer_methods
17
+ define_proxy_calls(@register_map, @register_map.properties)
19
18
  end
20
19
 
21
20
  def children?
22
- !source.children.empty?
21
+ !register_map.children.empty?
23
22
  end
24
23
 
25
24
  def add_feature(feature)
@@ -28,7 +27,7 @@ module RgGen
28
27
  end
29
28
 
30
29
  def printables
31
- @source.printables
30
+ register_map.printables
32
31
  end
33
32
 
34
33
  def pre_build
@@ -40,8 +39,9 @@ module RgGen
40
39
  @children.each(&:build)
41
40
  end
42
41
 
43
- def generate_code(kind, mode, code = nil)
44
- code_generators(kind, mode).inject(code) { |c, g| g[c] }
42
+ def generate_code(code, kind, mode, target_or_range = nil, depth = 0)
43
+ code_generator_contexts(kind, mode, target_or_range, depth)
44
+ .each { |context| context.generate(code) }
45
45
  end
46
46
 
47
47
  def write_file(directory = nil)
@@ -51,18 +51,6 @@ module RgGen
51
51
 
52
52
  private
53
53
 
54
- INDICATOR_NAMES = {
55
- register_map: :register_blocks?,
56
- register_block: :registers?,
57
- register: :bit_fields?
58
- }.freeze
59
-
60
- def define_children_presense_indicator
61
- indicator_name = INDICATOR_NAMES[hierarchy]
62
- indicator_name &&
63
- singleton_exec { alias_method indicator_name, :children? }
64
- end
65
-
66
54
  def build_feature(feature)
67
55
  feature.build
68
56
  import_feature_methods(feature, :object)
@@ -73,25 +61,40 @@ module RgGen
73
61
  define_proxy_calls(feature, methods)
74
62
  end
75
63
 
76
- def code_generators(kind, mode)
64
+ CodeGeneratorContext = Struct.new(:receivers, :args) do
65
+ def generate(code)
66
+ receivers.each { |receiver| receiver.generate_code(code, *args) }
67
+ end
68
+ end
69
+
70
+ def code_generator_contexts(kind, mode, target_or_range, depth)
77
71
  [
78
- [@features.each_value, [:pre_code, kind]],
79
- *main_code_contexts(kind, mode),
80
- [@features.each_value, [:post_code, kind]]
81
- ].map do |receivers, args|
82
- lambda do |code|
83
- receivers.inject(code) { |c, r| r.generate_code(*args, c) }
84
- end
72
+ feature_code_generator_context(:pre_code, kind, target_or_range, depth),
73
+ *main_code_generator_contexts(kind, mode, target_or_range, depth),
74
+ feature_code_generator_context(:post_code, kind, target_or_range, depth)
75
+ ].compact
76
+ end
77
+
78
+ def feature_code_generator_context(phase, kind, target_or_range, depth)
79
+ (target_depth?(depth, target_or_range) || nil) &&
80
+ CodeGeneratorContext.new(@features.each_value, [phase, kind])
81
+ end
82
+
83
+ def target_depth?(depth, target_or_range)
84
+ if target_or_range.nil?
85
+ true
86
+ elsif target_or_range.respond_to?(:include?)
87
+ target_or_range.include?(depth)
88
+ else
89
+ depth == target_or_range
85
90
  end
86
91
  end
87
92
 
88
- def main_code_contexts(kind, mode)
89
- contexts = [
90
- [@features.each_value, [:main_code, kind]],
91
- [@children, [kind, mode]]
92
- ]
93
- contexts.reverse! if mode == :bottom_up
94
- contexts
93
+ def main_code_generator_contexts(kind, mode, target_or_range, depth)
94
+ [
95
+ feature_code_generator_context(:main_code, kind, target_or_range, depth),
96
+ CodeGeneratorContext.new(@children, [kind, mode, target_or_range, depth + 1])
97
+ ].tap { |contexts| mode == :bottom_up && contexts.reverse! }
95
98
  end
96
99
  end
97
100
  end
@@ -22,6 +22,10 @@ module RgGen
22
22
  end
23
23
  end
24
24
 
25
+ def find_child_factory(_configuration, register_map)
26
+ component_factories[register_map.layer]
27
+ end
28
+
25
29
  def post_build(component)
26
30
  component.pre_build
27
31
  end
@@ -4,7 +4,7 @@ module RgGen
4
4
  module Core
5
5
  module OutputBase
6
6
  class Feature < Base::Feature
7
- include Base::HierarchicalFeatureAccessors
7
+ include Base::FeatureLayerExtension
8
8
  include RaiseError
9
9
 
10
10
  class << self
@@ -64,9 +64,8 @@ module RgGen
64
64
 
65
65
  def export(*methods)
66
66
  methods.each do |method|
67
- exported_methods.include?(method) || (
68
- exported_methods << method
69
- )
67
+ exported_methods.include?(method) ||
68
+ (exported_methods << method)
70
69
  end
71
70
  end
72
71
  end
@@ -90,7 +89,7 @@ module RgGen
90
89
  end
91
90
 
92
91
  def post_initialize
93
- define_hierarchical_accessors
92
+ define_layer_methods
94
93
  end
95
94
 
96
95
  def pre_build
@@ -122,9 +121,9 @@ module RgGen
122
121
  end
123
122
  end
124
123
 
125
- def generate_code(phase, kind, code = nil)
124
+ def generate_code(code, phase, kind)
126
125
  generator = self.class.code_generators[phase]
127
- (generator&.generate(self, kind, code)) || code
126
+ generator&.generate(self, code, kind)
128
127
  end
129
128
 
130
129
  def write_file(directory = nil)
@@ -18,18 +18,20 @@ module RgGen
18
18
  end
19
19
 
20
20
  def run(builder, options)
21
- verbose? && load_setup_file(builder, options[:setup])
21
+ verbose? && load_plugins(builder, options)
22
22
  puts version_message(builder)
23
23
  end
24
24
 
25
25
  private
26
26
 
27
- def verbose?
28
- @verbose
27
+ def load_plugins(builder, options)
28
+ plugins = options[:plugins]
29
+ no_default_plugins = options[:no_default_plugins]
30
+ builder.load_plugins(plugins, no_default_plugins, false)
29
31
  end
30
32
 
31
- def load_setup_file(builder, file)
32
- file.nil? || file.empty? || builder.load_setup_file(file, false)
33
+ def verbose?
34
+ @verbose
33
35
  end
34
36
 
35
37
  def version_message(builder)
@@ -44,8 +46,10 @@ module RgGen
44
46
  end
45
47
 
46
48
  def verbose_version(builder)
47
- ["rggen-core #{Core::VERSION}", *builder.plugins.version_info]
48
- .map { |version_info| " - #{version_info}" }
49
+ [
50
+ "rggen-core #{Core::VERSION}",
51
+ *builder.plugin_manager.version_info
52
+ ].map { |version_info| " - #{version_info}" }
49
53
  end
50
54
  end
51
55
  end