expressir 2.2.1 → 2.3.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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.rubocop_todo.yml +681 -78
  4. data/Gemfile +4 -1
  5. data/README.adoc +63 -26
  6. data/benchmark/srl_benchmark.rb +399 -0
  7. data/benchmark/srl_native_benchmark.rb +146 -0
  8. data/benchmark/srl_ruby_benchmark.rb +132 -0
  9. data/expressir.gemspec +3 -2
  10. data/lib/expressir/benchmark.rb +1 -1
  11. data/lib/expressir/changes/item_change.rb +0 -2
  12. data/lib/expressir/changes/mapping_change.rb +0 -2
  13. data/lib/expressir/changes/schema_change.rb +0 -3
  14. data/lib/expressir/changes/version_change.rb +0 -4
  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 +2 -5
  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_ascii.rb +0 -1
  25. data/lib/expressir/commands/validate_load.rb +1 -1
  26. data/lib/expressir/commands.rb +20 -0
  27. data/lib/expressir/config.rb +0 -2
  28. data/lib/expressir/coverage.rb +11 -4
  29. data/lib/expressir/eengine/arm_compare_report.rb +1 -5
  30. data/lib/expressir/eengine/changes_section.rb +1 -4
  31. data/lib/expressir/eengine/compare_report.rb +1 -13
  32. data/lib/expressir/eengine/mim_compare_report.rb +1 -5
  33. data/lib/expressir/eengine/modified_object.rb +1 -3
  34. data/lib/expressir/eengine.rb +9 -0
  35. data/lib/expressir/errors.rb +3 -5
  36. data/lib/expressir/express/builder.rb +82 -24
  37. data/lib/expressir/express/builder_registry.rb +411 -0
  38. data/lib/expressir/express/builders/attribute_decl_builder.rb +0 -6
  39. data/lib/expressir/express/builders/built_in_builder.rb +5 -18
  40. data/lib/expressir/express/builders/constant_builder.rb +4 -19
  41. data/lib/expressir/express/builders/declaration_builder.rb +0 -4
  42. data/lib/expressir/express/builders/derive_clause_builder.rb +0 -2
  43. data/lib/expressir/express/builders/derived_attr_builder.rb +0 -2
  44. data/lib/expressir/express/builders/domain_rule_builder.rb +0 -2
  45. data/lib/expressir/express/builders/entity_decl_builder.rb +11 -13
  46. data/lib/expressir/express/builders/explicit_attr_builder.rb +5 -8
  47. data/lib/expressir/express/builders/expression_builder.rb +25 -67
  48. data/lib/expressir/express/builders/function_decl_builder.rb +20 -18
  49. data/lib/expressir/express/builders/interface_builder.rb +0 -20
  50. data/lib/expressir/express/builders/inverse_attr_builder.rb +0 -2
  51. data/lib/expressir/express/builders/inverse_attr_type_builder.rb +0 -6
  52. data/lib/expressir/express/builders/inverse_clause_builder.rb +0 -2
  53. data/lib/expressir/express/builders/literal_builder.rb +1 -15
  54. data/lib/expressir/express/builders/procedure_decl_builder.rb +20 -19
  55. data/lib/expressir/express/builders/qualifier_builder.rb +0 -27
  56. data/lib/expressir/express/builders/reference_builder.rb +1 -10
  57. data/lib/expressir/express/builders/rule_decl_builder.rb +21 -19
  58. data/lib/expressir/express/builders/schema_body_decl_builder.rb +0 -4
  59. data/lib/expressir/express/builders/schema_decl_builder.rb +7 -13
  60. data/lib/expressir/express/builders/schema_version_builder.rb +0 -6
  61. data/lib/expressir/express/builders/simple_id_builder.rb +1 -10
  62. data/lib/expressir/express/builders/statement_builder.rb +4 -32
  63. data/lib/expressir/express/builders/subtype_constraint_builder.rb +6 -30
  64. data/lib/expressir/express/builders/syntax_builder.rb +18 -7
  65. data/lib/expressir/express/builders/type_builder.rb +3 -45
  66. data/lib/expressir/express/builders/type_decl_builder.rb +1 -7
  67. data/lib/expressir/express/builders/unique_clause_builder.rb +1 -3
  68. data/lib/expressir/express/builders/unique_rule_builder.rb +0 -2
  69. data/lib/expressir/express/builders/where_clause_builder.rb +1 -3
  70. data/lib/expressir/express/builders.rb +47 -35
  71. data/lib/expressir/express/error.rb +0 -3
  72. data/lib/expressir/express/formatter.rb +17 -19
  73. data/lib/expressir/express/formatters/data_types_formatter.rb +295 -293
  74. data/lib/expressir/express/formatters/declarations_formatter.rb +617 -615
  75. data/lib/expressir/express/formatters/expressions_formatter.rb +146 -144
  76. data/lib/expressir/express/formatters/literals_formatter.rb +35 -33
  77. data/lib/expressir/express/formatters/references_formatter.rb +34 -32
  78. data/lib/expressir/express/formatters/remark_formatter.rb +174 -209
  79. data/lib/expressir/express/formatters/remark_item_formatter.rb +18 -16
  80. data/lib/expressir/express/formatters/statements_formatter.rb +190 -188
  81. data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +41 -39
  82. data/lib/expressir/express/formatters.rb +22 -0
  83. data/lib/expressir/express/parser.rb +266 -47
  84. data/lib/expressir/express/pretty_formatter.rb +68 -47
  85. data/lib/expressir/express/remark_attacher.rb +254 -162
  86. data/lib/expressir/express/streaming_builder.rb +0 -3
  87. data/lib/expressir/express/transformer/remark_handling.rb +1 -3
  88. data/lib/expressir/express.rb +29 -0
  89. data/lib/expressir/manifest/resolver.rb +0 -3
  90. data/lib/expressir/manifest/validator.rb +0 -3
  91. data/lib/expressir/manifest.rb +6 -0
  92. data/lib/expressir/model/cache.rb +1 -1
  93. data/lib/expressir/model/concerns.rb +19 -0
  94. data/lib/expressir/model/data_types/aggregate.rb +1 -1
  95. data/lib/expressir/model/data_types/array.rb +1 -1
  96. data/lib/expressir/model/data_types/bag.rb +1 -1
  97. data/lib/expressir/model/data_types/binary.rb +1 -1
  98. data/lib/expressir/model/data_types/boolean.rb +1 -1
  99. data/lib/expressir/model/data_types/enumeration.rb +1 -1
  100. data/lib/expressir/model/data_types/enumeration_item.rb +1 -1
  101. data/lib/expressir/model/data_types/generic.rb +1 -1
  102. data/lib/expressir/model/data_types/generic_entity.rb +1 -1
  103. data/lib/expressir/model/data_types/integer.rb +1 -1
  104. data/lib/expressir/model/data_types/list.rb +1 -1
  105. data/lib/expressir/model/data_types/logical.rb +1 -1
  106. data/lib/expressir/model/data_types/number.rb +1 -1
  107. data/lib/expressir/model/data_types/real.rb +1 -1
  108. data/lib/expressir/model/data_types/select.rb +1 -1
  109. data/lib/expressir/model/data_types/set.rb +1 -1
  110. data/lib/expressir/model/data_types/string.rb +1 -1
  111. data/lib/expressir/model/data_types.rb +25 -0
  112. data/lib/expressir/model/declarations/attribute.rb +1 -1
  113. data/lib/expressir/model/declarations/constant.rb +1 -1
  114. data/lib/expressir/model/declarations/derived_attribute.rb +1 -1
  115. data/lib/expressir/model/declarations/entity.rb +4 -1
  116. data/lib/expressir/model/declarations/function.rb +3 -1
  117. data/lib/expressir/model/declarations/informal_proposition_rule.rb +2 -1
  118. data/lib/expressir/model/declarations/interface.rb +1 -1
  119. data/lib/expressir/model/declarations/interface_item.rb +1 -1
  120. data/lib/expressir/model/declarations/interfaced_item.rb +1 -1
  121. data/lib/expressir/model/declarations/inverse_attribute.rb +1 -1
  122. data/lib/expressir/model/declarations/parameter.rb +1 -1
  123. data/lib/expressir/model/declarations/procedure.rb +3 -1
  124. data/lib/expressir/model/declarations/remark_item.rb +1 -1
  125. data/lib/expressir/model/declarations/rule.rb +4 -1
  126. data/lib/expressir/model/declarations/schema.rb +2 -1
  127. data/lib/expressir/model/declarations/schema_version.rb +1 -1
  128. data/lib/expressir/model/declarations/schema_version_item.rb +1 -1
  129. data/lib/expressir/model/declarations/subtype_constraint.rb +1 -1
  130. data/lib/expressir/model/declarations/type.rb +4 -1
  131. data/lib/expressir/model/declarations/unique_rule.rb +1 -1
  132. data/lib/expressir/model/declarations/variable.rb +1 -1
  133. data/lib/expressir/model/declarations/where_rule.rb +1 -1
  134. data/lib/expressir/model/declarations.rb +31 -0
  135. data/lib/expressir/model/dependency_resolver.rb +0 -2
  136. data/lib/expressir/model/exp_file.rb +39 -0
  137. data/lib/expressir/model/expressions/aggregate_initializer.rb +1 -1
  138. data/lib/expressir/model/expressions/aggregate_initializer_item.rb +1 -1
  139. data/lib/expressir/model/expressions/binary_expression.rb +1 -1
  140. data/lib/expressir/model/expressions/entity_constructor.rb +1 -1
  141. data/lib/expressir/model/expressions/function_call.rb +1 -1
  142. data/lib/expressir/model/expressions/interval.rb +1 -1
  143. data/lib/expressir/model/expressions/query_expression.rb +1 -1
  144. data/lib/expressir/model/expressions/unary_expression.rb +1 -1
  145. data/lib/expressir/model/expressions.rb +18 -0
  146. data/lib/expressir/model/identifier.rb +5 -1
  147. data/lib/expressir/model/indexes.rb +11 -0
  148. data/lib/expressir/model/literals/binary.rb +1 -1
  149. data/lib/expressir/model/literals/integer.rb +1 -1
  150. data/lib/expressir/model/literals/logical.rb +1 -1
  151. data/lib/expressir/model/literals/real.rb +1 -1
  152. data/lib/expressir/model/literals/string.rb +1 -1
  153. data/lib/expressir/model/literals.rb +13 -0
  154. data/lib/expressir/model/model_element.rb +7 -15
  155. data/lib/expressir/model/references/attribute_reference.rb +1 -1
  156. data/lib/expressir/model/references/group_reference.rb +1 -1
  157. data/lib/expressir/model/references/index_reference.rb +1 -1
  158. data/lib/expressir/model/references/simple_reference.rb +1 -1
  159. data/lib/expressir/model/references.rb +12 -0
  160. data/lib/expressir/model/remark_info.rb +1 -7
  161. data/lib/expressir/model/repository.rb +76 -41
  162. data/lib/expressir/model/repository_validator.rb +0 -2
  163. data/lib/expressir/model/search_engine.rb +12 -35
  164. data/lib/expressir/model/statements/alias.rb +1 -1
  165. data/lib/expressir/model/statements/assignment.rb +1 -1
  166. data/lib/expressir/model/statements/case.rb +1 -1
  167. data/lib/expressir/model/statements/case_action.rb +1 -1
  168. data/lib/expressir/model/statements/compound.rb +1 -1
  169. data/lib/expressir/model/statements/escape.rb +1 -1
  170. data/lib/expressir/model/statements/if.rb +1 -1
  171. data/lib/expressir/model/statements/null.rb +1 -1
  172. data/lib/expressir/model/statements/procedure_call.rb +1 -1
  173. data/lib/expressir/model/statements/repeat.rb +1 -1
  174. data/lib/expressir/model/statements/return.rb +1 -1
  175. data/lib/expressir/model/statements/skip.rb +1 -1
  176. data/lib/expressir/model/statements.rb +20 -0
  177. data/lib/expressir/model/supertype_expressions/binary_supertype_expression.rb +1 -1
  178. data/lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb +1 -1
  179. data/lib/expressir/model/supertype_expressions.rb +12 -0
  180. data/lib/expressir/model.rb +28 -4
  181. data/lib/expressir/package/builder.rb +35 -4
  182. data/lib/expressir/package/metadata.rb +0 -2
  183. data/lib/expressir/package/reader.rb +0 -1
  184. data/lib/expressir/package.rb +8 -0
  185. data/lib/expressir/schema_manifest.rb +5 -7
  186. data/lib/expressir/schema_manifest_entry.rb +3 -5
  187. data/lib/expressir/transformer.rb +7 -0
  188. data/lib/expressir/version.rb +1 -1
  189. data/lib/expressir.rb +23 -171
  190. metadata +46 -6
  191. data/lib/expressir/express/builders/token_builder.rb +0 -15
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Model
5
+ # Represents a single EXPRESS file containing schemas and preamble remarks.
6
+ # This class preserves file-level information including:
7
+ # - File path for reference
8
+ # - Preamble remarks (comments at the top of the file before any schema)
9
+ # - Schemas defined in this file
10
+ #
11
+ # A Repository contains multiple ExpFile instances when parsing multiple files,
12
+ # or a single ExpFile when parsing a single file.
13
+ class ExpFile < ModelElement
14
+ include ScopeContainer
15
+
16
+ attribute :path, :string
17
+ attribute :schemas, Declarations::Schema, collection: true,
18
+ initialize_empty: true
19
+ attribute :_class, :string, default: -> { self.class.name }
20
+
21
+ key_value do
22
+ map "_class", to: :_class, render_default: true
23
+ map "path", to: :path
24
+ map "schemas", to: :schemas
25
+ end
26
+
27
+ # Returns the file path as the identifier
28
+ # @return [String, nil] The file path or nil
29
+ def id
30
+ path
31
+ end
32
+
33
+ # @return [Array<Declaration>]
34
+ def children
35
+ schemas
36
+ end
37
+ end
38
+ end
39
+ end
@@ -5,7 +5,7 @@ module Expressir
5
5
  # - section 12.9 Aggregate initializer
6
6
  class AggregateInitializer < ModelElement
7
7
  attribute :items, 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
@@ -6,7 +6,7 @@ module Expressir
6
6
  class AggregateInitializerItem < ModelElement
7
7
  attribute :expression, ModelElement
8
8
  attribute :repetition, 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
@@ -44,7 +44,7 @@ module Expressir
44
44
  ]
45
45
  attribute :operand1, ModelElement
46
46
  attribute :operand2, ModelElement
47
- attribute :_class, :string, default: -> { send(:name) }
47
+ attribute :_class, :string, default: -> { self.class.name }
48
48
 
49
49
  key_value do
50
50
  map "_class", to: :_class, render_default: true
@@ -6,7 +6,7 @@ module Expressir
6
6
  class EntityConstructor < ModelElement
7
7
  attribute :entity, ModelElement
8
8
  attribute :parameters, ModelElement, collection: true
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 FunctionCall < ModelElement
7
7
  attribute :function, ModelElement
8
8
  attribute :parameters, ModelElement, collection: true
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
@@ -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.grep(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,48 @@ 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)
28
- super(*args, **kwargs)
35
+ def initialize(*, base_dir: nil, schemas: nil, **)
36
+ super(*, **)
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
+ schemas&.each { |schema| @_schemas << schema }
45
+ end
46
+
47
+ # Get all schemas (from both files and direct storage)
48
+ # @return [Array<Declarations::Schema>]
49
+ def schemas
50
+ file_schemas = files&.flat_map(&:schemas)&.compact || []
51
+ file_schemas + @_schemas
52
+ end
53
+
54
+ # Alias for schemas
55
+ # @return [Array<Declarations::Schema>]
56
+ def all_schemas
57
+ schemas
58
+ end
59
+
60
+ # Add a schema to the repository
61
+ # @param schema [Declarations::Schema] Schema to add
62
+ def add_schema(schema)
63
+ return unless schema
64
+
65
+ @_schemas << schema
33
66
  end
34
67
 
35
- # @return [Array<Declaration>]
68
+ # @return [Array<Declarations::Schema>]
36
69
  def children
37
70
  schemas
38
71
  end
@@ -40,9 +73,10 @@ module Expressir
40
73
  # Build indexes for entities, types, and references
41
74
  # @return [void]
42
75
  def build_indexes
43
- @entity_index = Indexes::EntityIndex.new(schemas)
44
- @type_index = Indexes::TypeIndex.new(schemas)
45
- @reference_index = Indexes::ReferenceIndex.new(schemas)
76
+ target_schemas = all_schemas
77
+ @entity_index = Indexes::EntityIndex.new(target_schemas)
78
+ @type_index = Indexes::TypeIndex.new(target_schemas)
79
+ @reference_index = Indexes::ReferenceIndex.new(target_schemas)
46
80
  end
47
81
 
48
82
  # Find entity by qualified name
@@ -104,7 +138,7 @@ module Expressir
104
138
  # @return [Hash] Validation results with :valid?, :errors, :warnings
105
139
  def validate(strict: false)
106
140
  ensure_indexes_built
107
- validator = RepositoryValidator.new(schemas, @reference_index)
141
+ validator = RepositoryValidator.new(all_schemas, @reference_index)
108
142
  validator.validate(strict: strict)
109
143
  end
110
144
 
@@ -115,7 +149,7 @@ module Expressir
115
149
  ensure_indexes_built
116
150
 
117
151
  stats = {
118
- total_schemas: schemas.size,
152
+ total_schemas: all_schemas.size,
119
153
  total_entities: count_entities,
120
154
  total_types: count_types,
121
155
  total_functions: count_functions,
@@ -141,15 +175,16 @@ module Expressir
141
175
  # Group schemas by category based on their contents
142
176
  # @return [Hash] Hash with category keys and schema arrays
143
177
  def schemas_by_category
178
+ target_schemas = all_schemas
144
179
  {
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|
180
+ with_entities: target_schemas.select { |s| s.entities&.any? },
181
+ with_types: target_schemas.select { |s| s.types&.any? },
182
+ with_functions: target_schemas.select { |s| s.functions&.any? },
183
+ with_rules: target_schemas.select { |s| s.rules&.any? },
184
+ interface_only: target_schemas.select do |s|
150
185
  s.interfaces&.any? && !s.entities&.any? && !s.types&.any?
151
186
  end,
152
- empty: schemas.select do |s|
187
+ empty: target_schemas.select do |s|
153
188
  !s.entities&.any? && !s.types&.any? && !s.functions&.any?
154
189
  end,
155
190
  }
@@ -159,7 +194,7 @@ module Expressir
159
194
  # @param limit [Integer] Maximum number of schemas to return
160
195
  # @return [Array<Hash>] Array of hashes with :schema and :total_elements
161
196
  def largest_schemas(limit = 10)
162
- schemas.map do |s|
197
+ all_schemas.map do |s|
163
198
  {
164
199
  schema: s,
165
200
  total_elements: count_schema_elements(s),
@@ -186,7 +221,7 @@ module Expressir
186
221
  # @param limit [Integer] Maximum number of schemas to return
187
222
  # @return [Array<Hash>] Array of hashes with :schema and :complexity
188
223
  def schemas_by_complexity(limit = 10)
189
- schemas.map { |s| { schema: s, complexity: schema_complexity(s) } }
224
+ all_schemas.map { |s| { schema: s, complexity: schema_complexity(s) } }
190
225
  .sort_by { |item| -item[:complexity] }
191
226
  .take(limit)
192
227
  end
@@ -205,7 +240,7 @@ module Expressir
205
240
  reference_counts = Hash.new(0)
206
241
  dependency_counts = Hash.new(0)
207
242
 
208
- schemas.each do |schema|
243
+ all_schemas.each do |schema|
209
244
  next unless schema.interfaces&.any?
210
245
 
211
246
  stats[:total_interfaces] += schema.interfaces.size
@@ -232,7 +267,7 @@ module Expressir
232
267
  # @return [SchemaManifest] Manifest describing all schemas
233
268
  def to_manifest
234
269
  manifest = Expressir::SchemaManifest.new
235
- schemas.each do |schema|
270
+ all_schemas.each do |schema|
236
271
  manifest.schemas << Expressir::SchemaManifestEntry.new(
237
272
  id: schema.id,
238
273
  path: schema.file || "#{schema.id}.exp",
@@ -250,7 +285,9 @@ module Expressir
250
285
 
251
286
  file_paths.each do |path|
252
287
  parsed = Expressir::Express::Parser.from_file(path)
253
- parsed&.schemas&.each { |schema| repo.schemas << schema }
288
+ next unless parsed
289
+
290
+ repo.files << parsed if parsed.is_a?(ExpFile)
254
291
  end
255
292
 
256
293
  repo.resolve_all_references
@@ -261,7 +298,6 @@ module Expressir
261
298
  # @param package_path [String] Path to .ler package file
262
299
  # @return [Repository] Loaded repository
263
300
  def self.from_package(package_path)
264
- require_relative "../package/reader"
265
301
  Package::Reader.load(package_path)
266
302
  end
267
303
 
@@ -276,7 +312,6 @@ module Expressir
276
312
  # @option options [String] :serialization_format ('marshal') Serialization format
277
313
  # @return [String] Path to created package
278
314
  def export_to_package(output_path, options = {})
279
- require_relative "../package/builder"
280
315
  builder = Package::Builder.new
281
316
  builder.build(self, output_path, options)
282
317
  end
@@ -306,16 +341,16 @@ module Expressir
306
341
  # @param format [Symbol] Output format
307
342
  # @yield [item] Block to convert item to hash
308
343
  # @return [Array, String] Formatted output
309
- def format_output(items, format, &block)
344
+ def format_output(items, format, &)
310
345
  case format
311
346
  when :hash
312
- items.map(&block)
347
+ items.map(&)
313
348
  when :json
314
349
  require "json"
315
- items.map(&block).to_json
350
+ items.map(&).to_json
316
351
  when :yaml
317
352
  require "yaml"
318
- items.map(&block).to_yaml
353
+ items.map(&).to_yaml
319
354
  else
320
355
  items
321
356
  end
@@ -325,7 +360,7 @@ module Expressir
325
360
  # @return [Hash<String, Integer>] Entity counts per schema
326
361
  def entities_by_schema_counts
327
362
  counts = {}
328
- schemas.each do |schema|
363
+ all_schemas.each do |schema|
329
364
  counts[schema.id] = schema.entities&.size || 0
330
365
  end
331
366
  counts
@@ -341,7 +376,7 @@ module Expressir
341
376
  defined: 0,
342
377
  }
343
378
 
344
- schemas.each do |schema|
379
+ all_schemas.each do |schema|
345
380
  next unless schema.types
346
381
 
347
382
  schema.types.each do |type|
@@ -362,7 +397,7 @@ module Expressir
362
397
  reference_from: 0,
363
398
  }
364
399
 
365
- schemas.each do |schema|
400
+ all_schemas.each do |schema|
366
401
  next unless schema.interfaces
367
402
 
368
403
  schema.interfaces.each do |interface|
@@ -383,7 +418,7 @@ module Expressir
383
418
  def count_entities
384
419
  return @entity_index.count if @entity_index && !@entity_index.empty?
385
420
 
386
- schemas.sum { |schema| schema.entities&.size || 0 }
421
+ all_schemas.sum { |schema| schema.entities&.size || 0 }
387
422
  end
388
423
 
389
424
  # Count total types across all schemas
@@ -392,25 +427,25 @@ module Expressir
392
427
  def count_types
393
428
  return @type_index.count if @type_index && !@type_index.empty?
394
429
 
395
- schemas.sum { |schema| schema.types&.size || 0 }
430
+ all_schemas.sum { |schema| schema.types&.size || 0 }
396
431
  end
397
432
 
398
433
  # Count total functions across all schemas
399
434
  # @return [Integer] Total function count
400
435
  def count_functions
401
- schemas.sum { |schema| schema.functions&.size || 0 }
436
+ all_schemas.sum { |schema| schema.functions&.size || 0 }
402
437
  end
403
438
 
404
439
  # Count total rules across all schemas
405
440
  # @return [Integer] Total rule count
406
441
  def count_rules
407
- schemas.sum { |schema| schema.rules&.size || 0 }
442
+ all_schemas.sum { |schema| schema.rules&.size || 0 }
408
443
  end
409
444
 
410
445
  # Count total procedures across all schemas
411
446
  # @return [Integer] Total procedure count
412
447
  def count_procedures
413
- schemas.sum { |schema| schema.procedures&.size || 0 }
448
+ all_schemas.sum { |schema| schema.procedures&.size || 0 }
414
449
  end
415
450
  end
416
451
  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