expressir 2.4.29-arm-linux-musl
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,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Express
|
|
5
|
+
# EXPRESS grammar namespace. Houses the Parsanol grammar definition
|
|
6
|
+
# separate from the I/O orchestration on the outer Parser facade.
|
|
7
|
+
module Grammar
|
|
8
|
+
autoload :Parser, "#{__dir__}/grammar/parser"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Expressir
|
|
2
|
+
module Express
|
|
3
|
+
# Formatter module - format references as hyperlinks
|
|
4
|
+
# @example Include into Formatter subclass
|
|
5
|
+
# formatter = Class.new(Expressir::Express::Formatter) do
|
|
6
|
+
# include Expressir::Express::HyperlinkFormatter
|
|
7
|
+
# end
|
|
8
|
+
module HyperlinkFormatter
|
|
9
|
+
# @!visibility private
|
|
10
|
+
def self.included(mod)
|
|
11
|
+
unless mod.superclass <= Expressir::Express::Formatter
|
|
12
|
+
raise Error::FormatterMethodMissingError.new("HyperlinkFormatter",
|
|
13
|
+
"format_references_simple_reference")
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def format_references_simple_reference(node)
|
|
18
|
+
return node.id unless node.base_path
|
|
19
|
+
|
|
20
|
+
# find closest node with path
|
|
21
|
+
current_node = node
|
|
22
|
+
while !current_node.path
|
|
23
|
+
current_node = current_node.parent
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# skip if this reference and target node are in the same node with path
|
|
27
|
+
node_base_path_parts = node.base_path.split(".")
|
|
28
|
+
current_node_path_parts = current_node.path.split(".")
|
|
29
|
+
return node.id if node_base_path_parts[0..1] == current_node_path_parts[0..1]
|
|
30
|
+
|
|
31
|
+
"{{{<<express:#{node.base_path},#{node.id}>>}}}"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Express
|
|
5
|
+
# Interface dependency GraphViz emitter — port of eeng
|
|
6
|
+
# kernel/dot-graph.lisp `:interface` graph (parity-ee stage 10).
|
|
7
|
+
#
|
|
8
|
+
# Nodes are schema names (lowercase); edges are USE FROM (default
|
|
9
|
+
# blue) and REFERENCE FROM (default green). An edge with an item
|
|
10
|
+
# list uses arrowhead=curve; a bare interface uses arrowhead=normal.
|
|
11
|
+
class InterfaceDot
|
|
12
|
+
def initialize(root_schema, repository,
|
|
13
|
+
iface: :both, uf_color: :blue, rf_color: :green,
|
|
14
|
+
depth: nil, prune: [])
|
|
15
|
+
@root = root_schema
|
|
16
|
+
@repository = repository
|
|
17
|
+
@iface = iface
|
|
18
|
+
@uf_color = uf_color
|
|
19
|
+
@rf_color = rf_color
|
|
20
|
+
@depth = depth
|
|
21
|
+
@prune = Array(prune).map { |n| n.to_s.downcase }
|
|
22
|
+
@by_name = repository.schemas.compact.to_h { |s| [s.id.safe_downcase, s] }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def write(io = nil)
|
|
26
|
+
owned = io.nil?
|
|
27
|
+
io ||= +""
|
|
28
|
+
schemas, edges = collect
|
|
29
|
+
io << "// -*- Mode: Dot -*-\n\n"
|
|
30
|
+
io << "// Dot File Written by Expressir\n"
|
|
31
|
+
io << "// #{Expressir::VERSION}\n"
|
|
32
|
+
io << "\ndigraph interfaces {\n"
|
|
33
|
+
io << " node [shape=none];\n"
|
|
34
|
+
if %i[both use].include?(@iface)
|
|
35
|
+
io << " edge [color=#{@uf_color}];\n"
|
|
36
|
+
edges.select { |e| e[:kind] == :use }.each do |e|
|
|
37
|
+
head = e[:items] ? "curve" : "normal"
|
|
38
|
+
io << " #{e[:from]} -> #{e[:to]} [arrowhead=#{head}];\n"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
if %i[both ref].include?(@iface)
|
|
42
|
+
io << " edge [color=#{@rf_color}];\n"
|
|
43
|
+
edges.select { |e| e[:kind] == :ref }.each do |e|
|
|
44
|
+
head = e[:items] ? "curve" : "normal"
|
|
45
|
+
io << " #{e[:from]} -> #{e[:to]} [arrowhead=#{head}];\n"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
# Ensure isolated schemas still appear as nodes.
|
|
49
|
+
named = edges.flat_map { |e| [e[:from], e[:to]] }.uniq
|
|
50
|
+
(schemas.map { |s| s.id.downcase } - named).each do |n|
|
|
51
|
+
io << " #{n};\n"
|
|
52
|
+
end
|
|
53
|
+
io << "}\n"
|
|
54
|
+
owned ? io : nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def collect
|
|
60
|
+
visited = {}
|
|
61
|
+
edges = []
|
|
62
|
+
queue = [[@root, 0]]
|
|
63
|
+
until queue.empty?
|
|
64
|
+
schema, level = queue.shift
|
|
65
|
+
key = schema.id.safe_downcase
|
|
66
|
+
next if visited.key?(key)
|
|
67
|
+
next if @prune.include?(key)
|
|
68
|
+
|
|
69
|
+
visited[key] = schema
|
|
70
|
+
|
|
71
|
+
Array(schema.interfaces).each do |iface|
|
|
72
|
+
target_name = iface_schema_name(iface)
|
|
73
|
+
next unless target_name
|
|
74
|
+
|
|
75
|
+
tkey = target_name.safe_downcase
|
|
76
|
+
next if @prune.include?(tkey)
|
|
77
|
+
next if tkey == key
|
|
78
|
+
|
|
79
|
+
kind = iface.kind == Model::Declarations::Interface::REFERENCE ? :ref : :use
|
|
80
|
+
next if @iface == :use && kind != :use
|
|
81
|
+
next if @iface == :ref && kind != :ref
|
|
82
|
+
|
|
83
|
+
edges << {
|
|
84
|
+
kind: kind,
|
|
85
|
+
items: Array(iface.items).any?,
|
|
86
|
+
from: key,
|
|
87
|
+
to: tkey,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
target = @by_name[tkey]
|
|
91
|
+
next unless target
|
|
92
|
+
next if @depth && level + 1 >= @depth
|
|
93
|
+
|
|
94
|
+
queue << [target, level + 1]
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
[visited.values, edges.uniq]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def iface_schema_name(iface)
|
|
101
|
+
iface.schema.is_a?(String) ? iface.schema : iface.schema&.id
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "liquid"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Express
|
|
7
|
+
# Lazy read path over a compiled-set artifact (M2 slice 2,
|
|
8
|
+
# TODO.parity-ee/19): schemas hydrate individually, on first touch,
|
|
9
|
+
# instead of the whole repository at once. Metanorma schema-doc
|
|
10
|
+
# rendering touches one schema per page — the lazy repository makes
|
|
11
|
+
# that pay: one hydration per page, not one per schema in the set.
|
|
12
|
+
#
|
|
13
|
+
# Duck-types the read surface of Model::Repository used by
|
|
14
|
+
# rendering (schemas, files, each, size, children). Anything beyond
|
|
15
|
+
# the read surface should wait for eager hydration via
|
|
16
|
+
# #to_eager (returns a real Model::Repository).
|
|
17
|
+
class LazyRepository
|
|
18
|
+
attr_reader :set_path
|
|
19
|
+
|
|
20
|
+
# @param set_path [String] compiled-set artifact path
|
|
21
|
+
# @param read_paths [Hash{String => String}] wire path => source path
|
|
22
|
+
def initialize(set_path, read_paths = {})
|
|
23
|
+
@set_path = set_path
|
|
24
|
+
@set = Core.lazy_set(set_path)
|
|
25
|
+
@read_paths = read_paths
|
|
26
|
+
@wire_paths = @set.wire_paths
|
|
27
|
+
@mutex = Mutex.new
|
|
28
|
+
@file_cache = {}
|
|
29
|
+
@hydration_count = 0
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Wire paths in artifact order — no hydration.
|
|
33
|
+
# @return [Array<String>]
|
|
34
|
+
def wire_paths
|
|
35
|
+
@wire_paths.dup
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Files in artifact order, each wrapped so it hydrates on first
|
|
39
|
+
# use. The file is the hydration grain: an artifact stores wire
|
|
40
|
+
# JSON per source file.
|
|
41
|
+
# @return [Array<LazyFile>]
|
|
42
|
+
def files
|
|
43
|
+
@wire_paths.map { |wire_path| file_by_wire_path(wire_path) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Hydrated (or hydrating) file for one wire path.
|
|
47
|
+
def file_by_wire_path(wire_path)
|
|
48
|
+
@mutex.synchronize do
|
|
49
|
+
@file_cache[wire_path] ||= LazyFile.new(wire_path) do
|
|
50
|
+
hydrate(wire_path)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Schemas across all files. EAGER by definition: it hydrates
|
|
56
|
+
# every file. Lazy callers iterate #files, or render through
|
|
57
|
+
# #to_liquid, which keeps per-file hydration lazy.
|
|
58
|
+
# @return [Array<Declarations::Schema>]
|
|
59
|
+
def schemas
|
|
60
|
+
files.map(&:__target__).flat_map(&:schemas).compact
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Liquid binding for metanorma (M2): returns a Drop whose
|
|
64
|
+
# `schemas` is a lazy per-file list — each entry hydrates only
|
|
65
|
+
# its own file when the template touches it. Schema count per
|
|
66
|
+
# file is unknown until hydration, so the Drop presents one
|
|
67
|
+
# entry per FILE; single-schema files (the corpus norm) render
|
|
68
|
+
# identically to the eager path.
|
|
69
|
+
def to_liquid
|
|
70
|
+
LazyRepositoryDrop.new(self)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# How many files have actually been hydrated (observability for
|
|
74
|
+
# the laziness contract).
|
|
75
|
+
def hydration_count
|
|
76
|
+
@hydration_count
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Hydrate everything and return a real Model::Repository — the
|
|
80
|
+
# escape hatch for callers needing the full read surface.
|
|
81
|
+
def to_eager
|
|
82
|
+
repo = Model::Repository.new
|
|
83
|
+
repo.files = files.map(&:__target__)
|
|
84
|
+
repo
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def each(&)
|
|
88
|
+
files.each(&)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def size
|
|
92
|
+
@wire_paths.size
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def children
|
|
96
|
+
schemas
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# The read path on disk for a wire path (may be nil when the
|
|
100
|
+
# caller did not supply source paths).
|
|
101
|
+
def read_path_for(wire_path)
|
|
102
|
+
@read_paths[wire_path]
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def matches_sources?
|
|
106
|
+
@set.matches_sources(@read_paths.dup) == true
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
private
|
|
110
|
+
|
|
111
|
+
def hydrate(wire_path)
|
|
112
|
+
@mutex.synchronize do
|
|
113
|
+
_wire, model = @set.hydrate_one(wire_path)
|
|
114
|
+
@hydration_count += 1
|
|
115
|
+
model
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Liquid::Drop over a LazyRepository: `schemas` enumerates lazy
|
|
121
|
+
# per-file entries; touching an entry hydrates that file and
|
|
122
|
+
# presents its schemas (single-schema files present the schema
|
|
123
|
+
# itself, matching the eager Drop's element contract).
|
|
124
|
+
class LazyRepositoryDrop < ::Liquid::Drop
|
|
125
|
+
def initialize(repo)
|
|
126
|
+
@repo = repo
|
|
127
|
+
super()
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def schemas
|
|
131
|
+
@repo.files.map do |file|
|
|
132
|
+
LazyFileDrop.new(file)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def size
|
|
137
|
+
@repo.size
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Per-file lazy drop: hydrates on first access, then presents the
|
|
142
|
+
# file's single schema directly (or the schema list for
|
|
143
|
+
# multi-schema files).
|
|
144
|
+
class LazyFileDrop < ::Liquid::Drop
|
|
145
|
+
def initialize(file)
|
|
146
|
+
@file = file
|
|
147
|
+
super()
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def __file__
|
|
151
|
+
@file.__target__
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def method_missing(name, *, &)
|
|
155
|
+
schemas = __file__.schemas
|
|
156
|
+
if schemas.size == 1
|
|
157
|
+
schemas.first.public_send(name, *, &)
|
|
158
|
+
else
|
|
159
|
+
__file__.public_send(name, *, &)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def respond_to_missing?(name, include_private = false)
|
|
164
|
+
__file__.respond_to?(name, include_private) ||
|
|
165
|
+
__file__.schemas.first.respond_to?(name, include_private)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Stands in for a Model::ExpFile until first method access, then
|
|
170
|
+
# hydrates through the block and forwards everything.
|
|
171
|
+
class LazyFile
|
|
172
|
+
def initialize(wire_path, &hydrator)
|
|
173
|
+
@wire_path = wire_path
|
|
174
|
+
@hydrator = hydrator
|
|
175
|
+
@mutex = Mutex.new
|
|
176
|
+
@target = nil
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
attr_reader :wire_path
|
|
180
|
+
|
|
181
|
+
# The real Schema, hydrating on first call.
|
|
182
|
+
def __target__
|
|
183
|
+
@mutex.synchronize do
|
|
184
|
+
@__target__ ||= @hydrator.call
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def method_missing(name, *, &)
|
|
189
|
+
__target__.public_send(name, *, &)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def respond_to_missing?(name, include_private = false)
|
|
193
|
+
__target__.respond_to?(name, include_private)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Identity through the wrapper: rendering compares and groups by
|
|
197
|
+
# class/is_a?, which the real file answers.
|
|
198
|
+
def is_a?(klass)
|
|
199
|
+
super || __target__.is_a?(klass)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def instance_of?(klass)
|
|
203
|
+
__target__.instance_of?(klass)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def class
|
|
207
|
+
__target__.class
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Express
|
|
5
|
+
# Maps byte positions in a source string to 1-based line numbers.
|
|
6
|
+
#
|
|
7
|
+
# Single source of truth for byte→line lookup across the remark pipeline
|
|
8
|
+
# (RemarkScanner and RemarkAttacher both rely on it). Builds an offset
|
|
9
|
+
# table once and answers queries in O(log n) via binary search.
|
|
10
|
+
class LineMap
|
|
11
|
+
# Newline byte (ASCII 0x0A).
|
|
12
|
+
NEWLINE = "\n"
|
|
13
|
+
|
|
14
|
+
# @param source_bytes [String] BINARY / ASCII-8BIT encoded source.
|
|
15
|
+
def initialize(source_bytes)
|
|
16
|
+
@offsets = build_offsets(source_bytes)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Returns the 1-based line number that contains the given byte position.
|
|
20
|
+
# Returns 1 for position 0 (or any position before the first newline).
|
|
21
|
+
# Returns the last line number for positions past the final newline.
|
|
22
|
+
#
|
|
23
|
+
# @param byte_pos [Integer, nil]
|
|
24
|
+
# @return [Integer] 1-based line number; nil input yields 1.
|
|
25
|
+
def line_number(byte_pos)
|
|
26
|
+
return 1 if byte_pos.nil? || byte_pos <= 0
|
|
27
|
+
|
|
28
|
+
idx = @offsets.bsearch_index { |offset| offset > byte_pos }
|
|
29
|
+
idx || @offsets.size
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
# Builds the sorted array of byte positions where each line begins.
|
|
35
|
+
# offsets[0] = 0 (line 1 begins at byte 0).
|
|
36
|
+
# offsets[i] = (byte position of the i-th newline) + 1 (line i+1 begins).
|
|
37
|
+
def build_offsets(source_bytes)
|
|
38
|
+
offsets = [0]
|
|
39
|
+
i = 0
|
|
40
|
+
while (i = source_bytes.index(NEWLINE, i))
|
|
41
|
+
offsets << (i + 1)
|
|
42
|
+
i += 1
|
|
43
|
+
end
|
|
44
|
+
offsets
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "stringio"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Express
|
|
7
|
+
# Declaration listing and SMRL index writers — ports of eeng
|
|
8
|
+
# plugins/p11/wo-list.lisp and wo-smrl-xml.lisp (parity-ee stage 09).
|
|
9
|
+
#
|
|
10
|
+
# Two encodings share the same schema walk and declaration ordering
|
|
11
|
+
# (TYPE, ENTITY, SUBTYPE_CONSTRAINT, FUNCTION, RULE, PROCEDURE —
|
|
12
|
+
# each sorted by name):
|
|
13
|
+
# :list — human-readable SCHEMA.name; inventory
|
|
14
|
+
# :smrl_xml — <concatenated_express_file_content_list> index
|
|
15
|
+
class Listing
|
|
16
|
+
DECL_ORDER = %i[types entities subtype_constraints functions rules procedures].freeze
|
|
17
|
+
DECL_LABEL = {
|
|
18
|
+
types: "TYPE",
|
|
19
|
+
entities: "ENTITY",
|
|
20
|
+
subtype_constraints: "SUBTYPE_CONSTRAINT",
|
|
21
|
+
functions: "FUNCTION",
|
|
22
|
+
rules: "RULE",
|
|
23
|
+
procedures: "PROCEDURE",
|
|
24
|
+
}.freeze
|
|
25
|
+
XML_TAG = {
|
|
26
|
+
types: "type",
|
|
27
|
+
entities: "entity",
|
|
28
|
+
subtype_constraints: "subtype_constraint",
|
|
29
|
+
functions: "function",
|
|
30
|
+
rules: "rule",
|
|
31
|
+
procedures: "procedure",
|
|
32
|
+
}.freeze
|
|
33
|
+
|
|
34
|
+
def self.list(schemas, io = nil)
|
|
35
|
+
new(Array(schemas)).write(:list, io)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.smrl_xml(schemas, io = nil, source: nil)
|
|
39
|
+
new(Array(schemas)).write(:smrl_xml, io, source: source)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def initialize(schemas)
|
|
43
|
+
@schemas = schemas.compact.sort_by { |s| s.id.to_s.downcase }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def write(encoding, io = nil, source: nil)
|
|
47
|
+
owned = io.nil?
|
|
48
|
+
io ||= +""
|
|
49
|
+
case encoding
|
|
50
|
+
when :list then write_list(io)
|
|
51
|
+
when :smrl_xml then write_smrl_xml(io, source: source)
|
|
52
|
+
else
|
|
53
|
+
raise ArgumentError, "unknown listing encoding #{encoding.inspect}"
|
|
54
|
+
end
|
|
55
|
+
owned ? io : nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def write_list(io)
|
|
61
|
+
@schemas.each_with_index do |schema, i|
|
|
62
|
+
io << "\n" if i.positive?
|
|
63
|
+
write_schema_list(schema, io)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def write_schema_list(schema, io)
|
|
68
|
+
version = schema.version ? " #{schema.version}" : ""
|
|
69
|
+
io << "SCHEMA #{schema.id.downcase}#{version};\n\n"
|
|
70
|
+
counts = decl_counts(schema)
|
|
71
|
+
DECL_ORDER.each do |key|
|
|
72
|
+
io << format("(* %-20s %4d *)\n", DECL_LABEL[key], counts[key])
|
|
73
|
+
end
|
|
74
|
+
ifaces = Array(schema.interfaces)
|
|
75
|
+
if ifaces.any?
|
|
76
|
+
io << "\n"
|
|
77
|
+
ifaces.each do |iface|
|
|
78
|
+
kind = iface.kind == Model::Declarations::Interface::REFERENCE ? "REFERENCE FROM" : "USE FROM"
|
|
79
|
+
target = iface_name(iface)
|
|
80
|
+
suffix = Array(iface.items).any? ? "(...)" : ""
|
|
81
|
+
io << " #{kind} #{target}#{suffix};\n"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
constants = Array(schema.constants).sort_by { |c| c.id.to_s.downcase }
|
|
85
|
+
if constants.any?
|
|
86
|
+
io << "\n"
|
|
87
|
+
constants.each { |c| io << " CONSTANT #{c.id.downcase};\n" }
|
|
88
|
+
end
|
|
89
|
+
decls = ordered_decls(schema)
|
|
90
|
+
if decls.any?
|
|
91
|
+
io << "\n"
|
|
92
|
+
decls.each do |key, name|
|
|
93
|
+
io << " #{DECL_LABEL[key]} #{schema.id}.#{name.downcase};\n"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def write_smrl_xml(io, source: nil)
|
|
99
|
+
io << "<!-- Written by Expressir -->\n"
|
|
100
|
+
io << "<!-- #{Expressir::VERSION} -->\n"
|
|
101
|
+
io << "<!-- File: #{source} -->\n" if source
|
|
102
|
+
io << "<concatenated_express_file_content_list>\n\n"
|
|
103
|
+
names = @schemas.map { |s| schema_name_string(s.id) }
|
|
104
|
+
io << "<!-- #{@schemas.size} Schema#{'ta' unless @schemas.size == 1}:\n"
|
|
105
|
+
io << " #{names.join(', ')}\n"
|
|
106
|
+
io << "-->\n"
|
|
107
|
+
@schemas.each do |schema|
|
|
108
|
+
io << "\n\n"
|
|
109
|
+
write_schema_xml(schema, io)
|
|
110
|
+
end
|
|
111
|
+
io << "\n</concatenated_express_file_content_list>\n"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def write_schema_xml(schema, io)
|
|
115
|
+
io << "<schema>#{schema_name_string(schema.id)}</schema>\n"
|
|
116
|
+
if schema.version
|
|
117
|
+
io << " <schema_version>#{schema.version}</schema_version>\n"
|
|
118
|
+
end
|
|
119
|
+
counts = decl_counts(schema)
|
|
120
|
+
DECL_ORDER.each do |key|
|
|
121
|
+
io << format(" <!-- %-20s %4d -->\n", DECL_LABEL[key], counts[key])
|
|
122
|
+
end
|
|
123
|
+
Array(schema.interfaces).each do |iface|
|
|
124
|
+
tag = iface.kind == Model::Declarations::Interface::REFERENCE ? "reference-from" : "use-from"
|
|
125
|
+
target = iface_name(iface)
|
|
126
|
+
suffix = Array(iface.items).any? ? "(...)" : ""
|
|
127
|
+
io << " <#{tag}>#{target}#{suffix}</#{tag}>\n"
|
|
128
|
+
end
|
|
129
|
+
Array(schema.constants).sort_by { |c| c.id.to_s.downcase }.each do |c|
|
|
130
|
+
io << " <constant>#{c.id.downcase}</constant>\n"
|
|
131
|
+
end
|
|
132
|
+
ordered_decls(schema).each do |key, name|
|
|
133
|
+
tag = XML_TAG[key] || key.to_s
|
|
134
|
+
cased = if key == :entities && arm_mode?(schema)
|
|
135
|
+
name.split("_").map(&:capitalize).join("_")
|
|
136
|
+
else
|
|
137
|
+
name.downcase
|
|
138
|
+
end
|
|
139
|
+
io << " <#{tag}>#{schema.id}.#{cased}</#{tag}>\n"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def decl_counts(schema)
|
|
144
|
+
DECL_ORDER.to_h { |k| [k, Array(schema.public_send(k)).size] }
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def ordered_decls(schema)
|
|
148
|
+
DECL_ORDER.flat_map do |key|
|
|
149
|
+
Array(schema.public_send(key))
|
|
150
|
+
.sort_by { |d| d.id.to_s.downcase }
|
|
151
|
+
.map { |d| [key, d.id] }
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def iface_name(iface)
|
|
156
|
+
name = iface.schema.is_a?(String) ? iface.schema : iface.schema&.id
|
|
157
|
+
schema_name_string(name)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# eeng schema-name-string: arm/mim/arm_lf/mim_lf tails stay lowercase;
|
|
161
|
+
# everything else downcased.
|
|
162
|
+
def schema_name_string(name)
|
|
163
|
+
return "" unless name
|
|
164
|
+
|
|
165
|
+
name.to_s.downcase
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def arm_mode?(schema)
|
|
169
|
+
id = schema.id.to_s.downcase
|
|
170
|
+
id.end_with?("arm", "arm_lf")
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Express
|
|
5
|
+
# Structural traversal over model trees, mirroring {ModelVisitor}:
|
|
6
|
+
# every typed attribute, statements included. Nodes are keyed by
|
|
7
|
+
# attribute path plus array index — stable across a compiled-set
|
|
8
|
+
# round trip because the wire is byte-identical — which is what the
|
|
9
|
+
# remark and reference overlays key on ({Model::ModelElement#path}
|
|
10
|
+
# is empty for id-less nodes).
|
|
11
|
+
module ModelTraversal
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
def each_node(node, key, &block)
|
|
15
|
+
yield node, key
|
|
16
|
+
return unless node.is_a?(Model::ModelElement)
|
|
17
|
+
|
|
18
|
+
node.class.attributes.each_key do |attr|
|
|
19
|
+
next if Model::ModelElement::SKIP_ATTRIBUTES.include?(attr) || attr == :parent
|
|
20
|
+
|
|
21
|
+
value = node.public_send(attr)
|
|
22
|
+
case value
|
|
23
|
+
when Array
|
|
24
|
+
value.each_with_index do |item, index|
|
|
25
|
+
next unless item.is_a?(Model::ModelElement)
|
|
26
|
+
|
|
27
|
+
each_node(item, "#{key}/#{attr}[#{index}]", &block)
|
|
28
|
+
end
|
|
29
|
+
when Model::ModelElement
|
|
30
|
+
each_node(value, "#{key}/#{attr}", &block)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def each_model(models, &block)
|
|
36
|
+
models.each_with_index do |model, index|
|
|
37
|
+
each_node(model, "model[#{index}]", &block)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Expressir
|
|
2
|
+
module Express
|
|
3
|
+
# @abstract
|
|
4
|
+
class ModelVisitor
|
|
5
|
+
def visit(node)
|
|
6
|
+
node.class.attributes.each_key do |symbol|
|
|
7
|
+
next if ::Expressir::Model::ModelElement::SKIP_ATTRIBUTES.include?(symbol)
|
|
8
|
+
|
|
9
|
+
value = node.public_send(symbol)
|
|
10
|
+
|
|
11
|
+
case value
|
|
12
|
+
when Array
|
|
13
|
+
value.each do |val|
|
|
14
|
+
if val.is_a? Model::ModelElement
|
|
15
|
+
visit(val)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
when Model::ModelElement
|
|
19
|
+
visit(value)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|