expressir 2.4.5 → 2.4.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 +4 -4
- data/TODO.parity-ee/00-overview.md +18 -0
- data/TODO.parity-ee/12-full-check-catalog.md +67 -0
- data/TODO.parity-ee/13-population-p21.md +54 -0
- data/TODO.parity-ee/14-shtolo-completion.md +44 -0
- data/TODO.parity-ee/15-part28-xml.md +51 -0
- data/TODO.parity-ee/16-compare-patch.md +48 -0
- data/TODO.parity-ee/17-official-tests.md +42 -0
- data/expressir.gemspec +1 -1
- data/lib/expressir/express/shtolo.rb +129 -1
- data/lib/expressir/version.rb +1 -1
- metadata +10 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d4cb3a63d16dd31f57a8050366d6b9d9d4e442d65e7df44c01f5edad8f330565
|
|
4
|
+
data.tar.gz: f234902848350d1abbca9aef98c0ca2bd562fe19463a51e395ec53688ef4e72b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f25c7bf185356ceaea4a9ac257683ef56db6f24923baa6f00e3a566b8e923de2b18500fa8e9b20173b4a83d90a94aa92a2f3fda2dc239fc0eba900bd713ea23d
|
|
7
|
+
data.tar.gz: 0d310df7b81ada4f9a0a9c73a1e962c100af3082b9911d7c88430de01016a2566a2ff42e30f1b94b6a256c6bd50a5d05263c52e1ff667e0f3798d0958546ac0e
|
|
@@ -56,3 +56,21 @@ SHTOLO paper, BNFs, DTDs)
|
|
|
56
56
|
`docs/issues/` — bug corpus incl. a shtolo old-vs-new differential;
|
|
57
57
|
`docs/` — SHTOLO paper PDF, Part 11/14/21 BNFs, XML DTDs,
|
|
58
58
|
interface/qualify notes; `00check.txt` — check design notes.
|
|
59
|
+
|
|
60
|
+
## Phase 2 — full eengine parity (2026-09-22, user-directed)
|
|
61
|
+
|
|
62
|
+
| # | plan | status |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| 12 | full check-p11 catalog port | planned |
|
|
65
|
+
| 13 | population / Part 21 validation | planned |
|
|
66
|
+
| 14 | SHTOLO completion (Annex G + corpus differential) | in progress |
|
|
67
|
+
| 15 | Part 28 XML + SMRL index | planned |
|
|
68
|
+
| 16 | schema compare & patch | planned |
|
|
69
|
+
| 17 | official test-case incorporation | standing structure |
|
|
70
|
+
|
|
71
|
+
Execution order: 14 (finish Shtolo) → 12 (checks) → 15 (XML index)
|
|
72
|
+
→ 16 (compare) → 13 (population, biggest). Each slice ships a PR and
|
|
73
|
+
a patch release as it lands ("release as we go"). Reference repos:
|
|
74
|
+
`~/src/external/exp-engine-engine` (oracle), `~/src/mn/iso-10303-11`
|
|
75
|
+
(normative text), `~/src/mn/iso-10303-detached-docs` (Parts 21/28
|
|
76
|
+
sources and fixtures).
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# 12 — Full check-p11 catalog port (eeng `kernel/check.lisp`)
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Bring `Expressir::Express::Checker` from the current documented subset
|
|
6
|
+
to the full eeng check-p11 catalog: every note eeng 5.1.0 emits over
|
|
7
|
+
the SRL/SMRL corpora, with note ids and severities aligned so oracle
|
|
8
|
+
differentials stay cross-referenceable.
|
|
9
|
+
|
|
10
|
+
## Current subset (shipped)
|
|
11
|
+
|
|
12
|
+
check-schema-interface-redundant, check-schema-iface-resource-duplicate,
|
|
13
|
+
check-subtype-ref, check-subtype-cycle (path-tracked DFS),
|
|
14
|
+
check-duplicate-declaration, check-where-name-pattern,
|
|
15
|
+
check-unique-name-pattern, check-unresolved-ref,
|
|
16
|
+
check-select-extended-type, check-enumeration-extended-type,
|
|
17
|
+
check-self-schema-reference (#125), parse-failure → nonzero exit.
|
|
18
|
+
|
|
19
|
+
## Sources
|
|
20
|
+
|
|
21
|
+
- `~/src/external/exp-engine-engine/kernel/check.lisp` (835 lines,
|
|
22
|
+
`check-p11` generic + per-node-type methods) and
|
|
23
|
+
`kernel/check-notes.lisp` (note catalog).
|
|
24
|
+
- ISO 10303-11:2004 clause text — `~/src/mn/iso-10303-11/sources/sections/`
|
|
25
|
+
(each ported check cites its clause).
|
|
26
|
+
- Existing plan: `07-semantic-checks-port.md`; current impl
|
|
27
|
+
`lib/expressir/express/checker.rb`.
|
|
28
|
+
|
|
29
|
+
## Design
|
|
30
|
+
|
|
31
|
+
1. **Catalog extraction**: enumerate every `post-message` site in
|
|
32
|
+
check.lisp/check-notes.lisp → (note-id, severity, node type,
|
|
33
|
+
message shape). Commit as `spec/fixtures/eeng/check-catalog.md`
|
|
34
|
+
with our coverage column; CI gate diffs the catalog against the
|
|
35
|
+
oracle so new eeng notes surface.
|
|
36
|
+
2. **Port order** (by eeng's own walk): schema-level (interfaces,
|
|
37
|
+
constants) → entity (supertype/subtype-of, attributes, derives,
|
|
38
|
+
inverses, uniques, wheres) → type (select/enumeration/aggregate
|
|
39
|
+
bounds) → function/procedure/rule bodies (expression typing lite:
|
|
40
|
+
arity/name resolution of called functions, built-ins from BUILTINS,
|
|
41
|
+
variable scoping via ScopeResolver) → attribute-level
|
|
42
|
+
redeclaration consistency (redispatches, `SELF\` qualifiers).
|
|
43
|
+
3. **Differential gate**: run eeng `--validate` and our `validate
|
|
44
|
+
check` over the SRL corpus + module arm/mim set; every corpus file
|
|
45
|
+
must produce the SAME note-id multiset (message text may differ).
|
|
46
|
+
Land as `checker_eeng_full_catalog_differential_spec`
|
|
47
|
+
(production_scale-tagged for the big corpus; small fixtures in the
|
|
48
|
+
default suite).
|
|
49
|
+
4. **Severity mapping** table: eeng `:error/:warning` → ours verbatim.
|
|
50
|
+
|
|
51
|
+
## Acceptance
|
|
52
|
+
|
|
53
|
+
- Catalog file lists 100% of eeng note ids with status columns.
|
|
54
|
+
- SRL differential: zero unexplained note-id mismatches.
|
|
55
|
+
- `validate check` docs updated (README table).
|
|
56
|
+
|
|
57
|
+
## Test cases
|
|
58
|
+
|
|
59
|
+
- eeng `docs/issues/` corpus inputs; qualify loops
|
|
60
|
+
(`scripts/qual-*.sh`) over resources.lst/modules.lst.
|
|
61
|
+
- Per-clause unit fixtures citing ISO 10303-11 clause numbers.
|
|
62
|
+
|
|
63
|
+
## Release checkpoint
|
|
64
|
+
|
|
65
|
+
PR + expressir patch release once the entity/type/schema tiers land
|
|
66
|
+
(expression-tier notes may follow in a second PR — keep the catalog
|
|
67
|
+
honest about which tier each note belongs to).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# 13 — Population / Part 21 instance validation
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Validate STEP Part 21 instance data (.stp/.p21) against a loaded
|
|
6
|
+
schema — eeng's core strength (`--validate` with population), absent
|
|
7
|
+
from expressir today.
|
|
8
|
+
|
|
9
|
+
## Sources
|
|
10
|
+
|
|
11
|
+
- ISO 10303-21: exchange structure grammar — BNF in
|
|
12
|
+
`~/src/mn/iso-10303-detached-docs/sources/iso-10303-21*/` (and
|
|
13
|
+
eeng's copy under `plugins/p21/`, incl. its parser + validation).
|
|
14
|
+
- eeng: `plugins/p21/` (p21 reader, population), `--validate`
|
|
15
|
+
(`run-op` population path), `wo-xml.lisp` instance-side references.
|
|
16
|
+
- eeng banner: population validation "not fully supported" upstream —
|
|
17
|
+
our target is the supported subset, documented precisely.
|
|
18
|
+
|
|
19
|
+
## Design (scope ladder; each step ships)
|
|
20
|
+
|
|
21
|
+
1. **P21 reader**: parsanol grammar for the exchange structure
|
|
22
|
+
(header entities + DATA section: complex entity `(`name(...)`)`,
|
|
23
|
+
entity instances, list/set values, typed refs `#1`, enums `.T.`,
|
|
24
|
+
binary `\"..."`, redefines `/`). Emit a Population model
|
|
25
|
+
(`Model::Population`): instances with entity name + attribute
|
|
26
|
+
values keyed by explicit attribute position.
|
|
27
|
+
2. **Structural validation**: every instance maps to a known entity
|
|
28
|
+
in the schema closure (complex entities → all parts); attribute
|
|
29
|
+
arity matches; value kinds match declared types (aggregate bounds,
|
|
30
|
+
select members, string/binary widths, REAL precision) — the
|
|
31
|
+
aggregate of eeng's population notes.
|
|
32
|
+
3. **Constraint validation**: UNIQUE rules (per-entity + inherited),
|
|
33
|
+
WHERE rules — evaluation needs an EXPRESS expression interpreter;
|
|
34
|
+
reuse/extend the `benchmark`/expression-walk machinery, evaluate
|
|
35
|
+
over instance bindings (scope: no INVERSE/derives first).
|
|
36
|
+
4. **CLI**: `expressir validate population SCHEMA -p DATA.p21`,
|
|
37
|
+
JSON/plain reports aligned with Checker notes.
|
|
38
|
+
|
|
39
|
+
## Acceptance
|
|
40
|
+
|
|
41
|
+
- Official Part 21 test corpora parse + validate (see tests).
|
|
42
|
+
- Differential vs eeng `--validate` on shared fixtures: same
|
|
43
|
+
accept/reject decision and note ids.
|
|
44
|
+
|
|
45
|
+
## Test cases
|
|
46
|
+
|
|
47
|
+
- ISO 10303-21 validation suite files from detached-docs where
|
|
48
|
+
available; else eeng `tests/` + `scripts/test-tt*.sh` fixtures.
|
|
49
|
+
- Hand fixtures: arity mismatch, bad enum, UNIQUE collision, WHERE
|
|
50
|
+
failure, complex-entity mismatch.
|
|
51
|
+
|
|
52
|
+
## Release checkpoint
|
|
53
|
+
|
|
54
|
+
Steps 1–2 = first release (structural validator); step 3 second.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# 14 — SHTOLO completion (expressir#32, Annex G)
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Finish `Expressir::Express::Shtolo` to full Annex G conformance and
|
|
6
|
+
close the eeng differential over the whole corpus. Current state:
|
|
7
|
+
G.1 + G.2 stages implemented (522 lines), suite green (10 examples),
|
|
8
|
+
`extenders:` :all/:none matches the eeng-default split.
|
|
9
|
+
|
|
10
|
+
## Remaining work
|
|
11
|
+
|
|
12
|
+
1. **Rule audit**: walk `spec/fixtures/shtolo/annex-g-rules.md`
|
|
13
|
+
(G.NM.1-2, G.1.1-10, G.2.1-7) and mark every rule PASS/partial/✖
|
|
14
|
+
in the file; a fixture per rule. Known-thin areas from the audit:
|
|
15
|
+
- G.1.6 dependently-instantiable rule output (function + WHERE
|
|
16
|
+
wiring) — verify against Annex G text, not eeng (eeng ✖).
|
|
17
|
+
- name-munging policy (`_dot_` and friends) — eeng ✖; standard wins.
|
|
18
|
+
- prune pass reachability (unreachable subtype branches).
|
|
19
|
+
2. **Corpus differential**: for every module arm/mim in modules.lst,
|
|
20
|
+
compare our flatten output to `eengine --flat` (eeng default =
|
|
21
|
+
`extenders: :none` shape); classify divergences
|
|
22
|
+
standard-conformant vs bug. Feed the mismatch corpus into specs.
|
|
23
|
+
3. **Scale**: SMRL full set flatten over the compiled-set warm model;
|
|
24
|
+
memory ceiling documented.
|
|
25
|
+
4. **CLI**: `expressir shtolo MANIFEST -o longform.exp` (root schema
|
|
26
|
+
+ closure resolution reuses ParityInputs).
|
|
27
|
+
|
|
28
|
+
## Acceptance
|
|
29
|
+
|
|
30
|
+
- Every Annex G rule has a green fixture.
|
|
31
|
+
- Corpus differential: zero unexplained diffs; every explained
|
|
32
|
+
divergence documented in `parity-matrix.md`.
|
|
33
|
+
- SMRL flatten completes; output parses under the 1994 profile.
|
|
34
|
+
|
|
35
|
+
## Test cases
|
|
36
|
+
|
|
37
|
+
- annex-g-rules.md fixtures; eeng `docs/issues/bug39` shtolo outputs
|
|
38
|
+
(old-vs-new vs stepcode exppp); `scripts/qual-*.sh` loops;
|
|
39
|
+
`pretty-test.sh` ap209/210/242 × arm/mim shape checks.
|
|
40
|
+
|
|
41
|
+
## Release checkpoint
|
|
42
|
+
|
|
43
|
+
One PR per coherent slice (rule audit + fixtures; differential gate;
|
|
44
|
+
CLI), patch releases as each merges.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# 15 — EXPRESS → XML (ISO 10303-28 / eeng --xml)
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Generate XML Schema output for a schema (expressir#276): eeng's
|
|
6
|
+
`--xml` (`wo-xml-p11.lisp`) plus the SMRL index listing
|
|
7
|
+
(`wo-smrl-xml.lisp`, feeds the SMRL document set).
|
|
8
|
+
|
|
9
|
+
## Sources
|
|
10
|
+
|
|
11
|
+
- ISO 10303-28:2007 ( EXPRESS-driven XML representation) — detached
|
|
12
|
+
docs `~/src/mn/iso-10303-detached-docs/sources/iso-10303-28*/`;
|
|
13
|
+
eeng `docs/` carries `express_model.dtd` + module.dtd (legacy
|
|
14
|
+
forms).
|
|
15
|
+
- eeng: `plugins/p11/wo-xml-p11.lisp` (schema → XSD),
|
|
16
|
+
`wo-smrl-xml.lisp` (SMRL index XML), `--xml` run-op.
|
|
17
|
+
- Consumer: iso-10303 repo's `schemas/data/*.xml` SMRL pages
|
|
18
|
+
(rendered by metanorma today) — our output must be drop-in for
|
|
19
|
+
that pipeline.
|
|
20
|
+
|
|
21
|
+
## Design
|
|
22
|
+
|
|
23
|
+
1. **SMRL index XML first** (small, high value for iso-10303): the
|
|
24
|
+
index of all schemas in a repository (name, file, interfaces,
|
|
25
|
+
counts) as the repo's data-layer source — replaces the
|
|
26
|
+
hand-maintained entries.
|
|
27
|
+
2. **express2xsd**: schema → XSD via a declarative mapping table
|
|
28
|
+
(entity → element+complexType, type → simpleType/complexType,
|
|
29
|
+
select → choice, explicit attrs in order, supertype substitution
|
|
30
|
+
groups for SUBTYPE OF, aggregates → minOccurs/maxOccurs). Emit
|
|
31
|
+
through a Nokogiri-free XML writer (ROXML via lutaml-model where
|
|
32
|
+
it fits; hand-rolled tree otherwise — the mapping is the product,
|
|
33
|
+
not the serialization).
|
|
34
|
+
3. **CLI**: `expressir xml SCHEMA -o schema.xsd`;
|
|
35
|
+
`expressir xml-index REPO -o smrl.xml`.
|
|
36
|
+
|
|
37
|
+
## Acceptance
|
|
38
|
+
|
|
39
|
+
- Output validates against the Part 28 reference XSDs (detached
|
|
40
|
+
docs) for the fixture set; xsd diff vs eeng --xml on SRL corpus
|
|
41
|
+
classified standard-vs-eeng.
|
|
42
|
+
- iso-10303 SMRL pages render from our generated index unchanged.
|
|
43
|
+
|
|
44
|
+
## Test cases
|
|
45
|
+
|
|
46
|
+
- eeng `scripts/build-xml.sh` full-corpus reference outputs;
|
|
47
|
+
`test-tt{,1}.sh` (XML + Saxon HTM chain) as end-to-end smoke.
|
|
48
|
+
|
|
49
|
+
## Release checkpoint
|
|
50
|
+
|
|
51
|
+
SMRL index first (unblocks iso-10303 pipeline), express2xsd second.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# 16 — Schema compare & patch (eeng --compare / --patch)
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Structural diff of two schemata with a machine-applicable patch
|
|
6
|
+
output — eeng `--compare` (+ `--concat_compare`, `--patch`,
|
|
7
|
+
`--patch_schema_name`), used by WG12 to track schema revisions.
|
|
8
|
+
|
|
9
|
+
## Sources
|
|
10
|
+
|
|
11
|
+
- eeng `plugins/p11/wo-*.lisp` compare entry (`run-op (:compare)`
|
|
12
|
+
in top-level.lisp) and patch application paths; mode args:
|
|
13
|
+
`:trial_schema :reference_schema :xml-output :patch-output`.
|
|
14
|
+
- Semantics baseline: declaration-level matching by id within the
|
|
15
|
+
flattened/concatenated form (eeng compares post-concat shapes for
|
|
16
|
+
shortforms).
|
|
17
|
+
|
|
18
|
+
## Design
|
|
19
|
+
|
|
20
|
+
1. **Model diff** on the resolved repositories: declarations matched
|
|
21
|
+
by canonical path (`schema.item`); kinds of delta — added,
|
|
22
|
+
removed, changed (per-attribute structural diff: types,
|
|
23
|
+
attribute lists, where/unique bodies via formatted-text
|
|
24
|
+
comparison first, structural second).
|
|
25
|
+
2. **Outputs**: unified-ish text report (human), XML
|
|
26
|
+
(`--xml-output` parity), and patch script (the eeng patch
|
|
27
|
+
format: rename/redefine vocabulary it defines — ported from
|
|
28
|
+
wo-patch output shapes).
|
|
29
|
+
3. **CLI**: `expressir compare TRIAL.exp REFERENCE.exp [--xml|--patch]`;
|
|
30
|
+
`concat-compare` rides the Concatenator for shortform pairs.
|
|
31
|
+
4. **Patch application**: apply a patch file to a model (rename
|
|
32
|
+
declarations, remap interfaces) — the write-back side eeng uses
|
|
33
|
+
for round-trip patching.
|
|
34
|
+
|
|
35
|
+
## Acceptance
|
|
36
|
+
|
|
37
|
+
- SRL corpus self-compare = empty diff; mutated fixtures (rename,
|
|
38
|
+
add/remove attr, retype) produce the expected delta kinds.
|
|
39
|
+
- Differential vs eeng `--compare` XML on the same pairs.
|
|
40
|
+
|
|
41
|
+
## Test cases
|
|
42
|
+
|
|
43
|
+
- eeng `docs/issues/` pairs; hand-mutated fixture ladder; the
|
|
44
|
+
`--concat_compare` module-vs-module pairs from scripts.
|
|
45
|
+
|
|
46
|
+
## Release checkpoint
|
|
47
|
+
|
|
48
|
+
Text+XML diff first release; patch apply second.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# 17 — Official test-case incorporation
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
One place that maps every OFFICIAL/reference test corpus to our
|
|
6
|
+
specs, and CI gates that run the tractable tier on every push.
|
|
7
|
+
|
|
8
|
+
## Corpora
|
|
9
|
+
|
|
10
|
+
1. **eeng suite** (already imported, `spec/fixtures/eeng/`):
|
|
11
|
+
`scripts/*.sh` 14 drivers (qual-arm/mod/res loops, pretty-test.sh
|
|
12
|
+
ap209/210/242 × arm/mim × shortform/longform, ap210 giant file,
|
|
13
|
+
test-tt{,1}.sh XML chain, build-xml.sh), `docs/issues/` bug
|
|
14
|
+
corpus (bug39 shtolo old-vs-new vs stepcode exppp; bug40 pretty
|
|
15
|
+
expressions), `qualify.txt`, `interfaces.txt`, `00check.txt`.
|
|
16
|
+
2. **ISO 10303-11** grammar/conformance sources:
|
|
17
|
+
`~/src/mn/iso-10303-11/sources/sections/` — Annex G rules
|
|
18
|
+
(fixtures live in `spec/fixtures/shtolo/annex-g-rules.md`),
|
|
19
|
+
syntax annexes for negative/positive grammar tests.
|
|
20
|
+
3. **ISO detached docs** `~/src/mn/iso-10303-detached-docs/sources/
|
|
21
|
+
iso-10303-*`: Part 21 exchange-structure fixtures (population),
|
|
22
|
+
Part 28 reference XSDs (XML), Part 22 (SDAI vocabulary, later).
|
|
23
|
+
4. **SRL/SMRL corpora** (`resources.lst`/`modules.lst` names match
|
|
24
|
+
our checkout): the differential tier.
|
|
25
|
+
|
|
26
|
+
## Structure
|
|
27
|
+
|
|
28
|
+
- `spec/expressir/eeng_parity/` — one spec per capability matrix
|
|
29
|
+
row; each example tags its source corpus file in a comment.
|
|
30
|
+
- Tiering: `:fast` (fixtures, every push) / `:corpus`
|
|
31
|
+
(SRL differential, nightly or manual tag `production_scale`) /
|
|
32
|
+
`:smoke_eeng` (runs the local eeng oracle when the binary exists —
|
|
33
|
+
skipped otherwise).
|
|
34
|
+
- `rake parity:status` prints the capability × corpus matrix with
|
|
35
|
+
green/gray cells — the single progress view.
|
|
36
|
+
|
|
37
|
+
## Rules
|
|
38
|
+
|
|
39
|
+
- No test is added without its provenance row in the fixture dir's
|
|
40
|
+
PROVENANCE.md (established practice, keep it).
|
|
41
|
+
- Oracle outputs are regenerated, never hand-edited; the regeneration
|
|
42
|
+
command lives next to each golden.
|
data/expressir.gemspec
CHANGED
|
@@ -36,7 +36,7 @@ Gem::Specification.new do |spec|
|
|
|
36
36
|
spec.add_dependency "benchmark-ips"
|
|
37
37
|
spec.add_dependency "csv"
|
|
38
38
|
spec.add_dependency "liquid"
|
|
39
|
-
spec.add_dependency "lutaml-model", "~> 0.8.
|
|
39
|
+
spec.add_dependency "lutaml-model", "~> 0.8.50"
|
|
40
40
|
spec.add_dependency "moxml"
|
|
41
41
|
spec.add_dependency "nokogiri"
|
|
42
42
|
spec.add_dependency "paint"
|
|
@@ -33,12 +33,21 @@ module Expressir
|
|
|
33
33
|
# closure into its base type (Annex G.2.3/G.2.4);
|
|
34
34
|
# :none leaves extensible types exactly as declared —
|
|
35
35
|
# the shape eengine's default --flat emits.
|
|
36
|
+
# `prune` — true (default) runs the G.1.9 prune pass;
|
|
37
|
+
# false keeps the artifact's full declaration set.
|
|
38
|
+
# `stage` — :longform (default) runs the G.2 rewrites;
|
|
39
|
+
# :artifact stops after stage 1 — the annex's
|
|
40
|
+
# intermediate schema, the shape eengine's
|
|
41
|
+
# --concat_schema output corresponds to (copy
|
|
42
|
+
# pass, no prune, no 1994 rewrite).
|
|
36
43
|
def initialize(root_schema, repository, longform_name: nil,
|
|
37
|
-
extenders: :all)
|
|
44
|
+
extenders: :all, prune: true, stage: :longform)
|
|
38
45
|
@root = root_schema
|
|
39
46
|
@repository = repository
|
|
40
47
|
@longform_name = longform_name || @root.id
|
|
41
48
|
@extenders = extenders
|
|
49
|
+
@prune = prune
|
|
50
|
+
@stage = stage
|
|
42
51
|
@reference_entities = [] # G.1.6 entities
|
|
43
52
|
end
|
|
44
53
|
|
|
@@ -274,6 +283,8 @@ module Expressir
|
|
|
274
283
|
|
|
275
284
|
def build_longform
|
|
276
285
|
artifact = build_artifact
|
|
286
|
+
prune!(artifact) if @prune
|
|
287
|
+
return artifact if @stage == :artifact
|
|
277
288
|
|
|
278
289
|
if @extenders == :all
|
|
279
290
|
resolve_extensible_enumerations!(artifact)
|
|
@@ -288,6 +299,123 @@ module Expressir
|
|
|
288
299
|
artifact
|
|
289
300
|
end
|
|
290
301
|
|
|
302
|
+
# G.1.9 prune pass: the artifact keeps only what stays visible
|
|
303
|
+
# and reachable. Runs before the stage-2 rewrites so they never
|
|
304
|
+
# see declarations the longform would drop.
|
|
305
|
+
def prune!(schema)
|
|
306
|
+
visible_ids = visible_declaration_ids(schema)
|
|
307
|
+
|
|
308
|
+
# rules whose parameter entities are not all visible
|
|
309
|
+
schema.rules = schema.rules.reject do |rule|
|
|
310
|
+
Array(rule.applies_to).any? do |ref|
|
|
311
|
+
id = ref.is_a?(String) ? ref : ref.id
|
|
312
|
+
id && !visible_ids.key?(id.safe_downcase)
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# select items pointing at declarations the artifact lacks
|
|
317
|
+
schema.types.each do |type|
|
|
318
|
+
next unless type.underlying_type.is_a?(Model::DataTypes::Select)
|
|
319
|
+
|
|
320
|
+
items = Array(type.underlying_type.items)
|
|
321
|
+
kept = items.select do |item|
|
|
322
|
+
item.id.nil? || visible_ids.key?(item.id.safe_downcase)
|
|
323
|
+
end
|
|
324
|
+
# An emptied select disappears from the representation
|
|
325
|
+
# (annex G.1.9 s1/s2/s3 example).
|
|
326
|
+
type.underlying_type.items = kept unless kept.empty? && items.empty?
|
|
327
|
+
if kept.empty? && !items.empty?
|
|
328
|
+
type.underlying_type = nil
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
schema.types = schema.types.reject { |t| t.underlying_type.nil? }
|
|
332
|
+
|
|
333
|
+
# functions/procedures nothing calls, to fixpoint (a helper only
|
|
334
|
+
# a dropped function called is itself unreachable)
|
|
335
|
+
loop do
|
|
336
|
+
called = called_ids(schema)
|
|
337
|
+
drop = schema.functions.any? { |f| !called[f.id.safe_downcase] } ||
|
|
338
|
+
schema.procedures.any? { |p| !called[p.id.safe_downcase] }
|
|
339
|
+
break unless drop
|
|
340
|
+
|
|
341
|
+
schema.functions = schema.functions.select { |f| called[f.id.safe_downcase] }
|
|
342
|
+
schema.procedures = schema.procedures.select { |p| called[p.id.safe_downcase] }
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
prune_supertype_expressions!(schema, visible_ids)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def visible_declaration_ids(schema)
|
|
349
|
+
all_decls(schema).each_with_object({}) do |decl, hash|
|
|
350
|
+
hash[decl.id.safe_downcase] = true if decl.respond_to?(:id) && decl.id
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# Every identifier a FunctionCall site names, across the
|
|
355
|
+
# artifact's surviving declarations.
|
|
356
|
+
def called_ids(schema)
|
|
357
|
+
called = {}
|
|
358
|
+
each_node(schema) do |node|
|
|
359
|
+
next unless node.is_a?(Model::Expressions::FunctionCall)
|
|
360
|
+
|
|
361
|
+
ref = node.function
|
|
362
|
+
id = ref.is_a?(String) ? ref : ref&.id
|
|
363
|
+
called[id.safe_downcase] = true if id
|
|
364
|
+
end
|
|
365
|
+
called
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
# Annex C reductions over supertype expressions: references to
|
|
369
|
+
# invisible entities leave ONEOF; ONEOF(a) => a; AND/OR sides
|
|
370
|
+
# that become empty collapse; a vacuous expression deletes the
|
|
371
|
+
# constraint.
|
|
372
|
+
def prune_supertype_expressions!(schema, visible_ids)
|
|
373
|
+
keep = []
|
|
374
|
+
schema.subtype_constraints.each do |constraint|
|
|
375
|
+
expr = constraint.supertype_expression
|
|
376
|
+
if expr.nil?
|
|
377
|
+
# total-over-only constraints carry no expression; stage 2
|
|
378
|
+
# turns their TOTAL_OVER into a rule.
|
|
379
|
+
keep << constraint
|
|
380
|
+
next
|
|
381
|
+
end
|
|
382
|
+
reduced = reduce_supertype_expression(expr, visible_ids)
|
|
383
|
+
# Annex C: a vacuous expression deletes the constraint.
|
|
384
|
+
next if reduced.nil?
|
|
385
|
+
|
|
386
|
+
constraint.supertype_expression = reduced
|
|
387
|
+
keep << constraint
|
|
388
|
+
end
|
|
389
|
+
schema.subtype_constraints = keep
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def reduce_supertype_expression(expr, visible_ids)
|
|
393
|
+
case expr
|
|
394
|
+
when Model::SupertypeExpressions::OneofSupertypeExpression
|
|
395
|
+
refs = Array(expr.operands).select do |ref|
|
|
396
|
+
id = ref.is_a?(String) ? ref : ref.id
|
|
397
|
+
id.nil? || visible_ids.key?(id.safe_downcase)
|
|
398
|
+
end
|
|
399
|
+
return nil if refs.empty?
|
|
400
|
+
|
|
401
|
+
refs.one? ? refs.first : reset_oneof(expr, refs)
|
|
402
|
+
when Model::SupertypeExpressions::BinarySupertypeExpression
|
|
403
|
+
left = reduce_supertype_expression(expr.operands[0], visible_ids)
|
|
404
|
+
right = reduce_supertype_expression(expr.operands[1], visible_ids)
|
|
405
|
+
return nil if left.nil? && right.nil?
|
|
406
|
+
|
|
407
|
+
left || right
|
|
408
|
+
else
|
|
409
|
+
expr
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
def reset_oneof(expr, refs)
|
|
414
|
+
copy = deep_copy(expr)
|
|
415
|
+
copy.operands = refs
|
|
416
|
+
copy
|
|
417
|
+
end
|
|
418
|
+
|
|
291
419
|
def resolve_extensible_enumerations!(schema)
|
|
292
420
|
schema.types.select do |t|
|
|
293
421
|
t.underlying_type.is_a?(Model::DataTypes::Enumeration) && t.underlying_type.extensible
|
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.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-09-
|
|
11
|
+
date: 2026-09-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|
|
@@ -86,14 +86,14 @@ dependencies:
|
|
|
86
86
|
requirements:
|
|
87
87
|
- - "~>"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: 0.8.
|
|
89
|
+
version: 0.8.50
|
|
90
90
|
type: :runtime
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: 0.8.
|
|
96
|
+
version: 0.8.50
|
|
97
97
|
- !ruby/object:Gem::Dependency
|
|
98
98
|
name: moxml
|
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -312,6 +312,12 @@ files:
|
|
|
312
312
|
- TODO.parity-ee/09-smrl-index-and-listing.md
|
|
313
313
|
- TODO.parity-ee/10-interface-dot-graph.md
|
|
314
314
|
- TODO.parity-ee/11-import-eeng-tests.md
|
|
315
|
+
- TODO.parity-ee/12-full-check-catalog.md
|
|
316
|
+
- TODO.parity-ee/13-population-p21.md
|
|
317
|
+
- TODO.parity-ee/14-shtolo-completion.md
|
|
318
|
+
- TODO.parity-ee/15-part28-xml.md
|
|
319
|
+
- TODO.parity-ee/16-compare-patch.md
|
|
320
|
+
- TODO.parity-ee/17-official-tests.md
|
|
315
321
|
- TODO.parity-ee/parity-matrix.md
|
|
316
322
|
- benchmark/srl_benchmark.rb
|
|
317
323
|
- benchmark/srl_native_benchmark.rb
|