expressir 2.4.31-aarch64-linux → 2.4.36-aarch64-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
@@ -0,0 +1,53 @@
1
+ # 03 — Conformance: measure against the standard's own yardstick
2
+
3
+ ## Parts (each ships)
4
+
5
+ 1. Part 21 conformance corpus: extract the conformance-requirement
6
+ examples from the detached ISO 10303-21 source (annexes + body
7
+ worked examples) into fixtures; a gate spec runs the P21
8
+ reader/validator over every positive fixture (clean) and every
9
+ negative fixture (the intended note id, only).
10
+ 2. Grammar-conformance harness: property-based generation from the
11
+ ISO 10303-11 Annex A/B productions (finite fragments first:
12
+ declarations, then expressions). Invariants: parse→format→parse
13
+ idempotence, formatter output re-parses, ill-formed input rejected
14
+ with a diagnostic (no silent recovery on the strict faces).
15
+ Promoted to a nightly CI tier.
16
+ 3. G.1.7 closure: the BASED_ON enumeration-chain corpus fixture —
17
+ the last unaudited Annex G rule (annex-g-rules.md table tail).
18
+
19
+ ## Acceptance
20
+
21
+ - `rake conformance` (or the spec tier) green; negatives fail with
22
+ exactly the intended note, positives with zero notes.
23
+
24
+ ## Status: done
25
+
26
+ - Part 1 (Part 21 conformance corpus): the ISO 10303-21 detachment
27
+ examples are extracted to `spec/fixtures/p21/conformance/`:
28
+ annex-e-0/1 (named data sections), annex-h-0 (the worked exchange
29
+ structure, 13 instances), annex-i-0/1 (ANCHOR/REFERENCE), annex-j-0
30
+ (constants). `spec/expressir/p21/parser_conformance_spec.rb` parses
31
+ every positive fixture with zero notes and asserts the intended
32
+ failure for the forms this ladder does not implement yet (annex E
33
+ named sections and `..`, annex I ANCHOR/REFERENCE, annex J
34
+ constants/`....` and STEP-21-ED2 extended literals) — they fail
35
+ loudly, not silently. Malformed negatives are rejected.
36
+ - Part 2 (grammar-conformance harness):
37
+ `spec/expressir/express/formatter_roundtrip_conformance_spec.rb`
38
+ asserts parse → format → parse structural idempotence over a fixture
39
+ slice, over generated fragments (Annex A/B production levels:
40
+ expression → simple_expression → term, declarations, arrays, QUERY,
41
+ unary/logical/relational forms, deterministically seeded), and
42
+ rejection of terminators removed from generated input. The
43
+ `EXPRESSIR_CONFORMANCE=1` tier round-trips the full stepmod resource
44
+ slice (<250 KB; 266 files on this box) and `rake conformance` runs it; the
45
+ nightly `conformance.yml` workflow checks out the sparse stepmod
46
+ corpus. En route the generator found a formatter bug: nested unary
47
+ minus formatted as `--x`, which EXPRESS reads as a comment; unary
48
+ operands are now parenthesized. Generator lesson: relational
49
+ operators are non-associative, and reserved words (e.g. `VALUE`)
50
+ cannot name parameters.
51
+ - Part 3 (G.1.7 closure): the BASED_ON enumeration-chain example is in
52
+ `shtolo_annex_g_rule_audit_spec.rb`; every Annex G rule now has a
53
+ live worked example and the audit table has no unaudited tail.
@@ -0,0 +1,70 @@
1
+ # 04 — LSP + incremental platform
2
+
3
+ Make Expressir IDE-grade. The resolution/checking machinery is the
4
+ hard part and it exists; this task wires it to a language server.
5
+
6
+ ## Parts (each ships)
7
+
8
+ 1. Scaffold: `expressir-lsp` (solo binary or gem — decide by the
9
+ metanorma toolchain's needs) speaking stdio LSP 3.17: initialize,
10
+ diagnostics push, document symbols.
11
+ 2. Diagnostics: Checker notes as publishDiagnostics with model-node
12
+ → LSP range mapping (NodePositionIndex exists).
13
+ 3. Navigation: definition (ScopeResolver + the USE/REFERENCE ladder +
14
+ alias map), references, document/rename — rename updates the
15
+ model in place and re-emits via the Formatter (the compare/patch
16
+ engine provides the structural diff safety net).
17
+ 4. Hover: PrettyFormatter excerpt of the target declaration + its
18
+ remarks.
19
+ 5. Incremental: document-open/parse via the expressir-rs core path
20
+ when available (parsanol incremental machinery); fallback full
21
+ reparse. Cold-open target: SRL-scale schema set interactive on
22
+ this box.
23
+
24
+ ## Acceptance
25
+
26
+ - A live editor session on the stepmod corpus: diagnostics on open,
27
+ go-to-definition across a USE ladder, rename across two schemas
28
+ with the diff verified by SchemaCompare.
29
+
30
+ ## Status: done
31
+
32
+ - Part 1 (scaffold): `exe/expressir-lsp` ships in the gem
33
+ (`executables`), speaking JSON-RPC 2.0 over stdio with LSP 3.17
34
+ framing (`Content-Length`), lifecycle (initialize/shutdown/exit) and
35
+ full-sync text documents (didOpen/didChange/didSave/didClose).
36
+ `Expressir::Lsp::{Document,Workspace,Server}` are autoloaded from
37
+ `lib/expressir/lsp.rb`.
38
+ - Part 2 (diagnostics): `Workspace#diagnostics` runs the Checker over
39
+ the open documents, maps notes through NodePositionIndex/LineMap to
40
+ byte→UTF-16 ranges, and publishes `textDocument/publishDiagnostics`.
41
+ Parse failures publish a diagnostic at the reported line/char and
42
+ keep the last good tree for navigation. Cross-document unresolved
43
+ notes are suppressed when another open document supplies the
44
+ referenced schema or interfaced declaration (the checker sees one
45
+ file at a time).
46
+ - Part 3 (navigation): definition resolves declaration tokens,
47
+ local references, the USE/REFERENCE ladder and its alias map
48
+ (`colour AS hue` jumps to `colour`); references walks every open
49
+ document and interface item; rename computes minimal edits for the
50
+ declaration and every reference across schemas, then applies them in
51
+ memory, verifies each document reparses, runs SchemaCompare to
52
+ reject any removal other than the renamed declaration, and re-emits
53
+ the renamed schema through the Formatter to prove it formats. Rename
54
+ keeps aliases untouched: only the imported name at the interface
55
+ item and usages written with the original name change.
56
+ - Part 4 (hover): `Express::PrettyFormatter` excerpt in a markdown
57
+ `express` code fence (remarks included by the formatter).
58
+ - Part 5 (incremental): changes reparse through the native/core parser
59
+ path; identical text is a no-op and checker results are memoized
60
+ across requests for the same document set. There is no incremental
61
+ parse API in the expressir-rs core to call, so true content-
62
+ incremental reparse remains a measured gap: cold open of the 186 KB
63
+ geometric_model_schema on this loaded box takes ~9.4 s (document
64
+ parse) and ~0.03 s for the symbol index. Recorded for an
65
+ expressir-rs incremental API when it exists; semantics stay Ruby.
66
+ - Specs: `spec/expressir/lsp/document_spec.rb` (positions, UTF-16,
67
+ tokens, symbols, parse-failure retention) and
68
+ `spec/expressir/lsp/server_spec.rb` (capabilities, diagnostics,
69
+ symbols, USE/alias definition, references, hover, cross-schema
70
+ rename verified by SchemaCompare and Formatter) — 14 examples.
@@ -0,0 +1,55 @@
1
+ # 05 — Interop exports: EXPRESS as a source
2
+
3
+ Expressir as the interchange point between EXPRESS and the rest of the
4
+ modeling world. These mappings are contributions (no ISO mapping
5
+ exists) — every decision is documented in the output module's docs.
6
+
7
+ ## Parts (each ships)
8
+
9
+ 1. JSON Schema export: entities → object schemas (attribute order,
10
+ OPTIONAL → nullable, aggregates → arrays with bounds where
11
+ expressible, SELECT → anyOf, ENUM → enum). Subtype handling: the
12
+ closure flattened into allOf groups. Documented decisions file.
13
+ 2. OWL/RDF export: the ifcOWL lineage generalized to arbitrary
14
+ EXPRESS — entities → classes, supertype closure → subclass axes,
15
+ attributes → properties with domain/range from the model, SELECT
16
+ → union semantics, WHERE rules NOT exported (documented scope
17
+ limit). Cite ifcOWL/EXPRESS→OWL literature in the decisions file.
18
+ 3. Optional tier: UML/XMI export.
19
+
20
+ ## Acceptance
21
+
22
+ - Export the SRL corpus; a consumer round-trip (validate exported
23
+ JSON Schema against a Part 21-derived JSON serialization of the
24
+ Annex H population).
25
+
26
+ ## Status: done
27
+
28
+ - Part 1 (JSON Schema): `Expressir::Interop::JsonSchema` renders a
29
+ schema as JSON Schema 2020-12 — entities as object definitions
30
+ composed with `allOf` over `SUBTYPE OF` parents, explicit attributes
31
+ in declaration order, OPTIONAL attributes nullable and out of
32
+ `required`, aggregates as arrays with declared bounds, SELECT as
33
+ `anyOf` (BASED_ON folded), ENUMERATION as a string enum (BASED_ON
34
+ folded), defined types through to their underlying primitive.
35
+ Derived/inverse attributes, WHERE/UNIQUE rules and constants are
36
+ documented exclusions. CLI: `expressir export-json-schema`.
37
+ Decisions: `docs/_guides/interop/json-schema.adoc`.
38
+ - Part 2 (OWL/RDF): `Expressir::Interop::Owl` renders Turtle — entities
39
+ as `owl:Class` with `rdfs:subClassOf` per supertype, explicit
40
+ attributes as object/datatype properties with domain and range,
41
+ SELECT as an `owl:unionOf` equivalent class, ENUMERATION items as
42
+ individuals, primitive defined types as `rdfs:Datatype` with XSD
43
+ equivalences; aggregates range over `rdf:List`. WHERE/UNIQUE bodies,
44
+ cardinalities and aggregate bounds are documented scope limits. CLI:
45
+ `expressir export-owl`. Decisions and the ifcOWL lineage citations:
46
+ `docs/_guides/interop/owl-rdf.adoc`.
47
+ - Part 3 (UML/XMI): explicitly the optional tier; not shipped.
48
+ - Acceptance: the Annex H population is serialized to JSON in Part 21
49
+ slot order (supertype attributes first, `$`/`*` null, references
50
+ expanded with a cycle guard) and validated against the exported
51
+ entity definitions with an independent consumer validator in
52
+ `spec/expressir/interop/json_schema_spec.rb` — 13 instances, zero
53
+ errors; dropping a required attribute fails. A gated
54
+ `EXPRESSIR_CONFORMANCE` tier exports every schema in the stepmod
55
+ resource slice (<250 KB; >200 schemas).
@@ -0,0 +1,57 @@
1
+ # 06 — Dialect awareness
2
+
3
+ EXPRESS the standard has editions; Expressir should speak them
4
+ explicitly.
5
+
6
+ ## Parts (each ships)
7
+
8
+ 1. Dialect flag: parser + checker accept `dialect: :"10303-11:1994" |
9
+ :"10303-11:2004"` (default 2004). Gating: EXTENSIBLE/BASED_ON/
10
+ GENERIC_ENTITY are 2004-only (1994 corpora exist in legacy
11
+ resources); 1994 rejects them with a dialect note, 2004 accepts.
12
+ 2. Amendment tracking: the Amd1 change list as a source document;
13
+ edition-sensitive checker notes (`:check_dialect_*`).
14
+ 3. Corpus pass: run both dialects over the resource slice; mixed
15
+ dialects in one file produce a clear diagnostic.
16
+
17
+ ## Acceptance
18
+
19
+ - A 1994-era resource schema parses clean under 1994, flags its
20
+ non-1994 constructs under 2004-diagnostics mode.
21
+
22
+ ## Status: done
23
+
24
+ - Part 1 (dialect flag): `Expressir::Express::Dialect` normalizes the
25
+ `:"10303-11:1994"` / `:"10303-11:2004"` editions (also "1994",
26
+ "2004", full strings) and rejects anything else with
27
+ `InvalidOptionError`. `Parser.from_file/from_files/from_exp` accept
28
+ `dialect:` (default 2004) and validate it; the grammar parses the
29
+ union of both editions so a model can be inspected under either.
30
+ `Checker.new(repository, dialect:)` emits the edition notes:
31
+ under 1994, `:check_dialect_2004_only` (error) for EXTENSIBLE,
32
+ BASED_ON, GENERIC_ENTITY and SUBTYPE_CONSTRAINT declarations; under
33
+ 2004, `:check_dialect_deprecated` (warning) for the edition-1 inline
34
+ subtype-constraint syntax that Annex K deprecates in favour of
35
+ SUBTYPE_CONSTRAINT. Notes are emitted only when a dialect is passed,
36
+ so the default checker report is unchanged.
37
+ - Part 2 (amendment tracking): the audited change list is a checked-in
38
+ source document at
39
+ `spec/fixtures/dialects/iso-10303-11-2004-changes.yaml`, with the
40
+ clause each construct comes from (8.4.1, 8.4.2, clause 9, Annex K,
41
+ Annex G) and a live example per entry.
42
+ `spec/expressir/express/dialect_spec.rb` asserts every change entry's
43
+ declared note fires under 1994 (or 2004 for the deprecated syntax),
44
+ that no note id is outside `Dialect::NOTE_IDS`, and that the 2004
45
+ examples are accepted under 2004. A 1994-era plain schema produces
46
+ no notes under either dialect.
47
+ - Part 3 (corpus pass): a gated `EXPRESSIR_CONFORMANCE` tier runs both
48
+ dialects over the stepmod resource slice (266 files <250 KB), and
49
+ `:check_dialect_mixed` gives one clear diagnostic when a file
50
+ combines 2004-only declarations with edition-1 inline
51
+ subtype-constraint syntax. Installations without the corpus skip the
52
+ tier.
53
+ - Limitation recorded: the 2004 text grammar is effectively a superset
54
+ of 1994, so the only edition-1-only signals available to a text
55
+ checker are the Annex K deprecations; EXPRESS-G notation and the
56
+ enumeration-ordering semantics deprecated by Annex K have no text
57
+ form to flag.
@@ -0,0 +1,55 @@
1
+ # 07 — Reference artifacts: the citable Expressir
2
+
3
+ The academic endgame — make the implementation provable and citable.
4
+
5
+ ## Parts (each ships)
6
+
7
+ 1. Grammar cross-walk: rule-by-rule table, parsanol grammar rule ↔
8
+ ISO 10303-11 Annex A/B production, with divergences (extensions,
9
+ recoveries) classified — rendered into docs/ and kept in sync by a
10
+ spec that fails when a grammar rule lacks a row.
11
+ 2. Property-based corpus testing as a published nightly tier (03's
12
+ harness, trended: parse rate, diagnostic rate, idempotence rate).
13
+ 3. Published guides: one doc per subsystem (checker + note-id
14
+ catalog, shtolo + annex-g-rules linkage, p21, evaluator, lsp),
15
+ generated where possible from the model (note-id catalog from the
16
+ Checker's constants).
17
+
18
+ ## Acceptance
19
+
20
+ - docs/ builds with the cross-walk and guides; the sync spec is part
21
+ of the default suite.
22
+
23
+ ## Status: done
24
+
25
+ - Part 1 (grammar cross-walk): `Expressir::Reference::GrammarCrosswalk`
26
+ reads the audited mapping in
27
+ `lib/expressir/reference/grammar_crosswalk.yml` and renders
28
+ `docs/_guides/reference/grammar-crosswalk.adoc`. All 250 parsanol
29
+ rules are accounted for: 207 aligned with the same-named Annex A
30
+ production (CamelCase normalized to snake_case), 8 decomposed into
31
+ PEG sub-rules, 30 literal operator/delimiter tokens, 4 lexical
32
+ whitespace/delimiter rules and 1 PEG-internal keyword guard. The 12
33
+ Annex A productions without a dedicated rule are listed and
34
+ classified (remark productions are handled by
35
+ RemarkScanner/RemarkAttacher; the rest are PEG lookaheads or
36
+ character classes). The Annex A snapshot lives at
37
+ `spec/fixtures/reference/annex-ab-productions.txt`. The spec fails
38
+ when a grammar rule lacks a row, a row names a missing rule/status,
39
+ an Annex production is unaccounted for, or the published guide is
40
+ stale; regenerate with `rake reference:crosswalk`.
41
+ - Part 2 (trended nightly tier): `Expressir::Conformance::Trend`
42
+ measures a corpus slice — file count, parse rate, format-idempotence
43
+ rate, diagnostic rate (Checker notes per parsed file), error/warning counts and per-note-id counts —
44
+ and writes a JSON artifact. `rake conformance:trend` runs it over the
45
+ stepmod resource slice; the nightly `conformance.yml` workflow runs
46
+ it after the round-trip tier and uploads `conformance-trend.json`.
47
+ Spec: `spec/expressir/conformance/trend_spec.rb`.
48
+ - Part 3 (published guides): `docs/_guides/reference/` now carries an
49
+ index plus subsystem guides — checker (with the generated note-id
50
+ catalog, `rake reference:notes`), Part 21, SHTOLO/Annex G (linked to
51
+ `annex-g-rules.md` and the audit spec), evaluator, and the language
52
+ server. The two generated pages are checked for staleness by
53
+ `spec/expressir/reference/*_spec.rb`, which run in the default suite.
54
+ The docs site build (`.github/workflows/docs.yml`) covers the new
55
+ pages.
@@ -1,15 +1,12 @@
1
- # 07 — Part 28 XML: select mapping v2 (#276)
1
+ # 07 — Part 28 XML: select mapping v2 (#276) — DONE
2
2
 
3
- ## Goal
4
- Full ISO 10303-28 EXPRESS-to-XML beyond the v1 skeleton
5
- (lib/expressir/express/xsd.rb): proper SELECT mapping (currently
6
- xs:anyType), aggregate/optional fidelity, schema-level structure.
3
+ Shipped: the ISO 10303-28 SELECT mapping lives in
4
+ lib/expressir/express/xsd.rb (complexType + xs:choice, entity members
5
+ as global-element refs, defined-type members by name+type, extensible-
6
+ empty fallback to sequence) and is covered by spec/expressir/express/
7
+ xsd_spec.rb. The CLI exposes both halves: `expressir xsd` and
8
+ `expressir xml-index` (#503).
7
9
 
8
- ## Steps
9
- - ISO 10303-28 mapping rules for SELECT types (union/member semantics)
10
- - apply on top of xsd.rb's element/complexType generation
11
- - validate generated XSDs against the ISO 10303-28 conformance examples
12
-
13
- ## Acceptance
14
- - a select-typed attribute renders per the standard (not xs:anyType)
15
- - the v1 examples still generate unchanged except where v2 improves them
10
+ Remaining escalation (moved to parity-ee 17 scope): validating the
11
+ generated XSDs against the Part 28 reference corpus — the detached
12
+ docs carry the standard text only, not the reference XSDs.
@@ -0,0 +1,25 @@
1
+ ---
2
+ title: Interop Exports
3
+ nav_order: 12
4
+ has_children: true
5
+ ---
6
+
7
+ = Interop Exports
8
+
9
+ == Purpose
10
+
11
+ Expressir can render an EXPRESS schema into JSON Schema and OWL/RDF.
12
+ No ISO mapping exists for either rendering: these are contributions of
13
+ the Expressir project, and the decisions behind them are documented in
14
+ the child guides so consumers can rely on stable semantics.
15
+
16
+ == Commands
17
+
18
+ [source,shell]
19
+ ----
20
+ expressir export-json-schema path/to/schema.exp -o schema.json
21
+ expressir export-owl path/to/schema.exp -o schema.ttl
22
+ ----
23
+
24
+ The Ruby API is available as `Expressir::Interop::JsonSchema` and
25
+ `Expressir::Interop::Owl`.
@@ -0,0 +1,88 @@
1
+ ---
2
+ title: JSON Schema Export
3
+ parent: Interop Exports
4
+ grand_parent: Guides
5
+ nav_order: 1
6
+ ---
7
+
8
+ = JSON Schema Export
9
+
10
+ == Purpose
11
+
12
+ `Expressir::Interop::JsonSchema` renders one EXPRESS schema as a JSON
13
+ Schema 2020-12 document. The mapping is a project contribution; this
14
+ guide records every decision so consumers can depend on it.
15
+
16
+ == Mapping decisions
17
+
18
+ Entities::
19
+ Each entity becomes a definition under `$defs`. An entity with
20
+ supertypes is an `allOf` of one `$ref` per `SUBTYPE OF` parent plus an
21
+ object schema holding its own explicit attributes. The subtype closure
22
+ is therefore expressed compositionally rather than duplicated.
23
+ Attributes appear in declaration order (inherited attributes come
24
+ through the parent branch of `allOf`). An entity without supertypes is
25
+ the object schema itself with a `title`.
26
+
27
+ Explicit attributes::
28
+ Only explicit attributes are exported. Derived and inverse attributes
29
+ are not part of the Part 21 exchange structure and are omitted.
30
+
31
+ OPTIONAL attributes::
32
+ An optional attribute is left out of `required` and its type becomes
33
+ `anyOf: [type, {type: null}]` — absent and explicit `$` both validate.
34
+
35
+ Types::
36
+ `INTEGER` → `integer`; `REAL`/`NUMBER` → `number`; `STRING` → `string`;
37
+ `BOOLEAN` → `boolean`; `LOGICAL` → `enum: [true, false, null]`
38
+ (`UNKNOWN` maps to null); `BINARY` → a string matching `[01]*`.
39
+
40
+ Enumerations::
41
+ An `ENUMERATION` becomes `{type: string, enum: [...]}`. `BASED_ON`
42
+ chains are folded into the full domain, matching Annex G semantics.
43
+
44
+ SELECT::
45
+ A named select becomes `{anyOf: [$ref, ...]}` over its items;
46
+ `BASED_ON` chains are folded into the full item list. Items referencing
47
+ declarations are `$ref`s.
48
+
49
+ Aggregates::
50
+ `LIST`, `ARRAY`, `SET` and `BAG` become JSON arrays. `minItems` and
51
+ `maxItems` come from the declared bounds (an unbounded upper bound is
52
+ omitted). `SET`, and `LIST ... OF UNIQUE`, set `uniqueItems: true`.
53
+
54
+ Names::
55
+ EXPRESS identifiers are used verbatim. EXPRESS is case-insensitive but
56
+ preserves case; JSON property names are case-sensitive, so consumers
57
+ must use the declared spelling.
58
+
59
+ Root document::
60
+ The root carries `$schema`, `$id`, `title`, every declaration in
61
+ `$defs`, and an `anyOf` over the entity definitions (one JSON document
62
+ describes one entity instance). A schema with no entities has no root
63
+ `anyOf`. Because an instance of a subtype also satisfies each ancestor
64
+ definition, a consumer that knows the EXPRESS entity of an instance
65
+ should validate against that entity's definition under `$defs` rather
66
+ than the root `anyOf`.
67
+
68
+ Not exported::
69
+ `WHERE` and `UNIQUE` rules, `GENERIC`/`GENERIC_ENTITY`, constants and
70
+ subtype constraint expressions. They have no direct JSON Schema
71
+ counterpart and are left to the consumer's semantic layer.
72
+
73
+ == Programmatic use
74
+
75
+ [source,ruby]
76
+ ----
77
+ schema = Expressir::Express::Parser.from_file("example.exp").schemas.first
78
+ document = Expressir::Interop::JsonSchema.new(schema).to_json
79
+ File.write("example.schema.json", document)
80
+ ----
81
+
82
+ == Part 21 population check
83
+
84
+ Part 21 instances serialize to JSON objects keyed by attribute name in
85
+ the Part 21 slot order (supertype attributes first), with `$` and `*`
86
+ omitted or null, enum values as strings, and references expanded
87
+ in-line (a cycle guard falls back to `{"$ref": "#id"}`). The acceptance
88
+ spec validates the Annex H population against the exported schema.
@@ -0,0 +1,87 @@
1
+ ---
2
+ title: OWL/RDF Export
3
+ parent: Interop Exports
4
+ grand_parent: Guides
5
+ nav_order: 2
6
+ ---
7
+
8
+ = OWL/RDF Export
9
+
10
+ == Purpose
11
+
12
+ `Expressir::Interop::Owl` renders one EXPRESS schema as OWL 2 in Turtle.
13
+ The approach generalizes the ifcOWL lineage from IFC to arbitrary
14
+ EXPRESS. This guide records the decisions and the literature the
15
+ approach follows.
16
+
17
+ == Lineage
18
+
19
+ The mapping follows the published EXPRESS-to-OWL work:
20
+
21
+ * J. Beetz, J. van Leeuwen, B. de Vries, "IfcOWL: A case of transforming
22
+ EXPRESS schemas into ontologies", _Artificial Intelligence for
23
+ Engineering Design, Analysis and Manufacturing_ 23(1), 2009, 89-101.
24
+ * P. Pauwels, W. Terkaj, "EXPRESS to OWL for construction industry:
25
+ Towards a recommendable and usable ifcOWL ontology", _Automation in
26
+ Construction_ 63, 2016, 100-133.
27
+ * W. Terkaj, A. Sojic, "Ontology-based representation of IFC EXPRESS
28
+ rules: An enhancement of the ifcOWL ontology", _Automation in
29
+ Construction_ 57, 2015, 188-201.
30
+
31
+ The last reference is the source of our scope decision on WHERE rules:
32
+ this exporter does not translate rule bodies (see below).
33
+
34
+ == Mapping decisions
35
+
36
+ Entities::
37
+ Each entity becomes an `owl:Class` with one `rdfs:subClassOf` per
38
+ `SUBTYPE OF` parent. Abstract entities carry an `rdfs:comment
39
+ "EXPRESS ABSTRACT SUPERTYPE"`; they are not made equivalent to their
40
+ subtype union.
41
+
42
+ Explicit attributes::
43
+ Each explicit attribute becomes a property with `rdfs:domain` on its
44
+ entity and `rdfs:range` from the attribute type. Entity, select and
45
+ enumeration ranges are object properties; primitive ranges are
46
+ datatype properties. `OPTIONAL` is recorded as an `rdfs:comment`
47
+ rather than an OWL cardinality restriction, because cardinalities
48
+ belong to the entity class and would multiply restrictions per
49
+ attribute.
50
+
51
+ Primitive types::
52
+ `INTEGER` → `xsd:integer`; `REAL`/`NUMBER` → `xsd:double`; `STRING` →
53
+ `xsd:string`; `BOOLEAN` → `xsd:boolean`; `BINARY` → `xsd:hexBinary`.
54
+ `LOGICAL` maps to `xsd:boolean`; EXPRESS `UNKNOWN` has no XSD
55
+ counterpart and is a documented loss. Defined types over primitives are
56
+ emitted as `rdfs:Datatype` with `owl:equivalentClass` to the XSD type.
57
+
58
+ Aggregates::
59
+ `LIST`, `ARRAY`, `SET` and `BAG` attributes are object properties with
60
+ range `rdf:List`; element type and ordering live in the RDF collection.
61
+
62
+ SELECT::
63
+ A named select becomes an `owl:Class` with an `owl:equivalentClass`
64
+ restriction whose `owl:unionOf` lists the item classes (union
65
+ semantics). `BASED_ON` chains are folded into the item list.
66
+
67
+ Enumerations::
68
+ An enumeration becomes an `owl:Class`; each item becomes an
69
+ `owl:NamedIndividual` of that class. `BASED_ON` chains are folded.
70
+
71
+ Not exported::
72
+ `WHERE` and `UNIQUE` rule bodies, subtype constraint expressions,
73
+ derived and inverse attributes, and aggregate bounds. Rule translation
74
+ is a research problem in its own right (see Terkaj & Sojic); consumers
75
+ that need rule semantics should consume the EXPRESS model directly.
76
+
77
+ == Programmatic use
78
+
79
+ [source,ruby]
80
+ ----
81
+ schema = Expressir::Express::Parser.from_file("example.exp").schemas.first
82
+ turtle = Expressir::Interop::Owl.new(
83
+ schema,
84
+ base_iri: "https://example.org/my-schema#",
85
+ ).export
86
+ File.write("example.ttl", turtle)
87
+ ----
@@ -0,0 +1,55 @@
1
+ = Checker note-id catalog
2
+
3
+ // Generated from lib/expressir/express/checker.rb by
4
+ // `rake reference:notes`. Do not edit by hand; the reference
5
+ // spec fails when this file is stale.
6
+
7
+ == Purpose
8
+
9
+ Every note id the Checker can raise, with the number of call
10
+ sites in the implementation. New checks use `:check_*` ids;
11
+ the conformance-derived ids (`:check_expr_*`, `:check_dialect_*`)
12
+ cite their clause in the note message.
13
+
14
+ [cols="3,1", options="header"]
15
+ |===
16
+ | Note id | Call sites
17
+
18
+ | `check_agg_type` | 1
19
+ | `check_attrib_name_fun` | 1
20
+ | `check_attribute_redeclaration` | 3
21
+ | `check_dialect_2004_only` | 1
22
+ | `check_dialect_deprecated` | 1
23
+ | `check_dialect_mixed` | 1
24
+ | `check_duplicate_declaration` | 1
25
+ | `check_enumeration_extended_type` | 1
26
+ | `check_expr_assignment_type` | 1
27
+ | `check_expr_initializer_type` | 1
28
+ | `check_expr_operand_domain` | 7
29
+ | `check_expr_return` | 2
30
+ | `check_expr_unique_duplicate` | 1
31
+ | `check_expr_where_boolean` | 1
32
+ | `check_interface_kind_restriction` | 1
33
+ | `check_inverse_attrib_ref` | 2
34
+ | `check_inverse_derive` | 1
35
+ | `check_inverse_entity` | 1
36
+ | `check_inverse_inverse` | 1
37
+ | `check_schema_iface_resource_duplicate` | 1
38
+ | `check_schema_interface_redundant` | 1
39
+ | `check_select_extended_type` | 1
40
+ | `check_select_named_type` | 1
41
+ | `check_self_schema_reference` | 2
42
+ | `check_string_no_entity` | 1
43
+ | `check_subtype_cycle` | 1
44
+ | `check_subtype_ref` | 1
45
+ | `check_subtypeof_invalid` | 1
46
+ | `check_supertype_ref` | 2
47
+ | `check_unique_name_pattern` | 1
48
+ | `check_unresolved_ref` | 3
49
+ | `check_where_name_pattern` | 1
50
+ | `qualified_attrib_attr_not_found` | 1
51
+ | `qualified_attrib_group_not_ancestor` | 1
52
+ | `qualified_attrib_group_not_found` | 1
53
+ |===
54
+
55
+ The catalog covers 35 note ids.
@@ -0,0 +1,36 @@
1
+ ---
2
+ title: Checker
3
+ parent: Reference
4
+ grand_parent: Guides
5
+ nav_order: 3
6
+ ---
7
+
8
+ = Checker
9
+
10
+ == Purpose
11
+
12
+ `Expressir::Express::Checker` performs static, edition-aware semantic
13
+ checks over a parsed repository. Notes carry a stable id, a severity,
14
+ the schema, a message citing the ISO 10303-11 clause where the check
15
+ comes from, and the offending model node.
16
+
17
+ == Note ids
18
+
19
+ The catalog is generated from the checker source and published as the
20
+ "Checker note-id catalog" guide. New conformance-derived
21
+ checks use `:check_expr_*`, `:check_statement_*`, `:check_rule_*` and
22
+ `:check_dialect_*` ids; the message carries the clause.
23
+
24
+ == Dialects
25
+
26
+ `Checker.new(repository, dialect: :"10303-11:1994")` reports
27
+ 2004-only constructs as errors when targeting the 1994 edition;
28
+ `dialect: :"10303-11:2004"` reports the Annex K deprecated inline
29
+ subtype-constraint syntax as warnings. Without a dialect the report is
30
+ unchanged. See the Dialect awareness task notes (TODO.sota/06).
31
+
32
+ == Severities and validity
33
+
34
+ `Checker#valid?` is true when no error-severity note was raised.
35
+ Indeterminate expression results are not violations; only a proven
36
+ false WHERE rule is.
@@ -0,0 +1,40 @@
1
+ ---
2
+ title: Evaluator
3
+ parent: Reference
4
+ grand_parent: Guides
5
+ nav_order: 6
6
+ ---
7
+
8
+ = Evaluator
9
+
10
+ == Purpose
11
+
12
+ `Expressir::Eval` executes EXPRESS: expressions over a value model,
13
+ functions (parameters, locals, control flow), and WHERE rules over a
14
+ Part 21 population.
15
+
16
+ == Expressions
17
+
18
+ `Expressir::Eval::Expression` implements ISO 10303-11 clause 12:
19
+ arithmetic with result typing, logical tables (12.4), relational
20
+ orderings (12.2.1), IN (12.2.3), LIKE patterns (12.2.5, table 11),
21
+ intervals, aggregate operations (tables 16-18 including element
22
+ singletons), QUERY, and indeterminate propagation. The value model
23
+ lives in `Values`: logical constants, enumeration and binary values,
24
+ aggregates and Part 21 instances.
25
+
26
+ == Execution
27
+
28
+ `Expressir::Eval::Interpreter` runs functions and procedures:
29
+ assignment (including indexed), IF/CASE, WHILE/UNTIL/increment REPEAT
30
+ with SKIP and ESCAPE, RETURN (falling off the end is an error), and the
31
+ builtin set A (`ABS` … `VALUE`, `TYPEOF`, `USEDIN`). Populations are
32
+ read through `Expressir::Eval::Environment`, which maps Part 21 slots
33
+ in clause 12 order.
34
+
35
+ == Rules
36
+
37
+ `Expressir::Eval::Rules.check(population, schema)` evaluates each
38
+ instance's entity WHERE rules with `SELF` and both bare and
39
+ `SELF\attribute` bindings. A rule is violated only when it evaluates
40
+ to false; indeterminate is not a violation (clause 9.4).