expressir 2.4.33 → 2.4.34
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 +4 -4
- data/lib/expressir/express/shtolo.rb +172 -63
- data/lib/expressir/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 11ae98e1866bac67ff62c5a8f27abd2f06d94c62f8f7468c43d67554e1d4cd48
|
|
4
|
+
data.tar.gz: a4ee98f12efb95ca5d3302aa8835120b2bad67ca37181430c9c4fcc1bbc8c561
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0ec3c593547ace542482f7b5371d446dc7810e5e52f250281f0b5a6bca742d05c31abf15a8dc25456845314c98bdc673351a458a88384ea5e2d06b499904a411
|
|
7
|
+
data.tar.gz: b2f7b4a8c851a61024baa8601c826c649bcff17393d91934a4faf5d75ee2ecf0936697bd5178a92dd36d3c850a809ac9c6ed39cf70fda3fb4aba3646698b65b8
|
|
@@ -130,16 +130,20 @@ module Expressir
|
|
|
130
130
|
schema.interfaces.each do |iface|
|
|
131
131
|
next unless iface.kind == Model::Declarations::Interface::REFERENCE
|
|
132
132
|
|
|
133
|
+
iface_schema = iface.schema.is_a?(String) ? iface.schema : iface.schema&.id
|
|
134
|
+
target = closure[iface_schema&.safe_downcase]
|
|
133
135
|
iface.items.each do |item|
|
|
134
136
|
original = original_name(item, schema)
|
|
135
|
-
next unless
|
|
137
|
+
next unless target&.entities&.find do |e|
|
|
138
|
+
e.id.safe_downcase == original.safe_downcase
|
|
139
|
+
end
|
|
136
140
|
|
|
137
141
|
@reference_entities << original.safe_downcase
|
|
138
142
|
end
|
|
139
143
|
end
|
|
140
144
|
end
|
|
141
145
|
|
|
142
|
-
declarations
|
|
146
|
+
declarations.concat(build_dependent_declarations) if @reference_entities.any?
|
|
143
147
|
|
|
144
148
|
Model::Declarations::Schema.new(
|
|
145
149
|
id: @longform_name,
|
|
@@ -166,7 +170,18 @@ module Expressir
|
|
|
166
170
|
# OWN schema's id, and the global map redirects the bare name so
|
|
167
171
|
# declarations from third schemas resolve to the first occurrence.
|
|
168
172
|
def plan_ids(schemas)
|
|
169
|
-
|
|
173
|
+
# G.NM.1: EVERY clashing declaration is prefixed (the annex
|
|
174
|
+
# example munges farming_dot_dog AND pet_shows_dot_dog), so the
|
|
175
|
+
# clash set is computed over the whole population first.
|
|
176
|
+
counts = Hash.new(0)
|
|
177
|
+
schemas.each do |schema|
|
|
178
|
+
all_decls(schema).each do |decl|
|
|
179
|
+
next unless decl.respond_to?(:id) && decl.id
|
|
180
|
+
|
|
181
|
+
counts[decl.id.safe_downcase] += 1
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
170
185
|
global = {} # downcase id => munged final
|
|
171
186
|
own_by_schema = {} # schema => {downcase id => final id}
|
|
172
187
|
schemas.each do |schema|
|
|
@@ -175,14 +190,11 @@ module Expressir
|
|
|
175
190
|
next unless decl.respond_to?(:id) && decl.id
|
|
176
191
|
|
|
177
192
|
key = decl.id.safe_downcase
|
|
178
|
-
if
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
seen_first[key] = schema
|
|
184
|
-
own[key] = decl.id
|
|
185
|
-
end
|
|
193
|
+
own[key] = if counts[key] > 1
|
|
194
|
+
global[key] = "#{schema.id.safe_downcase}_dot_#{decl.id}"
|
|
195
|
+
else
|
|
196
|
+
decl.id
|
|
197
|
+
end
|
|
186
198
|
end
|
|
187
199
|
own_by_schema[schema] = own
|
|
188
200
|
end
|
|
@@ -253,11 +265,20 @@ module Expressir
|
|
|
253
265
|
current == current.upcase ? new.upcase : new
|
|
254
266
|
end
|
|
255
267
|
|
|
256
|
-
# G.1.6: parse-templates keep the annex rule/function verbatim
|
|
257
|
-
|
|
268
|
+
# G.1.6: parse-templates keep the annex rule/function verbatim;
|
|
269
|
+
# the pair is emitted together (the rule's WHERE calls the
|
|
270
|
+
# function, and the prune pass would drop an uncalled function).
|
|
271
|
+
def build_dependent_declarations
|
|
272
|
+
snippet = parse_schema_snippet(dependent_template_src)
|
|
273
|
+
rule = snippet.schemas.first.rules.first
|
|
274
|
+
fn = snippet.schemas.first.functions.first
|
|
275
|
+
[rule, fn].compact
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def dependent_template_src
|
|
258
279
|
list = @reference_entities.map(&:upcase).join(", ")
|
|
259
280
|
union = @reference_entities.join("+")
|
|
260
|
-
|
|
281
|
+
<<~EXP
|
|
261
282
|
SCHEMA __dependent__;
|
|
262
283
|
RULE #{DEPENDENT_RULE_NAME} FOR (#{list});
|
|
263
284
|
LOCAL
|
|
@@ -270,9 +291,62 @@ module Expressir
|
|
|
270
291
|
WHERE
|
|
271
292
|
wr1: dependently_instantiated(all_instances, set_of_input_types, previous_in_chain);
|
|
272
293
|
END_RULE;
|
|
294
|
+
|
|
295
|
+
FUNCTION dependently_instantiated(
|
|
296
|
+
set_of_input_instances : SET OF GENERIC:igen;
|
|
297
|
+
set_of_input_types : SET OF STRING;
|
|
298
|
+
previous_in_chain : LIST OF GENERIC:cgen): BOOLEAN;
|
|
299
|
+
LOCAL
|
|
300
|
+
number_of_input_instances : INTEGER;
|
|
301
|
+
number_of_referring_instances : INTEGER;
|
|
302
|
+
bag_of_referring_instances : BAG OF GENERIC:igen := [];
|
|
303
|
+
dependently_instantiated_flag : BOOLEAN;
|
|
304
|
+
previous_in_chain_plus : LIST OF GENERIC:cgen := [];
|
|
305
|
+
result : BOOLEAN := true;
|
|
306
|
+
set_of_types : SET OF STRING := [];
|
|
307
|
+
END_LOCAL;
|
|
308
|
+
IF EXISTS(set_of_input_instances) THEN
|
|
309
|
+
number_of_input_instances := SIZEOF(set_of_input_instances);
|
|
310
|
+
set_of_input_types := set_of_input_types + 'GENERIC';
|
|
311
|
+
REPEAT i := 1 TO number_of_input_instances;
|
|
312
|
+
bag_of_referring_instances := USEDIN(set_of_input_instances[i], '');
|
|
313
|
+
IF EXISTS(bag_of_referring_instances) THEN
|
|
314
|
+
number_of_referring_instances := SIZEOF(bag_of_referring_instances);
|
|
315
|
+
dependently_instantiated_flag := false;
|
|
316
|
+
REPEAT j := 1 TO number_of_referring_instances;
|
|
317
|
+
set_of_types := TYPEOF(bag_of_referring_instances[j]);
|
|
318
|
+
IF set_of_types <= set_of_input_types THEN
|
|
319
|
+
IF NOT (bag_of_referring_instances[j] IN previous_in_chain) THEN
|
|
320
|
+
previous_in_chain_plus := previous_in_chain +
|
|
321
|
+
set_of_input_instances[i];
|
|
322
|
+
IF dependently_instantiated([bag_of_referring_instances[j]],
|
|
323
|
+
set_of_input_types,
|
|
324
|
+
previous_in_chain_plus) THEN
|
|
325
|
+
dependently_instantiated_flag := true;
|
|
326
|
+
ESCAPE;
|
|
327
|
+
ELSE
|
|
328
|
+
SKIP;
|
|
329
|
+
END_IF;
|
|
330
|
+
END_IF;
|
|
331
|
+
ELSE
|
|
332
|
+
dependently_instantiated_flag := true;
|
|
333
|
+
ESCAPE;
|
|
334
|
+
END_IF;
|
|
335
|
+
END_REPEAT;
|
|
336
|
+
IF NOT dependently_instantiated_flag THEN
|
|
337
|
+
RETURN(false);
|
|
338
|
+
END_IF;
|
|
339
|
+
ELSE
|
|
340
|
+
RETURN(false);
|
|
341
|
+
END_IF;
|
|
342
|
+
END_REPEAT;
|
|
343
|
+
ELSE
|
|
344
|
+
RETURN(false);
|
|
345
|
+
END_IF;
|
|
346
|
+
RETURN(true);
|
|
347
|
+
END_FUNCTION;
|
|
273
348
|
END_SCHEMA;
|
|
274
349
|
EXP
|
|
275
|
-
parse_schema_snippet(src).schemas.first.rules.first
|
|
276
350
|
end
|
|
277
351
|
|
|
278
352
|
def parse_schema_snippet(src)
|
|
@@ -499,57 +573,95 @@ module Expressir
|
|
|
499
573
|
end
|
|
500
574
|
end
|
|
501
575
|
|
|
576
|
+
# G.2.2/G.2.4: every extensible/extending select becomes a
|
|
577
|
+
# non-extensible select whose items are the full domain in
|
|
578
|
+
# longform scope. Chains fold in dependency order (a node whose
|
|
579
|
+
# own BASED_ON is still pending is deferred), so an extending
|
|
580
|
+
# type that is itself extensible resolves against its base's
|
|
581
|
+
# folded domain.
|
|
582
|
+
# G.2.2/G.2.4: every extensible/extending select becomes a
|
|
583
|
+
# non-extensible select whose items are the full domain in
|
|
584
|
+
# longform scope. Chains fold in dependency order (a node whose
|
|
585
|
+
# own BASED_ON is still pending is deferred), so an extending
|
|
586
|
+
# type that is itself extensible resolves against its base's
|
|
587
|
+
# folded domain.
|
|
502
588
|
def resolve_extensible_selects!(schema)
|
|
503
|
-
schema.types.select do |
|
|
504
|
-
|
|
505
|
-
end
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
# every entity the artifact carries, so the longform select is
|
|
511
|
-
# complete against the closure. Flags stay as declared: the
|
|
512
|
-
# extensible/generic-entity markers are part of the shortform's
|
|
513
|
-
# semantics and are not expressir's to drop.
|
|
514
|
-
if sel.generic_entity
|
|
515
|
-
sel.items = schema.entities.map do |e|
|
|
516
|
-
Model::References::SimpleReference.new(id: e.id)
|
|
517
|
-
end
|
|
518
|
-
next
|
|
519
|
-
end
|
|
589
|
+
select_types = schema.types.select do |ty|
|
|
590
|
+
ty.underlying_type.is_a?(Model::DataTypes::Select)
|
|
591
|
+
end
|
|
592
|
+
select_types.select { |ty| sel_pending?(ty) }.each do |base|
|
|
593
|
+
fold_select_node(schema, select_types, base)
|
|
594
|
+
end
|
|
595
|
+
end
|
|
520
596
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
597
|
+
def sel_pending?(select_type)
|
|
598
|
+
sel = select_type.underlying_type
|
|
599
|
+
sel.extensible || sel.based_on
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
def fold_select_node(schema, select_types, base_type)
|
|
603
|
+
sel = base_type.underlying_type
|
|
604
|
+
return unless sel_pending?(base_type)
|
|
605
|
+
|
|
606
|
+
# all-extenders for GENERIC_ENTITY selects (WG12 requirement,
|
|
607
|
+
# #32): the extenders are the entity types themselves — fold in
|
|
608
|
+
# every entity the artifact carries, so the longform select is
|
|
609
|
+
# complete against the closure. Flags stay as declared: the
|
|
610
|
+
# extensible/generic-entity markers are part of the shortform's
|
|
611
|
+
# semantics and are not expressir's to drop.
|
|
612
|
+
if sel.generic_entity && !sel.based_on
|
|
613
|
+
sel.items = schema.entities.map do |e|
|
|
614
|
+
Model::References::SimpleReference.new(id: e.id)
|
|
525
615
|
end
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
616
|
+
return
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
own_items = Array(sel.items)
|
|
620
|
+
inherited = []
|
|
621
|
+
if sel.based_on
|
|
622
|
+
base_ty = select_types.find do |ty|
|
|
623
|
+
ty.id&.safe_downcase == sel.based_on&.id&.safe_downcase
|
|
534
624
|
end
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
625
|
+
fold_select_node(schema, select_types, base_ty) if base_ty && sel_pending?(base_ty)
|
|
626
|
+
inherited = base_ty ? Array(base_ty.underlying_type.items) : []
|
|
627
|
+
end
|
|
538
628
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
629
|
+
extenders = select_types.select do |ty|
|
|
630
|
+
!ty.equal?(base_type) &&
|
|
631
|
+
ty.underlying_type.based_on&.id&.safe_downcase == base_type.id&.safe_downcase
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
merged = inherited + own_items +
|
|
635
|
+
extenders.flat_map { |ty| Array(ty.underlying_type.items) }
|
|
636
|
+
seen = {}
|
|
637
|
+
uniq = merged.select do |item|
|
|
638
|
+
key = item.id.safe_downcase
|
|
639
|
+
next false if key.empty? || seen.key?(key)
|
|
640
|
+
|
|
641
|
+
seen[key] = true
|
|
642
|
+
end
|
|
643
|
+
sel.items = uniq
|
|
644
|
+
sel.extensible = false
|
|
645
|
+
sel.based_on = nil
|
|
646
|
+
|
|
647
|
+
extenders.each do |ty|
|
|
648
|
+
ext_sel = ty.underlying_type
|
|
649
|
+
keep = Array(ext_sel.items).map { |i| i.id.upcase }
|
|
650
|
+
base_ref = "#{@longform_name.upcase}.#{base_type.id.upcase}"
|
|
651
|
+
ty.underlying_type = Model::DataTypes::Select.new(
|
|
652
|
+
items: uniq.map { |i| Model::References::SimpleReference.new(id: i.id) },
|
|
653
|
+
)
|
|
654
|
+
ext_sel_items = ty.underlying_type.items
|
|
655
|
+
exclusions = uniq.reject { |i| keep.include?(i.id.upcase) }
|
|
656
|
+
ty.where_rules = exclusions.each_with_index.map do |item, i|
|
|
657
|
+
Model::Declarations::WhereRule.new(
|
|
658
|
+
id: "wr#{i + 1}",
|
|
659
|
+
expression: parse_expression(
|
|
660
|
+
"NOT ('#{base_ref}.#{item.id.upcase}' IN TYPEOF(SELF));",
|
|
661
|
+
),
|
|
545
662
|
)
|
|
546
|
-
ext.where_rules = exclusions.each_with_index.map do |item, i|
|
|
547
|
-
Model::Declarations::WhereRule.new(
|
|
548
|
-
id: "wr#{i + 1}",
|
|
549
|
-
expression: parse_expression("NOT ('#{base_ref}.#{item.id.upcase}' IN TYPEOF(SELF));"),
|
|
550
|
-
)
|
|
551
|
-
end
|
|
552
663
|
end
|
|
664
|
+
ext_sel_items
|
|
553
665
|
end
|
|
554
666
|
end
|
|
555
667
|
|
|
@@ -565,10 +677,7 @@ module Expressir
|
|
|
565
677
|
entity.supertype_expression =
|
|
566
678
|
entity.supertype_expression ? combine_andor(entity.supertype_expression, expr) : expr
|
|
567
679
|
end
|
|
568
|
-
if
|
|
569
|
-
# G.2.6: abstract entity ⇒ ABSTRACT SUPERTYPE (formatter
|
|
570
|
-
# renders from abstract + supertype status).
|
|
571
|
-
end
|
|
680
|
+
entity.abstract = true if sc.abstract
|
|
572
681
|
next if Array(sc.total_over).empty?
|
|
573
682
|
|
|
574
683
|
rule_name = "total_over_#{sc.id}"
|
data/lib/expressir/version.rb
CHANGED
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.4.
|
|
4
|
+
version: 2.4.34
|
|
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-10-
|
|
11
|
+
date: 2026-10-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rb_sys
|