rggen-core 0.20.0 → 0.24.0

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +2 -1
  4. data/exe/rggen +2 -2
  5. data/lib/rggen/core.rb +9 -1
  6. data/lib/rggen/core/builder/builder.rb +30 -36
  7. data/lib/rggen/core/builder/component_registry.rb +8 -9
  8. data/lib/rggen/core/builder/feature_registry.rb +6 -9
  9. data/lib/rggen/core/builder/input_component_registry.rb +43 -10
  10. data/lib/rggen/core/builder/layer.rb +44 -29
  11. data/lib/rggen/core/builder/loader_registry.rb +48 -0
  12. data/lib/rggen/core/builder/plugin_manager.rb +122 -0
  13. data/lib/rggen/core/builder/plugin_spec.rb +83 -0
  14. data/lib/rggen/core/configuration.rb +5 -3
  15. data/lib/rggen/core/configuration/hash_loader.rb +4 -2
  16. data/lib/rggen/core/configuration/toml_loader.rb +18 -0
  17. data/lib/rggen/core/dsl.rb +3 -1
  18. data/lib/rggen/core/exceptions.rb +9 -4
  19. data/lib/rggen/core/facets.rb +0 -1
  20. data/lib/rggen/core/generator.rb +3 -3
  21. data/lib/rggen/core/input_base/feature.rb +2 -2
  22. data/lib/rggen/core/input_base/input_data.rb +8 -4
  23. data/lib/rggen/core/input_base/input_value_extractor.rb +34 -0
  24. data/lib/rggen/core/input_base/loader.rb +64 -20
  25. data/lib/rggen/core/input_base/toml_loader.rb +16 -0
  26. data/lib/rggen/core/input_base/yaml_loader.rb +12 -8
  27. data/lib/rggen/core/options.rb +18 -14
  28. data/lib/rggen/core/output_base/code_generator.rb +1 -1
  29. data/lib/rggen/core/plugin.rb +16 -0
  30. data/lib/rggen/core/printers.rb +11 -7
  31. data/lib/rggen/core/register_map.rb +6 -6
  32. data/lib/rggen/core/register_map/hash_loader.rb +58 -17
  33. data/lib/rggen/core/register_map/toml_loader.rb +18 -0
  34. data/lib/rggen/core/utility/attribute_setter.rb +5 -0
  35. data/lib/rggen/core/utility/error_utility.rb +33 -6
  36. data/lib/rggen/core/version.rb +2 -4
  37. metadata +32 -5
  38. data/lib/rggen/core/builder/plugins.rb +0 -79
@@ -4,39 +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
11
-
12
- def support?(file)
13
- file_ext = File.ext(file).to_sym
14
- @support_types.any? { |type| type.casecmp?(file_ext) }
15
- end
7
+ def self.support_types(types = nil)
8
+ types && (@support_types ||= []).concat(types.map(&:to_sym))
9
+ @support_types
10
+ end
16
11
 
17
- def load_file(file, input_data, valid_value_list)
18
- new(input_data, valid_value_list).load_file(file)
19
- end
12
+ def initialize(extractors, ignore_values)
13
+ @extractors = extractors
14
+ @ignore_values = ignore_values
20
15
  end
21
16
 
22
- def initialize(input_data, valid_value_lists)
23
- @input_data = input_data
24
- @valid_value_lists = valid_value_lists
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
25
21
  end
26
22
 
27
- def load_file(file)
23
+ def load_file(file, input_data, valid_value_lists)
28
24
  File.readable?(file) ||
29
25
  (raise Core::LoadError.new('cannot load such file', file))
30
- format(read_file(file), file)
26
+ @input_data = input_data
27
+ @valid_value_lists = valid_value_lists
28
+ format(read_file(file), input_data, input_data.layer, file)
31
29
  end
32
30
 
33
31
  private
34
32
 
35
- def format(_read_data, _file)
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)
36
42
  end
37
43
 
38
- attr_reader :input_data
39
- attr_reader :valid_value_lists
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
51
+
52
+ def format_layer_data(_read_data, _layer, _file)
53
+ end
54
+
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
40
84
  end
41
85
  end
42
86
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module InputBase
6
+ module TOMLLoader
7
+ private
8
+
9
+ def load_toml(file)
10
+ toml = File.binread(file)
11
+ Tomlrb.parse(toml, symbolize_keys: true)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -25,16 +25,20 @@ module RgGen
25
25
  end
26
26
 
27
27
  def symbolize_keys(result)
28
- if result.is_a? Hash
29
- result.each_with_object({}) do |(key, value), hash|
30
- hash[key.to_sym] = symbolize_keys(value)
31
- end
32
- elsif result.is_a? Array
33
- result.map(&method(:symbolize_keys))
34
- else
35
- result
28
+ case result
29
+ when Hash then symbolize_hash(result)
30
+ when Array then symbolize_array(result)
31
+ else result
36
32
  end
37
33
  end
34
+
35
+ def symbolize_hash(result)
36
+ result.map { |key, value| [key.to_sym, symbolize_keys(value)] }.to_h
37
+ end
38
+
39
+ def symbolize_array(result)
40
+ result.map(&method(:symbolize_keys))
41
+ end
38
42
  end
39
43
 
40
44
  def load_yaml(file)
@@ -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
@@ -31,7 +31,7 @@ module RgGen
31
31
  if block.arity.zero?
32
32
  code << context.instance_exec(&block)
33
33
  else
34
- context .instance_exec(code, &block)
34
+ context.instance_exec(code, &block)
35
35
  end
36
36
  end
37
37
 
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Plugin
6
+ attr_reader :plugin_spec
7
+
8
+ private
9
+
10
+ def setup_plugin(name)
11
+ @plugin_spec = Builder::PluginSpec.new(name, self)
12
+ block_given? && yield(@plugin_spec)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -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
@@ -5,15 +5,15 @@ module RgGen
5
5
  module RegisterMap
6
6
  def self.setup(builder)
7
7
  builder.input_component_registry(:register_map) do
8
- register_component [
9
- :root, :register_block, :register_file, :register, :bit_field
10
- ] do |layer|
8
+ register_component do
11
9
  component Component, ComponentFactory
12
- feature Feature, FeatureFactory if layer != :root
10
+ feature Feature, FeatureFactory
13
11
  end
14
12
 
15
- base_loader Loader
16
- register_loaders [RubyLoader, JSONLoader, YAMLLoader]
13
+ register_loader :ruby, RubyLoader
14
+ register_loader :json, JSONLoader
15
+ register_loader :toml, TOMLLoader
16
+ register_loader :yaml, YAMLLoader
17
17
  end
18
18
  end
19
19
  end
@@ -4,36 +4,77 @@ module RgGen
4
4
  module Core
5
5
  module RegisterMap
6
6
  module HashLoader
7
- def format(read_data, file)
8
- format_data(:root, root, read_data, file)
9
- rescue TypeError => e
10
- raise Core::LoadError.new(e.message, file)
11
- end
12
-
13
7
  private
14
8
 
15
- LAYER_MAP = {
9
+ SUB_LAYER_KEYS = {
10
+ root: [:register_block, :register_blocks],
11
+ register_block: [:register_file, :register_files, :register, :registers],
12
+ register_file: [:register_file, :register_files, :register, :registers],
13
+ register: [:bit_field, :bit_fields]
14
+ }.freeze
15
+
16
+ SUB_LAYER_KEY_MAP = {
16
17
  root: { register_blocks: :register_block },
17
18
  register_block: { register_files: :register_file, registers: :register },
18
19
  register_file: { register_files: :register_file, registers: :register },
19
20
  register: { bit_fields: :bit_field }
20
21
  }.freeze
21
22
 
22
- def format_data(layer, input_data, read_data, file)
23
- read_data = Hash(read_data)
24
- input_data.values(read_data, file)
25
- format_next_layer_data(layer, input_data, read_data, file)
23
+ def format_layer_data(read_data, layer, file)
24
+ if read_data.is_a?(Array)
25
+ format_array_layer_data(read_data, layer, file)
26
+ else
27
+ fomrat_hash_layer_data(read_data, layer, file)
28
+ end
29
+ end
30
+
31
+ def format_array_layer_data(read_data, layer, file)
32
+ read_data.each_with_object({}) do |data, layer_data|
33
+ layer_data.merge!(fomrat_hash_layer_data(data, layer, file))
34
+ end
35
+ end
36
+
37
+ def fomrat_hash_layer_data(read_data, layer, file)
38
+ convert_to_hash(read_data, file)
39
+ .reject { |key, _| SUB_LAYER_KEYS[layer]&.include?(key) }
26
40
  end
27
41
 
28
- def format_next_layer_data(layer, input_data, read_data, file)
29
- LAYER_MAP[layer]&.each do |key, next_layer|
30
- Array(read_data[key]).each do |data|
31
- format_data(
32
- next_layer, input_data.child(next_layer), data, file
33
- )
42
+ def format_sub_layer_data(read_data, layer, file)
43
+ if read_data.is_a?(Array)
44
+ format_array_sub_layer_data(read_data, layer, file)
45
+ else
46
+ format_hash_sub_layer_data(read_data, layer, file)
47
+ end
48
+ end
49
+
50
+ def format_array_sub_layer_data(read_data, layer, file)
51
+ read_data.each_with_object({}) do |data, sub_layer_data|
52
+ format_hash_sub_layer_data(data, layer, file, sub_layer_data)
53
+ end
54
+ end
55
+
56
+ def format_hash_sub_layer_data(read_data, layer, file, sub_layer_data = {})
57
+ convert_to_hash(read_data, file)
58
+ .select { |key, _| SUB_LAYER_KEYS[layer]&.include?(key) }
59
+ .each do |key, value|
60
+ merge_sub_layer_data(sub_layer_data, layer, key, value)
34
61
  end
62
+ sub_layer_data
63
+ end
64
+
65
+ def merge_sub_layer_data(sub_layer_data, layer, key, value)
66
+ if SUB_LAYER_KEY_MAP[layer].key?(key)
67
+ (sub_layer_data[SUB_LAYER_KEY_MAP[layer][key]] ||= []).concat(value)
68
+ else
69
+ (sub_layer_data[key] ||= []) << value
35
70
  end
36
71
  end
72
+
73
+ def convert_to_hash(read_data, file)
74
+ Hash(read_data)
75
+ rescue TypeError => e
76
+ raise Core::LoadError.new(e.message, file)
77
+ end
37
78
  end
38
79
  end
39
80
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module RegisterMap
6
+ class TOMLLoader < Loader
7
+ include HashLoader
8
+ include InputBase::TOMLLoader
9
+
10
+ support_types [:toml]
11
+
12
+ def read_file(file)
13
+ load_toml(file)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -24,6 +24,11 @@ module RgGen
24
24
  end
25
25
  end
26
26
  end
27
+
28
+ def inherited(subclass)
29
+ super
30
+ export_instance_variable(:@attributes, subclass, &:dup)
31
+ end
27
32
  end
28
33
 
29
34
  def self.included(class_or_module)
@@ -4,14 +4,41 @@ module RgGen
4
4
  module Core
5
5
  module Utility
6
6
  module ErrorUtility
7
- module_function
7
+ class MessageComposer
8
+ def compose(error, verbose, backtrace)
9
+ lines = []
10
+ add_basic_info(error, lines)
11
+ add_verbose_info(error, lines) if verbose
12
+ add_backtrace(error, lines) if backtrace
13
+ lines.join("\n")
14
+ end
15
+
16
+ private
17
+
18
+ def add_basic_info(error, lines)
19
+ lines << "[#{error.class.lastname}] #{error}"
20
+ end
21
+
22
+ def add_verbose_info(error, lines)
23
+ return unless error.respond_to?(:verbose_info)
24
+ return unless error.verbose_info
25
+
26
+ lines << 'verbose information:'
27
+ error
28
+ .verbose_info.lines(chomp: true)
29
+ .each { |info| lines << " #{info}" }
30
+ end
8
31
 
9
- def compose_error_message(error, verbose)
10
- lines = []
11
- lines << "[#{error.class.lastname}] #{error.message}"
12
- verbose &&
32
+ def add_backtrace(error, lines)
33
+ lines << 'backtrace:'
13
34
  error.backtrace.each { |trace| lines << " #{trace}" }
14
- lines.join("\n")
35
+ end
36
+ end
37
+
38
+ module_function
39
+
40
+ def compose_error_message(error, verbose, backtrace)
41
+ MessageComposer.new.compose(error, verbose, backtrace)
15
42
  end
16
43
  end
17
44
  end