expressir 2.4.29-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.
- checksums.yaml +7 -0
- data/.cargo/config.toml +3 -0
- data/.github/scripts/test_installed_gem.rb +34 -0
- data/.github/workflows/codeql.yml +35 -0
- data/.github/workflows/docs.yml +99 -0
- data/.github/workflows/links.yml +100 -0
- data/.github/workflows/native-gems.yml +201 -0
- data/.github/workflows/rake.yml +19 -0
- data/.github/workflows/release.yml +37 -0
- data/.github/workflows/rust-ext.yml +41 -0
- data/.github/workflows/stress.yml +36 -0
- data/.github/workflows/validate_schemas.yml +48 -0
- data/.github/workflows/verify_remarks.yml +33 -0
- data/.gitignore +55 -0
- data/.hound.yml +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +18 -0
- data/.rubocop_todo.yml +297 -0
- data/CHANGELOG.md +159 -0
- data/Gemfile +18 -0
- data/README.adoc +2783 -0
- data/Rakefile +41 -0
- data/TODO.bugs/01-stale-transformer-autoload.md +39 -0
- data/TODO.bugs/02-parser-class-instance-vars.md +36 -0
- data/TODO.bugs/03-builder-mutable-state.md +43 -0
- data/TODO.bugs/04-formatter-public-send-dispatch.md +53 -0
- data/TODO.bugs/05-anonymous-formatter-subclass.md +45 -0
- data/TODO.bugs/06-collection-registry-single-source.md +53 -0
- data/TODO.bugs/07-require-relative-cleanup.md +42 -0
- data/TODO.bugs/08-require-expressir-in-commands.md +34 -0
- data/TODO.bugs/09-parser-split.md +53 -0
- data/TODO.bugs/10-to-s-override.md +42 -0
- data/TODO.bugs/11-parser-class-variables.md +39 -0
- data/TODO.bugs/12-marker-modules-vs-registry.md +64 -0
- data/TODO.bugs/13-string-literal-scanner-limitation.md +52 -0
- data/TODO.bugs/14-model-formatting-leak.md +30 -0
- data/TODO.bugs/15-expression-children-macro.md +27 -0
- data/TODO.bugs/16-pretty-formatter-duplication.md +28 -0
- data/TODO.bugs/17-snake-case-cache-mutable-constant.md +28 -0
- data/TODO.bugs/18-const-get-private-constants.md +30 -0
- data/TODO.bugs/19-format-methods-public.md +22 -0
- data/TODO.bugs/20-coverage-nested-entities-dedup.md +20 -0
- data/TODO.bugs/21-operator-tokens-secondary-dispatch.md +21 -0
- data/TODO.bugs/22-builder-fast-path-wrappers.md +32 -0
- data/TODO.bugs/23-coverage-inverse-maps.md +21 -0
- data/TODO.bugs/24-streaming-builder-complexity.md +19 -0
- data/TODO.bugs/25-debug-puts-in-production.md +21 -0
- data/TODO.bugs/26-generic-entity-children-misplaced.md +21 -0
- data/TODO.bugs/27-package-build-god-method.md +19 -0
- data/TODO.bugs/28-package-god-class.md +30 -0
- data/TODO.bugs/29-validate-ascii-god-class.md +24 -0
- data/TODO.bugs/30-unicode-map-extraction.md +19 -0
- data/TODO.bugs/README.md +43 -0
- data/TODO.max-perf/01-restore-ci-green.md +36 -0
- data/TODO.max-perf/02-streaming-parse-path.md +31 -0
- data/TODO.max-perf/03-cli-parallel-opt-in.md +27 -0
- data/TODO.max-perf/04-benchmark-harness.md +28 -0
- data/TODO.max-perf/05-parallel-fidelity-specs.md +22 -0
- data/TODO.max-perf/06-builder-cpu-audit.md +41 -0
- data/TODO.max-perf/07-upstream-parsanol-roadmap.md +27 -0
- data/TODO.max-perf/08-builder-build-perf.md +45 -0
- data/TODO.max-perf/09-grammar-cold-start.md +25 -0
- data/TODO.max-perf/10-parser-facade-hygiene.md +23 -0
- data/TODO.max-perf/11-ci-green-closeout.md +25 -0
- data/TODO.max-perf/12-require-boot-profile.md +25 -0
- data/TODO.max-perf/13-key-conversion-specs.md +26 -0
- data/TODO.max-perf/14-builder-call-handler-audit.md +28 -0
- data/TODO.parity-ee/00-overview.md +76 -0
- data/TODO.parity-ee/01-annex-g-rule-extraction.md +41 -0
- data/TODO.parity-ee/02-eeng-algorithm-inventory.md +8 -0
- data/TODO.parity-ee/03-eeng-oracle-harness.md +33 -0
- data/TODO.parity-ee/04-shtolo-concatenate.md +44 -0
- data/TODO.parity-ee/05-shtolo-longform-flatten.md +53 -0
- data/TODO.parity-ee/06-interface-scheduling-parity.md +47 -0
- data/TODO.parity-ee/07-semantic-checks-port.md +35 -0
- data/TODO.parity-ee/08-pretty-roundtrip-gate.md +27 -0
- data/TODO.parity-ee/09-smrl-index-and-listing.md +22 -0
- data/TODO.parity-ee/10-interface-dot-graph.md +21 -0
- data/TODO.parity-ee/11-import-eeng-tests.md +79 -0
- data/TODO.parity-ee/12-full-check-catalog.md +67 -0
- data/TODO.parity-ee/13-population-p21.md +54 -0
- data/TODO.parity-ee/14-shtolo-completion.md +44 -0
- data/TODO.parity-ee/15-part28-xml.md +51 -0
- data/TODO.parity-ee/16-compare-patch.md +48 -0
- data/TODO.parity-ee/17-official-tests.md +42 -0
- data/TODO.parity-ee/18-mim-mapping.md +47 -0
- data/TODO.parity-ee/19-architecture.md +97 -0
- data/TODO.parity-ee/parity-matrix.md +108 -0
- data/TODO.refpath-v2/00-overview.md +64 -0
- data/TODO.suma-improvements/00-overview.md +23 -0
- data/TODO.suma-improvements/01-prebuilt-platform-gems.md +33 -0
- data/TODO.suma-improvements/02-suma-e2e.md +39 -0
- data/TODO.suma-improvements/03-item-graph.md +22 -0
- data/TODO.suma-improvements/04-compiled-set-default.md +16 -0
- data/TODO.suma-improvements/05-validation-in-docs.md +17 -0
- data/TODO.suma-improvements/06-memory-remeasure.md +36 -0
- data/TODO.suma-improvements/07-part28-xml.md +15 -0
- data/TODO.suma-improvements/08-windows-gnu-toolchain.md +15 -0
- data/TODO.suma-improvements/09-checker-tranche3.md +13 -0
- data/TODO.suma-improvements/10-expressdoc.md +8 -0
- data/benchmark/srl_benchmark.rb +458 -0
- data/benchmark/srl_native_benchmark.rb +146 -0
- data/benchmark/srl_ruby_benchmark.rb +132 -0
- data/bin/console +11 -0
- data/bin/rspec +30 -0
- data/bin/setup +8 -0
- data/docs/Gemfile +12 -0
- data/docs/_config.yml +141 -0
- data/docs/_guides/changes/changes-format.adoc +778 -0
- data/docs/_guides/changes/importing-eengine.adoc +898 -0
- data/docs/_guides/changes/index.adoc +396 -0
- data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
- data/docs/_guides/changes/validating-changes.adoc +681 -0
- data/docs/_guides/cli/benchmark-performance.adoc +834 -0
- data/docs/_guides/cli/coverage-analysis.adoc +921 -0
- data/docs/_guides/cli/format-schemas.adoc +547 -0
- data/docs/_guides/cli/index.adoc +8 -0
- data/docs/_guides/cli/managing-changes.adoc +927 -0
- data/docs/_guides/cli/validate-ascii.adoc +645 -0
- data/docs/_guides/cli/validate-schemas.adoc +534 -0
- data/docs/_guides/formatter/formatter-architecture.adoc +401 -0
- data/docs/_guides/index.adoc +165 -0
- data/docs/_guides/ler/creating-packages.adoc +664 -0
- data/docs/_guides/ler/index.adoc +305 -0
- data/docs/_guides/ler/loading-packages.adoc +707 -0
- data/docs/_guides/ler/package-formats.adoc +748 -0
- data/docs/_guides/ler/querying-packages.adoc +826 -0
- data/docs/_guides/ler/step-packages.adoc +385 -0
- data/docs/_guides/ler/validating-packages.adoc +750 -0
- data/docs/_guides/liquid/basic-templates.adoc +813 -0
- data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
- data/docs/_guides/liquid/drops-reference.adoc +829 -0
- data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
- data/docs/_guides/liquid/index.adoc +468 -0
- data/docs/_guides/manifests/creating-manifests.adoc +483 -0
- data/docs/_guides/manifests/index.adoc +307 -0
- data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
- data/docs/_guides/manifests/validating-manifests.adoc +713 -0
- data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
- data/docs/_guides/ruby-api/index.adoc +257 -0
- data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
- data/docs/_guides/ruby-api/search-engine.adoc +609 -0
- data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
- data/docs/_pages/data-model.adoc +665 -0
- data/docs/_pages/express-language.adoc +506 -0
- data/docs/_pages/getting-started.adoc +414 -0
- data/docs/_pages/index.adoc +116 -0
- data/docs/_pages/introduction.adoc +256 -0
- data/docs/_pages/ler-packages.adoc +837 -0
- data/docs/_pages/parsers.adoc +709 -0
- data/docs/_pages/schema-manifests.adoc +431 -0
- data/docs/_references/index.adoc +228 -0
- data/docs/_tutorials/creating-ler-package.adoc +735 -0
- data/docs/_tutorials/documentation-coverage.adoc +795 -0
- data/docs/_tutorials/formatting-schemas.adoc +89 -0
- data/docs/_tutorials/index.adoc +231 -0
- data/docs/_tutorials/liquid-templates.adoc +806 -0
- data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
- data/docs/_tutorials/querying-schemas.adoc +751 -0
- data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
- data/docs/index.adoc +242 -0
- data/docs/lychee.toml +90 -0
- data/examples/demo_ler_usage.sh +86 -0
- data/examples/ler/README.md +111 -0
- data/examples/ler/simple_example.ler +0 -0
- data/examples/ler/simple_schema.exp +33 -0
- data/examples/ler_build.rb +75 -0
- data/examples/ler_cli.rb +79 -0
- data/examples/ler_demo_complete.rb +276 -0
- data/examples/ler_query.rb +91 -0
- data/examples/ler_query_examples.rb +305 -0
- data/examples/ler_stats.rb +81 -0
- data/examples/phase3_demo.rb +159 -0
- data/examples/query_demo_simple.rb +131 -0
- data/exe/expressir +11 -0
- data/exe/expressir-format +14 -0
- data/exe/expressir-format-test +82 -0
- data/expressir.gemspec +61 -0
- data/lib/expressir/3.2/expressir_core.so +0 -0
- data/lib/expressir/3.3/expressir_core.so +0 -0
- data/lib/expressir/3.4/expressir_core.so +0 -0
- data/lib/expressir/4.0/expressir_core.so +0 -0
- data/lib/expressir/benchmark.rb +310 -0
- data/lib/expressir/changes/item_change.rb +20 -0
- data/lib/expressir/changes/mapping_change.rb +16 -0
- data/lib/expressir/changes/schema_change.rb +85 -0
- data/lib/expressir/changes/version_change.rb +26 -0
- data/lib/expressir/changes.rb +9 -0
- data/lib/expressir/cli.rb +148 -0
- data/lib/expressir/commands/base.rb +25 -0
- data/lib/expressir/commands/benchmark.rb +59 -0
- data/lib/expressir/commands/benchmark_cache.rb +80 -0
- data/lib/expressir/commands/changes.rb +34 -0
- data/lib/expressir/commands/changes_import_eengine.rb +146 -0
- data/lib/expressir/commands/changes_validate.rb +63 -0
- data/lib/expressir/commands/check.rb +56 -0
- data/lib/expressir/commands/clean.rb +20 -0
- data/lib/expressir/commands/coverage.rb +458 -0
- data/lib/expressir/commands/expand.rb +26 -0
- data/lib/expressir/commands/file_violations.rb +70 -0
- data/lib/expressir/commands/fix.rb +33 -0
- data/lib/expressir/commands/flatten.rb +29 -0
- data/lib/expressir/commands/format.rb +43 -0
- data/lib/expressir/commands/manifest.rb +420 -0
- data/lib/expressir/commands/mapping_validate.rb +68 -0
- data/lib/expressir/commands/non_ascii_character.rb +49 -0
- data/lib/expressir/commands/non_ascii_violation_collection.rb +301 -0
- data/lib/expressir/commands/package.rb +1222 -0
- data/lib/expressir/commands/parity_inputs.rb +160 -0
- data/lib/expressir/commands/validate.rb +106 -0
- data/lib/expressir/commands/validate_ascii.rb +94 -0
- data/lib/expressir/commands/validate_load.rb +91 -0
- data/lib/expressir/commands/version.rb +9 -0
- data/lib/expressir/commands/xsd.rb +23 -0
- data/lib/expressir/commands.rb +30 -0
- data/lib/expressir/config.rb +60 -0
- data/lib/expressir/coverage.rb +510 -0
- data/lib/expressir/eengine/arm_compare_report.rb +23 -0
- data/lib/expressir/eengine/changes_section.rb +16 -0
- data/lib/expressir/eengine/compare_report.rb +69 -0
- data/lib/expressir/eengine/mim_compare_report.rb +23 -0
- data/lib/expressir/eengine/modified_object.rb +21 -0
- data/lib/expressir/eengine.rb +9 -0
- data/lib/expressir/errors.rb +113 -0
- data/lib/expressir/express/adoc_hyperlink_formatter.rb +30 -0
- data/lib/expressir/express/adoc_source_formatter.rb +12 -0
- data/lib/expressir/express/ast_key_converter.rb +114 -0
- data/lib/expressir/express/builder.rb +277 -0
- data/lib/expressir/express/builder_context.rb +22 -0
- data/lib/expressir/express/builder_registry.rb +397 -0
- data/lib/expressir/express/builders/attribute_decl_builder.rb +32 -0
- data/lib/expressir/express/builders/built_in_builder.rb +75 -0
- data/lib/expressir/express/builders/constant_builder.rb +108 -0
- data/lib/expressir/express/builders/declaration_builder.rb +20 -0
- data/lib/expressir/express/builders/derive_clause_builder.rb +14 -0
- data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
- data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
- data/lib/expressir/express/builders/entity_decl_builder.rb +116 -0
- data/lib/expressir/express/builders/explicit_attr_builder.rb +49 -0
- data/lib/expressir/express/builders/expression_builder.rb +416 -0
- data/lib/expressir/express/builders/function_decl_builder.rb +86 -0
- data/lib/expressir/express/builders/helpers.rb +148 -0
- data/lib/expressir/express/builders/interface_builder.rb +151 -0
- data/lib/expressir/express/builders/inverse_attr_builder.rb +43 -0
- data/lib/expressir/express/builders/inverse_attr_type_builder.rb +30 -0
- data/lib/expressir/express/builders/inverse_clause_builder.rb +14 -0
- data/lib/expressir/express/builders/literal_builder.rb +93 -0
- data/lib/expressir/express/builders/procedure_decl_builder.rb +82 -0
- data/lib/expressir/express/builders/qualifier_builder.rb +102 -0
- data/lib/expressir/express/builders/reference_builder.rb +18 -0
- data/lib/expressir/express/builders/rule_decl_builder.rb +97 -0
- data/lib/expressir/express/builders/schema_body_decl_builder.rb +18 -0
- data/lib/expressir/express/builders/schema_decl_builder.rb +56 -0
- data/lib/expressir/express/builders/schema_version_builder.rb +34 -0
- data/lib/expressir/express/builders/simple_id_builder.rb +17 -0
- data/lib/expressir/express/builders/statement_builder.rb +243 -0
- data/lib/expressir/express/builders/subtype_constraint_builder.rb +166 -0
- data/lib/expressir/express/builders/syntax_builder.rb +30 -0
- data/lib/expressir/express/builders/type_builder.rb +238 -0
- data/lib/expressir/express/builders/type_decl_builder.rb +26 -0
- data/lib/expressir/express/builders/unique_clause_builder.rb +20 -0
- data/lib/expressir/express/builders/unique_rule_builder.rb +41 -0
- data/lib/expressir/express/builders/where_clause_builder.rb +20 -0
- data/lib/expressir/express/builders.rb +55 -0
- data/lib/expressir/express/cache.rb +76 -0
- data/lib/expressir/express/checker.rb +812 -0
- data/lib/expressir/express/concatenator.rb +79 -0
- data/lib/expressir/express/core.rb +95 -0
- data/lib/expressir/express/error.rb +124 -0
- data/lib/expressir/express/formatter.rb +149 -0
- data/lib/expressir/express/formatters/data_types_formatter.rb +362 -0
- data/lib/expressir/express/formatters/declarations_formatter.rb +753 -0
- data/lib/expressir/express/formatters/expressions_formatter.rb +180 -0
- data/lib/expressir/express/formatters/literals_formatter.rb +55 -0
- data/lib/expressir/express/formatters/references_formatter.rb +53 -0
- data/lib/expressir/express/formatters/remark_formatter.rb +270 -0
- data/lib/expressir/express/formatters/remark_item_formatter.rb +28 -0
- data/lib/expressir/express/formatters/statements_formatter.rb +272 -0
- data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +54 -0
- data/lib/expressir/express/formatters.rb +22 -0
- data/lib/expressir/express/grammar/parser.rb +712 -0
- data/lib/expressir/express/grammar.rb +11 -0
- data/lib/expressir/express/hyperlink_formatter.rb +35 -0
- data/lib/expressir/express/interface_dot.rb +105 -0
- data/lib/expressir/express/lazy_repository.rb +211 -0
- data/lib/expressir/express/line_map.rb +48 -0
- data/lib/expressir/express/listing.rb +174 -0
- data/lib/expressir/express/model_traversal.rb +42 -0
- data/lib/expressir/express/model_visitor.rb +25 -0
- data/lib/expressir/express/node_position_index.rb +342 -0
- data/lib/expressir/express/parallel_files.rb +229 -0
- data/lib/expressir/express/parser.rb +523 -0
- data/lib/expressir/express/pretty_formatter.rb +586 -0
- data/lib/expressir/express/pretty_gate.rb +61 -0
- data/lib/expressir/express/refs_overlay.rb +47 -0
- data/lib/expressir/express/remark_attacher.rb +1098 -0
- data/lib/expressir/express/remark_overlay.rb +86 -0
- data/lib/expressir/express/remark_scanner.rb +245 -0
- data/lib/expressir/express/resolve_references_model_visitor.rb +29 -0
- data/lib/expressir/express/schema_block_scanner.rb +137 -0
- data/lib/expressir/express/schema_head_formatter.rb +22 -0
- data/lib/expressir/express/schema_plain_source_formatter.rb +11 -0
- data/lib/expressir/express/schema_source_formatter.rb +15 -0
- data/lib/expressir/express/scope_resolver.rb +223 -0
- data/lib/expressir/express/self_schema_reference.rb +126 -0
- data/lib/expressir/express/shtolo.rb +679 -0
- data/lib/expressir/express/smrl_xml.rb +125 -0
- data/lib/expressir/express/source_formatter.rb +15 -0
- data/lib/expressir/express/streaming_builder.rb +435 -0
- data/lib/expressir/express/xsd.rb +259 -0
- data/lib/expressir/express.rb +53 -0
- data/lib/expressir/liquid.rb +1 -0
- data/lib/expressir/manifest/resolver.rb +210 -0
- data/lib/expressir/manifest/validator.rb +192 -0
- data/lib/expressir/manifest.rb +6 -0
- data/lib/expressir/mapping/refpath.rb +857 -0
- data/lib/expressir/mapping.rb +253 -0
- data/lib/expressir/model/cache.rb +18 -0
- data/lib/expressir/model/concerns.rb +42 -0
- data/lib/expressir/model/data_types/aggregate.rb +26 -0
- data/lib/expressir/model/data_types/array.rb +25 -0
- data/lib/expressir/model/data_types/bag.rb +21 -0
- data/lib/expressir/model/data_types/binary.rb +19 -0
- data/lib/expressir/model/data_types/boolean.rb +15 -0
- data/lib/expressir/model/data_types/enumeration.rb +21 -0
- data/lib/expressir/model/data_types/enumeration_item.rb +24 -0
- data/lib/expressir/model/data_types/generic.rb +24 -0
- data/lib/expressir/model/data_types/generic_entity.rb +24 -0
- data/lib/expressir/model/data_types/integer.rb +15 -0
- data/lib/expressir/model/data_types/list.rb +23 -0
- data/lib/expressir/model/data_types/logical.rb +15 -0
- data/lib/expressir/model/data_types/number.rb +15 -0
- data/lib/expressir/model/data_types/real.rb +17 -0
- data/lib/expressir/model/data_types/select.rb +23 -0
- data/lib/expressir/model/data_types/set.rb +21 -0
- data/lib/expressir/model/data_types/string.rb +19 -0
- data/lib/expressir/model/data_types.rb +25 -0
- data/lib/expressir/model/declarations/attribute.rb +38 -0
- data/lib/expressir/model/declarations/constant.rb +28 -0
- data/lib/expressir/model/declarations/derived_attribute.rb +25 -0
- data/lib/expressir/model/declarations/entity.rb +62 -0
- data/lib/expressir/model/declarations/function.rb +59 -0
- data/lib/expressir/model/declarations/informal_proposition_rule.rb +25 -0
- data/lib/expressir/model/declarations/interface.rb +37 -0
- data/lib/expressir/model/declarations/interface_item.rb +21 -0
- data/lib/expressir/model/declarations/interfaced_item.rb +33 -0
- data/lib/expressir/model/declarations/inverse_attribute.rb +25 -0
- data/lib/expressir/model/declarations/parameter.rb +28 -0
- data/lib/expressir/model/declarations/procedure.rb +57 -0
- data/lib/expressir/model/declarations/remark_item.rb +21 -0
- data/lib/expressir/model/declarations/rule.rb +66 -0
- data/lib/expressir/model/declarations/schema.rb +215 -0
- data/lib/expressir/model/declarations/schema_version.rb +19 -0
- data/lib/expressir/model/declarations/schema_version_item.rb +19 -0
- data/lib/expressir/model/declarations/subtype_constraint.rb +32 -0
- data/lib/expressir/model/declarations/type.rb +45 -0
- data/lib/expressir/model/declarations/unique_rule.rb +26 -0
- data/lib/expressir/model/declarations/variable.rb +28 -0
- data/lib/expressir/model/declarations/where_rule.rb +26 -0
- data/lib/expressir/model/declarations.rb +31 -0
- data/lib/expressir/model/dependency_resolver.rb +268 -0
- data/lib/expressir/model/exp_file.rb +42 -0
- data/lib/expressir/model/expressions/aggregate_initializer.rb +18 -0
- data/lib/expressir/model/expressions/aggregate_initializer_item.rb +20 -0
- data/lib/expressir/model/expressions/binary_expression.rb +59 -0
- data/lib/expressir/model/expressions/entity_constructor.rb +20 -0
- data/lib/expressir/model/expressions/function_call.rb +20 -0
- data/lib/expressir/model/expressions/interval.rb +29 -0
- data/lib/expressir/model/expressions/query_expression.rb +31 -0
- data/lib/expressir/model/expressions/unary_expression.rb +25 -0
- data/lib/expressir/model/expressions.rb +18 -0
- data/lib/expressir/model/identifier.rb +26 -0
- data/lib/expressir/model/indexes/entity_index.rb +103 -0
- data/lib/expressir/model/indexes/item_graph.rb +185 -0
- data/lib/expressir/model/indexes/reference_index.rb +148 -0
- data/lib/expressir/model/indexes/type_index.rb +149 -0
- data/lib/expressir/model/indexes.rb +12 -0
- data/lib/expressir/model/interface_validator.rb +384 -0
- data/lib/expressir/model/literals/binary.rb +17 -0
- data/lib/expressir/model/literals/integer.rb +17 -0
- data/lib/expressir/model/literals/logical.rb +21 -0
- data/lib/expressir/model/literals/real.rb +17 -0
- data/lib/expressir/model/literals/string.rb +20 -0
- data/lib/expressir/model/literals.rb +13 -0
- data/lib/expressir/model/model_element.rb +377 -0
- data/lib/expressir/model/references/attribute_reference.rb +19 -0
- data/lib/expressir/model/references/group_reference.rb +19 -0
- data/lib/expressir/model/references/index_reference.rb +23 -0
- data/lib/expressir/model/references/simple_reference.rb +21 -0
- data/lib/expressir/model/references.rb +12 -0
- data/lib/expressir/model/remark_format.rb +17 -0
- data/lib/expressir/model/remark_info.rb +92 -0
- data/lib/expressir/model/remark_placement.rb +42 -0
- data/lib/expressir/model/repository.rb +483 -0
- data/lib/expressir/model/repository_validator.rb +293 -0
- data/lib/expressir/model/search_engine.rb +551 -0
- data/lib/expressir/model/statements/alias.rb +31 -0
- data/lib/expressir/model/statements/assignment.rb +23 -0
- data/lib/expressir/model/statements/case.rb +42 -0
- data/lib/expressir/model/statements/case_action.rb +20 -0
- data/lib/expressir/model/statements/compound.rb +21 -0
- data/lib/expressir/model/statements/escape.rb +18 -0
- data/lib/expressir/model/statements/if.rb +26 -0
- data/lib/expressir/model/statements/null.rb +18 -0
- data/lib/expressir/model/statements/procedure_call.rb +22 -0
- data/lib/expressir/model/statements/repeat.rb +40 -0
- data/lib/expressir/model/statements/return.rb +20 -0
- data/lib/expressir/model/statements/skip.rb +18 -0
- data/lib/expressir/model/statements.rb +20 -0
- data/lib/expressir/model/supertype_expressions/binary_supertype_expression.rb +25 -0
- data/lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb +17 -0
- data/lib/expressir/model/supertype_expressions.rb +12 -0
- data/lib/expressir/model.rb +39 -0
- data/lib/expressir/package/builder.rb +231 -0
- data/lib/expressir/package/metadata.rb +79 -0
- data/lib/expressir/package/reader.rb +149 -0
- data/lib/expressir/package.rb +8 -0
- data/lib/expressir/schema_manifest.rb +159 -0
- data/lib/expressir/schema_manifest_entry.rb +15 -0
- data/lib/expressir/version.rb +8 -0
- data/lib/expressir.rb +94 -0
- data/lib/tasks/verify_remarks.rake +16 -0
- data/rakelib/native.rake +24 -0
- data/rakelib/oracle.rake +52 -0
- data/rakelib/verify_remarks.rake +16 -0
- metadata +692 -0
|
@@ -0,0 +1,679 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Express
|
|
5
|
+
# SHTOLO — short-to-long conversion per ISO 10303-11:2004 Annex G
|
|
6
|
+
# (expressir#32): flattens a multi-schema specification into a
|
|
7
|
+
# single ISO 10303-11:1994 longform schema.
|
|
8
|
+
#
|
|
9
|
+
# Two stages (annex-g-rules.md):
|
|
10
|
+
# G.1 multi-schema → intermediate `artifact` schema: interface
|
|
11
|
+
# closure copied as local declarations, renames resolved to
|
|
12
|
+
# original names, name clashes munged (G.NM.1), REFERENCE
|
|
13
|
+
# entities kept with the dependent-instantiability rule
|
|
14
|
+
# (G.1.6), select/rules/supertype expressions pruned (G.1.9).
|
|
15
|
+
# G.2 artifact → `longform`: extensible enums/selects resolved
|
|
16
|
+
# (G.2.3/G.2.4), subtype constraints eliminated (supertype
|
|
17
|
+
# expression → SUPERTYPE, total_over → rule, G.2.5), abstract
|
|
18
|
+
# entity → ABSTRACT SUPERTYPE, GENERIC_ENTITY → GENERIC,
|
|
19
|
+
# RENAMED → DERIVE (G.2.7), qualified strings rewritten.
|
|
20
|
+
#
|
|
21
|
+
# The output is a Model::Declarations::Schema named per the root
|
|
22
|
+
# schema; format it with the Formatter to obtain the longform file.
|
|
23
|
+
class Shtolo
|
|
24
|
+
DEPENDENT_RULE_NAME = "validate_dependently_instantiable_entity_data_types"
|
|
25
|
+
DEPENDENT_FN_NAME = "dependently_instantiated"
|
|
26
|
+
|
|
27
|
+
attr_reader :longform, :renames, :schema
|
|
28
|
+
|
|
29
|
+
# `root_schema` — the resolved root schema node.
|
|
30
|
+
# `repository` — must hold the full interface closure.
|
|
31
|
+
# `extenders` — :all (default, the WG12 requirement) folds every
|
|
32
|
+
# extensible SELECT/ENUMERATION extension found in the
|
|
33
|
+
# closure into its base type (Annex G.2.3/G.2.4);
|
|
34
|
+
# :none leaves extensible types exactly as declared —
|
|
35
|
+
# the shape eengine's default --flat emits.
|
|
36
|
+
# `prune` — true (default) runs the G.1.9 prune pass;
|
|
37
|
+
# false keeps the artifact's full declaration set.
|
|
38
|
+
# `stage` — :longform (default) runs the G.2 rewrites;
|
|
39
|
+
# :artifact stops after stage 1 — the annex's
|
|
40
|
+
# intermediate schema, the shape eengine's
|
|
41
|
+
# --concat_schema output corresponds to (copy
|
|
42
|
+
# pass, no prune, no 1994 rewrite).
|
|
43
|
+
def initialize(root_schema, repository, longform_name: nil,
|
|
44
|
+
extenders: :all, prune: true, stage: :longform)
|
|
45
|
+
@root = root_schema
|
|
46
|
+
@repository = repository
|
|
47
|
+
@longform_name = longform_name || @root.id
|
|
48
|
+
@extenders = extenders
|
|
49
|
+
@prune = prune
|
|
50
|
+
@stage = stage
|
|
51
|
+
@reference_entities = [] # G.1.6 entities
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def flatten
|
|
55
|
+
@schema = build_longform
|
|
56
|
+
self
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
IdPlan = Struct.new(:global, :own_by_schema, keyword_init: true) do
|
|
60
|
+
def own(schema)
|
|
61
|
+
own_by_schema[schema] || {}
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
# ---- interface closure (same semantics as Concatenator) ----
|
|
68
|
+
|
|
69
|
+
def closure
|
|
70
|
+
@closure ||= begin
|
|
71
|
+
by_name = @repository.schemas.to_h { |s| [s.id.safe_downcase, s] }
|
|
72
|
+
visited = {}
|
|
73
|
+
queue = [@root]
|
|
74
|
+
until queue.empty?
|
|
75
|
+
schema = queue.shift
|
|
76
|
+
key = schema.id.safe_downcase
|
|
77
|
+
next if visited.key?(key)
|
|
78
|
+
|
|
79
|
+
visited[key] = schema
|
|
80
|
+
Array(schema.interfaces).each do |iface|
|
|
81
|
+
name = iface.schema.is_a?(String) ? iface.schema : iface.schema&.id
|
|
82
|
+
next unless name
|
|
83
|
+
|
|
84
|
+
target = by_name[name.safe_downcase]
|
|
85
|
+
queue << target if target && !visited.key?(name.safe_downcase)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
visited
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# ---- G.1 stage 1 ----
|
|
93
|
+
|
|
94
|
+
# Two-phase copy: plan every declaration's final id across the whole
|
|
95
|
+
# closure FIRST (G.NM.1 clashes are only known once every schema has
|
|
96
|
+
# been seen), then copy+rewrite each declaration against the complete
|
|
97
|
+
# map. Rewriting as we copy left stale references in declarations
|
|
98
|
+
# copied before a later clash was munged.
|
|
99
|
+
def build_artifact
|
|
100
|
+
schemas = [@root, *closure.values.reject { |s| s.equal?(@root) }]
|
|
101
|
+
plan = plan_ids(schemas)
|
|
102
|
+
|
|
103
|
+
declarations = []
|
|
104
|
+
schemas.each do |schema|
|
|
105
|
+
rename_map = renames_for(schema)
|
|
106
|
+
# Resolution order for a reference in this schema: its own local
|
|
107
|
+
# declarations (which may be munged), then interface aliases
|
|
108
|
+
# resolved through the referenced declaration's final id, then
|
|
109
|
+
# the global munge map for names the schema doesn't declare.
|
|
110
|
+
full = plan.global.dup
|
|
111
|
+
plan.own(schema).each { |k, final| full[k] = final }
|
|
112
|
+
rename_map.each do |alias_name, original|
|
|
113
|
+
resolved = plan.own(schema)[original.safe_downcase] ||
|
|
114
|
+
plan.global[original.safe_downcase] || original
|
|
115
|
+
full[alias_name.safe_downcase] = resolved
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
all_decls(schema).each do |decl|
|
|
119
|
+
copy = deep_copy(decl)
|
|
120
|
+
rewrite_references(copy, full)
|
|
121
|
+
if decl.respond_to?(:id) && decl.id &&
|
|
122
|
+
(final = plan.own(schema)[decl.id.safe_downcase])
|
|
123
|
+
copy.id = final
|
|
124
|
+
end
|
|
125
|
+
declarations << copy
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# G.1.2: interfaces themselves dissolve; REFERENCE entities
|
|
129
|
+
# keep dependent-instantiability semantics (G.1.6).
|
|
130
|
+
schema.interfaces.each do |iface|
|
|
131
|
+
next unless iface.kind == Model::Declarations::Interface::REFERENCE
|
|
132
|
+
|
|
133
|
+
iface.items.each do |item|
|
|
134
|
+
original = original_name(item, schema)
|
|
135
|
+
next unless closure[original]&.entities&.find { |e| e.id == original }
|
|
136
|
+
|
|
137
|
+
@reference_entities << original.safe_downcase
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
declarations << build_dependent_rule if @reference_entities.any?
|
|
143
|
+
|
|
144
|
+
Model::Declarations::Schema.new(
|
|
145
|
+
id: @longform_name,
|
|
146
|
+
version: nil,
|
|
147
|
+
interfaces: [],
|
|
148
|
+
constants: declarations.grep(Model::Declarations::Constant).compact,
|
|
149
|
+
types: declarations.grep(Model::Declarations::Type).compact,
|
|
150
|
+
entities: declarations.grep(Model::Declarations::Entity).compact,
|
|
151
|
+
subtype_constraints: declarations.grep(Model::Declarations::SubtypeConstraint).compact,
|
|
152
|
+
functions: declarations.grep(Model::Declarations::Function).compact,
|
|
153
|
+
procedures: declarations.grep(Model::Declarations::Procedure).compact,
|
|
154
|
+
rules: declarations.grep(Model::Declarations::Rule).compact,
|
|
155
|
+
)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def all_decls(schema)
|
|
159
|
+
schema.constants + schema.types + schema.entities +
|
|
160
|
+
schema.subtype_constraints + schema.functions +
|
|
161
|
+
schema.rules + schema.procedures
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# G.NM.1: the first schema in closure order to declare a name keeps
|
|
165
|
+
# it; every later declaration of the same name is prefixed with ITS
|
|
166
|
+
# OWN schema's id, and the global map redirects the bare name so
|
|
167
|
+
# declarations from third schemas resolve to the first occurrence.
|
|
168
|
+
def plan_ids(schemas)
|
|
169
|
+
seen_first = {} # downcase id => owning schema (first occurrence)
|
|
170
|
+
global = {} # downcase id => munged final
|
|
171
|
+
own_by_schema = {} # schema => {downcase id => final id}
|
|
172
|
+
schemas.each do |schema|
|
|
173
|
+
own = {}
|
|
174
|
+
all_decls(schema).each do |decl|
|
|
175
|
+
next unless decl.respond_to?(:id) && decl.id
|
|
176
|
+
|
|
177
|
+
key = decl.id.safe_downcase
|
|
178
|
+
if seen_first.key?(key)
|
|
179
|
+
final = "#{schema.id.safe_downcase}_dot_#{decl.id}"
|
|
180
|
+
own[key] = final
|
|
181
|
+
global[key] = final
|
|
182
|
+
else
|
|
183
|
+
seen_first[key] = schema
|
|
184
|
+
own[key] = decl.id
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
own_by_schema[schema] = own
|
|
188
|
+
end
|
|
189
|
+
IdPlan.new(global: global, own_by_schema: own_by_schema)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Alias → original map applied when copying `schema`'s
|
|
193
|
+
# declarations: the aliases are declared by the schema's own
|
|
194
|
+
# interface items (`USE FROM s (orig AS alias)`, G.1.3).
|
|
195
|
+
def renames_for(schema)
|
|
196
|
+
map = {}
|
|
197
|
+
Array(schema.interfaces).each do |iface|
|
|
198
|
+
iface.items.each do |item|
|
|
199
|
+
original = item.ref.is_a?(String) ? item.ref : item.ref&.id
|
|
200
|
+
next unless original
|
|
201
|
+
|
|
202
|
+
map[item.id.safe_downcase] = original if item.id &&
|
|
203
|
+
item.id.safe_downcase != original.safe_downcase
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
map
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def original_name(item, schema)
|
|
210
|
+
original = item.ref.is_a?(String) ? item.ref : item.ref&.id
|
|
211
|
+
return schema.id unless original
|
|
212
|
+
|
|
213
|
+
original
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def deep_copy(obj)
|
|
217
|
+
sever = []
|
|
218
|
+
node = obj
|
|
219
|
+
while node.respond_to?(:parent) && node.parent
|
|
220
|
+
sever << node
|
|
221
|
+
node = node.parent
|
|
222
|
+
end
|
|
223
|
+
saved = sever.map(&:parent)
|
|
224
|
+
sever.each { |n| n.parent = nil }
|
|
225
|
+
Marshal.load(Marshal.dump(obj))
|
|
226
|
+
ensure
|
|
227
|
+
sever.each_with_index { |n, i| n.parent = saved[i] }
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Rewrite SimpleReference ids against a rename map in ONE tree walk
|
|
231
|
+
# (each declaration is walked once, whatever the map's size — walking
|
|
232
|
+
# once per rename made flattening quadratic in the closure).
|
|
233
|
+
# Map keys are downcased old names, values the final names.
|
|
234
|
+
def rewrite_references(node, map)
|
|
235
|
+
return unless node.is_a?(Model::ModelElement)
|
|
236
|
+
|
|
237
|
+
if node.is_a?(Model::References::SimpleReference) && node.id &&
|
|
238
|
+
(to = map[node.id.safe_downcase])
|
|
239
|
+
node.id = preserve_case(node.id, to)
|
|
240
|
+
end
|
|
241
|
+
node.class.attributes.each_key do |attr|
|
|
242
|
+
next if Model::ModelElement::SKIP_ATTRIBUTES.include?(attr) || attr == :parent
|
|
243
|
+
|
|
244
|
+
value = node.public_send(attr)
|
|
245
|
+
case value
|
|
246
|
+
when Array then value.each { |item| rewrite_references(item, map) }
|
|
247
|
+
when Model::ModelElement then rewrite_references(value, map)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def preserve_case(current, new)
|
|
253
|
+
current == current.upcase ? new.upcase : new
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# G.1.6: parse-templates keep the annex rule/function verbatim.
|
|
257
|
+
def build_dependent_rule
|
|
258
|
+
list = @reference_entities.map(&:upcase).join(", ")
|
|
259
|
+
union = @reference_entities.join("+")
|
|
260
|
+
src = <<~EXP
|
|
261
|
+
SCHEMA __dependent__;
|
|
262
|
+
RULE #{DEPENDENT_RULE_NAME} FOR (#{list});
|
|
263
|
+
LOCAL
|
|
264
|
+
number_of_input_instances : INTEGER;
|
|
265
|
+
previous_in_chain : LIST OF GENERIC := [];
|
|
266
|
+
set_of_input_types : SET OF STRING := [];
|
|
267
|
+
all_instances : SET OF GENERIC := [];
|
|
268
|
+
END_LOCAL;
|
|
269
|
+
all_instances := #{union};
|
|
270
|
+
WHERE
|
|
271
|
+
wr1: dependently_instantiated(all_instances, set_of_input_types, previous_in_chain);
|
|
272
|
+
END_RULE;
|
|
273
|
+
END_SCHEMA;
|
|
274
|
+
EXP
|
|
275
|
+
parse_schema_snippet(src).schemas.first.rules.first
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def parse_schema_snippet(src)
|
|
279
|
+
Expressir::Express::Parser.from_exp(src)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# ---- G.2 stage 2 ----
|
|
283
|
+
|
|
284
|
+
def build_longform
|
|
285
|
+
artifact = build_artifact
|
|
286
|
+
prune!(artifact) if @prune
|
|
287
|
+
return artifact if @stage == :artifact
|
|
288
|
+
|
|
289
|
+
if @extenders == :all
|
|
290
|
+
resolve_extensible_enumerations!(artifact)
|
|
291
|
+
resolve_extensible_selects!(artifact)
|
|
292
|
+
end
|
|
293
|
+
eliminate_subtype_constraints!(artifact)
|
|
294
|
+
convert_abstract_entities!(artifact)
|
|
295
|
+
convert_generic_entities!(artifact)
|
|
296
|
+
convert_renamed_attributes!(artifact)
|
|
297
|
+
rewrite_qualified_strings!(artifact)
|
|
298
|
+
|
|
299
|
+
artifact
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# G.1.9 prune pass: the artifact keeps only what stays visible
|
|
303
|
+
# and reachable. Runs before the stage-2 rewrites so they never
|
|
304
|
+
# see declarations the longform would drop.
|
|
305
|
+
def prune!(schema)
|
|
306
|
+
visible_ids = visible_declaration_ids(schema)
|
|
307
|
+
|
|
308
|
+
# rules whose parameter entities are not all visible
|
|
309
|
+
schema.rules = schema.rules.reject do |rule|
|
|
310
|
+
Array(rule.applies_to).any? do |ref|
|
|
311
|
+
id = ref.is_a?(String) ? ref : ref.id
|
|
312
|
+
id && !visible_ids.key?(id.safe_downcase)
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# select items pointing at declarations the artifact lacks
|
|
317
|
+
schema.types.each do |type|
|
|
318
|
+
next unless type.underlying_type.is_a?(Model::DataTypes::Select)
|
|
319
|
+
|
|
320
|
+
items = Array(type.underlying_type.items)
|
|
321
|
+
kept = items.select do |item|
|
|
322
|
+
item.id.nil? || visible_ids.key?(item.id.safe_downcase)
|
|
323
|
+
end
|
|
324
|
+
# An emptied select disappears from the representation
|
|
325
|
+
# (annex G.1.9 s1/s2/s3 example).
|
|
326
|
+
type.underlying_type.items = kept unless kept.empty? && items.empty?
|
|
327
|
+
if kept.empty? && !items.empty?
|
|
328
|
+
type.underlying_type = nil
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
schema.types = schema.types.reject { |t| t.underlying_type.nil? }
|
|
332
|
+
|
|
333
|
+
# functions/procedures nothing calls, to fixpoint (a helper only
|
|
334
|
+
# a dropped function called is itself unreachable)
|
|
335
|
+
loop do
|
|
336
|
+
called = called_ids(schema)
|
|
337
|
+
drop = schema.functions.any? { |f| !called[f.id.safe_downcase] } ||
|
|
338
|
+
schema.procedures.any? { |p| !called[p.id.safe_downcase] }
|
|
339
|
+
break unless drop
|
|
340
|
+
|
|
341
|
+
schema.functions = schema.functions.select { |f| called[f.id.safe_downcase] }
|
|
342
|
+
schema.procedures = schema.procedures.select { |p| called[p.id.safe_downcase] }
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
prune_supertype_expressions!(schema, visible_ids)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def visible_declaration_ids(schema)
|
|
349
|
+
all_decls(schema).each_with_object({}) do |decl, hash|
|
|
350
|
+
hash[decl.id.safe_downcase] = true if decl.respond_to?(:id) && decl.id
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# Every identifier a call site or reference names, across the
|
|
355
|
+
# artifact's surviving declarations: FunctionCall for functions,
|
|
356
|
+
# ProcedureCall statements for procedures, and ANY SimpleReference
|
|
357
|
+
# naming a schema function/procedure — a zero-argument function
|
|
358
|
+
# used bare (`v < limit_value`) parses as a plain reference, not
|
|
359
|
+
# a FunctionCall, and dropping it would leave the longform with a
|
|
360
|
+
# dangling call. Over-retaining is safe: prune only decides what
|
|
361
|
+
# may be dropped.
|
|
362
|
+
def called_ids(schema)
|
|
363
|
+
invocable = (schema.functions.to_a + schema.procedures.to_a)
|
|
364
|
+
.map { |d| d.id.safe_downcase }
|
|
365
|
+
called = {}
|
|
366
|
+
each_node(schema) do |node|
|
|
367
|
+
id = nil
|
|
368
|
+
case node
|
|
369
|
+
when Expressir::Model::Expressions::FunctionCall
|
|
370
|
+
id = node.function.is_a?(String) ? node.function : node.function&.id
|
|
371
|
+
when Expressir::Model::Statements::ProcedureCall
|
|
372
|
+
id = node.procedure.is_a?(String) ? node.procedure : node.procedure&.id
|
|
373
|
+
when Model::References::SimpleReference
|
|
374
|
+
id = node.id
|
|
375
|
+
end
|
|
376
|
+
called[id.safe_downcase] = true if id && invocable.include?(id.safe_downcase)
|
|
377
|
+
end
|
|
378
|
+
called
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
# Annex C reductions over supertype expressions: references to
|
|
382
|
+
# invisible entities leave ONEOF; ONEOF(a) => a; AND/OR sides
|
|
383
|
+
# that become empty collapse; a vacuous expression deletes the
|
|
384
|
+
# constraint.
|
|
385
|
+
def prune_supertype_expressions!(schema, visible_ids)
|
|
386
|
+
keep = []
|
|
387
|
+
schema.subtype_constraints.each do |constraint|
|
|
388
|
+
expr = constraint.supertype_expression
|
|
389
|
+
if expr.nil?
|
|
390
|
+
# total-over-only constraints carry no expression; stage 2
|
|
391
|
+
# turns their TOTAL_OVER into a rule.
|
|
392
|
+
keep << constraint
|
|
393
|
+
next
|
|
394
|
+
end
|
|
395
|
+
reduced = reduce_supertype_expression(expr, visible_ids)
|
|
396
|
+
# Annex C: a vacuous expression deletes the constraint.
|
|
397
|
+
next if reduced.nil?
|
|
398
|
+
|
|
399
|
+
constraint.supertype_expression = reduced
|
|
400
|
+
keep << constraint
|
|
401
|
+
end
|
|
402
|
+
schema.subtype_constraints = keep
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
def reduce_supertype_expression(expr, visible_ids)
|
|
406
|
+
case expr
|
|
407
|
+
when Model::SupertypeExpressions::OneofSupertypeExpression
|
|
408
|
+
reduced = expr.operands.filter_map do |operand|
|
|
409
|
+
reduce_supertype_expression(operand, visible_ids)
|
|
410
|
+
end
|
|
411
|
+
return nil if reduced.empty?
|
|
412
|
+
|
|
413
|
+
reduced.one? ? reduced.first : reset_oneof(expr, reduced)
|
|
414
|
+
when Model::SupertypeExpressions::BinarySupertypeExpression
|
|
415
|
+
left = reduce_supertype_expression(expr.operand1, visible_ids)
|
|
416
|
+
right = reduce_supertype_expression(expr.operand2, visible_ids)
|
|
417
|
+
if left.nil?
|
|
418
|
+
return right
|
|
419
|
+
end
|
|
420
|
+
if right.nil?
|
|
421
|
+
return left
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
rebuild_binary(expr, left, right)
|
|
425
|
+
when Model::References::SimpleReference
|
|
426
|
+
id = expr.id
|
|
427
|
+
return nil if id && !visible_ids.key?(id.safe_downcase)
|
|
428
|
+
|
|
429
|
+
expr
|
|
430
|
+
else
|
|
431
|
+
expr
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
def reset_oneof(expr, refs)
|
|
436
|
+
copy = deep_copy(expr)
|
|
437
|
+
copy.operands = refs
|
|
438
|
+
copy
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
def rebuild_binary(expr, left, right)
|
|
442
|
+
copy = deep_copy(expr)
|
|
443
|
+
copy.operand1 = left
|
|
444
|
+
copy.operand2 = right
|
|
445
|
+
copy
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def resolve_extensible_enumerations!(schema)
|
|
449
|
+
schema.types.select do |t|
|
|
450
|
+
t.underlying_type.is_a?(Model::DataTypes::Enumeration) && t.underlying_type.extensible
|
|
451
|
+
end.each do |base|
|
|
452
|
+
enum = base.underlying_type
|
|
453
|
+
extensions = schema.types.select do |t|
|
|
454
|
+
t.underlying_type.is_a?(Model::DataTypes::Enumeration) &&
|
|
455
|
+
!t.underlying_type.extensible &&
|
|
456
|
+
t.underlying_type.based_on&.id&.safe_downcase == base.id.safe_downcase
|
|
457
|
+
end
|
|
458
|
+
merged = enum.items.map(&:id) +
|
|
459
|
+
extensions.flat_map { |x| x.underlying_type.items.map(&:id) }
|
|
460
|
+
enum.items = merged.uniq.map { |id| Model::DataTypes::EnumerationItem.new(id: id) }
|
|
461
|
+
enum.extensible = false
|
|
462
|
+
enum.based_on = nil
|
|
463
|
+
|
|
464
|
+
extensions.each do |ext|
|
|
465
|
+
ext_items = ext.underlying_type.items.map(&:id)
|
|
466
|
+
exclusions = merged - ext_items
|
|
467
|
+
ext.underlying_type = Model::DataTypes::Enumeration.new(
|
|
468
|
+
items: enum.items,
|
|
469
|
+
)
|
|
470
|
+
ext.where_rules = exclusions.each_with_index.map do |item, i|
|
|
471
|
+
Model::Declarations::WhereRule.new(
|
|
472
|
+
id: "wr#{i + 1}",
|
|
473
|
+
expression: parse_expression("SELF <> #{item};"),
|
|
474
|
+
)
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
def resolve_extensible_selects!(schema)
|
|
481
|
+
schema.types.select do |t|
|
|
482
|
+
t.underlying_type.is_a?(Model::DataTypes::Select) && t.underlying_type.extensible
|
|
483
|
+
end.each do |base|
|
|
484
|
+
sel = base.underlying_type
|
|
485
|
+
|
|
486
|
+
# all-extenders for GENERIC_ENTITY selects (WG12 requirement,
|
|
487
|
+
# #32): the extenders are the entity types themselves — fold in
|
|
488
|
+
# every entity the artifact carries, so the longform select is
|
|
489
|
+
# complete against the closure. Flags stay as declared: the
|
|
490
|
+
# extensible/generic-entity markers are part of the shortform's
|
|
491
|
+
# semantics and are not expressir's to drop.
|
|
492
|
+
if sel.generic_entity
|
|
493
|
+
sel.items = schema.entities.map do |e|
|
|
494
|
+
Model::References::SimpleReference.new(id: e.id)
|
|
495
|
+
end
|
|
496
|
+
next
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
extensions = schema.types.select do |t|
|
|
500
|
+
t.underlying_type.is_a?(Model::DataTypes::Select) &&
|
|
501
|
+
!t.underlying_type.extensible &&
|
|
502
|
+
t.underlying_type.based_on&.id&.safe_downcase == base.id.safe_downcase
|
|
503
|
+
end
|
|
504
|
+
merged_items = sel.items +
|
|
505
|
+
extensions.flat_map { |x| x.underlying_type.items }
|
|
506
|
+
seen_ids = {}
|
|
507
|
+
uniq = merged_items.select do |item|
|
|
508
|
+
key = item.id.safe_downcase
|
|
509
|
+
next false if seen_ids.key?(key) || key.empty?
|
|
510
|
+
|
|
511
|
+
seen_ids[key] = true
|
|
512
|
+
end
|
|
513
|
+
sel.items = uniq
|
|
514
|
+
sel.extensible = false
|
|
515
|
+
sel.based_on = nil
|
|
516
|
+
|
|
517
|
+
extensions.each do |ext|
|
|
518
|
+
keep = ext.underlying_type.items.map { |i| i.id.upcase }
|
|
519
|
+
exclusions = uniq.reject { |i| keep.include?(i.id.upcase) }
|
|
520
|
+
base_ref = "#{@longform_name.upcase}.#{base.id.upcase}"
|
|
521
|
+
ext.underlying_type = Model::DataTypes::Select.new(
|
|
522
|
+
items: sel.items.map { |i| Model::References::SimpleReference.new(id: i.id) },
|
|
523
|
+
)
|
|
524
|
+
ext.where_rules = exclusions.each_with_index.map do |item, i|
|
|
525
|
+
Model::Declarations::WhereRule.new(
|
|
526
|
+
id: "wr#{i + 1}",
|
|
527
|
+
expression: parse_expression("NOT ('#{base_ref}.#{item.id.upcase}' IN TYPEOF(SELF));"),
|
|
528
|
+
)
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
def eliminate_subtype_constraints!(schema)
|
|
535
|
+
schema.subtype_constraints.each do |sc|
|
|
536
|
+
entity = schema.entities.find do |e|
|
|
537
|
+
e.id.safe_downcase == sc.applies_to&.id&.safe_downcase
|
|
538
|
+
end
|
|
539
|
+
next unless entity
|
|
540
|
+
|
|
541
|
+
if sc.supertype_expression
|
|
542
|
+
expr = sc.supertype_expression
|
|
543
|
+
entity.supertype_expression =
|
|
544
|
+
entity.supertype_expression ? combine_andor(entity.supertype_expression, expr) : expr
|
|
545
|
+
end
|
|
546
|
+
if entity.abstract
|
|
547
|
+
# G.2.6: abstract entity ⇒ ABSTRACT SUPERTYPE (formatter
|
|
548
|
+
# renders from abstract + supertype status).
|
|
549
|
+
end
|
|
550
|
+
next if Array(sc.total_over).empty?
|
|
551
|
+
|
|
552
|
+
rule_name = "total_over_#{sc.id}"
|
|
553
|
+
targets = Array(sc.total_over).map { |r| r.id.upcase }
|
|
554
|
+
supertype = sc.applies_to&.id
|
|
555
|
+
rule = parse_schema_snippet(<<~EXP).schemas.first.rules.first
|
|
556
|
+
SCHEMA __to__;
|
|
557
|
+
RULE #{rule_name} FOR (#{supertype.upcase});
|
|
558
|
+
WHERE
|
|
559
|
+
wr1: SIZEOF(QUERY(#{supertype.downcase}_i <* #{supertype} |
|
|
560
|
+
SIZEOF(['#{@longform_name.upcase}.#{targets.first}'] * TYPEOF(#{supertype.downcase}_i)) = 0)) = 0;
|
|
561
|
+
END_RULE;
|
|
562
|
+
END_SCHEMA;
|
|
563
|
+
EXP
|
|
564
|
+
rule.id = rule_name
|
|
565
|
+
schema.rules = Array(schema.rules) + [rule]
|
|
566
|
+
end
|
|
567
|
+
schema.subtype_constraints = []
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
def combine_andor(left, right)
|
|
571
|
+
Model::SupertypeExpressions::BinarySupertypeExpression.new(
|
|
572
|
+
operator: Model::SupertypeExpressions::BinarySupertypeExpression::ANDOR,
|
|
573
|
+
operand1: left, operand2: right
|
|
574
|
+
)
|
|
575
|
+
rescue StandardError
|
|
576
|
+
left
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
def convert_abstract_entities!(schema)
|
|
580
|
+
schema.entities.each do |entity|
|
|
581
|
+
next unless entity.abstract
|
|
582
|
+
|
|
583
|
+
entity.abstract = true # formatter renders ABSTRACT SUPERTYPE when supertype present
|
|
584
|
+
end
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
def convert_generic_entities!(schema)
|
|
588
|
+
each_node(schema) do |node|
|
|
589
|
+
replace_in_parent(node, Model::DataTypes::Generic.new) if node.is_a?(Model::DataTypes::GenericEntity)
|
|
590
|
+
end
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
def replace_in_parent(node, replacement)
|
|
594
|
+
parent = node.parent
|
|
595
|
+
return unless parent
|
|
596
|
+
|
|
597
|
+
parent.class.attributes.each_key do |attr|
|
|
598
|
+
next if Model::ModelElement::SKIP_ATTRIBUTES.include?(attr)
|
|
599
|
+
|
|
600
|
+
value = parent.public_send(attr)
|
|
601
|
+
case value
|
|
602
|
+
when Array
|
|
603
|
+
value.each_with_index do |item, index|
|
|
604
|
+
parent.public_send(attr)[index] = replacement if item.equal?(node)
|
|
605
|
+
end
|
|
606
|
+
else
|
|
607
|
+
parent.public_send(:"#{attr}=", replacement) if value.equal?(node) && parent.respond_to?(:"#{attr}=")
|
|
608
|
+
end
|
|
609
|
+
end
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
def convert_renamed_attributes!(schema)
|
|
613
|
+
schema.entities.each do |entity|
|
|
614
|
+
entity.attributes.each_with_index do |attr, i|
|
|
615
|
+
next unless attr.supertype_attribute
|
|
616
|
+
|
|
617
|
+
old_name, supertype = supertype_target(attr.supertype_attribute)
|
|
618
|
+
entity.attributes[i] = Model::Declarations::DerivedAttribute.new(
|
|
619
|
+
id: attr.id || old_name,
|
|
620
|
+
type: attr.type,
|
|
621
|
+
expression: parse_expression("SELF\\#{supertype}.#{old_name}"),
|
|
622
|
+
)
|
|
623
|
+
end
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
# `SELF\ENTITY.attr` parses as AttributeReference(ref: GroupReference
|
|
628
|
+
# (SELF, entity), attribute: attr); a bare qualified attribute has
|
|
629
|
+
# only the attribute name.
|
|
630
|
+
def supertype_target(ref)
|
|
631
|
+
return [ref.id, nil] unless ref.is_a?(Model::References::AttributeReference)
|
|
632
|
+
|
|
633
|
+
group = ref.ref
|
|
634
|
+
[ref.attribute&.id,
|
|
635
|
+
group.is_a?(Model::References::GroupReference) ? group.entity&.id : nil]
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
# G.NM.2: string literals carrying schema-qualified names (e.g.
|
|
639
|
+
# TYPEOF arguments 'SCHEMA.TYPE') move to the longform name.
|
|
640
|
+
# Structurally these appear as DataTypes::String; path references
|
|
641
|
+
# in expressions are already renamed by the copy pass.
|
|
642
|
+
def rewrite_qualified_strings!(schema)
|
|
643
|
+
prefixes = closure.keys.map(&:upcase)
|
|
644
|
+
each_node(schema) do |node|
|
|
645
|
+
next unless node.is_a?(Model::Literals::String) && node.value
|
|
646
|
+
|
|
647
|
+
node.value = node.value.sub(/\A(#{prefixes.join('|')})\./i,
|
|
648
|
+
"#{@longform_name.upcase}.")
|
|
649
|
+
end
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
# Attribute-driven structural traversal over the whole subtree.
|
|
653
|
+
def each_node(root, &)
|
|
654
|
+
stack = [root]
|
|
655
|
+
until stack.empty?
|
|
656
|
+
node = stack.pop
|
|
657
|
+
yield node
|
|
658
|
+
next unless node.is_a?(Model::ModelElement)
|
|
659
|
+
|
|
660
|
+
node.class.attributes.each_key do |attr|
|
|
661
|
+
next if Model::ModelElement::SKIP_ATTRIBUTES.include?(attr)
|
|
662
|
+
|
|
663
|
+
value = node.public_send(attr)
|
|
664
|
+
case value
|
|
665
|
+
when Array then value.each { |item| stack << item if item.is_a?(Model::ModelElement) }
|
|
666
|
+
when Model::ModelElement then stack << value
|
|
667
|
+
end
|
|
668
|
+
end
|
|
669
|
+
end
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
def parse_expression(src)
|
|
673
|
+
snippet = "SCHEMA __x__; ENTITY __e__; WHERE w1 : #{src.chomp(';')}; END_ENTITY; END_SCHEMA;"
|
|
674
|
+
parsed = parse_schema_snippet(snippet)
|
|
675
|
+
parsed.schemas.first.entities.first.where_rules.first.expression
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
end
|
|
679
|
+
end
|