expressir 2.4.35 → 2.4.37
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/.github/workflows/conformance.yml +34 -0
- data/.gitignore +3 -0
- data/Gemfile +1 -1
- data/TODO.sota/00-overview.md +57 -0
- data/TODO.sota/01-type-checking.md +115 -0
- data/TODO.sota/02-evaluator.md +86 -0
- data/TODO.sota/03-conformance.md +53 -0
- data/TODO.sota/04-lsp.md +70 -0
- data/TODO.sota/05-interop.md +55 -0
- data/TODO.sota/06-dialects.md +57 -0
- data/TODO.sota/07-reference-artifacts.md +55 -0
- data/docs/_guides/interop/index.adoc +25 -0
- data/docs/_guides/interop/json-schema.adoc +88 -0
- data/docs/_guides/interop/owl-rdf.adoc +87 -0
- data/docs/_guides/reference/checker-notes.adoc +55 -0
- data/docs/_guides/reference/checker.adoc +36 -0
- data/docs/_guides/reference/evaluator.adoc +40 -0
- data/docs/_guides/reference/grammar-crosswalk.adoc +299 -0
- data/docs/_guides/reference/index.adoc +22 -0
- data/docs/_guides/reference/lsp.adoc +41 -0
- data/docs/_guides/reference/p21.adoc +30 -0
- data/docs/_guides/reference/shtolo.adoc +36 -0
- data/exe/expressir-lsp +6 -0
- data/expressir.gemspec +2 -2
- data/ext/expressir_core/Cargo.toml +1 -1
- data/lib/expressir/cli.rb +18 -0
- data/lib/expressir/commands/check.rb +3 -1
- data/lib/expressir/commands/export_json_schema.rb +29 -0
- data/lib/expressir/commands/export_owl.rb +26 -0
- data/lib/expressir/commands/validate.rb +3 -0
- data/lib/expressir/commands.rb +2 -0
- data/lib/expressir/conformance/trend.rb +100 -0
- data/lib/expressir/conformance.rb +8 -0
- data/lib/expressir/eval/environment.rb +83 -0
- data/lib/expressir/eval/expression.rb +610 -0
- data/lib/expressir/eval/interpreter.rb +316 -0
- data/lib/expressir/eval/rules.rb +88 -0
- data/lib/expressir/eval/values.rb +74 -0
- data/lib/expressir/eval.rb +17 -0
- data/lib/expressir/express/builders/expression_builder.rb +9 -1
- data/lib/expressir/express/checker.rb +779 -2
- data/lib/expressir/express/dialect.rb +44 -0
- data/lib/expressir/express/formatters/expressions_formatter.rb +4 -1
- data/lib/expressir/express/parser.rb +9 -4
- data/lib/expressir/express.rb +1 -0
- data/lib/expressir/interop/json_schema.rb +195 -0
- data/lib/expressir/interop/owl.rb +216 -0
- data/lib/expressir/interop.rb +13 -0
- data/lib/expressir/lsp/document.rb +226 -0
- data/lib/expressir/lsp/server.rb +184 -0
- data/lib/expressir/lsp/workspace.rb +402 -0
- data/lib/expressir/lsp.rb +11 -0
- data/lib/expressir/mapping/refpath.rb +65 -4
- data/lib/expressir/reference/grammar_crosswalk.rb +122 -0
- data/lib/expressir/reference/grammar_crosswalk.yml +800 -0
- data/lib/expressir/reference/note_catalog.rb +54 -0
- data/lib/expressir/reference.rb +10 -0
- data/lib/expressir/version.rb +1 -1
- data/lib/expressir.rb +4 -0
- data/lib/tasks/conformance.rake +27 -0
- data/lib/tasks/reference.rake +25 -0
- metadata +50 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 46faf8f6bb37c2f1849a2d131b1489e35deed5511f07c8ec873cd07057f7bf79
|
|
4
|
+
data.tar.gz: e123c04c9745923412e7119140130e07805836aea196848420b11df6871cf93f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7531e5fe41e6c6a338d0157837cba39f9d23cecece891517963e122fec9cd90dc01d8901689b171f2e68798788da19bee80cc25204cb42b786df8c55ea1ac27c
|
|
7
|
+
data.tar.gz: c6b759368286b4562933e4871e735df7347fcda3ba548215bb28d574f416db8e00c9b8958966fd650878d538a13962be79c27ed2d002e4ddc07597bb3983c88f
|
|
@@ -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
data/Gemfile
CHANGED
|
@@ -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
|
|
@@ -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.
|
data/TODO.sota/04-lsp.md
ADDED
|
@@ -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.
|
|
@@ -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`.
|