expressir 2.4.31-arm-linux → 2.4.36-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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/conformance.yml +34 -0
  3. data/.gitignore +3 -0
  4. data/Gemfile +1 -1
  5. data/TODO.eengine/00-overview.md +39 -0
  6. data/TODO.eengine/01-resolution-diagnostics.md +30 -0
  7. data/TODO.eengine/02-check-catalog-completion.md +53 -0
  8. data/TODO.eengine/03-entity-computations.md +22 -0
  9. data/TODO.eengine/04-shtolo-rule-audit.md +32 -0
  10. data/TODO.eengine/05-shtolo-longform-flatten.md +12 -0
  11. data/TODO.eengine/06-population-p21.md +34 -0
  12. data/TODO.eengine/07-schema-compare-patch.md +25 -0
  13. data/TODO.eengine/08-official-corpus-gate.md +7 -0
  14. data/TODO.eengine/09-mim-mapping-parser.md +9 -0
  15. data/TODO.parity-ee/00-overview.md +1 -1
  16. data/TODO.sota/00-overview.md +57 -0
  17. data/TODO.sota/01-type-checking.md +115 -0
  18. data/TODO.sota/02-evaluator.md +86 -0
  19. data/TODO.sota/03-conformance.md +53 -0
  20. data/TODO.sota/04-lsp.md +70 -0
  21. data/TODO.sota/05-interop.md +55 -0
  22. data/TODO.sota/06-dialects.md +57 -0
  23. data/TODO.sota/07-reference-artifacts.md +55 -0
  24. data/TODO.suma-improvements/07-part28-xml.md +10 -13
  25. data/docs/_guides/interop/index.adoc +25 -0
  26. data/docs/_guides/interop/json-schema.adoc +88 -0
  27. data/docs/_guides/interop/owl-rdf.adoc +87 -0
  28. data/docs/_guides/reference/checker-notes.adoc +55 -0
  29. data/docs/_guides/reference/checker.adoc +36 -0
  30. data/docs/_guides/reference/evaluator.adoc +40 -0
  31. data/docs/_guides/reference/grammar-crosswalk.adoc +299 -0
  32. data/docs/_guides/reference/index.adoc +22 -0
  33. data/docs/_guides/reference/lsp.adoc +41 -0
  34. data/docs/_guides/reference/p21.adoc +30 -0
  35. data/docs/_guides/reference/shtolo.adoc +36 -0
  36. data/exe/expressir-lsp +6 -0
  37. data/expressir.gemspec +2 -2
  38. data/lib/expressir/3.2/expressir_core.so +0 -0
  39. data/lib/expressir/3.3/expressir_core.so +0 -0
  40. data/lib/expressir/3.4/expressir_core.so +0 -0
  41. data/lib/expressir/4.0/expressir_core.so +0 -0
  42. data/lib/expressir/cli.rb +25 -0
  43. data/lib/expressir/commands/check.rb +3 -1
  44. data/lib/expressir/commands/export_json_schema.rb +29 -0
  45. data/lib/expressir/commands/export_owl.rb +26 -0
  46. data/lib/expressir/commands/smrl_xml_index.rb +25 -0
  47. data/lib/expressir/commands/validate.rb +3 -0
  48. data/lib/expressir/commands.rb +3 -0
  49. data/lib/expressir/conformance/trend.rb +100 -0
  50. data/lib/expressir/conformance.rb +8 -0
  51. data/lib/expressir/eval/environment.rb +83 -0
  52. data/lib/expressir/eval/expression.rb +610 -0
  53. data/lib/expressir/eval/interpreter.rb +316 -0
  54. data/lib/expressir/eval/rules.rb +88 -0
  55. data/lib/expressir/eval/values.rb +74 -0
  56. data/lib/expressir/eval.rb +17 -0
  57. data/lib/expressir/express/builder.rb +17 -5
  58. data/lib/expressir/express/builders/entity_decl_builder.rb +17 -5
  59. data/lib/expressir/express/builders/expression_builder.rb +9 -1
  60. data/lib/expressir/express/checker.rb +970 -5
  61. data/lib/expressir/express/dialect.rb +44 -0
  62. data/lib/expressir/express/formatters/declarations_formatter.rb +21 -14
  63. data/lib/expressir/express/formatters/expressions_formatter.rb +4 -1
  64. data/lib/expressir/express/parser.rb +9 -4
  65. data/lib/expressir/express/pretty_formatter.rb +9 -14
  66. data/lib/expressir/express/schema_compare.rb +194 -0
  67. data/lib/expressir/express/shtolo.rb +194 -63
  68. data/lib/expressir/express.rb +3 -0
  69. data/lib/expressir/interop/json_schema.rb +195 -0
  70. data/lib/expressir/interop/owl.rb +216 -0
  71. data/lib/expressir/interop.rb +13 -0
  72. data/lib/expressir/lsp/document.rb +226 -0
  73. data/lib/expressir/lsp/server.rb +184 -0
  74. data/lib/expressir/lsp/workspace.rb +402 -0
  75. data/lib/expressir/lsp.rb +11 -0
  76. data/lib/expressir/model/declarations/entity.rb +132 -0
  77. data/lib/expressir/model/declarations/schema.rb +37 -6
  78. data/lib/expressir/p21/builder.rb +92 -0
  79. data/lib/expressir/p21/grammar.rb +107 -0
  80. data/lib/expressir/p21/parser.rb +16 -0
  81. data/lib/expressir/p21/population.rb +35 -0
  82. data/lib/expressir/p21/validator.rb +213 -0
  83. data/lib/expressir/p21.rb +17 -0
  84. data/lib/expressir/reference/grammar_crosswalk.rb +122 -0
  85. data/lib/expressir/reference/grammar_crosswalk.yml +800 -0
  86. data/lib/expressir/reference/note_catalog.rb +54 -0
  87. data/lib/expressir/reference.rb +10 -0
  88. data/lib/expressir/version.rb +1 -1
  89. data/lib/expressir.rb +5 -0
  90. data/lib/tasks/conformance.rake +27 -0
  91. data/lib/tasks/reference.rake +25 -0
  92. metadata +68 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e0e96e0c96035dcd1f531e9cba2ec3d3d31c875c1ef3b97864a55010d3398ed9
4
- data.tar.gz: eacc9eb8749354b913f1e3929fee3618562658a664322a536373a6f81c728747
3
+ metadata.gz: c72783e8f6c513d4cfa15112815f3891bb6ed64ab91ba221bba567c8b030a48e
4
+ data.tar.gz: 5caf683d6e94958d32e77eecca618f264ba47d41108aafec2fbee50face6ec02
5
5
  SHA512:
6
- metadata.gz: ac76423d1191ab399b20f2bf67a3401abfa79eae8067ec7273e3d361fd84c0f7a1cec4cfc91d372014c5086bb001da0b494319c3a7d3599bb0238df28e3a24f7
7
- data.tar.gz: 373681991da618c64633f61baecb30bcb8468f277bb40289a91b14e6ef57052825c6bf5735f3d3de8fbd321b1feb01d929ec9c9d27bf2ad06ff1feb30204d840
6
+ metadata.gz: 0676e389c413bb6ff53548d41c065f8da2dab6661fc5540b71a4819e8f983194365af904b8a6383c0af3ea31f07d233c5c6efadea24458674e97bc37f8d300f4
7
+ data.tar.gz: a038d633a4fc00ee2164e1f1e3453f5ef6477537ee1e40c3a9b1f67190d728e8a76a92f6a3081a75f8fc61f6a12e14c339b5dac8a7983b498f0291634c6a4124
@@ -0,0 +1,34 @@
1
+ name: conformance
2
+
3
+ on:
4
+ schedule:
5
+ - cron: "0 3 * * *"
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ conformance:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/checkout@v4
14
+ with:
15
+ repository: metanorma/iso-10303-stepmod
16
+ path: stepmod
17
+ sparse-checkout: data/resources
18
+ - uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: "3.4"
21
+ bundler-cache: true
22
+ - name: Round-trip conformance over the stepmod corpus
23
+ run: bundle exec rake conformance
24
+ env:
25
+ STEPMOD_DIR: ${{ github.workspace }}/stepmod
26
+ - name: Trended property metrics
27
+ run: bundle exec rake conformance:trend
28
+ env:
29
+ STEPMOD_DIR: ${{ github.workspace }}/stepmod
30
+ - name: Upload the trend artifact
31
+ uses: actions/upload-artifact@v4
32
+ with:
33
+ name: conformance-trend
34
+ path: conformance-trend.json
data/.gitignore CHANGED
@@ -53,3 +53,6 @@ Cargo.lock
53
53
  /lib/expressir/expressir_core.bundle
54
54
  /lib/expressir/expressir_core.so
55
55
  /lib/expressir/expressir_core.dll
56
+
57
+ # nightly conformance trend artifact (rake conformance:trend)
58
+ /conformance-trend.json
data/Gemfile CHANGED
@@ -6,7 +6,7 @@ gemspec
6
6
 
7
7
  gem "canon"
8
8
  gem "irb"
9
- gem "lutaml-model", "0.8.76"
9
+ gem "lutaml-model", "0.8.114"
10
10
  gem "openssl", "~> 3.0"
11
11
  gem "rake"
12
12
  gem "rake-compiler"
@@ -0,0 +1,39 @@
1
+ # TODO.eengine — the eengine-parity program
2
+
3
+ Consolidates the remaining eengine-parity tasks (formerly scattered
4
+ across TODO.parity-ee) into one execution-ordered series. The oracle
5
+ is eengine-5.1.0 (GIT eeng-5.1.0) at `~/src/external/exp-engine-engine`; where
6
+ eengine and ISO 10303-11 disagree, the standard wins and the
7
+ divergence is classified in the differential output.
8
+
9
+ ## Execution order and status
10
+
11
+ | n | task | folds | status |
12
+ |---|------|-------|--------|
13
+ | 01 | resolution diagnostics + USE/REFERENCE tiering | 06-remainder, 07-part | done |
14
+ | 02 | check-p11 catalog completion | 07, 12 | done (type-resolution tranche; generic unresolved-ref walk covers expression bodies; subtype-constraint supertype refs + SELF redeclaration resolution added; constness has no eeng rule — covered by the generic walk) |
15
+ | 03 | entity computations (inherited/derived/inverse closures) | matrix §3, 05-prereq | done |
16
+ | 04 | SHTOLO rule audit + corpus differential | 14-remainder | done (audit spec live; G.NM.2 + G.1.10 fixed; G.1.6 synthesis remains per annex-g-rules.md) |
17
+ | 05 | SHTOLO longform flatten (Annex G) | 05 | done |
18
+ | 06 | population / Part 21 reader + validation | 13 | done (parsanol reader; schema-mapping validator; Annex H corpus clean; eengine p21 differential blocked — eeng 5.1.0 aborts bare-p11 validate/*PARSE-MODE* NIL, every -MODE demands stepmod context) |
19
+ | 07 | schema compare & patch | 16 | done (SchemaCompare canonical-path deltas + SchemaPatch.apply; oracle differential vs eeng --compare green on add/remove entity/attribute + enum-value changes) |
20
+ | 08 | official corpus CI gate | 17 | done |
21
+ | 09 | MIM mapping parser | 18 | done |
22
+
23
+ ## Sources
24
+
25
+ - eengine: `~/src/external/exp-engine-engine` (kernel/*.lisp,
26
+ plugins/p11/*.lisp, plugins/p21/*).
27
+ - ISO 10303-11 clause text: `~/src/mn/iso-10303-11/sources/sections/`.
28
+ - Detached docs: `~/src/mn/iso-10303-detached-docs/sources/` (Part 21
29
+ grammar, Part 28 text).
30
+
31
+ ## Standing rules
32
+
33
+ - Semantics land in Ruby; parse-adjacent and graph-scale work lands in
34
+ expressir-rs (TODO.parity-ee 19, option B).
35
+ - Where eengine and the standard disagree, the standard wins; every
36
+ such divergence is classified in the differential output, never
37
+ silently copied.
38
+ - Every ported check keeps its eengine note id for oracle
39
+ cross-referencing, and cites its ISO 10303-11 clause.
@@ -0,0 +1,30 @@
1
+ # 01 — Resolution diagnostics + USE/REFERENCE tiering
2
+
3
+ Folds the shipped remainder of TODO.parity-ee 06 (transitive USE and
4
+ the cycle guard are in; `interface_visibility_spec.rb` gates them)
5
+ with the tiering half of 07.
6
+
7
+ ## Gaps
8
+
9
+ - USE FROM resolves **type + entity only**; REFERENCE FROM resolves
10
+ constant/entity/function/procedure/type (eeng
11
+ resolve-interface.lisp:30-66). Our resolution treats both alike.
12
+ - Unresolved resources: eeng hard-errors `Resource '~A' not found`;
13
+ we warn (severity folded here from 07).
14
+
15
+ ## Design
16
+
17
+ - `Schema#interfaced_items(kind:)` filters by interface kind.
18
+ - `Schema#resolve_item(name, kinds:)` walks own declarations then
19
+ interfaces (transitively through USE for :use-from scope),
20
+ cycle-guarded, honoring per-kind restriction.
21
+ - `Expressir::Express::Checker` reports unresolved references as
22
+ errors (`E-RES-001`, the eeng note id family) with schema+name.
23
+
24
+ ## Acceptance
25
+
26
+ - USE-only visibility: an interface's function is NOT visible through
27
+ USE FROM; IS visible through REFERENCE FROM.
28
+ - Transitive USE chains still resolve (06's shipped behavior).
29
+ - Cycle-guarded resolution terminates.
30
+ - The checker flags an unresolved USE FROM resource as an error.
@@ -0,0 +1,53 @@
1
+ # 02 — check-p11 catalog completion
2
+
3
+ Folds TODO.parity-ee 07 + 12. Shipped subset: interface redundant,
4
+ interface resource duplicate, subtype ref/cycle, duplicate
5
+ declaration, where/unique name pattern, unresolved ref, select/enumeration
6
+ extended type, self-schema reference, parse failure.
7
+
8
+ ## Sources
9
+
10
+ - `~/src/external/exp-engine-engine/kernel/check.lisp` (835 lines,
11
+ per-node-type check-p11 methods) + `kernel/check-notes.lisp`.
12
+ - ISO 10303-11:2004 clause text:
13
+ `~/src/mn/iso-10303-11/sources/sections/`.
14
+
15
+ ## Port list (diff of eeng methods vs shipped subset)
16
+
17
+ Per eeng check-p11: entity attribute redeclare compatibility,
18
+ inverse target/entity/attribute existence, derive aggregation rules,
19
+ rule-entity reference containment, function/procedure parameter and
20
+ return checks, subtype-constraint reflexive/rule references,
21
+ constant expression constness. Each ported check keeps the eeng note
22
+ id and cites its ISO 10303-11 clause.
23
+
24
+ ## Acceptance
25
+
26
+ - eeng-differential over the SRL corpus: every eeng-emitted note of
27
+ the ported kinds is emitted here with matching schema/name; no
28
+ false positives on clean corpora (express suite green).
29
+
30
+ ## Status: done
31
+
32
+ Shipped across three tranches:
33
+
34
+ 1. Original subset — interface redundant, interface resource
35
+ duplicate, subtype ref/cycle, duplicate declaration, where/unique
36
+ name pattern, unresolved ref, select/enumeration extended type,
37
+ self-schema reference, parse failure; inverse target/entity/
38
+ attribute checks; group references; aggregate bounds;
39
+ check-attrib-name-fun.
40
+ 2. Type-resolution tranche — constant/local/parameter/return types
41
+ (eeng check-constant-type, check-local-type, check-parameter-type,
42
+ check-fun-return-type) plus rule FOR entity refs.
43
+ 3. Remainder — subtype-constraint supertype-expression refs (eeng
44
+ kernel/check.lisp:426, check_supertype_ref note id) and
45
+ SELF\ redeclaration resolution (ISO 10303-11:2004 9.2.2.3; eeng
46
+ kernel/check.lisp:255 comment-only). Expression bodies are covered
47
+ generically by check_unresolved_refs; eengine has no separate
48
+ constant-expression constness rule (kernel/check.lisp only checks
49
+ the constant's type), so that port-list item closes as covered.
50
+
51
+ Foreign-blindness rule: names that do not resolve in a single-file
52
+ parse (USE FROM targets of unloaded schemas) are skipped, not flagged —
53
+ both new checks verified note-free over 265 stepmod resource schemas.
@@ -0,0 +1,22 @@
1
+ # 03 — Entity computations
2
+
3
+ Matrix §3: eeng materializes inherited attributes and closures
4
+ (kernel/compute-inheritance.lisp, derive-attrs.lisp,
5
+ inverse-attrs.lisp, supertypes.lisp, explicit-attrs.lisp); expressir
6
+ walks supertype chains ad hoc. Needed by Annex G.2.6 select synthesis
7
+ (04/05) and the entity checks (02).
8
+
9
+ ## Design
10
+
11
+ - `Entity#supertype_closure` — transitively closed supertype refs,
12
+ cycle-safe.
13
+ - `Entity#inherited_explicit_attributes` — explicit attributes from
14
+ the full closure, redeclaration-aware (SELF\\supertype.attr
15
+ overrides).
16
+ - `Entity#derived_attributes` / `Entity#inverse_attributes` —
17
+ accumulated from the closure.
18
+
19
+ ## Acceptance
20
+
21
+ - chain + multiple inheritance + redeclaration fixtures; the
22
+ materialization matches a hand-computed table.
@@ -0,0 +1,32 @@
1
+ # 04 — SHTOLO rule audit + corpus differential
2
+
3
+ Folds TODO.parity-ee 14's remainder.
4
+
5
+ - Walk `spec/fixtures/shtolo/annex-g-rules.md` (G.NM.1-2, G.1.1-10,
6
+ G.2.1-7): mark every rule PASS/partial/✖ with a fixture per rule.
7
+ - G.1.6 dependently-instantiable output verified against the Annex G
8
+ text (eeng ✖ there; the standard wins).
9
+ - name-munging policy (`_dot_` and friends): eeng ✖; standard wins.
10
+ - prune-pass reachability (unreachable subtype branches).
11
+ - corpus differential: every modules.lst module arm/mim, flat output
12
+ diffed vs eeng :flat, divergences classified.
13
+
14
+ ## Result: DONE (2026-10-15) — the audit is a live spec
15
+
16
+ `shtolo_annex_g_rule_audit_spec.rb` — 8 examples, one per previously
17
+ uncovered rule. Audited outcome:
18
+
19
+ - G.NM.2, G.1.2, G.1.5, G.1.8 (model-direct), G.2.3, G.2.4, G.2.6 —
20
+ PASS (G.2.4's folded extension keeps its G.NM.1-munged name —
21
+ correct per the name-clash rule).
22
+ - G.1.10 — was absent; **implemented** (`add_provenance_remark!`):
23
+ all-or-none provenance remark on the longform schema with
24
+ schema + schema_version_id lines.
25
+ - Still open (recorded in annex-g-rules.md): G.1.6
26
+ dependently-instantiable RULE/FUNCTION synthesis (eeng ✖; annex is
27
+ the contract) and the G.1.9 prune-depth notes.
28
+
29
+ Fixture note: `EXTENSIBLE_ENUMERATION` as a single composite keyword
30
+ is not in the grammar and not in the corpus — the corpus writes
31
+ `EXTENSIBLE ENUMERATION` (302×) / `EXTENSIBLE SELECT` (546×), both
32
+ supported.
@@ -0,0 +1,12 @@
1
+ # 05 — SHTOLO longform flatten (Annex G)
2
+
3
+ TODO.parity-ee 05. Convert the STEPmod multi-schema web into ONE
4
+ ISO 10303-11:1994 longform schema: no interfaces, visibility
5
+ preserved as rules, no name clashes, unreachable declarations pruned.
6
+
7
+ Sources: `ag-single-schema.adoc` (rule ids), eeng run-op (:flat) +
8
+ print-flatten + wo-flat.lisp (373 lines; eeng keeps structure and
9
+ lowercases — the standard wins on divergence), add/remove-declaration
10
+ and cleanup-interface lisps.
11
+
12
+ Builds on 01 (visibility), 03 (closures), 04 (rule audit).
@@ -0,0 +1,34 @@
1
+ # 06 — Population / Part 21
2
+
3
+ TODO.parity-ee 13, scope ladder (each step ships):
4
+
5
+ 1. P21 reader: parsanol grammar for ISO 10303-21 (HEADER entities,
6
+ DATA section: complex instances `(A(...)B(...))`, simple
7
+ `#1=TYPE(...)`, list/set/typed-ref values, enums `.T.`, binary
8
+ `"...`, redefines `/`); a `Model::Population` (header + instances).
9
+ 2. Population validation against a loaded schema: instance entity
10
+ exists (direct or complex against the supertype graph), attribute
11
+ names/arity match, value types check.
12
+ 3. eengine differential on the Part 21 fixtures
13
+ (`~/src/mn/iso-10303-detached-docs/sources/iso-10303-21*`).
14
+
15
+ ## Status: done
16
+
17
+ 1. Reader — `Expressir::P21` (parsanol grammar + PopulationBuilder):
18
+ HEADER FILE_* entities, DATA simple/complex instances, lists,
19
+ typed parameters, references, enumerations, binaries, strings
20
+ (doubled-quote escape), `$`/`*`, `/* */` comments.
21
+ 2. Validator — `Expressir::P21::Validator`: FILE_SCHEMA name,
22
+ instance keywords, complex-record supertype cliques, mapped
23
+ attribute arity in Part 21 order (supertype attributes first;
24
+ DERIVE-redeclared slots keep their position valued `*` per clause
25
+ 12.2.6), enumeration membership, instance references,
26
+ typed-parameter resolution; optional short_names map for clause
27
+ 12.3 short names.
28
+ 3. Corpus — ISO 10303-21 Annex H complete exchange structure parses
29
+ and validates clean (13 instances, comments, short names).
30
+
31
+ eengine differential (ladder step 3) is blocked by the oracle build:
32
+ eengine 5.1.0 --validate/--xref abort loading a bare p11 schema
33
+ (*PARSE-MODE* NIL) and every -MODE demands a stepmod context, while
34
+ --validate itself is flagged "not fully supported" upstream.
@@ -0,0 +1,25 @@
1
+ # 07 — Schema compare & patch
2
+
3
+ TODO.parity-ee 16. Structural diff of two schemata with a
4
+ machine-applicable patch: declarations matched by canonical path
5
+ (`schema.item`); deltas added/removed/changed (per-attribute
6
+ structural diff: types, optionality, aggregates); patch output
7
+ declarable against the flattened base (eeng `--compare`/`--patch`
8
+ semantics, plugin/p11 compare entry).
9
+
10
+ ## Status: done
11
+
12
+ - `Expressir::Express::SchemaCompare` — deltas at `schema.item` and
13
+ entity-attribute `schema.item.attribute` paths; signatures are
14
+ lutaml-model `to_hash` trees stripped of resolution artifacts
15
+ (`base_path`, `ref`, `source`, remarks).
16
+ - `Expressir::Express::SchemaPatch.apply` — rebuilds the revised
17
+ schema through the framework round trip; the base is never mutated;
18
+ item-level `:changed` nodes subsume their attribute sub-deltas.
19
+ - Interfaces are out of scope by design: the patch target is a
20
+ flattened (longform) schema.
21
+ - Oracle: `spec/expressir/express/schema_compare_oracle_spec.rb`
22
+ agrees with `eengine --compare -MODE RESOURCE -STEPMOD <checkout>`
23
+ on added/removed entities, removed attributes and enum-value type
24
+ changes; gated on binary + stepmod checkout presence
25
+ (EENGINE_BIN / STEPMOD_DIR).
@@ -0,0 +1,7 @@
1
+ # 08 — Official corpus CI gate
2
+
3
+ TODO.parity-ee 17. One rake task mapping every official corpus to
4
+ specs, with CI tiers: (a) every push — eeng bug corpus (bug39/40),
5
+ SHTOLO rule fixtures, Part 21 grammar fixtures; (b) nightly/manual —
6
+ SRL/SMRL full corpus differentials (pretty/flat/xml) when the eengine
7
+ oracle is on PATH.
@@ -0,0 +1,9 @@
1
+ # 09 — MIM mapping parser
2
+
3
+ TODO.parity-ee 18 (expressir#88). Parse + validate MIM reference
4
+ paths into a typed model: entity chains `A -> B -> C`, qualifiers
5
+ `[attr => val]`, `=>` derived references, `->>` subtype traversal,
6
+ `<>` select member. Sources: this checkout's
7
+ `schemas/modules/*/mapping.yaml` (`<<express:SCHEMA.ITEM,ITEM>>` link
8
+ markup), upstream module.xml `reference_path` bodies, the Part 1x
9
+ mapping-annex grammar; the module corpus is the oracle.
@@ -64,7 +64,7 @@ interface/qualify notes; `00check.txt` — check design notes.
64
64
  | 12 | full check-p11 catalog port | planned |
65
65
  | 13 | population / Part 21 validation | planned |
66
66
  | 14 | SHTOLO completion (Annex G + corpus differential) | in progress |
67
- | 15 | Part 28 XML + SMRL index | planned |
67
+ | 15 | Part 28 XML + SMRL index | done (SMRL index + express2xsd shipped, #276; reference-XSD diff harness escalated to 17) |
68
68
  | 16 | schema compare & patch | planned |
69
69
  | 17 | official test-case incorporation | standing structure |
70
70
 
@@ -0,0 +1,57 @@
1
+ # TODO.sota — the SOTA program (vision)
2
+
3
+ Expressir is the open compiler-infrastructure layer for ISO 10303
4
+ information models: a faithful, programmable model of EXPRESS
5
+ (ISO 10303-11), the standard transformations between the language's
6
+ normative forms (Annex G longform, Part 21, Part 28/XML, XSD, MIM
7
+ mappings), and CI-grade guarantees for the standards corpus. The
8
+ eengine-parity program (TODO.eengine, done) made it the ecosystem's
9
+ reference toolchain. This program takes it to SOTA — the point where
10
+ Expressir is not just the ecosystem's parser but its *engine*, its
11
+ developer platform, and its interoperability hub.
12
+
13
+ ## Execution order and status
14
+
15
+ | n | task | tier | status |
16
+ |---|------|------|--------|
17
+ | 01 | static type checking of expressions | semantics | done (tiers 1-6; :check_expr_operand_domain/:check_expr_initializer_type/:check_expr_assignment_type/:check_expr_return/:check_expr_where_boolean/:check_expr_unique_duplicate; corpus 261-slice 0 notes) |
18
+ | 02 | evaluator — run EXPRESS (functions, WHERE rules over populations) | execution | done (value model + ch.12 expressions, ch.13 interpreter + builtin set A, instance-aware eval over P21 populations, Rules.check with SELF; eengine validate broken — mutation-sweep differential) |
19
+ | 03 | conformance (Part 21 conformance corpus, property-based grammar harness, G.1.7 closure) | rigor | done (P21 annex corpus + negative ladder-exclusion gate; generated round-trip harness + nightly corpus tier + rake conformance; every Annex G rule audited) |
20
+ | 04 | LSP + incremental platform | platform | done (stdio LSP 3.17 server + `expressir-lsp` binary; Checker diagnostics; USE/alias definition, references, hover; cross-schema rename verified by SchemaCompare+Formatter; full reparse — expr-rs incremental API is the measured gap) |
21
+ | 05 | interop exports (JSON Schema, OWL/RDF) | interop | done (JSON Schema 2020-12 + OWL/Turtle exporters, CLI commands, decision guides; Annex H population consumer round-trip; SRL corpus tier; UML/XMI optional not shipped) |
22
+ | 06 | dialect awareness (1994 vs 2004, amendments) | semantics | done (Dialect normalize + parser/checker flag; :check_dialect_2004_only/:check_dialect_deprecated/:check_dialect_mixed; audited 2004 change list fixture with live examples; both-dialect corpus tier) |
23
+ | 07 | reference artifacts (grammar cross-walk, published guides) | reference | done (250-rule generated cross-walk with divergence classes + sync spec; trended nightly metrics artifact; checker/p21/shtolo/evaluator/lsp guides with generated note-id catalog) |
24
+
25
+ Dependency shape: 02 consumes 01's type tiers loosely (interleave by
26
+ tier when a check needs execution semantics). 04 scaffolds
27
+ independently; its diagnostics richness grows with 01. 03/05/06/07 are
28
+ independent.
29
+
30
+ ## Sources
31
+
32
+ - ISO 10303-11 text: `~/src/mn/iso-10303-11/sources/sections/`
33
+ (expressions ch.12, statements ch.13, data types ch.8, rules 9.x,
34
+ Annex A/B productions).
35
+ - Part 21: `~/src/mn/iso-10303-detached-docs/sources/iso-10303-21/`.
36
+ - stepmod corpus: `~/src/mn/iso-10303-stepmod/data/` (SRL/BOM/module
37
+ manifests; the 265-file <250KB resource slice is the fast
38
+ differential set).
39
+ - eengine oracle: `~/bin/eengine` — schema ops need
40
+ `-MODE RESOURCE -STEPMOD ~/src/mn/iso-10303-stepmod`;
41
+ --validate/--xref are broken on bare p11 (never build on them).
42
+ - leptris runs FFI-fallback on this box; no spec may assume the native
43
+ engine.
44
+
45
+ ## Standing rules
46
+
47
+ - Where eengine and ISO 10303-11 disagree, the standard wins; classify
48
+ the divergence in the differential output, never copy silently.
49
+ - Every ported check keeps its eengine note id (where one exists) and
50
+ cites its ISO 10303-11 clause.
51
+ - Semantics land in Ruby; parse-adjacent and graph-scale hot paths may
52
+ land in expressir-rs (gated per task).
53
+ - All model (de)serialization goes through lutaml-model mappings —
54
+ never hand-rolled to_h/from_h.
55
+ - Specs use real model instances, never doubles; rubocop clean is a
56
+ merge gate; the suite runs in chunks on this box (full single-process
57
+ runs OOM).
@@ -0,0 +1,115 @@
1
+ # 01 — Static type checking of expressions
2
+
3
+ The Checker resolves references (TODO.eengine/02/03); this task gives
4
+ it TYPES: full static checking of the expression and statement
5
+ language per ISO 10303-11 ch.12/13/8/9.
6
+
7
+ ## Tiers (each ships)
8
+
9
+ 1. Clause map: expression grammar ↔ ISO 10303-11 12.x productions ↔
10
+ eeng check.lisp expression methods, with the typing rule for each
11
+ (operand domains, result type). Table in this file before code.
12
+ 2. Operator domains: arithmetic on the NUMBER family, logical on
13
+ BOOLEAN/LOGICAL, relational polymorphism, string/binary ops,
14
+ aggregate operators (INDEX/QUERY/SUM and friends).
15
+ 3. Aggregates: element types through indexing/slicing, bounds vs
16
+ literals where static, nested aggregates.
17
+ 4. SELECT/ENUM membership: assignment compatibility, IN-of-enum,
18
+ `x : t := expr` compatibility in CONSTANT/LOCAL/DERIVE initializers.
19
+ 5. Statement flow: assignment compatibility, IF/CASE selector types,
20
+ REPEAT control types, function RETURN type vs return statements.
21
+ 6. WHERE/UNIQUE structural checks: expression boolean-ness, UNIQUE
22
+ label uniqueness, rule FOR-entity containment for referenced
23
+ attributes.
24
+
25
+ ## Interface
26
+
27
+ `Checker#check_expression_types(schema)` emitting notes with eeng ids
28
+ where check.lisp has them, own ids (`:check_expr_*`) citing clauses
29
+ where it does not (mirror TODO.eengine/02's SELF-redeclaration
30
+ precedent).
31
+
32
+ ## Acceptance
33
+
34
+ - Corpus-clean over the 265-file resource slice (foreign-blindness
35
+ rule applies: unresolvable names skipped, not flagged).
36
+ - eeng differential for the expression checks eengine actually
37
+ implements; standard wins on divergence.
38
+
39
+ ## Clause map (tier 2 — operator domains)
40
+
41
+ Model operator vocabulary: `BinaryExpression` constants (ADDITION,
42
+ SUBTRACTION, MULTIPLICATION, REAL_DIVISION, INTEGER_DIVISION, MODULO,
43
+ EXPONENTIATION, COMBINE, EQUAL, NOT_EQUAL, LESS_THAN,
44
+ LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL, IN, LIKE,
45
+ INSTANCE_EQUAL, INSTANCE_NOT_EQUAL, AND, OR, XOR);
46
+ `UnaryExpression` (PLUS, MINUS, NOT); `Interval`.
47
+
48
+ | operator | ISO 10303-11:2004 clause | operand domains | result |
49
+ |----------|--------------------------|-----------------|--------|
50
+ | unary `+` `-` (PLUS/MINUS) | 12.1 | numeric | numeric |
51
+ | `not` (NOT) | 12.4 | logical | logical |
52
+ | `+` (ADDITION) | 12.1 add; 12.5.2 string concat; 12.3.2 binary concat; 12.6 union (table 17 admits aggregate+element singletons on either side) | num,num; str,str; bin,bin; agg,agg; agg,elem; elem,agg | num / str / bin / agg |
53
+ | `-` (SUBTRACTION) | 12.1; 12.6 difference (table 18: aggregate left, element singleton right) | num,num; agg,agg; agg,elem | num / agg |
54
+ | `*` (MULTIPLICATION) | 12.1; 12.6 intersection (both operands aggregates) | num,num; agg,agg | num / agg |
55
+ | `/` (REAL_DIVISION) | 12.1 | numeric | real |
56
+ | `**` (EXPONENTIATION) | 12.1 | numeric | num (int if both int) |
57
+ | `div` `mod` | 12.1 | numeric (reals truncated) | integer |
58
+ | `and` `or` `xor` | 12.4 | logical,logical | logical |
59
+ | `=` `<>` | 12.2.1 | comparable: numeric, logical, string, binary, enum; aggregates and entities also admitted | logical |
60
+ | `<` `<=` `>` `>=` | 12.2.1; 12.6 subset/superset | ordering families only (numeric, logical, string, binary, non-extensible enum); if either side is aggregate, subset/superset semantics (agg,agg) | logical |
61
+ | `:=:` `:<>>:` (INSTANCE_EQUAL/NOT_EQUAL) | 12.2.2 | instance types (entity, aggregate) | logical |
62
+ | `in` (IN) | 12.2.3 | rhs aggregate; lhs compatible with rhs base | logical |
63
+ | `like` (LIKE) | 12.2.5 | string,string | logical |
64
+ | `\|\|` (COMBINE) | 12 intro (precedence table note) | complex entity construction (entity operands) | entity |
65
+ | interval | 12.2.4 | low/item/high mutually comparable (numeric, string, enum) | logical |
66
+
67
+ Static type lattice: `:integer :real :number :logical :boolean :string
68
+ :binary :enum :aggregate :entity :select :generic :unknown`. Inference:
69
+ literals direct; declared types via the schema's types (SimpleReference
70
+ → find_type → underlying_type recursion); references via the enclosing
71
+ declaration's environment (constants, parameters, variables, entity
72
+ attributes); enum members are AttributeReferences whose base resolves
73
+ to an enumeration TYPE; function calls resolve to the function's
74
+ return type.
75
+
76
+ Flagging rule: a domain violation is noted only when BOTH operand
77
+ types are known (`:generic` and `:unknown` never flag) — the corpus
78
+ never produces false positives.
79
+
80
+ eengine divergence: kernel/check.lisp's expression check-p11 methods
81
+ traverse structurally only — eengine performs NO operator-domain
82
+ typing. These checks therefore carry new `:check_expr_operand_domain`
83
+ ids citing their clauses; there is no eengine note id to keep.
84
+
85
+ - Tier 1 clause map: done (above).
86
+ - Tier 2 operator domains: done — `Checker#check_expression_types`,
87
+ note id `:check_expr_operand_domain` with the clause in the message;
88
+ spec `spec/expressir/express/checker_expression_types_spec.rb`
89
+ (9 examples); corpus-clean over the 265-file resource slice (255
90
+ scanned, 0 notes) after clause 12.6 table 17's union-with-singleton
91
+ was admitted.
92
+ - Tier 3 indexing: done — IndexReference resolves to the aggregate's
93
+ base element (12.6.1/12.3.1/12.5.1); index positions numeric
94
+ (production 236); the difference operator admits an element
95
+ singleton right operand with an aggregate left (12.6 table 18).
96
+ - Tier 4 initializer compatibility: done — CONSTANT/DERIVE/LOCAL
97
+ initializers checked against their declared types (12.11): numeric
98
+ widening integer→real→number, logical/boolean family, enum identity
99
+ via declaration resolution, entity specialization via
100
+ supertype_closure, select-accepting slots, aggregate slots. Corpus
101
+ clean (261 schemas, 0 notes).
102
+ - Tier 5 statement flow: done — assignment compatibility (13.2.1),
103
+ if conditions logical (13.5), repeat controls (13.6), return
104
+ compatibility + procedure-return restriction (13.7).
105
+ - Tier 6 WHERE/UNIQUE structure: done — WHERE expressions logical
106
+ (9.4), duplicate UNIQUE labels (9.4); rule FOR-entity containment
107
+ remains covered by bound_identifiers' deliberate over-approximation.
108
+
109
+ ## Status: done
110
+
111
+ Engine finding: parsing identical source after many interleaved
112
+ check-parse cycles in one process can diverge (attr type arrives as a
113
+ SimpleReference instead of the builtin node) — a parsanol parse-cache
114
+ issue, worked around in the initializer spec by checking in a fresh
115
+ subprocess; separate investigation owed.
@@ -0,0 +1,86 @@
1
+ # 02 — The evaluator: run EXPRESS
2
+
3
+ The SOTA-defining capability: execute the language. Functions and
4
+ WHERE rules evaluated over Part 21 populations — the line between a
5
+ toolchain that reads EXPRESS and one that runs it. No open
6
+ implementation has this (eengine's --validate is the cautionary tale).
7
+
8
+ ## Steps (each ships)
9
+
10
+ 1. Value model + expression core: IMMUTABLE value classes (NUMBER
11
+ family, STRING/BINARY, LOGICAL, enumeration, aggregate arrays as
12
+ frozen structs), literal → value, pure expression evaluation
13
+ (operators per 01's domain table), environmental lookup through a
14
+ Scope chain. Interface: `Expressir::Eval.expression(ast, env)`.
15
+ 2. Function interpreter: parameter binding (incl. VAR semantics),
16
+ LOCALs with initializers, IF/CASE/REPEAT/compound/RETURN, ESCAPE/
17
+ SKIP, recursion with depth guard. Builtin set A (math/string,
18
+ ISO 10303-11 15.x): SIN..BLENGTH class.
19
+ 3. Instance-aware builtins: TYPEOF, USEDIN, EXISTS, QUERY (lazy
20
+ binding), attribute access through the model's computation layer
21
+ (Entity#all_explicit_attributes, supertype_closure, redeclaration
22
+ resolution — TODO.eengine/03), complex-instance (GROUP) access.
23
+ Builtin set B (instance/aggregate: SIZEOF, HIBOUND..).
24
+ 4. WHERE-rule checking: `Expressir::Rules.check(population, schema)`
25
+ → per-instance, per-rule results with the failing subexpression
26
+ path. Wraps the P21 Validator's structural tiers (TODO.eengine/06)
27
+ into semantic validation.
28
+ 5. Differential: eengine where its validate answers; property-based
29
+ round-trips otherwise (evaluate a rule against a corpus population,
30
+ cross-check pure-Ruby reference impls for builtins). If hot loops
31
+ dominate, drop the evaluation core to expressir-rs (option B) —
32
+ gate on measured need, not speculation.
33
+
34
+ ## Design constraints
35
+
36
+ - The evaluator consumes the SAME model the parser produces — no
37
+ parallel AST.
38
+ - Errors are notes/exceptions carrying node + path, never exit.
39
+ - Determinism: no reliance on hash order (corpus QA depends on it).
40
+
41
+ ## Acceptance
42
+
43
+ - Annex-level worked examples (function bodies from ISO 10303-11)
44
+ evaluate to the documented results.
45
+ - WHERE evaluation over the Annex H population: every rule provably
46
+ passes; a seeded-fault population fails the intended rule only.
47
+
48
+ ## Status: in progress
49
+
50
+ - Step 1 (value model + expression core): done — `Expressir::Eval`
51
+ (Values/Environment/Expression autoloads): ISO 10303-11 ch.12
52
+ arithmetic with result typing, logical tables (12.4), relational
53
+ orderings (12.2.1), IN (12.2.3), LIKE (12.2.5, table 11 patterns),
54
+ intervals, aggregates (tables 16-18 incl. element singletons), and
55
+ QUERY. Indeterminate (`?`) propagates per clause. Function calls
56
+ raise until step 2. Spec `spec/expressir/eval/expression_spec.rb`.
57
+ - Grammar bug fixed en route: `factor`'s `** rhs` capture was dropped
58
+ by the builder (`2 ** 3 + 1` parsed as `2 + 1`); build_factor now
59
+ emits EXPONENTIATION.
60
+ - Step 2 (function interpreter + builtin set A): done — functions
61
+ with parameter/local binding, assignment (incl. indexed), IF/CASE,
62
+ WHILE/UNTIL/increment REPEAT with SKIP and env-carrying ESCAPE,
63
+ RETURN (falling off the end is an error per 13.7), recursion.
64
+ Builtins: ABS SIN COS TAN ASIN ACOS ATAN ATAN2 SQRT EXP LOG LOG2
65
+ LOG10 ODD LENGTH BLENGTH SIZEOF HIINDEX LOINDEX HIBOUND LOBOUND
66
+ EXISTS NVL VALUE, plus PI/E/CONST_E constants. NOTE: the logical
67
+ value symbols live in Values::LOGICAL_* constants — bare :true/
68
+ :false literals get rewritten to booleans by Lint/BooleanSymbol.
69
+ - Step 3 (instance-aware evaluation): done — Values::Instance over
70
+ P21 population records with P21-data-to-value conversion (arrays →
71
+ aggregates, `#id` → instances, enums/binaries mapped); attribute
72
+ access through the Environment's Part 21 slot mapping (inherited
73
+ then own, same order as the P21 validator, incl. complex records);
74
+ TYPEOF (unqualified + schema-qualified names), USEDIN, EXISTS.
75
+ Fixtures: spec/fixtures/eval/population.{exp,p21}.
76
+ - Step 4 (WHERE-rule checking): done — `Expressir::Eval::Rules.check`
77
+ evaluates every instance's entity domain rules with SELF and the
78
+ mapped attributes bound (bare names and SELF\attr both resolve);
79
+ statuses pass/fail/unknown/error; a rule is violated only when it
80
+ evaluates false (9.4), indeterminate is not a violation.
81
+ - Step 5 (differential): done as substituted — eengine's --validate
82
+ aborts on bare p11 (TODO.eengine/06 step 3 finding), so the
83
+ differential face is the mutation sweep: corrupting one instance
84
+ attribute fails exactly the intended rule and no other (rules spec).
85
+
86
+ ## Status: done