expressir 2.4.36-arm-linux → 2.4.38-arm-linux

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.
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module P21
5
+ # Emits a {Population} back to ISO 10303-21 text (TODO.instance/03).
6
+ # Deterministic: the same population always serializes to the same
7
+ # bytes — HEADER entities in insertion order, DATA instances in id
8
+ # order, anchors/references/named sections re-emitted when present.
9
+ module Writer
10
+ module_function
11
+
12
+ def emit(population)
13
+ lines = ["ISO-10303-21;", "HEADER;"]
14
+ population.header.each do |keyword, params|
15
+ lines << "#{keyword}(#{emit_params(params)});"
16
+ end
17
+ lines << "ENDSEC;"
18
+ unless population.anchors.empty?
19
+ lines << "ANCHOR;"
20
+ population.anchors.each do |label, value|
21
+ lines << "<#{label}> = #{emit_value(value)};"
22
+ end
23
+ lines << "ENDSEC;"
24
+ end
25
+ unless population.references.empty?
26
+ lines << "REFERENCE;"
27
+ population.references.each do |id, anchor|
28
+ lines << "#{id} = #{anchor};"
29
+ end
30
+ lines << "ENDSEC;"
31
+ end
32
+ emit_data_sections(population, lines)
33
+ lines << "END-ISO-10303-21;"
34
+ "#{lines.join("\n")}\n"
35
+ end
36
+
37
+ def emit_data_sections(population, lines)
38
+ if population.sections.empty?
39
+ lines << "DATA;"
40
+ emit_instances(population.instances, lines)
41
+ lines << "ENDSEC;"
42
+ return
43
+ end
44
+
45
+ population.sections.each do |section|
46
+ lines << named_data_line(section)
47
+ section.instance_ids.each do |id|
48
+ lines << "#{id}=#{emit_record(population.instances[id])};"
49
+ end
50
+ lines << "ENDSEC;"
51
+ end
52
+ end
53
+
54
+ def named_data_line(section)
55
+ return "DATA;" if section.name.nil?
56
+
57
+ contexts = section.contexts
58
+ .map { |context| "'#{context}'" }.join(", ")
59
+ "DATA ('#{section.name}', (#{contexts}));"
60
+ end
61
+
62
+ def emit_instances(instances, lines)
63
+ instances.each do |id, record|
64
+ lines << "#{id}=#{emit_record(record)};"
65
+ end
66
+ end
67
+
68
+ def emit_record(record)
69
+ if record.is_a?(ComplexRecord)
70
+ "(#{record.records.map { |part| emit_simple(part) }.join})"
71
+ else
72
+ emit_simple(record)
73
+ end
74
+ end
75
+
76
+ def emit_simple(record)
77
+ "#{record.keyword}(#{emit_params(record.params)})"
78
+ end
79
+
80
+ def emit_params(params)
81
+ params.map { |value| emit_value(value) }.join(",")
82
+ end
83
+
84
+ def emit_value(value)
85
+ case value
86
+ when Array then "(#{value.map { |item| emit_value(item) }.join(',')})"
87
+ when TypedValue
88
+ "#{value.keyword}(#{emit_params(value.value)})"
89
+ when Enumeration then ".#{value.name}."
90
+ when Binary then "\"#{value.hex}\""
91
+ when :unset then "$"
92
+ when :derived then "*"
93
+ when true then ".T."
94
+ when false then ".F."
95
+ when String then string_or_reference(value)
96
+ else value.to_s
97
+ end
98
+ end
99
+
100
+ def string_or_reference(value)
101
+ return value if value.match?(/\A#\d+\z/)
102
+
103
+ "'#{value.gsub("'", "''")}'"
104
+ end
105
+ end
106
+ end
107
+ end
data/lib/expressir/p21.rb CHANGED
@@ -12,6 +12,12 @@ module Expressir
12
12
  autoload :Grammar, "#{__dir__}/p21/grammar"
13
13
  autoload :Builder, "#{__dir__}/p21/builder"
14
14
  autoload :Validator, "#{__dir__}/p21/validator"
15
+ autoload :Typing, "#{__dir__}/p21/typing"
16
+ autoload :DatasetManifest, "#{__dir__}/p21/dataset_manifest"
17
+ autoload :Receipt, "#{__dir__}/p21/receipt"
18
+ autoload :Diff, "#{__dir__}/p21/diff"
15
19
  autoload :Parser, "#{__dir__}/p21/parser"
20
+ autoload :Writer, "#{__dir__}/p21/writer"
21
+ autoload :Json, "#{__dir__}/p21/json"
16
22
  end
17
23
  end
@@ -3,6 +3,6 @@ module Expressir
3
3
  # autoload it (Ruby autoload only works for module/class constants, not
4
4
  # for string constants like `Expressir::VERSION`).
5
5
  module Version
6
- VERSION = "2.4.36".freeze
6
+ VERSION = "2.4.38".freeze
7
7
  end
8
8
  end
data/lib/expressir.rb CHANGED
@@ -76,6 +76,7 @@ module Expressir
76
76
  autoload :Model, "#{__dir__}/expressir/model"
77
77
  autoload :Commands, "#{__dir__}/expressir/commands"
78
78
  autoload :Changes, "#{__dir__}/expressir/changes"
79
+ autoload :Eval, "#{__dir__}/expressir/eval"
79
80
  autoload :Conformance, "#{__dir__}/expressir/conformance"
80
81
  autoload :Package, "#{__dir__}/expressir/package"
81
82
  autoload :Manifest, "#{__dir__}/expressir/manifest"
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :instance do
4
+ desc "Population rule-engine benchmark over a synthetic population " \
5
+ "(default 100000 instances; POPULATION_SIZE to override)"
6
+ task :benchmark do
7
+ require "expressir"
8
+ require "expressir/eval"
9
+ require "json"
10
+ require "tmpdir"
11
+
12
+ size = Integer(ENV.fetch("POPULATION_SIZE", "100 000").delete(" "), 10)
13
+ out = ENV["INSTANCE_BENCH_OUT"] || "instance-benchmark.json"
14
+
15
+ Dir.mktmpdir do |dir|
16
+ schema_path = File.join(dir, "bench.exp")
17
+ File.write(schema_path, <<~EXP)
18
+ SCHEMA bench;
19
+ ENTITY item;
20
+ code : INTEGER;
21
+ ref : item;
22
+ UNIQUE
23
+ u1 : code;
24
+ END_ENTITY;
25
+ RULE no_negative_codes FOR (item);
26
+ WHERE
27
+ ok : SIZEOF(QUERY(i <* item | i.code < 0)) = 0;
28
+ END_RULE;
29
+ END_SCHEMA;
30
+ EXP
31
+
32
+ population_path = File.join(dir, "bench.p21")
33
+ File.open(population_path, "w") do |file|
34
+ file.puts "ISO-10303-21;"
35
+ file.puts "HEADER;"
36
+ file.puts "FILE_NAME('bench','2026-01-01T00:00:00',('b'),('b')," \
37
+ "'p','s','a');"
38
+ file.puts "FILE_SCHEMA(('bench'));"
39
+ file.puts "ENDSEC;"
40
+ file.puts "DATA;"
41
+ size.times do |i|
42
+ ref = i.zero? ? "$" : "##{i}"
43
+ file.puts "##{i + 1}=ITEM(#{i},#{ref});"
44
+ end
45
+ file.puts "ENDSEC;"
46
+ file.puts "END-ISO-10303-21;"
47
+ end
48
+
49
+ clock = Process.method(:clock_gettime)
50
+ mono = Process::CLOCK_MONOTONIC
51
+ t0 = clock.call(mono)
52
+ schema = Expressir::Express::Parser.from_file(schema_path).schemas.first
53
+ population = Expressir::P21::Parser.parse(File.read(population_path))
54
+ timings = { load: (clock.call(mono) - t0).round(2) }
55
+
56
+ engine = Expressir::Eval::Population.new(schema, population)
57
+ t1 = clock.call(mono)
58
+ first = engine.check
59
+ timings[:check_first] = (clock.call(mono) - t1).round(2)
60
+ t2 = clock.call(mono)
61
+ second = engine.check
62
+ timings[:check_second] = (clock.call(mono) - t2).round(2)
63
+
64
+ report = {
65
+ instances: size,
66
+ rules: { where: 0, unique: 1, global: 1 },
67
+ findings: first.size,
68
+ deterministic: first == second,
69
+ timings_seconds: timings,
70
+ }
71
+ File.write(out, "#{JSON.pretty_generate(report)}\n")
72
+ puts "wrote #{out} (#{size} instances, findings #{first.size}, " \
73
+ "check #{timings[:check_first]}s, " \
74
+ "deterministic=#{report[:deterministic]})"
75
+ end
76
+ end
77
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expressir
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.36
4
+ version: 2.4.38
5
5
  platform: arm-linux
6
6
  authors:
7
7
  - Ribose Inc.
@@ -299,6 +299,11 @@ files:
299
299
  - TODO.eengine/07-schema-compare-patch.md
300
300
  - TODO.eengine/08-official-corpus-gate.md
301
301
  - TODO.eengine/09-mim-mapping-parser.md
302
+ - TODO.instance/00-overview.md
303
+ - TODO.instance/01-instance-typing.md
304
+ - TODO.instance/02-population-rules.md
305
+ - TODO.instance/03-p21-ladder-and-population-management.md
306
+ - TODO.instance/04-arm-mim-instance-mapping.md
302
307
  - TODO.max-perf/01-restore-ci-green.md
303
308
  - TODO.max-perf/02-streaming-parse-path.md
304
309
  - TODO.max-perf/03-cli-parallel-opt-in.md
@@ -479,6 +484,7 @@ files:
479
484
  - lib/expressir/commands/non_ascii_violation_collection.rb
480
485
  - lib/expressir/commands/package.rb
481
486
  - lib/expressir/commands/parity_inputs.rb
487
+ - lib/expressir/commands/population.rb
482
488
  - lib/expressir/commands/smrl_xml_index.rb
483
489
  - lib/expressir/commands/validate.rb
484
490
  - lib/expressir/commands/validate_ascii.rb
@@ -500,6 +506,7 @@ files:
500
506
  - lib/expressir/eval/environment.rb
501
507
  - lib/expressir/eval/expression.rb
502
508
  - lib/expressir/eval/interpreter.rb
509
+ - lib/expressir/eval/population.rb
503
510
  - lib/expressir/eval/rules.rb
504
511
  - lib/expressir/eval/values.rb
505
512
  - lib/expressir/express.rb
@@ -603,6 +610,7 @@ files:
603
610
  - lib/expressir/manifest/resolver.rb
604
611
  - lib/expressir/manifest/validator.rb
605
612
  - lib/expressir/mapping.rb
613
+ - lib/expressir/mapping/instance_verification.rb
606
614
  - lib/expressir/mapping/refpath.rb
607
615
  - lib/expressir/model.rb
608
616
  - lib/expressir/model/cache.rb
@@ -702,10 +710,16 @@ files:
702
710
  - lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb
703
711
  - lib/expressir/p21.rb
704
712
  - lib/expressir/p21/builder.rb
713
+ - lib/expressir/p21/dataset_manifest.rb
714
+ - lib/expressir/p21/diff.rb
705
715
  - lib/expressir/p21/grammar.rb
716
+ - lib/expressir/p21/json.rb
706
717
  - lib/expressir/p21/parser.rb
707
718
  - lib/expressir/p21/population.rb
719
+ - lib/expressir/p21/receipt.rb
720
+ - lib/expressir/p21/typing.rb
708
721
  - lib/expressir/p21/validator.rb
722
+ - lib/expressir/p21/writer.rb
709
723
  - lib/expressir/package.rb
710
724
  - lib/expressir/package/builder.rb
711
725
  - lib/expressir/package/metadata.rb
@@ -718,6 +732,7 @@ files:
718
732
  - lib/expressir/schema_manifest_entry.rb
719
733
  - lib/expressir/version.rb
720
734
  - lib/tasks/conformance.rake
735
+ - lib/tasks/instance.rake
721
736
  - lib/tasks/reference.rake
722
737
  - lib/tasks/verify_remarks.rake
723
738
  - rakelib/native.rake