rggen-core 0.19.0 → 0.23.1

Sign up to get free protection for your applications and to get access to all the features.
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