expressir 2.2.1 → 2.3.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 (190) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.rubocop_todo.yml +253 -81
  4. data/Gemfile +4 -1
  5. data/README.adoc +63 -26
  6. data/benchmark/srl_benchmark.rb +386 -0
  7. data/benchmark/srl_native_benchmark.rb +142 -0
  8. data/benchmark/srl_ruby_benchmark.rb +130 -0
  9. data/expressir.gemspec +3 -2
  10. data/lib/expressir/benchmark.rb +1 -1
  11. data/lib/expressir/changes/item_change.rb +0 -1
  12. data/lib/expressir/changes/mapping_change.rb +0 -1
  13. data/lib/expressir/changes/schema_change.rb +0 -2
  14. data/lib/expressir/changes/version_change.rb +0 -3
  15. data/lib/expressir/changes.rb +5 -6
  16. data/lib/expressir/cli.rb +10 -24
  17. data/lib/expressir/commands/changes.rb +0 -2
  18. data/lib/expressir/commands/changes_import_eengine.rb +0 -3
  19. data/lib/expressir/commands/changes_validate.rb +0 -2
  20. data/lib/expressir/commands/format.rb +1 -1
  21. data/lib/expressir/commands/manifest.rb +0 -7
  22. data/lib/expressir/commands/package.rb +16 -29
  23. data/lib/expressir/commands/validate.rb +0 -2
  24. data/lib/expressir/commands/validate_load.rb +1 -1
  25. data/lib/expressir/commands.rb +20 -0
  26. data/lib/expressir/config.rb +0 -2
  27. data/lib/expressir/coverage.rb +11 -4
  28. data/lib/expressir/eengine/arm_compare_report.rb +1 -4
  29. data/lib/expressir/eengine/changes_section.rb +1 -3
  30. data/lib/expressir/eengine/compare_report.rb +1 -13
  31. data/lib/expressir/eengine/mim_compare_report.rb +1 -4
  32. data/lib/expressir/eengine/modified_object.rb +1 -2
  33. data/lib/expressir/eengine.rb +9 -0
  34. data/lib/expressir/errors.rb +3 -5
  35. data/lib/expressir/express/builder.rb +22 -7
  36. data/lib/expressir/express/builder_registry.rb +411 -0
  37. data/lib/expressir/express/builders/attribute_decl_builder.rb +0 -6
  38. data/lib/expressir/express/builders/built_in_builder.rb +1 -16
  39. data/lib/expressir/express/builders/constant_builder.rb +4 -19
  40. data/lib/expressir/express/builders/declaration_builder.rb +0 -4
  41. data/lib/expressir/express/builders/derive_clause_builder.rb +0 -2
  42. data/lib/expressir/express/builders/derived_attr_builder.rb +0 -2
  43. data/lib/expressir/express/builders/domain_rule_builder.rb +0 -2
  44. data/lib/expressir/express/builders/entity_decl_builder.rb +7 -13
  45. data/lib/expressir/express/builders/explicit_attr_builder.rb +5 -8
  46. data/lib/expressir/express/builders/expression_builder.rb +31 -67
  47. data/lib/expressir/express/builders/function_decl_builder.rb +20 -18
  48. data/lib/expressir/express/builders/interface_builder.rb +0 -20
  49. data/lib/expressir/express/builders/inverse_attr_builder.rb +0 -2
  50. data/lib/expressir/express/builders/inverse_attr_type_builder.rb +0 -6
  51. data/lib/expressir/express/builders/inverse_clause_builder.rb +0 -2
  52. data/lib/expressir/express/builders/literal_builder.rb +1 -15
  53. data/lib/expressir/express/builders/procedure_decl_builder.rb +20 -19
  54. data/lib/expressir/express/builders/qualifier_builder.rb +0 -27
  55. data/lib/expressir/express/builders/reference_builder.rb +1 -10
  56. data/lib/expressir/express/builders/rule_decl_builder.rb +21 -19
  57. data/lib/expressir/express/builders/schema_body_decl_builder.rb +0 -4
  58. data/lib/expressir/express/builders/schema_decl_builder.rb +7 -13
  59. data/lib/expressir/express/builders/schema_version_builder.rb +0 -6
  60. data/lib/expressir/express/builders/simple_id_builder.rb +1 -10
  61. data/lib/expressir/express/builders/statement_builder.rb +4 -32
  62. data/lib/expressir/express/builders/subtype_constraint_builder.rb +6 -30
  63. data/lib/expressir/express/builders/syntax_builder.rb +60 -7
  64. data/lib/expressir/express/builders/type_builder.rb +3 -45
  65. data/lib/expressir/express/builders/type_decl_builder.rb +1 -7
  66. data/lib/expressir/express/builders/unique_clause_builder.rb +1 -3
  67. data/lib/expressir/express/builders/unique_rule_builder.rb +0 -2
  68. data/lib/expressir/express/builders/where_clause_builder.rb +1 -3
  69. data/lib/expressir/express/builders.rb +47 -35
  70. data/lib/expressir/express/error.rb +0 -3
  71. data/lib/expressir/express/formatter.rb +17 -19
  72. data/lib/expressir/express/formatters/data_types_formatter.rb +295 -293
  73. data/lib/expressir/express/formatters/declarations_formatter.rb +617 -615
  74. data/lib/expressir/express/formatters/expressions_formatter.rb +146 -144
  75. data/lib/expressir/express/formatters/literals_formatter.rb +35 -33
  76. data/lib/expressir/express/formatters/references_formatter.rb +34 -32
  77. data/lib/expressir/express/formatters/remark_formatter.rb +176 -209
  78. data/lib/expressir/express/formatters/remark_item_formatter.rb +18 -16
  79. data/lib/expressir/express/formatters/statements_formatter.rb +190 -188
  80. data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +41 -39
  81. data/lib/expressir/express/formatters.rb +22 -0
  82. data/lib/expressir/express/parser.rb +40 -41
  83. data/lib/expressir/express/pretty_formatter.rb +68 -47
  84. data/lib/expressir/express/remark_attacher.rb +210 -147
  85. data/lib/expressir/express/streaming_builder.rb +0 -3
  86. data/lib/expressir/express/transformer/remark_handling.rb +1 -2
  87. data/lib/expressir/express.rb +29 -0
  88. data/lib/expressir/manifest/resolver.rb +0 -3
  89. data/lib/expressir/manifest/validator.rb +0 -3
  90. data/lib/expressir/manifest.rb +6 -0
  91. data/lib/expressir/model/cache.rb +1 -1
  92. data/lib/expressir/model/concerns.rb +19 -0
  93. data/lib/expressir/model/data_types/aggregate.rb +1 -1
  94. data/lib/expressir/model/data_types/array.rb +1 -1
  95. data/lib/expressir/model/data_types/bag.rb +1 -1
  96. data/lib/expressir/model/data_types/binary.rb +1 -1
  97. data/lib/expressir/model/data_types/boolean.rb +1 -1
  98. data/lib/expressir/model/data_types/enumeration.rb +1 -1
  99. data/lib/expressir/model/data_types/enumeration_item.rb +1 -1
  100. data/lib/expressir/model/data_types/generic.rb +1 -1
  101. data/lib/expressir/model/data_types/generic_entity.rb +1 -1
  102. data/lib/expressir/model/data_types/integer.rb +1 -1
  103. data/lib/expressir/model/data_types/list.rb +1 -1
  104. data/lib/expressir/model/data_types/logical.rb +1 -1
  105. data/lib/expressir/model/data_types/number.rb +1 -1
  106. data/lib/expressir/model/data_types/real.rb +1 -1
  107. data/lib/expressir/model/data_types/select.rb +1 -1
  108. data/lib/expressir/model/data_types/set.rb +1 -1
  109. data/lib/expressir/model/data_types/string.rb +1 -1
  110. data/lib/expressir/model/data_types.rb +25 -0
  111. data/lib/expressir/model/declarations/attribute.rb +1 -1
  112. data/lib/expressir/model/declarations/constant.rb +1 -1
  113. data/lib/expressir/model/declarations/derived_attribute.rb +1 -1
  114. data/lib/expressir/model/declarations/entity.rb +4 -1
  115. data/lib/expressir/model/declarations/function.rb +3 -1
  116. data/lib/expressir/model/declarations/informal_proposition_rule.rb +2 -1
  117. data/lib/expressir/model/declarations/interface.rb +1 -1
  118. data/lib/expressir/model/declarations/interface_item.rb +1 -1
  119. data/lib/expressir/model/declarations/interfaced_item.rb +1 -1
  120. data/lib/expressir/model/declarations/inverse_attribute.rb +1 -1
  121. data/lib/expressir/model/declarations/parameter.rb +1 -1
  122. data/lib/expressir/model/declarations/procedure.rb +3 -1
  123. data/lib/expressir/model/declarations/remark_item.rb +1 -1
  124. data/lib/expressir/model/declarations/rule.rb +4 -1
  125. data/lib/expressir/model/declarations/schema.rb +2 -1
  126. data/lib/expressir/model/declarations/schema_version.rb +1 -1
  127. data/lib/expressir/model/declarations/schema_version_item.rb +1 -1
  128. data/lib/expressir/model/declarations/subtype_constraint.rb +1 -1
  129. data/lib/expressir/model/declarations/type.rb +4 -1
  130. data/lib/expressir/model/declarations/unique_rule.rb +1 -1
  131. data/lib/expressir/model/declarations/variable.rb +1 -1
  132. data/lib/expressir/model/declarations/where_rule.rb +1 -1
  133. data/lib/expressir/model/declarations.rb +31 -0
  134. data/lib/expressir/model/dependency_resolver.rb +0 -2
  135. data/lib/expressir/model/exp_file.rb +38 -0
  136. data/lib/expressir/model/expressions/aggregate_initializer.rb +1 -1
  137. data/lib/expressir/model/expressions/aggregate_initializer_item.rb +1 -1
  138. data/lib/expressir/model/expressions/binary_expression.rb +1 -1
  139. data/lib/expressir/model/expressions/entity_constructor.rb +1 -1
  140. data/lib/expressir/model/expressions/function_call.rb +1 -1
  141. data/lib/expressir/model/expressions/interval.rb +1 -1
  142. data/lib/expressir/model/expressions/query_expression.rb +1 -1
  143. data/lib/expressir/model/expressions/unary_expression.rb +1 -1
  144. data/lib/expressir/model/expressions.rb +18 -0
  145. data/lib/expressir/model/identifier.rb +5 -1
  146. data/lib/expressir/model/indexes.rb +11 -0
  147. data/lib/expressir/model/literals/binary.rb +1 -1
  148. data/lib/expressir/model/literals/integer.rb +1 -1
  149. data/lib/expressir/model/literals/logical.rb +1 -1
  150. data/lib/expressir/model/literals/real.rb +1 -1
  151. data/lib/expressir/model/literals/string.rb +1 -1
  152. data/lib/expressir/model/literals.rb +13 -0
  153. data/lib/expressir/model/model_element.rb +7 -15
  154. data/lib/expressir/model/references/attribute_reference.rb +1 -1
  155. data/lib/expressir/model/references/group_reference.rb +1 -1
  156. data/lib/expressir/model/references/index_reference.rb +1 -1
  157. data/lib/expressir/model/references/simple_reference.rb +1 -1
  158. data/lib/expressir/model/references.rb +12 -0
  159. data/lib/expressir/model/remark_info.rb +1 -7
  160. data/lib/expressir/model/repository.rb +72 -36
  161. data/lib/expressir/model/repository_validator.rb +0 -2
  162. data/lib/expressir/model/search_engine.rb +6 -30
  163. data/lib/expressir/model/statements/alias.rb +1 -1
  164. data/lib/expressir/model/statements/assignment.rb +1 -1
  165. data/lib/expressir/model/statements/case.rb +1 -1
  166. data/lib/expressir/model/statements/case_action.rb +1 -1
  167. data/lib/expressir/model/statements/compound.rb +1 -1
  168. data/lib/expressir/model/statements/escape.rb +1 -1
  169. data/lib/expressir/model/statements/if.rb +1 -1
  170. data/lib/expressir/model/statements/null.rb +1 -1
  171. data/lib/expressir/model/statements/procedure_call.rb +1 -1
  172. data/lib/expressir/model/statements/repeat.rb +1 -1
  173. data/lib/expressir/model/statements/return.rb +1 -1
  174. data/lib/expressir/model/statements/skip.rb +1 -1
  175. data/lib/expressir/model/statements.rb +20 -0
  176. data/lib/expressir/model/supertype_expressions/binary_supertype_expression.rb +1 -1
  177. data/lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb +1 -1
  178. data/lib/expressir/model/supertype_expressions.rb +12 -0
  179. data/lib/expressir/model.rb +28 -4
  180. data/lib/expressir/package/builder.rb +33 -4
  181. data/lib/expressir/package/metadata.rb +0 -1
  182. data/lib/expressir/package/reader.rb +0 -1
  183. data/lib/expressir/package.rb +8 -0
  184. data/lib/expressir/schema_manifest.rb +5 -6
  185. data/lib/expressir/schema_manifest_entry.rb +3 -4
  186. data/lib/expressir/transformer.rb +7 -0
  187. data/lib/expressir/version.rb +1 -1
  188. data/lib/expressir.rb +23 -171
  189. metadata +49 -9
  190. data/lib/expressir/express/builders/token_builder.rb +0 -15
@@ -12,7 +12,7 @@ module Expressir
12
12
  attribute :item, ModelElement
13
13
  attribute :operator2, :string, values: %w[LESS_THAN LESS_THAN_OR_EQUAL]
14
14
  attribute :high, ModelElement
15
- attribute :_class, :string, default: -> { send(:name) }
15
+ attribute :_class, :string, default: -> { self.class.name }
16
16
 
17
17
  key_value do
18
18
  map "_class", to: :_class, render_default: true
@@ -8,7 +8,7 @@ module Expressir
8
8
 
9
9
  attribute :aggregate_source, ModelElement
10
10
  attribute :expression, ModelElement
11
- attribute :_class, :string, default: -> { send(:name) }
11
+ attribute :_class, :string, default: -> { self.class.name }
12
12
 
13
13
  key_value do
14
14
  map "_class", to: :_class, render_default: true
@@ -11,7 +11,7 @@ module Expressir
11
11
 
12
12
  attribute :operator, :string, values: %w[MINUS NOT PLUS]
13
13
  attribute :operand, ModelElement
14
- attribute :_class, :string, default: -> { send(:name) }
14
+ attribute :_class, :string, default: -> { self.class.name }
15
15
 
16
16
  key_value do
17
17
  map "_class", to: :_class, render_default: true
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Model
5
+ module Expressions
6
+ autoload :AggregateInitializer,
7
+ "#{__dir__}/expressions/aggregate_initializer"
8
+ autoload :AggregateInitializerItem,
9
+ "#{__dir__}/expressions/aggregate_initializer_item"
10
+ autoload :BinaryExpression, "#{__dir__}/expressions/binary_expression"
11
+ autoload :EntityConstructor, "#{__dir__}/expressions/entity_constructor"
12
+ autoload :FunctionCall, "#{__dir__}/expressions/function_call"
13
+ autoload :Interval, "#{__dir__}/expressions/interval"
14
+ autoload :QueryExpression, "#{__dir__}/expressions/query_expression"
15
+ autoload :UnaryExpression, "#{__dir__}/expressions/unary_expression"
16
+ end
17
+ end
18
+ end
@@ -2,11 +2,15 @@ module Expressir
2
2
  module Model
3
3
  module Identifier
4
4
  def self.included(mod)
5
+ # Auto-include marker - all Identifier types can have remark_items
6
+ mod.include(HasRemarkItems)
7
+
5
8
  mod.attribute :id, :string
6
9
  mod.attribute :remarks, :string, collection: true
7
10
  mod.attribute :remark_items,
8
11
  ::Expressir::Model::Declarations::RemarkItem, collection: true
9
- mod.attribute :untagged_remarks, ::Expressir::Model::RemarkInfo, collection: true
12
+ mod.attribute :untagged_remarks, ::Expressir::Model::RemarkInfo,
13
+ collection: true
10
14
 
11
15
  mod.key_value do
12
16
  map "id", to: :id
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Model
5
+ module Indexes
6
+ autoload :EntityIndex, "#{__dir__}/indexes/entity_index"
7
+ autoload :TypeIndex, "#{__dir__}/indexes/type_index"
8
+ autoload :ReferenceIndex, "#{__dir__}/indexes/reference_index"
9
+ end
10
+ end
11
+ end
@@ -5,7 +5,7 @@ module Expressir
5
5
  # - section 7.5.1 Binary literal
6
6
  class Binary < ModelElement
7
7
  attribute :value, :string
8
- attribute :_class, :string, default: -> { send(:name) }
8
+ attribute :_class, :string, default: -> { self.class.name }
9
9
 
10
10
  key_value do
11
11
  map "_class", to: :_class, render_default: true
@@ -5,7 +5,7 @@ module Expressir
5
5
  # - section 7.5.2 Integer literal
6
6
  class Integer < ModelElement
7
7
  attribute :value, :string
8
- attribute :_class, :string, default: -> { send(:name) }
8
+ attribute :_class, :string, default: -> { self.class.name }
9
9
 
10
10
  key_value do
11
11
  map "_class", to: :_class, render_default: true
@@ -9,7 +9,7 @@ module Expressir
9
9
  UNKNOWN = "UNKNOWN".freeze
10
10
 
11
11
  attribute :value, :string, values: %w[TRUE FALSE UNKNOWN]
12
- attribute :_class, :string, default: -> { send(:name) }
12
+ attribute :_class, :string, default: -> { self.class.name }
13
13
 
14
14
  key_value do
15
15
  map "_class", to: :_class, render_default: true
@@ -5,7 +5,7 @@ module Expressir
5
5
  # - section 7.5.3 Real literal
6
6
  class Real < ModelElement
7
7
  attribute :value, :string
8
- attribute :_class, :string, default: -> { send(:name) }
8
+ attribute :_class, :string, default: -> { self.class.name }
9
9
 
10
10
  key_value do
11
11
  map "_class", to: :_class, render_default: true
@@ -6,7 +6,7 @@ module Expressir
6
6
  class String < ModelElement
7
7
  attribute :value, :string
8
8
  attribute :encoded, :boolean
9
- attribute :_class, :string, default: -> { send(:name) }
9
+ attribute :_class, :string, default: -> { self.class.name }
10
10
 
11
11
  key_value do
12
12
  map "_class", to: :_class, render_default: true
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Model
5
+ module Literals
6
+ autoload :Binary, "#{__dir__}/literals/binary"
7
+ autoload :Integer, "#{__dir__}/literals/integer"
8
+ autoload :Logical, "#{__dir__}/literals/logical"
9
+ autoload :Real, "#{__dir__}/literals/real"
10
+ autoload :String, "#{__dir__}/literals/string"
11
+ end
12
+ end
13
+ end
@@ -10,7 +10,7 @@ module Expressir
10
10
  # attribute :parent, ModelElement
11
11
  attr_accessor :parent
12
12
 
13
- attribute :_class, :string, default: -> { send(:name) },
13
+ attribute :_class, :string, default: -> { self.class.name },
14
14
  polymorphic_class: true
15
15
  attribute :source, :string
16
16
  attribute :source_offset, :integer
@@ -18,6 +18,7 @@ module Expressir
18
18
 
19
19
  POLYMORPHIC_CLASS_MAP = {
20
20
  "Expressir::Model::Cache" => "Expressir::Model::Cache",
21
+ "Expressir::Model::ExpFile" => "Expressir::Model::ExpFile",
21
22
  "Expressir::Model::Repository" => "Expressir::Model::Repository",
22
23
  "Expressir::Model::RemarkInfo" => "Expressir::Model::RemarkInfo",
23
24
  "Expressir::Model::DataTypes::Aggregate" => "Expressir::Model::DataTypes::Aggregate",
@@ -194,29 +195,20 @@ module Expressir
194
195
  end
195
196
 
196
197
  # Add a remark to this element
197
- # Supports both RemarkInfo objects and legacy strings
198
- # @param remark_or_info [RemarkInfo, String] Remark to add
199
- def add_remark(remark_or_info)
198
+ # @param remark_info [RemarkInfo] Remark to add
199
+ def add_remark(remark_info)
200
200
  self.untagged_remarks ||= []
201
+ return unless remark_info.is_a?(RemarkInfo)
201
202
 
202
- if remark_or_info.is_a?(RemarkInfo)
203
- self.untagged_remarks << remark_or_info
204
- elsif remark_or_info.is_a?(String)
205
- # Backward compatibility: assume embedded format for strings
206
- self.untagged_remarks << RemarkInfo.new(text: remark_or_info,
207
- format: "embedded")
208
- end
203
+ self.untagged_remarks << remark_info
209
204
  end
210
205
 
211
206
  # Get all remarks as RemarkInfo objects
212
- # Converts legacy string remarks to RemarkInfo for consistency
213
207
  # @return [Array<RemarkInfo>] Array of RemarkInfo objects
214
208
  def remark_infos
215
209
  return [] if untagged_remarks.nil?
216
210
 
217
- (untagged_remarks || []).map do |r|
218
- r.is_a?(RemarkInfo) ? r : RemarkInfo.new(text: r, format: "embedded")
219
- end
211
+ untagged_remarks.select { |r| r.is_a?(RemarkInfo) }
220
212
  end
221
213
 
222
214
  private
@@ -6,7 +6,7 @@ module Expressir
6
6
  class AttributeReference < ModelElement
7
7
  attribute :ref, ModelElement
8
8
  attribute :attribute, ModelElement
9
- attribute :_class, :string, default: -> { send(:name) }
9
+ attribute :_class, :string, default: -> { self.class.name }
10
10
 
11
11
  key_value do
12
12
  map "_class", to: :_class, render_default: true
@@ -6,7 +6,7 @@ module Expressir
6
6
  class GroupReference < ModelElement
7
7
  attribute :ref, ModelElement
8
8
  attribute :entity, ModelElement
9
- attribute :_class, :string, default: -> { send(:name) }
9
+ attribute :_class, :string, default: -> { self.class.name }
10
10
 
11
11
  key_value do
12
12
  map "_class", to: :_class, render_default: true
@@ -9,7 +9,7 @@ module Expressir
9
9
  attribute :ref, ModelElement
10
10
  attribute :index1, ModelElement
11
11
  attribute :index2, ModelElement
12
- attribute :_class, :string, default: -> { send(:name) }
12
+ attribute :_class, :string, default: -> { self.class.name }
13
13
 
14
14
  key_value do
15
15
  map "_class", to: :_class, render_default: true
@@ -7,7 +7,7 @@ module Expressir
7
7
  attribute :id, :string
8
8
  attribute :ref, ModelElement
9
9
  attribute :base_path, :string
10
- attribute :_class, :string, default: -> { send(:name) }
10
+ attribute :_class, :string, default: -> { self.class.name }
11
11
 
12
12
  key_value do
13
13
  map "_class", to: :_class, render_default: true
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Model
5
+ module References
6
+ autoload :AttributeReference, "#{__dir__}/references/attribute_reference"
7
+ autoload :GroupReference, "#{__dir__}/references/group_reference"
8
+ autoload :IndexReference, "#{__dir__}/references/index_reference"
9
+ autoload :SimpleReference, "#{__dir__}/references/simple_reference"
10
+ end
11
+ end
12
+ end
@@ -26,12 +26,6 @@ module Expressir
26
26
  !tag.nil? && !tag.empty?
27
27
  end
28
28
 
29
- # For backward compatibility with string-based remarks
30
- # @return [String] The remark text
31
- def to_s
32
- text.to_s
33
- end
34
-
35
29
  # YAML serialization
36
30
  yaml do
37
31
  map "text", to: :text
@@ -41,7 +35,7 @@ module Expressir
41
35
 
42
36
  # XML serialization
43
37
  xml do
44
- root "remark_info"
38
+ element "remark_info"
45
39
  map_element "text", to: :text
46
40
  map_element "format", to: :format
47
41
  map_element "tag", to: :tag
@@ -1,17 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../schema_manifest"
4
- require_relative "../schema_manifest_entry"
5
-
6
3
  module Expressir
7
4
  module Model
8
5
  # Multi-schema global scope with enhanced repository features
9
6
  # Focuses on schema management and delegates indexing/validation to specialized classes
7
+ #
8
+ # A Repository contains multiple ExpFile instances (one per parsed .exp file).
9
+ #
10
+ # Structure:
11
+ # Repository
12
+ # └── files: [ExpFile, ...]
13
+ # └── ExpFile (path: "a.exp")
14
+ # ├── untagged_remarks: [...] # file-level preamble
15
+ # └── schemas: [SchemaA]
10
16
  class Repository < ModelElement
11
- attribute :schemas, Expressir::Model::Declarations::Schema,
12
- collection: true,
13
- initialize_empty: true
14
- attribute :_class, :string, default: -> { send(:name) }
17
+ # Internal storage for schemas (used for direct manipulation)
18
+ attribute :files, ExpFile, collection: true, initialize_empty: true
19
+ attribute :_class, :string, default: -> { self.class.name }
15
20
 
16
21
  # Base directory for schema files
17
22
  attr_accessor :base_dir
@@ -19,20 +24,49 @@ module Expressir
19
24
  # Index instances (lazy-loaded)
20
25
  attr_reader :entity_index, :type_index, :reference_index
21
26
 
27
+ # Internal schema storage for direct manipulation
28
+ attr_reader :_schemas
29
+
22
30
  key_value do
23
31
  map "_class", to: :_class, render_default: true
24
- map "schemas", to: :schemas
32
+ map "files", to: :files
25
33
  end
26
34
 
27
- def initialize(*args, base_dir: nil, **kwargs)
35
+ def initialize(*args, base_dir: nil, schemas: nil, **kwargs)
28
36
  super(*args, **kwargs)
29
37
  @base_dir = base_dir
30
38
  @entity_index = nil
31
39
  @type_index = nil
32
40
  @reference_index = nil
41
+ @_schemas = []
42
+
43
+ # Support direct schemas initialization
44
+ if schemas
45
+ schemas.each { |schema| @_schemas << schema }
46
+ end
47
+ end
48
+
49
+ # Get all schemas (from both files and direct storage)
50
+ # @return [Array<Declarations::Schema>]
51
+ def schemas
52
+ file_schemas = files&.flat_map(&:schemas)&.compact || []
53
+ file_schemas + @_schemas
33
54
  end
34
55
 
35
- # @return [Array<Declaration>]
56
+ # Alias for schemas
57
+ # @return [Array<Declarations::Schema>]
58
+ def all_schemas
59
+ schemas
60
+ end
61
+
62
+ # Add a schema to the repository
63
+ # @param schema [Declarations::Schema] Schema to add
64
+ def add_schema(schema)
65
+ return unless schema
66
+ @_schemas << schema
67
+ end
68
+
69
+ # @return [Array<Declarations::Schema>]
36
70
  def children
37
71
  schemas
38
72
  end
@@ -40,9 +74,10 @@ module Expressir
40
74
  # Build indexes for entities, types, and references
41
75
  # @return [void]
42
76
  def build_indexes
43
- @entity_index = Indexes::EntityIndex.new(schemas)
44
- @type_index = Indexes::TypeIndex.new(schemas)
45
- @reference_index = Indexes::ReferenceIndex.new(schemas)
77
+ target_schemas = all_schemas
78
+ @entity_index = Indexes::EntityIndex.new(target_schemas)
79
+ @type_index = Indexes::TypeIndex.new(target_schemas)
80
+ @reference_index = Indexes::ReferenceIndex.new(target_schemas)
46
81
  end
47
82
 
48
83
  # Find entity by qualified name
@@ -104,7 +139,7 @@ module Expressir
104
139
  # @return [Hash] Validation results with :valid?, :errors, :warnings
105
140
  def validate(strict: false)
106
141
  ensure_indexes_built
107
- validator = RepositoryValidator.new(schemas, @reference_index)
142
+ validator = RepositoryValidator.new(all_schemas, @reference_index)
108
143
  validator.validate(strict: strict)
109
144
  end
110
145
 
@@ -115,7 +150,7 @@ module Expressir
115
150
  ensure_indexes_built
116
151
 
117
152
  stats = {
118
- total_schemas: schemas.size,
153
+ total_schemas: all_schemas.size,
119
154
  total_entities: count_entities,
120
155
  total_types: count_types,
121
156
  total_functions: count_functions,
@@ -141,15 +176,16 @@ module Expressir
141
176
  # Group schemas by category based on their contents
142
177
  # @return [Hash] Hash with category keys and schema arrays
143
178
  def schemas_by_category
179
+ target_schemas = all_schemas
144
180
  {
145
- with_entities: schemas.select { |s| s.entities&.any? },
146
- with_types: schemas.select { |s| s.types&.any? },
147
- with_functions: schemas.select { |s| s.functions&.any? },
148
- with_rules: schemas.select { |s| s.rules&.any? },
149
- interface_only: schemas.select do |s|
181
+ with_entities: target_schemas.select { |s| s.entities&.any? },
182
+ with_types: target_schemas.select { |s| s.types&.any? },
183
+ with_functions: target_schemas.select { |s| s.functions&.any? },
184
+ with_rules: target_schemas.select { |s| s.rules&.any? },
185
+ interface_only: target_schemas.select do |s|
150
186
  s.interfaces&.any? && !s.entities&.any? && !s.types&.any?
151
187
  end,
152
- empty: schemas.select do |s|
188
+ empty: target_schemas.select do |s|
153
189
  !s.entities&.any? && !s.types&.any? && !s.functions&.any?
154
190
  end,
155
191
  }
@@ -159,7 +195,7 @@ module Expressir
159
195
  # @param limit [Integer] Maximum number of schemas to return
160
196
  # @return [Array<Hash>] Array of hashes with :schema and :total_elements
161
197
  def largest_schemas(limit = 10)
162
- schemas.map do |s|
198
+ all_schemas.map do |s|
163
199
  {
164
200
  schema: s,
165
201
  total_elements: count_schema_elements(s),
@@ -186,7 +222,7 @@ module Expressir
186
222
  # @param limit [Integer] Maximum number of schemas to return
187
223
  # @return [Array<Hash>] Array of hashes with :schema and :complexity
188
224
  def schemas_by_complexity(limit = 10)
189
- schemas.map { |s| { schema: s, complexity: schema_complexity(s) } }
225
+ all_schemas.map { |s| { schema: s, complexity: schema_complexity(s) } }
190
226
  .sort_by { |item| -item[:complexity] }
191
227
  .take(limit)
192
228
  end
@@ -205,7 +241,7 @@ module Expressir
205
241
  reference_counts = Hash.new(0)
206
242
  dependency_counts = Hash.new(0)
207
243
 
208
- schemas.each do |schema|
244
+ all_schemas.each do |schema|
209
245
  next unless schema.interfaces&.any?
210
246
 
211
247
  stats[:total_interfaces] += schema.interfaces.size
@@ -232,7 +268,7 @@ module Expressir
232
268
  # @return [SchemaManifest] Manifest describing all schemas
233
269
  def to_manifest
234
270
  manifest = Expressir::SchemaManifest.new
235
- schemas.each do |schema|
271
+ all_schemas.each do |schema|
236
272
  manifest.schemas << Expressir::SchemaManifestEntry.new(
237
273
  id: schema.id,
238
274
  path: schema.file || "#{schema.id}.exp",
@@ -250,7 +286,9 @@ module Expressir
250
286
 
251
287
  file_paths.each do |path|
252
288
  parsed = Expressir::Express::Parser.from_file(path)
253
- parsed&.schemas&.each { |schema| repo.schemas << schema }
289
+ next unless parsed
290
+
291
+ repo.files << parsed if parsed.is_a?(ExpFile)
254
292
  end
255
293
 
256
294
  repo.resolve_all_references
@@ -261,7 +299,6 @@ module Expressir
261
299
  # @param package_path [String] Path to .ler package file
262
300
  # @return [Repository] Loaded repository
263
301
  def self.from_package(package_path)
264
- require_relative "../package/reader"
265
302
  Package::Reader.load(package_path)
266
303
  end
267
304
 
@@ -276,7 +313,6 @@ module Expressir
276
313
  # @option options [String] :serialization_format ('marshal') Serialization format
277
314
  # @return [String] Path to created package
278
315
  def export_to_package(output_path, options = {})
279
- require_relative "../package/builder"
280
316
  builder = Package::Builder.new
281
317
  builder.build(self, output_path, options)
282
318
  end
@@ -325,7 +361,7 @@ module Expressir
325
361
  # @return [Hash<String, Integer>] Entity counts per schema
326
362
  def entities_by_schema_counts
327
363
  counts = {}
328
- schemas.each do |schema|
364
+ all_schemas.each do |schema|
329
365
  counts[schema.id] = schema.entities&.size || 0
330
366
  end
331
367
  counts
@@ -341,7 +377,7 @@ module Expressir
341
377
  defined: 0,
342
378
  }
343
379
 
344
- schemas.each do |schema|
380
+ all_schemas.each do |schema|
345
381
  next unless schema.types
346
382
 
347
383
  schema.types.each do |type|
@@ -362,7 +398,7 @@ module Expressir
362
398
  reference_from: 0,
363
399
  }
364
400
 
365
- schemas.each do |schema|
401
+ all_schemas.each do |schema|
366
402
  next unless schema.interfaces
367
403
 
368
404
  schema.interfaces.each do |interface|
@@ -383,7 +419,7 @@ module Expressir
383
419
  def count_entities
384
420
  return @entity_index.count if @entity_index && !@entity_index.empty?
385
421
 
386
- schemas.sum { |schema| schema.entities&.size || 0 }
422
+ all_schemas.sum { |schema| schema.entities&.size || 0 }
387
423
  end
388
424
 
389
425
  # Count total types across all schemas
@@ -392,25 +428,25 @@ module Expressir
392
428
  def count_types
393
429
  return @type_index.count if @type_index && !@type_index.empty?
394
430
 
395
- schemas.sum { |schema| schema.types&.size || 0 }
431
+ all_schemas.sum { |schema| schema.types&.size || 0 }
396
432
  end
397
433
 
398
434
  # Count total functions across all schemas
399
435
  # @return [Integer] Total function count
400
436
  def count_functions
401
- schemas.sum { |schema| schema.functions&.size || 0 }
437
+ all_schemas.sum { |schema| schema.functions&.size || 0 }
402
438
  end
403
439
 
404
440
  # Count total rules across all schemas
405
441
  # @return [Integer] Total rule count
406
442
  def count_rules
407
- schemas.sum { |schema| schema.rules&.size || 0 }
443
+ all_schemas.sum { |schema| schema.rules&.size || 0 }
408
444
  end
409
445
 
410
446
  # Count total procedures across all schemas
411
447
  # @return [Integer] Total procedure count
412
448
  def count_procedures
413
- schemas.sum { |schema| schema.procedures&.size || 0 }
449
+ all_schemas.sum { |schema| schema.procedures&.size || 0 }
414
450
  end
415
451
  end
416
452
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "interface_validator"
4
-
5
3
  module Expressir
6
4
  module Model
7
5
  # Validator for repository consistency checks
@@ -352,9 +352,7 @@ module Expressir
352
352
  return [] unless schemas
353
353
 
354
354
  entities = collect_from_schemas(schemas, :entities)
355
- entities.flat_map { |e| e.attributes || [] }.select do |attr|
356
- attr.is_a?(Declarations::DerivedAttribute)
357
- end
355
+ entities.flat_map { |e| e.attributes || [] }.grep(Declarations::DerivedAttribute)
358
356
  end
359
357
 
360
358
  # Collect inverse attributes from entities
@@ -365,9 +363,7 @@ module Expressir
365
363
  return [] unless schemas
366
364
 
367
365
  entities = collect_from_schemas(schemas, :entities)
368
- entities.flat_map { |e| e.attributes || [] }.select do |attr|
369
- attr.is_a?(Declarations::InverseAttribute)
370
- end
366
+ entities.flat_map { |e| e.attributes || [] }.grep(Declarations::InverseAttribute)
371
367
  end
372
368
 
373
369
  # Collect parameters from functions and procedures
@@ -488,31 +484,11 @@ module Expressir
488
484
  def find_parent_schema(element)
489
485
  current = element
490
486
  while current
491
- # Duck typing - check if this looks like a schema
492
- # A schema has no parent or is explicitly a Schema type
493
- begin
494
- # First check using is_a? for real objects
495
- if current.is_a?(Declarations::Schema)
496
- return current
497
- end
498
-
499
- # For mock objects, check if parent is nil and has id (likely a schema)
500
- if !current.respond_to?(:parent) || current.parent.nil?
501
- # This might be a schema - check if it has an id
502
- if current.respond_to?(:id) && current.id
503
- return current
504
- end
505
- end
506
- rescue StandardError
507
- # Ignore errors from type checking
508
- end
509
-
510
- current = begin
511
- current.parent
512
- rescue StandardError
513
- nil
514
- end
487
+ return current if current.is_a?(Declarations::Schema)
488
+ current = current.parent
515
489
  end
490
+ rescue StandardError
491
+ # Handle objects that don't fully implement the interface
516
492
  nil
517
493
  end
518
494
 
@@ -8,7 +8,7 @@ module Expressir
8
8
 
9
9
  attribute :expression, ModelElement
10
10
  attribute :statements, ModelElement, collection: true
11
- attribute :_class, :string, default: -> { send(:name) }
11
+ attribute :_class, :string, default: -> { self.class.name }
12
12
 
13
13
  key_value do
14
14
  map "_class", to: :_class, render_default: true
@@ -6,7 +6,7 @@ module Expressir
6
6
  class Assignment < ModelElement
7
7
  attribute :ref, ModelElement
8
8
  attribute :expression, ModelElement
9
- attribute :_class, :string, default: -> { send(:name) }
9
+ attribute :_class, :string, default: -> { self.class.name }
10
10
 
11
11
  key_value do
12
12
  map "_class", to: :_class, render_default: true
@@ -7,7 +7,7 @@ module Expressir
7
7
  attribute :expression, ModelElement
8
8
  attribute :actions, CaseAction, collection: true
9
9
  attribute :otherwise_statement, ModelElement
10
- attribute :_class, :string, default: -> { send(:name) }
10
+ attribute :_class, :string, default: -> { self.class.name }
11
11
 
12
12
  key_value do
13
13
  map "_class", to: :_class, render_default: true
@@ -6,7 +6,7 @@ module Expressir
6
6
  class CaseAction < ModelElement
7
7
  attribute :labels, ModelElement, collection: true
8
8
  attribute :statement, ModelElement
9
- attribute :_class, :string, default: -> { send(:name) }
9
+ attribute :_class, :string, default: -> { self.class.name }
10
10
 
11
11
  key_value do
12
12
  map "_class", to: :_class, render_default: true
@@ -5,7 +5,7 @@ module Expressir
5
5
  # - section 13.5 Compound statement
6
6
  class Compound < ModelElement
7
7
  attribute :statements, ModelElement, collection: true
8
- attribute :_class, :string, default: -> { send(:name) }
8
+ attribute :_class, :string, default: -> { self.class.name }
9
9
 
10
10
  key_value do
11
11
  map "_class", to: :_class, render_default: true
@@ -4,7 +4,7 @@ module Expressir
4
4
  # Specified in ISO 10303-11:2004
5
5
  # - section 13.6 Escape statement
6
6
  class Escape < ModelElement
7
- attribute :_class, :string, default: -> { send(:name) }
7
+ attribute :_class, :string, default: -> { self.class.name }
8
8
 
9
9
  key_value do
10
10
  map "_class", to: :_class, render_default: true