expressir 2.3.4 → 2.3.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e990830fa008a30ebb6b937e503030069e175b329ff44f3eebe212adaa5066b
4
- data.tar.gz: 6f84bc382c6e49c6402298a5e1f6557343ad6864e7dfa5364bc52e4467fc6cf3
3
+ metadata.gz: 6af1982d1df8fc35cf696c67614f670e45386121feb42b962290a8b40acbc7f6
4
+ data.tar.gz: c03425e140c7b68391efef97105a3c86124d4269a8bb564515b0e83596a62932
5
5
  SHA512:
6
- metadata.gz: ae27b6f9b65e7622db436d3658867ce76587884b215b0a6f74954740c0110ae957b8ed35c887a7ebeda0c91ea7db4b30bb23836da21730e5cba296a7b2bfc9dd
7
- data.tar.gz: 362a01b5e21d36d050ec1049f626a44bb0e62cd2ced0cd74c5581faee4f9903313fe5aaefff20df5c2c814979df4bc806ef621b23cbdb9af71831128485cbc33
6
+ metadata.gz: a330cbcd461ed7099e473a4a3d8c689f238096afce4c581b35a198bc487ddf5bd7a8bb777af698b1553efc1950eb878aa03874cc0b6904cb451b95a128962998
7
+ data.tar.gz: 1c995702e07eb2756811f35cbde5dfad4f1d32452c77a45404d551a1bfce1e374789219c72be5383eb5f804cf4489aee05cb2e29def2245ddd2d40cf591fa4c3
data/.gitignore CHANGED
@@ -24,3 +24,19 @@
24
24
  _site/
25
25
 
26
26
  Gemfile.lock
27
+
28
+ # Claude Code
29
+ .claude/
30
+
31
+ # Development / transient files
32
+ *.ler
33
+ *.pax
34
+ TODO.*.md
35
+ debug_*.rb
36
+ measure_mem.rb
37
+ tmp_*.rb
38
+ mise.toml
39
+ Gemfile.local
40
+ Gemfile.local.lock
41
+ Gemfile.original
42
+ benchmark/
data/.rubocop_todo.yml CHANGED
@@ -1,20 +1,12 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2026-05-11 08:18:39 UTC using RuboCop version 1.86.0.
3
+ # on 2026-05-12 14:41:49 UTC using RuboCop version 1.86.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 4
10
- # This cop supports safe autocorrection (--autocorrect).
11
- # Configuration parameters: EnforcedStyle, IndentationWidth.
12
- # SupportedStyles: with_first_argument, with_fixed_indentation
13
- Layout/ArgumentAlignment:
14
- Exclude:
15
- - 'lib/expressir/express/remark_attacher.rb'
16
-
17
- # Offense count: 1082
9
+ # Offense count: 1084
18
10
  # This cop supports safe autocorrection (--autocorrect).
19
11
  # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
20
12
  # URISchemes: http, https
@@ -80,7 +72,7 @@ Metrics/BlockNesting:
80
72
  Metrics/CyclomaticComplexity:
81
73
  Enabled: false
82
74
 
83
- # Offense count: 287
75
+ # Offense count: 289
84
76
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
85
77
  Metrics/MethodLength:
86
78
  Max: 167
@@ -354,7 +354,7 @@ module Expressir
354
354
  end
355
355
 
356
356
  def attach_source_info(result, data)
357
- return unless @source && result.is_a?(Model::ModelElement)
357
+ return unless @source && result.is_a?(Expressir::Model::ModelElement)
358
358
 
359
359
  source_info = extract_source_info(data)
360
360
  return unless source_info
@@ -181,18 +181,18 @@ module Expressir
181
181
  Builder.register(:interval_high) { |d| expression.build_interval_high(d) }
182
182
  Builder.register(:interval_item) { |d| expression.build_interval_item(d) }
183
183
  Builder.register(:interval_op) do |d|
184
- expression.send(:extract_interval_op, d)
184
+ expression.extract_interval_op(d)
185
185
  end
186
186
 
187
187
  # Operators
188
188
  Builder.register(:add_like_op) do |d|
189
- expression.send(:extract_operator, d)
189
+ expression.extract_operator(d)
190
190
  end
191
191
  Builder.register(:mul_like_op) do |d|
192
- expression.send(:extract_operator, d)
192
+ expression.extract_operator(d)
193
193
  end
194
- Builder.register(:unary_op) { |d| expression.send(:extract_unary_op, d) }
195
- Builder.register(:rel_op) { |d| expression.send(:extract_rel_op, d) }
194
+ Builder.register(:unary_op) { |d| expression.extract_unary_op(d) }
195
+ Builder.register(:rel_op) { |d| expression.extract_rel_op(d) }
196
196
 
197
197
  # ========================================================================
198
198
  # Interface Builder (closures)
@@ -319,45 +319,20 @@ module Expressir
319
319
  subtype_constraint.build_total_over(d)
320
320
  end
321
321
 
322
- Builder.register(:subtype_constraint_decl) do |d|
323
- subtype_constraint.build_subtype_constraint_decl(d)
324
- end
325
- Builder.register(:total_over) do |d|
326
- subtype_constraint.build_total_over(d)
327
- end
328
- Builder.register(:supertype_expression) do |d|
329
- subtype_constraint.build_supertype_expression(d)
330
- end
331
- Builder.register(:supertype_factor) do |d|
332
- subtype_constraint.build_supertype_factor(d)
333
- end
334
- Builder.register(:supertype_term) do |d|
335
- subtype_constraint.build_supertype_term(d)
336
- end
337
- Builder.register(:one_of) { |d| subtype_constraint.build_one_of(d) }
338
- Builder.register(:supertype_rule) do |d|
339
- subtype_constraint.build_supertype_rule(d)
340
- end
341
- Builder.register(:subtype_constraint) do |d|
342
- subtype_constraint.build_subtype_constraint(d)
343
- end
344
- Builder.register(:subtype_declaration) do |d|
345
- subtype_constraint.build_subtype_declaration(d)
346
- end
347
-
348
322
  # ========================================================================
349
323
  # Type Builder (closures)
350
324
  # ========================================================================
351
325
 
352
326
  # Simple types
353
- %i[boolean_type integer_type logical_type number_type].each do |type|
354
- Builder.register(type) { |d| type_builder.send(:"build_#{type}", d) }
355
- end
327
+ Builder.register(:boolean_type) { |d| type_builder.build_boolean_type(d) }
328
+ Builder.register(:integer_type) { |d| type_builder.build_integer_type(d) }
329
+ Builder.register(:logical_type) { |d| type_builder.build_logical_type(d) }
330
+ Builder.register(:number_type) { |d| type_builder.build_number_type(d) }
356
331
 
357
332
  # Type constructors
358
333
  Builder.register(:generic_type) { |_d| Expressir::Model::DataTypes::Generic.new }
359
334
  Builder.register(:generic_entity_type) { |_d| Expressir::Model::DataTypes::GenericEntity.new }
360
- Builder.register(:aggregate_type) { |_d| Expressir::Model::DataTypes::Aggregate.new }
335
+ Builder.register(:aggregate_type) { |d| type_builder.build_aggregate_type(d) }
361
336
  Builder.register(:general_set_type) do |d|
362
337
  type_builder.build_general_set_type(d)
363
338
  end
@@ -12,7 +12,9 @@ module Expressir
12
12
  def build_constant_body(ast_data)
13
13
  id = Builder.build_optional(ast_data[:constant_id])
14
14
  type = Builder.build_optional(ast_data[:instantiable_type])
15
- expression = Builder.build_optional(ast_data[:expression])
15
+ expression = if ast_data[:expression]
16
+ Builder.build({ expression: ast_data[:expression] })
17
+ end
16
18
 
17
19
  Expressir::Model::Declarations::Constant.new(id: id, type: type,
18
20
  expression: expression)
@@ -34,7 +36,10 @@ module Expressir
34
36
  ids = if ids_data.is_a?(Hash)
35
37
  [Builder.build({ variable_id: ids_data })]
36
38
  elsif ids_data.is_a?(Array)
37
- ids_data.map { |id| Builder.build({ variable_id: id }) }
39
+ ids_data.filter_map do |elem|
40
+ actual_id = elem[:variable_id] || elem
41
+ Builder.build({ variable_id: actual_id })
42
+ end
38
43
  else
39
44
  []
40
45
  end
@@ -62,7 +67,10 @@ module Expressir
62
67
  ids = if ids_data.is_a?(Hash)
63
68
  [Builder.build({ parameter_id: ids_data })]
64
69
  elsif ids_data.is_a?(Array)
65
- ids_data.map { |id| Builder.build({ parameter_id: id }) }
70
+ ids_data.filter_map do |elem|
71
+ actual_id = elem[:parameter_id] || elem
72
+ Builder.build({ parameter_id: actual_id })
73
+ end
66
74
  else
67
75
  []
68
76
  end
@@ -11,7 +11,9 @@ module Expressir
11
11
  Builder.build({ attribute_decl: attr_decl_data })
12
12
  end
13
13
  type = Builder.build_optional(ast_data[:parameter_type])
14
- expression = Builder.build_optional(ast_data[:expression])
14
+ expression = if ast_data[:expression]
15
+ Builder.build({ expression: ast_data[:expression] })
16
+ end
15
17
 
16
18
  Expressir::Model::Declarations::DerivedAttribute.new(
17
19
  id: attr&.id,
@@ -9,7 +9,9 @@ module Expressir
9
9
  inner_data = ast_data[:domain_rule] || ast_data
10
10
 
11
11
  id = Builder.build_optional(inner_data[:rule_label_id])
12
- expression = Builder.build_optional(inner_data[:expression])
12
+ expression = if inner_data[:expression]
13
+ Builder.build({ expression: inner_data[:expression] })
14
+ end
13
15
  Expressir::Model::Declarations::WhereRule.new(id: id,
14
16
  expression: expression)
15
17
  end
@@ -223,13 +223,14 @@ module Expressir
223
223
  end
224
224
 
225
225
  def build_qualifier(ast_data)
226
- if ast_data[:attribute_qualifier]
226
+ data = ast_data[:qualifier] || ast_data
227
+ if data[:attribute_qualifier]
227
228
  Builder.build_node(:attribute_qualifier,
228
- ast_data[:attribute_qualifier])
229
- elsif ast_data[:group_qualifier]
230
- Builder.build_node(:group_qualifier, ast_data[:group_qualifier])
231
- elsif ast_data[:index_qualifier]
232
- Builder.build_node(:index_qualifier, ast_data[:index_qualifier])
229
+ data[:attribute_qualifier])
230
+ elsif data[:group_qualifier]
231
+ Builder.build_node(:group_qualifier, data[:group_qualifier])
232
+ elsif data[:index_qualifier]
233
+ Builder.build_node(:index_qualifier, data[:index_qualifier])
233
234
  end
234
235
  end
235
236
 
@@ -304,7 +305,9 @@ module Expressir
304
305
  end
305
306
 
306
307
  def build_parameter(ast_data)
307
- Builder.build_optional(ast_data[:expression])
308
+ if ast_data[:expression]
309
+ Builder.build({ expression: ast_data[:expression] })
310
+ end
308
311
  end
309
312
 
310
313
  # Entity constructor
@@ -354,7 +357,9 @@ module Expressir
354
357
  end
355
358
 
356
359
  def build_element(ast_data)
357
- expression = Builder.build_optional(ast_data[:expression])
360
+ expression = if ast_data[:expression]
361
+ Builder.build({ expression: ast_data[:expression] })
362
+ end
358
363
  repetition = Builder.build_optional(ast_data[:repetition])
359
364
 
360
365
  if repetition
@@ -138,6 +138,12 @@ module Expressir
138
138
  when Expressir::Model::References::IndexReference
139
139
  Expressir::Model::References::IndexReference.new(ref: ref,
140
140
  index1: qualifier.index1, index2: qualifier.index2)
141
+ when Expressir::Model::References::SimpleReference
142
+ Expressir::Model::References::AttributeReference.new(ref: ref,
143
+ attribute: qualifier)
144
+ when Hash
145
+ Expressir::Model::References::IndexReference.new(ref: ref,
146
+ index1: qualifier[:index1], index2: qualifier[:index2])
141
147
  else
142
148
  ref
143
149
  end
@@ -62,7 +62,8 @@ module Expressir
62
62
 
63
63
  parameters = []
64
64
  Builder.ensure_array(params_data).each do |param|
65
- result = Builder.build({ procedure_head_parameter: param })
65
+ actual_param = param[:procedure_head_parameter] || param
66
+ result = Builder.build({ procedure_head_parameter: actual_param })
66
67
  parameters.concat(Builder.ensure_array(result)) if result
67
68
  end
68
69
  parameters
@@ -36,7 +36,9 @@ module Expressir
36
36
 
37
37
  def build_assignment_stmt(ast_data)
38
38
  ref = Builder.build_optional(ast_data[:general_ref])
39
- expression = Builder.build_optional(ast_data[:expression])
39
+ expression = if ast_data[:expression]
40
+ Builder.build({ expression: ast_data[:expression] })
41
+ end
40
42
 
41
43
  if ast_data[:qualifier]
42
44
  Builder.ensure_array(ast_data[:qualifier]).each do |qual|
@@ -83,31 +85,48 @@ module Expressir
83
85
  def build_case_stmt(ast_data)
84
86
  selector = Builder.build_optional(ast_data[:selector])
85
87
  actions = Builder.build_children(ast_data[:case_action])
86
- otherwise = Builder.build_children(ast_data[:otherwise]&.dig(:stmt))
88
+ otherwise_stmt = if ast_data[:t_otherwise] && ast_data[:stmt].is_a?(Hash)
89
+ Builder.build({ stmt: ast_data[:stmt] })
90
+ end
87
91
 
88
92
  Expressir::Model::Statements::Case.new(
89
93
  expression: selector,
90
94
  actions: actions.compact,
91
- otherwise: otherwise.compact,
95
+ otherwise_statement: otherwise_stmt,
92
96
  )
93
97
  end
94
98
 
95
99
  def build_selector(ast_data)
96
- Builder.build_optional(ast_data[:expression])
100
+ if ast_data[:expression]
101
+ Builder.build({ expression: ast_data[:expression] })
102
+ end
97
103
  end
98
104
 
99
105
  def build_case_action(ast_data)
100
- labels = Builder.build_children(ast_data[:case_label])
101
- statements = Builder.build_children(ast_data[:stmt])
106
+ label_data = ast_data[:list_of_case_label]
107
+ labels = if label_data.is_a?(Hash)
108
+ Builder.build_children(label_data[:case_label])
109
+ elsif label_data.is_a?(Array)
110
+ label_data.flat_map do |item|
111
+ Builder.build_children(item.is_a?(Hash) ? item[:case_label] : item)
112
+ end
113
+ else
114
+ []
115
+ end
116
+ stmt = if ast_data[:stmt].is_a?(Hash)
117
+ Builder.build({ stmt: ast_data[:stmt] })
118
+ end
102
119
 
103
120
  Expressir::Model::Statements::CaseAction.new(
104
121
  labels: labels.compact,
105
- statements: statements.compact,
122
+ statement: stmt,
106
123
  )
107
124
  end
108
125
 
109
126
  def build_case_label(ast_data)
110
- Builder.build_optional(ast_data[:expression])
127
+ if ast_data[:expression]
128
+ Builder.build({ expression: ast_data[:expression] })
129
+ end
111
130
  end
112
131
 
113
132
  def build_compound_stmt(ast_data)
@@ -170,7 +189,9 @@ module Expressir
170
189
  end
171
190
 
172
191
  def build_return_stmt(ast_data)
173
- expression = Builder.build_optional(ast_data[:expression])
192
+ expression = if ast_data[:expression]
193
+ Builder.build({ expression: ast_data[:expression] })
194
+ end
174
195
  Expressir::Model::Statements::Return.new(expression: expression)
175
196
  end
176
197
 
@@ -7,18 +7,20 @@ module Expressir
7
7
  class TypeBuilder
8
8
  include ::Expressir::Express::Builders::Helpers
9
9
 
10
- # Simple types
11
- {
12
- boolean_type: Expressir::Model::DataTypes::Boolean,
13
- integer_type: Expressir::Model::DataTypes::Integer,
14
- logical_type: Expressir::Model::DataTypes::Logical,
15
- number_type: Expressir::Model::DataTypes::Number,
16
- generic_type: Expressir::Model::DataTypes::Generic,
17
- generic_entity_type: Expressir::Model::DataTypes::GenericEntity,
18
- }.each do |type_name, klass|
19
- define_method(:"build_#{type_name}") do |_ast_data|
20
- klass.new
21
- end
10
+ def build_boolean_type(_ast_data)
11
+ Expressir::Model::DataTypes::Boolean.new
12
+ end
13
+
14
+ def build_integer_type(_ast_data)
15
+ Expressir::Model::DataTypes::Integer.new
16
+ end
17
+
18
+ def build_logical_type(_ast_data)
19
+ Expressir::Model::DataTypes::Logical.new
20
+ end
21
+
22
+ def build_number_type(_ast_data)
23
+ Expressir::Model::DataTypes::Number.new
22
24
  end
23
25
 
24
26
  # String type
@@ -49,6 +51,12 @@ module Expressir
49
51
  end
50
52
  end
51
53
 
54
+ # Aggregate type (AGGREGATE OF type)
55
+ def build_aggregate_type(ast_data)
56
+ base_type = Builder.build_optional(ast_data[:parameter_type])
57
+ Expressir::Model::DataTypes::Aggregate.new(base_type: base_type)
58
+ end
59
+
52
60
  # Aggregation types
53
61
  def build_array_type(ast_data)
54
62
  build_aggregation_type(ast_data, Expressir::Model::DataTypes::Array)
@@ -4,8 +4,18 @@ module Expressir
4
4
  module DataTypesFormatter
5
5
  private
6
6
 
7
- def format_data_types_aggregate(_node)
8
- "AGGREGATE"
7
+ def format_data_types_aggregate(node)
8
+ [
9
+ "AGGREGATE",
10
+ *if node.base_type
11
+ [
12
+ " ",
13
+ "OF",
14
+ " ",
15
+ format(node.base_type),
16
+ ]
17
+ end,
18
+ ].join
9
19
  end
10
20
 
11
21
  def format_data_types_array(node)
@@ -257,7 +267,7 @@ module Expressir
257
267
  ].join
258
268
  end,
259
269
  ].join
260
- else
270
+ elsif node.items&.length&.positive?
261
271
  indent_char = self.class.const_get(:INDENT_CHAR)
262
272
  item_indent = indent_char * "(".length
263
273
  [
@@ -24,9 +24,9 @@ module Expressir
24
24
  def format_expressions_binary_expression(node)
25
25
  operator_precedence = self.class.const_get(:OPERATOR_PRECEDENCE)
26
26
  op1_bin_exp = node.operand1.is_a?(Model::Expressions::BinaryExpression) &&
27
- (operator_precedence[node.operand1.operator] > operator_precedence[node.operator])
27
+ (operator_precedence[node.operand1.operator] >= operator_precedence[node.operator])
28
28
  op2_bin_exp = node.operand2.is_a?(Model::Expressions::BinaryExpression) &&
29
- (operator_precedence[node.operand2.operator] > operator_precedence[node.operator])
29
+ (operator_precedence[node.operand2.operator] >= operator_precedence[node.operator])
30
30
 
31
31
  [
32
32
  *if op1_bin_exp
@@ -138,6 +138,9 @@ module Expressir
138
138
  end
139
139
 
140
140
  def format_expressions_unary_expression(node)
141
+ needs_parens = node.operand.is_a?(Model::Expressions::BinaryExpression) ||
142
+ node.operand.is_a?(Model::Expressions::Interval)
143
+
141
144
  [
142
145
  case node.operator
143
146
  when Model::Expressions::UnaryExpression::MINUS then "-"
@@ -147,11 +150,11 @@ module Expressir
147
150
  if node.operator == Model::Expressions::UnaryExpression::NOT
148
151
  " "
149
152
  end,
150
- *if node.operand.is_a? Model::Expressions::BinaryExpression
153
+ *if needs_parens
151
154
  "("
152
155
  end,
153
156
  format(node.operand),
154
- *if node.operand.is_a? Model::Expressions::BinaryExpression
157
+ *if needs_parens
155
158
  ")"
156
159
  end,
157
160
  ].join
@@ -5,10 +5,7 @@ module Expressir
5
5
  private
6
6
 
7
7
  def format_literals_binary(node)
8
- [
9
- "%",
10
- node.value,
11
- ].join
8
+ node.value
12
9
  end
13
10
 
14
11
  def format_literals_integer(node)
@@ -525,7 +525,7 @@ module Expressir
525
525
  def find_target_in_where_clause(scope, tag, remark_line)
526
526
  return nil unless supports_where_rules?(scope)
527
527
 
528
- where_rules = scope.where_rules
528
+ where_rules = safe_get_collection(scope, :where_rules)
529
529
  return nil unless where_rules&.any?
530
530
 
531
531
  # Search source text for WHERE clause containing this remark
@@ -6,7 +6,6 @@ module Expressir
6
6
  class Function < ModelElement
7
7
  include Identifier
8
8
  include ScopeContainer
9
- include HasWhereRules
10
9
 
11
10
  attribute :parameters, Parameter, collection: true
12
11
  attribute :return_type, ModelElement
@@ -6,7 +6,6 @@ module Expressir
6
6
  class Procedure < ModelElement
7
7
  include Identifier
8
8
  include ScopeContainer
9
- include HasWhereRules
10
9
 
11
10
  attribute :parameters, Parameter, collection: true
12
11
  attribute :types, ModelElement, collection: true
@@ -1,3 +1,3 @@
1
1
  module Expressir
2
- VERSION = "2.3.4".freeze
2
+ VERSION = "2.3.6".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expressir
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.4
4
+ version: 2.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-05-11 00:00:00.000000000 Z
11
+ date: 2026-05-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64