rggen-core 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/CODE_OF_CONDUCT.md +46 -0
  3. data/LICENSE +21 -0
  4. data/README.md +46 -0
  5. data/exe/rggen +13 -0
  6. data/lib/rggen/core.rb +101 -0
  7. data/lib/rggen/core/base/component.rb +54 -0
  8. data/lib/rggen/core/base/component_factory.rb +84 -0
  9. data/lib/rggen/core/base/feature.rb +46 -0
  10. data/lib/rggen/core/base/feature_factory.rb +37 -0
  11. data/lib/rggen/core/base/hierarchical_accessors.rb +91 -0
  12. data/lib/rggen/core/base/hierarchical_feature_accessors.rb +83 -0
  13. data/lib/rggen/core/base/internal_struct.rb +21 -0
  14. data/lib/rggen/core/base/shared_context.rb +18 -0
  15. data/lib/rggen/core/builder.rb +13 -0
  16. data/lib/rggen/core/builder/builder.rb +150 -0
  17. data/lib/rggen/core/builder/category.rb +116 -0
  18. data/lib/rggen/core/builder/component_entry.rb +29 -0
  19. data/lib/rggen/core/builder/component_registry.rb +47 -0
  20. data/lib/rggen/core/builder/feature_registry.rb +126 -0
  21. data/lib/rggen/core/builder/input_component_registry.rb +35 -0
  22. data/lib/rggen/core/builder/list_feature_entry.rb +98 -0
  23. data/lib/rggen/core/builder/output_component_registry.rb +10 -0
  24. data/lib/rggen/core/builder/simple_feature_entry.rb +39 -0
  25. data/lib/rggen/core/cli.rb +29 -0
  26. data/lib/rggen/core/configuration.rb +19 -0
  27. data/lib/rggen/core/configuration/component.rb +10 -0
  28. data/lib/rggen/core/configuration/component_factory.rb +19 -0
  29. data/lib/rggen/core/configuration/error.rb +16 -0
  30. data/lib/rggen/core/configuration/feature.rb +13 -0
  31. data/lib/rggen/core/configuration/feature_factory.rb +11 -0
  32. data/lib/rggen/core/configuration/hash_loader.rb +15 -0
  33. data/lib/rggen/core/configuration/json_loader.rb +18 -0
  34. data/lib/rggen/core/configuration/loader.rb +11 -0
  35. data/lib/rggen/core/configuration/ruby_loader.rb +15 -0
  36. data/lib/rggen/core/configuration/yaml_loader.rb +18 -0
  37. data/lib/rggen/core/core_extensions/casecmp.rb +12 -0
  38. data/lib/rggen/core/core_extensions/forwardable.rb +12 -0
  39. data/lib/rggen/core/core_extensions/forwardable_workaround.rb +22 -0
  40. data/lib/rggen/core/core_extensions/object.rb +14 -0
  41. data/lib/rggen/core/dsl.rb +30 -0
  42. data/lib/rggen/core/exceptions.rb +29 -0
  43. data/lib/rggen/core/facets.rb +7 -0
  44. data/lib/rggen/core/generator.rb +51 -0
  45. data/lib/rggen/core/input_base/component.rb +30 -0
  46. data/lib/rggen/core/input_base/component_factory.rb +88 -0
  47. data/lib/rggen/core/input_base/feature.rb +130 -0
  48. data/lib/rggen/core/input_base/feature_factory.rb +80 -0
  49. data/lib/rggen/core/input_base/input_data.rb +98 -0
  50. data/lib/rggen/core/input_base/input_matcher.rb +79 -0
  51. data/lib/rggen/core/input_base/input_value.rb +34 -0
  52. data/lib/rggen/core/input_base/json_loader.rb +16 -0
  53. data/lib/rggen/core/input_base/loader.rb +44 -0
  54. data/lib/rggen/core/input_base/property.rb +76 -0
  55. data/lib/rggen/core/input_base/verifier.rb +41 -0
  56. data/lib/rggen/core/input_base/yaml_loader.rb +34 -0
  57. data/lib/rggen/core/options.rb +181 -0
  58. data/lib/rggen/core/output_base/code_generator.rb +59 -0
  59. data/lib/rggen/core/output_base/component.rb +100 -0
  60. data/lib/rggen/core/output_base/component_factory.rb +35 -0
  61. data/lib/rggen/core/output_base/erb_engine.rb +21 -0
  62. data/lib/rggen/core/output_base/feature.rb +147 -0
  63. data/lib/rggen/core/output_base/feature_factory.rb +13 -0
  64. data/lib/rggen/core/output_base/file_writer.rb +40 -0
  65. data/lib/rggen/core/output_base/template_engine.rb +27 -0
  66. data/lib/rggen/core/printers.rb +53 -0
  67. data/lib/rggen/core/register_map.rb +21 -0
  68. data/lib/rggen/core/register_map/component.rb +20 -0
  69. data/lib/rggen/core/register_map/component_factory.rb +19 -0
  70. data/lib/rggen/core/register_map/error.rb +16 -0
  71. data/lib/rggen/core/register_map/feature.rb +22 -0
  72. data/lib/rggen/core/register_map/feature_factory.rb +11 -0
  73. data/lib/rggen/core/register_map/hash_loader.rb +47 -0
  74. data/lib/rggen/core/register_map/input_data.rb +34 -0
  75. data/lib/rggen/core/register_map/json_loader.rb +18 -0
  76. data/lib/rggen/core/register_map/loader.rb +15 -0
  77. data/lib/rggen/core/register_map/ruby_loader.rb +15 -0
  78. data/lib/rggen/core/register_map/yaml_loader.rb +18 -0
  79. data/lib/rggen/core/utility/attribute_setter.rb +53 -0
  80. data/lib/rggen/core/utility/code_utility.rb +64 -0
  81. data/lib/rggen/core/utility/code_utility/code_block.rb +88 -0
  82. data/lib/rggen/core/utility/code_utility/line.rb +51 -0
  83. data/lib/rggen/core/utility/code_utility/source_file.rb +104 -0
  84. data/lib/rggen/core/utility/code_utility/structure_definition.rb +54 -0
  85. data/lib/rggen/core/utility/regexp_patterns.rb +38 -0
  86. data/lib/rggen/core/version.rb +10 -0
  87. metadata +188 -0
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module RegisterMap
6
+ class FeatureFactory < InputBase::FeatureFactory
7
+ include RaiseError
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module RegisterMap
6
+ module HashLoader
7
+ def format(read_data, file)
8
+ format_data(:register_map, register_map, read_data, file)
9
+ rescue TypeError => e
10
+ raise Core::LoadError.new(e.message, file)
11
+ end
12
+
13
+ private
14
+
15
+ CHILD_HIERARCHY = {
16
+ register_map: :register_block,
17
+ register_block: :register,
18
+ register: :bit_field
19
+ }.freeze
20
+
21
+ CHILD_HIERARCHY_KEY = {
22
+ register_map: :register_blocks,
23
+ register_block: :registers,
24
+ register: :bit_fields
25
+ }.freeze
26
+
27
+ def format_data(hierarchy, input_data, read_data, file)
28
+ read_data = Hash(read_data)
29
+ input_data.values(read_data, file)
30
+ read_data_for_child(hierarchy, read_data).each do |data|
31
+ format_data(
32
+ CHILD_HIERARCHY[hierarchy],
33
+ input_data.child,
34
+ data,
35
+ file
36
+ )
37
+ end
38
+ end
39
+
40
+ def read_data_for_child(hierarchy, read_data)
41
+ key = CHILD_HIERARCHY_KEY[hierarchy]
42
+ Array(key && read_data[key])
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module RegisterMap
6
+ class BitFieldData < InputBase::InputData
7
+ end
8
+
9
+ class RegisterData < InputBase::InputData
10
+ alias_method :bit_field, :child
11
+
12
+ def child_data_class
13
+ BitFieldData
14
+ end
15
+ end
16
+
17
+ class RegisterBlockData < InputBase::InputData
18
+ alias_method :register, :child
19
+
20
+ def child_data_class
21
+ RegisterData
22
+ end
23
+ end
24
+
25
+ class RegisterMapData < InputBase::InputData
26
+ alias_method :register_block, :child
27
+
28
+ def child_data_class
29
+ RegisterBlockData
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module RegisterMap
6
+ class JSONLoader < Loader
7
+ include HashLoader
8
+ include InputBase::JSONLoader
9
+
10
+ support_types [:json]
11
+
12
+ def read_file(file)
13
+ load_json(file)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module RegisterMap
6
+ class Loader < InputBase::Loader
7
+ private
8
+
9
+ def register_map
10
+ input_data
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module RegisterMap
6
+ class RubyLoader < Loader
7
+ support_types [:rb]
8
+
9
+ def read_file(file)
10
+ register_map.load_file(file)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module RegisterMap
6
+ class YAMLLoader < Loader
7
+ include HashLoader
8
+ include InputBase::YAMLLoader
9
+
10
+ support_types [:yaml, :yml]
11
+
12
+ def read_file(file)
13
+ load_yaml(file)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Utility
6
+ module AttributeSetter
7
+ module Extension
8
+ def attributes
9
+ @attributes ||= []
10
+ end
11
+
12
+ private
13
+
14
+ DEFAULT_VALUE = Object.new.freeze
15
+
16
+ def define_attribute(name, default_value = nil)
17
+ attributes << name.to_sym
18
+ variable_name = "@#{name}"
19
+ define_method(name) do |value = DEFAULT_VALUE|
20
+ if value.equal?(DEFAULT_VALUE)
21
+ attribute_value_get(variable_name, default_value)
22
+ else
23
+ instance_variable_set(variable_name, value)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def self.included(class_or_module)
30
+ class_or_module.extend(Extension)
31
+ end
32
+
33
+ def apply_attributes(**attributes)
34
+ attributes.each do |name, value|
35
+ __send__(name, value) if self.class.attributes.include?(name)
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def attribute_value_get(variable_name, default_value)
42
+ if instance_variable_defined?(variable_name)
43
+ instance_variable_get(variable_name)
44
+ elsif default_value.is_a?(Proc)
45
+ instance_exec(&default_value)
46
+ else
47
+ default_value
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Utility
6
+ module CodeUtility
7
+ def create_blank_code
8
+ code_block
9
+ end
10
+
11
+ private
12
+
13
+ def newline
14
+ "\n"
15
+ end
16
+
17
+ alias_method :nl, :newline
18
+
19
+ def comma
20
+ ','
21
+ end
22
+
23
+ def colon
24
+ ':'
25
+ end
26
+
27
+ def semicolon
28
+ ';'
29
+ end
30
+
31
+ def space(size = 1)
32
+ ' ' * size
33
+ end
34
+
35
+ def string(expression)
36
+ "\"#{expression}\""
37
+ end
38
+
39
+ def code_block(indent = 0, &body)
40
+ CodeBlock.new(indent, &body)
41
+ end
42
+
43
+ def indent(code, indent_size)
44
+ code << nl unless code.last_line_empty?
45
+ code.indent += indent_size
46
+ block_given? && yield(code)
47
+ code << nl unless code.last_line_empty?
48
+ code.indent -= indent_size
49
+ end
50
+
51
+ def wrap(code, head, tail)
52
+ code << head
53
+ block_given? && yield(code)
54
+ code << tail
55
+ end
56
+
57
+ def loop_index(level = 1)
58
+ return '' unless level.positive?
59
+ (1...level).inject(+'i') { |index, _| index.next! }
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Utility
6
+ module CodeUtility
7
+ class CodeBlock
8
+ def initialize(indent = 0)
9
+ @indent = indent
10
+ @lines = []
11
+ add_line
12
+ block_given? && yield(self)
13
+ end
14
+
15
+ attr_reader :indent
16
+
17
+ def <<(rhs)
18
+ return push_string(rhs) if rhs.is_a?(String)
19
+ return push_code_block(rhs) if rhs.is_a?(CodeBlock)
20
+ return rhs.inject(self, :<<) if rhs.is_a?(Array)
21
+ return self << rhs.to_code if rhs.respond_to?(:to_code)
22
+ push_word(rhs)
23
+ end
24
+
25
+ def indent=(indent)
26
+ @indent = indent
27
+ last_line.indent = indent
28
+ end
29
+
30
+ def last_line_empty?
31
+ last_line.empty?
32
+ end
33
+
34
+ def to_s
35
+ @lines.map(&:to_s).each(&:rstrip!).join(newline)
36
+ end
37
+
38
+ def eval_block(&block)
39
+ return unless block_given?
40
+ block.arity.zero? ? self << yield : yield(self)
41
+ end
42
+
43
+ private
44
+
45
+ def add_line
46
+ line = Line.new(@indent)
47
+ @lines << line
48
+ end
49
+
50
+ def push_string(rhs)
51
+ rhs += newline if rhs.end_with?(newline)
52
+ rhs.each_line.with_index do |line, i|
53
+ i.positive? && add_line
54
+ push_word(line.chomp)
55
+ end
56
+ self
57
+ end
58
+
59
+ def push_code_block(rhs)
60
+ rhs.lines.each_with_index do |line, i|
61
+ i.positive? && add_line
62
+ line.empty? || (last_line.indent += line.indent)
63
+ last_line.concat(line)
64
+ end
65
+ self
66
+ end
67
+
68
+ def last_line
69
+ @lines.last
70
+ end
71
+
72
+ def push_word(word)
73
+ last_line << word
74
+ self
75
+ end
76
+
77
+ def newline
78
+ "\n"
79
+ end
80
+
81
+ protected
82
+
83
+ attr_reader :lines
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Utility
6
+ module CodeUtility
7
+ class Line
8
+ def initialize(indent = 0)
9
+ @indent = indent
10
+ @words = []
11
+ end
12
+
13
+ attr_reader :indent
14
+
15
+ def indent=(indent)
16
+ empty? && (@indent = indent)
17
+ end
18
+
19
+ def <<(word)
20
+ @words << word
21
+ self
22
+ end
23
+
24
+ def concat(line)
25
+ @words.concat(line.words)
26
+ end
27
+
28
+ def empty?
29
+ @words.all?(&method(:empty_word?))
30
+ end
31
+
32
+ def to_s
33
+ [' ' * (@indent || 0), *@words].join
34
+ end
35
+
36
+ private
37
+
38
+ def empty_word?(word)
39
+ return true if word.nil?
40
+ return false unless word.respond_to?(:empty?)
41
+ word.empty?
42
+ end
43
+
44
+ protected
45
+
46
+ attr_reader :words
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module Core
5
+ module Utility
6
+ module CodeUtility
7
+ class SourceFile
8
+ include CodeUtility
9
+
10
+ class << self
11
+ attr_setter :ifndef_keyword
12
+ attr_setter :endif_keyword
13
+ attr_setter :define_keyword
14
+ attr_setter :include_keyword
15
+ end
16
+
17
+ def initialize(file_path)
18
+ @file_path = file_path
19
+ block_given? && yield(self)
20
+ end
21
+
22
+ attr_reader :file_path
23
+
24
+ def header(&block)
25
+ @file_header = -> { block.call(@file_path) }
26
+ end
27
+
28
+ def include_guard
29
+ @guard_macro =
30
+ if block_given?
31
+ yield(default_guard_macro)
32
+ else
33
+ default_guard_macro
34
+ end
35
+ end
36
+
37
+ def include_files(files)
38
+ @include_files ||= []
39
+ @include_files.concat(Array(files))
40
+ end
41
+
42
+ def include_file(file)
43
+ include_files([file])
44
+ end
45
+
46
+ def body(&block)
47
+ @bodies ||= []
48
+ @bodies << block
49
+ end
50
+
51
+ def to_code
52
+ CodeBlock.new do |code|
53
+ code_blocks.each { |block| execute_code_block(code, block, true) }
54
+ end
55
+ end
56
+
57
+ def to_s
58
+ to_code.to_s
59
+ end
60
+
61
+ private
62
+
63
+ def code_blocks
64
+ [
65
+ @file_header,
66
+ include_guard_header,
67
+ include_file_block,
68
+ *Array(@bodies),
69
+ include_guard_footer
70
+ ].compact
71
+ end
72
+
73
+ def execute_code_block(code, code_block, insert_newline)
74
+ code.eval_block(&code_block)
75
+ code << nl if insert_newline && !code.last_line_empty?
76
+ end
77
+
78
+ def default_guard_macro
79
+ File.basename(file_path).upcase.gsub(/\W/, '_')
80
+ end
81
+
82
+ def include_guard_header
83
+ @guard_macro && lambda do
84
+ [self.class.ifndef_keyword, self.class.define_keyword]
85
+ .flat_map { |keyword| [keyword, space, @guard_macro, nl] }
86
+ end
87
+ end
88
+
89
+ def include_file_block
90
+ @include_files && lambda do
91
+ keyword = self.class.include_keyword
92
+ @include_files
93
+ .flat_map { |file| [keyword, space, string(file), nl] }
94
+ end
95
+ end
96
+
97
+ def include_guard_footer
98
+ @guard_macro && (-> { self.class.endif_keyword })
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end