expressir 1.2.11-aarch64-linux → 2.4.29-aarch64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- 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 +10 -296
- data/.github/workflows/release.yml +26 -114
- 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 +33 -1
- data/.rubocop.yml +11 -11
- data/.rubocop_todo.yml +297 -0
- data/CHANGELOG.md +159 -0
- data/Gemfile +15 -1
- data/README.adoc +2675 -47
- data/Rakefile +34 -10
- 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/rspec +2 -1
- 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 +6 -17
- data/exe/expressir-format +14 -0
- data/exe/{format-test → expressir-format-test} +8 -7
- data/expressir.gemspec +50 -37
- 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 +138 -11
- 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 +40 -3
- 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 +43 -18
- 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 +89 -1548
- 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 +4 -5
- 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 +11 -10
- 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 +501 -62
- 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 +7 -9
- data/lib/expressir/express/schema_block_scanner.rb +137 -0
- data/lib/expressir/express/schema_head_formatter.rb +4 -5
- 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 +10 -9
- data/lib/expressir/model/concerns.rb +42 -0
- data/lib/expressir/model/data_types/aggregate.rb +8 -13
- data/lib/expressir/model/data_types/array.rb +15 -21
- data/lib/expressir/model/data_types/bag.rb +11 -15
- data/lib/expressir/model/data_types/binary.rb +9 -12
- data/lib/expressir/model/data_types/boolean.rb +7 -2
- data/lib/expressir/model/data_types/enumeration.rb +11 -15
- data/lib/expressir/model/data_types/enumeration_item.rb +5 -7
- data/lib/expressir/model/data_types/generic.rb +6 -8
- data/lib/expressir/model/data_types/generic_entity.rb +11 -13
- data/lib/expressir/model/data_types/integer.rb +7 -2
- data/lib/expressir/model/data_types/list.rb +13 -18
- data/lib/expressir/model/data_types/logical.rb +7 -2
- data/lib/expressir/model/data_types/number.rb +7 -2
- data/lib/expressir/model/data_types/real.rb +7 -9
- data/lib/expressir/model/data_types/select.rb +13 -18
- data/lib/expressir/model/data_types/set.rb +11 -15
- data/lib/expressir/model/data_types/string.rb +9 -12
- data/lib/expressir/model/data_types.rb +25 -0
- data/lib/expressir/model/declarations/attribute.rb +19 -28
- data/lib/expressir/model/declarations/constant.rb +10 -16
- data/lib/expressir/model/declarations/derived_attribute.rb +25 -0
- data/lib/expressir/model/declarations/entity.rb +39 -30
- data/lib/expressir/model/declarations/function.rb +32 -40
- data/lib/expressir/model/declarations/informal_proposition_rule.rb +25 -0
- data/lib/expressir/model/declarations/interface.rb +25 -16
- data/lib/expressir/model/declarations/interface_item.rb +9 -11
- data/lib/expressir/model/declarations/interfaced_item.rb +15 -19
- data/lib/expressir/model/declarations/inverse_attribute.rb +25 -0
- data/lib/expressir/model/declarations/parameter.rb +10 -16
- data/lib/expressir/model/declarations/procedure.rb +30 -37
- data/lib/expressir/model/declarations/remark_item.rb +11 -11
- data/lib/expressir/model/declarations/rule.rb +38 -43
- data/lib/expressir/model/declarations/schema.rb +162 -64
- data/lib/expressir/model/declarations/schema_version.rb +8 -11
- data/lib/expressir/model/declarations/schema_version_item.rb +8 -11
- data/lib/expressir/model/declarations/subtype_constraint.rb +14 -22
- data/lib/expressir/model/declarations/type.rb +18 -18
- data/lib/expressir/model/declarations/unique_rule.rb +8 -13
- data/lib/expressir/model/declarations/variable.rb +10 -16
- data/lib/expressir/model/declarations/where_rule.rb +8 -13
- 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 +8 -9
- data/lib/expressir/model/expressions/aggregate_initializer_item.rb +10 -12
- data/lib/expressir/model/expressions/binary_expression.rb +42 -36
- data/lib/expressir/model/expressions/entity_constructor.rb +10 -12
- data/lib/expressir/model/expressions/function_call.rb +10 -12
- data/lib/expressir/model/expressions/interval.rb +18 -23
- data/lib/expressir/model/expressions/query_expression.rb +11 -15
- data/lib/expressir/model/expressions/unary_expression.rb +13 -15
- data/lib/expressir/model/expressions.rb +18 -0
- data/lib/expressir/model/identifier.rb +18 -26
- 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 +7 -9
- data/lib/expressir/model/literals/integer.rb +7 -9
- data/lib/expressir/model/literals/logical.rb +10 -12
- data/lib/expressir/model/literals/real.rb +7 -9
- data/lib/expressir/model/literals/string.rb +10 -12
- data/lib/expressir/model/literals.rb +13 -0
- data/lib/expressir/model/model_element.rb +286 -117
- data/lib/expressir/model/references/attribute_reference.rb +9 -12
- data/lib/expressir/model/references/group_reference.rb +9 -12
- data/lib/expressir/model/references/index_reference.rb +11 -15
- data/lib/expressir/model/references/simple_reference.rb +11 -14
- 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 +472 -12
- 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 +12 -16
- data/lib/expressir/model/statements/assignment.rb +12 -11
- data/lib/expressir/model/statements/case.rb +31 -14
- data/lib/expressir/model/statements/case_action.rb +9 -11
- data/lib/expressir/model/statements/compound.rb +10 -8
- data/lib/expressir/model/statements/escape.rb +10 -2
- data/lib/expressir/model/statements/if.rb +15 -14
- data/lib/expressir/model/statements/null.rb +10 -2
- data/lib/expressir/model/statements/procedure_call.rb +11 -11
- data/lib/expressir/model/statements/repeat.rb +21 -28
- data/lib/expressir/model/statements/return.rb +9 -8
- data/lib/expressir/model/statements/skip.rb +10 -2
- data/lib/expressir/model/statements.rb +20 -0
- data/lib/expressir/model/supertype_expressions/binary_supertype_expression.rb +13 -17
- data/lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb +7 -9
- data/lib/expressir/model/supertype_expressions.rb +12 -0
- data/lib/expressir/model.rb +38 -78
- 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 +6 -1
- data/lib/expressir.rb +79 -9
- 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 +431 -129
- data/.cross_rubies +0 -20
- data/.gitmodules +0 -6
- data/.yardopts +0 -11
- data/docs/development.md +0 -90
- data/exe/format +0 -18
- data/exe/generate-parser +0 -51
- data/lib/expressir/cli/ui.rb +0 -36
- data/lib/expressir/express/2.7/express_parser.so +0 -0
- data/lib/expressir/express/3.0/express_parser.so +0 -0
- data/lib/expressir/express/3.1/express_parser.so +0 -0
- data/lib/expressir/express/3.2/express_parser.so +0 -0
- data/lib/expressir/express/visitor.rb +0 -2588
- data/lib/expressir/model/data_type.rb +0 -9
- data/lib/expressir/model/declaration.rb +0 -9
- data/lib/expressir/model/expression.rb +0 -9
- data/lib/expressir/model/literal.rb +0 -9
- data/lib/expressir/model/reference.rb +0 -9
- data/lib/expressir/model/statement.rb +0 -9
- data/lib/expressir/model/supertype_expression.rb +0 -9
- data/rakelib/antlr4-native.rake +0 -161
- data/rakelib/cross-ruby.rake +0 -368
- data/spec/acceptance/version_spec.rb +0 -27
- data/spec/expressir/express/cache_spec.rb +0 -89
- data/spec/expressir/express/formatter_spec.rb +0 -173
- data/spec/expressir/express/parser_spec.rb +0 -141
- data/spec/expressir/model/model_element_spec.rb +0 -318
- data/spec/spec_helper.rb +0 -24
- data/spec/support/console_helper.rb +0 -29
- data/spec/syntax/multiple.exp +0 -23
- data/spec/syntax/multiple.yaml +0 -198
- data/spec/syntax/multiple_formatted.exp +0 -71
- data/spec/syntax/multiple_hyperlink_formatted.exp +0 -71
- data/spec/syntax/multiple_schema_head_hyperlink_formatted.exp +0 -13
- data/spec/syntax/remark.exp +0 -193
- data/spec/syntax/remark.yaml +0 -471
- data/spec/syntax/remark_formatted.exp +0 -228
- data/spec/syntax/single.exp +0 -4
- data/spec/syntax/single.yaml +0 -18
- data/spec/syntax/single_formatted.exp +0 -10
- data/spec/syntax/single_formatted.yaml +0 -36
- data/spec/syntax/syntax.exp +0 -333
- data/spec/syntax/syntax.yaml +0 -3509
- data/spec/syntax/syntax_formatted.exp +0 -902
- data/spec/syntax/syntax_hyperlink_formatted.exp +0 -902
- data/spec/syntax/syntax_schema_head_formatted.exp +0 -18
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
module Expressir
|
|
2
|
+
module Express
|
|
3
|
+
# Pretty formatter for EXPRESS schemas following ELF specification
|
|
4
|
+
# @see https://www.express-language-foundation.org/pretty-print-spec/
|
|
5
|
+
class PrettyFormatter < Formatter
|
|
6
|
+
# Configuration class for MECE parameter management
|
|
7
|
+
# Follows the hierarchy: Options > ENV > Defaults
|
|
8
|
+
class Configuration
|
|
9
|
+
attr_accessor :indent, :line_length, :insert_newline, :insert_space,
|
|
10
|
+
:provenance_enabled, :provenance_name, :provenance_version
|
|
11
|
+
|
|
12
|
+
# Initialize configuration with options, environment variables, or defaults
|
|
13
|
+
# @param options [Hash] Configuration options
|
|
14
|
+
def initialize(options = {})
|
|
15
|
+
@indent = resolve_param(options, :indent, "EXPRESSIR_INDENT", 4)
|
|
16
|
+
@line_length = resolve_param(options, :line_length,
|
|
17
|
+
"EXPRESSIR_LINE_LENGTH", nil)
|
|
18
|
+
@insert_newline = resolve_param(options, :insert_newline,
|
|
19
|
+
"EXPRESSIR_INSERT_NEWLINE", true)
|
|
20
|
+
@insert_space = resolve_param(options, :insert_space,
|
|
21
|
+
"EXPRESSIR_INSERT_SPACE", true)
|
|
22
|
+
@provenance_enabled = resolve_param(options, :provenance,
|
|
23
|
+
"EXPRESSIR_PROVENANCE", true)
|
|
24
|
+
@provenance_name = resolve_param(options, :provenance_name,
|
|
25
|
+
"EXPRESSIR_PROVENANCE_NAME", "Expressir")
|
|
26
|
+
@provenance_version = resolve_param(options, :provenance_version,
|
|
27
|
+
"EXPRESSIR_PROVENANCE_VERSION", Expressir::Version::VERSION)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
# Resolve parameter value following MECE hierarchy: Options > ENV > Defaults
|
|
33
|
+
# @param options [Hash] Options hash
|
|
34
|
+
# @param key [Symbol] Option key
|
|
35
|
+
# @param env_key [String] Environment variable key
|
|
36
|
+
# @param default [Object] Default value
|
|
37
|
+
# @return [Object] Resolved value
|
|
38
|
+
def resolve_param(options, key, env_key, default)
|
|
39
|
+
return options[key] if options.key?(key)
|
|
40
|
+
|
|
41
|
+
env_value = ENV.fetch(env_key, nil)
|
|
42
|
+
return parse_env_value(env_value) unless env_value.nil?
|
|
43
|
+
|
|
44
|
+
default
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Parse environment variable value to appropriate type
|
|
48
|
+
# @param value [String] Environment variable value
|
|
49
|
+
# @return [Object] Parsed value
|
|
50
|
+
def parse_env_value(value)
|
|
51
|
+
return nil if value.nil? || value.empty?
|
|
52
|
+
return true if value.downcase == "true"
|
|
53
|
+
return false if value.downcase == "false"
|
|
54
|
+
return value.to_i if /^\d+$/.match?(value)
|
|
55
|
+
|
|
56
|
+
value
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
attr_reader :config
|
|
61
|
+
|
|
62
|
+
# Initialize PrettyFormatter with options
|
|
63
|
+
# @param options [Hash] Formatting options
|
|
64
|
+
# @option options [Integer] :indent Number of spaces per indentation level (default: 4)
|
|
65
|
+
# @option options [Integer, nil] :line_length Maximum line length (default: nil)
|
|
66
|
+
# @option options [Boolean] :insert_newline Insert newlines for readability (default: true)
|
|
67
|
+
# @option options [Boolean] :insert_space Insert spaces for readability (default: true)
|
|
68
|
+
# @option options [Boolean] :provenance Include provenance information (default: true)
|
|
69
|
+
# @option options [String] :provenance_name Tool name for provenance (default: "Expressir")
|
|
70
|
+
# @option options [String] :provenance_version Tool version for provenance (default: Expressir::Version::VERSION)
|
|
71
|
+
# @option options [Boolean] :no_remarks Suppress remarks in output (default: false)
|
|
72
|
+
def initialize(options = {})
|
|
73
|
+
@config = Configuration.new(options)
|
|
74
|
+
super(no_remarks: options.fetch(:no_remarks, false))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Override indent to use configured width
|
|
78
|
+
# @param str [String] String to indent
|
|
79
|
+
# @return [String] Indented string
|
|
80
|
+
def indent(str)
|
|
81
|
+
return if str.nil?
|
|
82
|
+
|
|
83
|
+
indent_str = " " * @config.indent
|
|
84
|
+
str.split("\n").map { |x| "#{indent_str}#{x}" }.join("\n")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Format inline tail remark
|
|
88
|
+
# @param node [Model::ModelElement] Node with potential tail remark
|
|
89
|
+
# @return [String] Tail remark or empty string
|
|
90
|
+
def format_inline_tail_remark(node)
|
|
91
|
+
return "" if @no_remarks
|
|
92
|
+
return "" unless node.is_a?(Model::ModelElement)
|
|
93
|
+
return "" if node.untagged_remarks.nil? || node.untagged_remarks.empty?
|
|
94
|
+
|
|
95
|
+
# Get first untagged remark
|
|
96
|
+
remark = node.untagged_remarks.first
|
|
97
|
+
return "" if remark.nil?
|
|
98
|
+
|
|
99
|
+
return "" unless remark.is_a?(Model::RemarkInfo)
|
|
100
|
+
|
|
101
|
+
text = remark.text
|
|
102
|
+
return "" if text.nil? || text.empty?
|
|
103
|
+
|
|
104
|
+
# Include tag if present
|
|
105
|
+
formatted_text = remark.tagged? ? "\"#{remark.tag}\" #{text}" : text
|
|
106
|
+
|
|
107
|
+
# Use format from RemarkInfo
|
|
108
|
+
remark.tail? ? " -- #{formatted_text}" : " (* #{formatted_text} *)"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Override to preserve tail remarks on attributes
|
|
112
|
+
# @param node [Model::Declarations::Entity] Entity node
|
|
113
|
+
# @return [String] Formatted entity
|
|
114
|
+
def format_declarations_entity(node)
|
|
115
|
+
if node.attributes.nil?
|
|
116
|
+
explicit_attributes = []
|
|
117
|
+
derived_attributes = []
|
|
118
|
+
inverse_attributes = []
|
|
119
|
+
else
|
|
120
|
+
explicit_attributes = node.attributes.select do |x|
|
|
121
|
+
x.kind == Model::Declarations::Attribute::EXPLICIT
|
|
122
|
+
end
|
|
123
|
+
derived_attributes = node.attributes.select do |x|
|
|
124
|
+
x.kind == Model::Declarations::Attribute::DERIVED
|
|
125
|
+
end
|
|
126
|
+
inverse_attributes = node.attributes.select do |x|
|
|
127
|
+
x.kind == Model::Declarations::Attribute::INVERSE
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
indent_str = " " * @config.indent
|
|
132
|
+
preamble = format_preamble_remarks(node, indent_str)
|
|
133
|
+
|
|
134
|
+
[
|
|
135
|
+
[
|
|
136
|
+
"ENTITY",
|
|
137
|
+
" ",
|
|
138
|
+
node.id,
|
|
139
|
+
*if node.abstract && !node.supertype_expression
|
|
140
|
+
[
|
|
141
|
+
"\n",
|
|
142
|
+
indent([
|
|
143
|
+
"ABSTRACT",
|
|
144
|
+
" ",
|
|
145
|
+
"SUPERTYPE",
|
|
146
|
+
].join),
|
|
147
|
+
].join
|
|
148
|
+
end,
|
|
149
|
+
*if node.abstract && node.supertype_expression
|
|
150
|
+
[
|
|
151
|
+
"\n",
|
|
152
|
+
indent([
|
|
153
|
+
"ABSTRACT",
|
|
154
|
+
" ",
|
|
155
|
+
"SUPERTYPE",
|
|
156
|
+
" ",
|
|
157
|
+
"OF",
|
|
158
|
+
" ",
|
|
159
|
+
"(",
|
|
160
|
+
format(node.supertype_expression),
|
|
161
|
+
")",
|
|
162
|
+
].join),
|
|
163
|
+
].join
|
|
164
|
+
end,
|
|
165
|
+
*if !node.abstract && node.supertype_expression
|
|
166
|
+
[
|
|
167
|
+
"\n",
|
|
168
|
+
indent([
|
|
169
|
+
"SUPERTYPE",
|
|
170
|
+
" ",
|
|
171
|
+
"OF",
|
|
172
|
+
" ",
|
|
173
|
+
"(",
|
|
174
|
+
format(node.supertype_expression),
|
|
175
|
+
")",
|
|
176
|
+
].join),
|
|
177
|
+
].join
|
|
178
|
+
end,
|
|
179
|
+
*if node.subtype_of&.length&.positive?
|
|
180
|
+
[
|
|
181
|
+
"\n",
|
|
182
|
+
indent([
|
|
183
|
+
"SUBTYPE",
|
|
184
|
+
" ",
|
|
185
|
+
"OF",
|
|
186
|
+
" ",
|
|
187
|
+
"(",
|
|
188
|
+
node.subtype_of.map { |x| format(x) }.join(", "),
|
|
189
|
+
")",
|
|
190
|
+
].join),
|
|
191
|
+
].join
|
|
192
|
+
end,
|
|
193
|
+
";",
|
|
194
|
+
].join,
|
|
195
|
+
*if preamble && !preamble.empty?
|
|
196
|
+
preamble.rstrip
|
|
197
|
+
end,
|
|
198
|
+
*if explicit_attributes&.length&.positive?
|
|
199
|
+
indent(explicit_attributes.map { |x| format(x) }.join("\n"))
|
|
200
|
+
end,
|
|
201
|
+
*if derived_attributes&.length&.positive?
|
|
202
|
+
[
|
|
203
|
+
"DERIVE",
|
|
204
|
+
indent(derived_attributes.map { |x| format(x) }.join("\n")),
|
|
205
|
+
]
|
|
206
|
+
end,
|
|
207
|
+
*if inverse_attributes&.length&.positive?
|
|
208
|
+
[
|
|
209
|
+
"INVERSE",
|
|
210
|
+
indent(inverse_attributes.map { |x| format(x) }.join("\n")),
|
|
211
|
+
]
|
|
212
|
+
end,
|
|
213
|
+
*if node.unique_rules&.length&.positive?
|
|
214
|
+
[
|
|
215
|
+
"UNIQUE",
|
|
216
|
+
indent(node.unique_rules.map { |x| format(x) }.join("\n")),
|
|
217
|
+
]
|
|
218
|
+
end,
|
|
219
|
+
*if node.where_rules&.length&.positive?
|
|
220
|
+
[
|
|
221
|
+
"WHERE",
|
|
222
|
+
indent(node.where_rules.map { |x| format(x) }.join("\n")),
|
|
223
|
+
]
|
|
224
|
+
end,
|
|
225
|
+
[
|
|
226
|
+
"END_ENTITY",
|
|
227
|
+
";",
|
|
228
|
+
format_end_scope_remark(node),
|
|
229
|
+
].join,
|
|
230
|
+
].join("\n")
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Format preamble remarks before SCHEMA
|
|
234
|
+
# @param source_remarks [Array<String>] Source remarks
|
|
235
|
+
# @return [Array<String>] Formatted preamble lines
|
|
236
|
+
def format_preamble(source_remarks)
|
|
237
|
+
return [] if source_remarks.nil? || source_remarks.empty?
|
|
238
|
+
|
|
239
|
+
preamble = source_remarks.map do |remark|
|
|
240
|
+
format_preamble_remark(remark)
|
|
241
|
+
end
|
|
242
|
+
preamble << "" # Blank line after preamble
|
|
243
|
+
preamble
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# Format a single preamble remark
|
|
247
|
+
# @param remark [RemarkInfo] RemarkInfo object
|
|
248
|
+
# @param indent_str [String] Indentation to use (optional)
|
|
249
|
+
# @return [String] Formatted remark
|
|
250
|
+
def format_preamble_remark(remark, _indent_str = "")
|
|
251
|
+
return "" unless remark.is_a?(Model::RemarkInfo)
|
|
252
|
+
|
|
253
|
+
text = remark.text
|
|
254
|
+
return "" if text.nil? || text.empty?
|
|
255
|
+
|
|
256
|
+
# Include tag if present
|
|
257
|
+
text = "\"#{remark.tag}\" #{text}" if remark.tagged?
|
|
258
|
+
|
|
259
|
+
# Use format from RemarkInfo
|
|
260
|
+
if remark.tail?
|
|
261
|
+
"-- #{text}"
|
|
262
|
+
elsif text.include?("\n")
|
|
263
|
+
# Embedded remark - always use embedded format for preamble
|
|
264
|
+
["(*", text,
|
|
265
|
+
"*)"].join("\n")
|
|
266
|
+
else
|
|
267
|
+
"(* #{text} *)"
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
# Generate provenance remark
|
|
272
|
+
# @return [String, nil] Provenance comment or nil if disabled
|
|
273
|
+
def format_provenance
|
|
274
|
+
return nil unless @config.provenance_enabled
|
|
275
|
+
|
|
276
|
+
params = []
|
|
277
|
+
params << "indent: #{@config.indent}"
|
|
278
|
+
params << "line_length: #{@config.line_length}" if @config.line_length
|
|
279
|
+
|
|
280
|
+
[
|
|
281
|
+
"(*",
|
|
282
|
+
" Generated by: #{@config.provenance_name} version #{@config.provenance_version}",
|
|
283
|
+
" Format parameters: #{params.join(', ')}",
|
|
284
|
+
"*)",
|
|
285
|
+
].join("\n")
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Override to add preamble and provenance
|
|
289
|
+
# @param node [Model::Repository] Repository node
|
|
290
|
+
# @return [String] Formatted repository
|
|
291
|
+
def format_repository(node)
|
|
292
|
+
result = []
|
|
293
|
+
|
|
294
|
+
# Format files if present
|
|
295
|
+
node.files&.each do |exp_file|
|
|
296
|
+
file_output = format_exp_file(exp_file)
|
|
297
|
+
result << file_output if file_output && !file_output.empty?
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Handle schemas directly added to repository (not via files)
|
|
301
|
+
direct_schemas = node.schemas.select do |s|
|
|
302
|
+
# Schema is direct if it's not in any file
|
|
303
|
+
node.files.nil? || node.files.none? { |f| f.schemas&.include?(s) }
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
if direct_schemas.any?
|
|
307
|
+
# Add preamble if repository has untagged remarks
|
|
308
|
+
if node.untagged_remarks && !node.untagged_remarks.empty?
|
|
309
|
+
result.concat(format_preamble(node.untagged_remarks))
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
# Add provenance
|
|
313
|
+
provenance = format_provenance
|
|
314
|
+
result << provenance if provenance
|
|
315
|
+
result << "" if provenance
|
|
316
|
+
|
|
317
|
+
# Add schemas
|
|
318
|
+
schemas_output = direct_schemas.map { |x| format(x) }.join("\n\n")
|
|
319
|
+
result << schemas_output if schemas_output
|
|
320
|
+
elsif result.empty?
|
|
321
|
+
# Empty repository - just add provenance
|
|
322
|
+
provenance = format_provenance
|
|
323
|
+
result << provenance if provenance
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
result.any? ? "#{result.join("\n")}\n" : ""
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# Format ExpFile with file-level preamble
|
|
330
|
+
# @param node [Model::ExpFile] ExpFile node
|
|
331
|
+
# @return [String] Formatted file
|
|
332
|
+
def format_exp_file(node)
|
|
333
|
+
result = []
|
|
334
|
+
|
|
335
|
+
# Add file-level preamble if present (skip provenance remarks from previous parses)
|
|
336
|
+
unless @no_remarks
|
|
337
|
+
source_remarks = (node.untagged_remarks || []).reject do |remark|
|
|
338
|
+
remark.is_a?(Model::RemarkInfo) && provenance_remark?(remark)
|
|
339
|
+
end
|
|
340
|
+
result.concat(format_preamble(source_remarks)) if source_remarks.any?
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
# Add provenance (only for first file or single file)
|
|
344
|
+
provenance = format_provenance
|
|
345
|
+
result << provenance if provenance
|
|
346
|
+
result << "" if provenance
|
|
347
|
+
|
|
348
|
+
# Add schemas
|
|
349
|
+
schemas = node.schemas&.map { |x| format(x) }&.join("\n\n")
|
|
350
|
+
result << schemas if schemas
|
|
351
|
+
|
|
352
|
+
result.empty? ? "" : "#{result.join("\n")}\n"
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# Format a block of constants with aligned colons and assignments
|
|
356
|
+
# @param constants [Array<Model::Declarations::Constant>] Constants to format
|
|
357
|
+
# @return [String] Formatted constants with alignment
|
|
358
|
+
def format_constant_block(constants)
|
|
359
|
+
return "" if constants.nil? || constants.empty?
|
|
360
|
+
|
|
361
|
+
# Calculate alignment positions
|
|
362
|
+
max_name_len = constants.map { |c| c.id.length }.max
|
|
363
|
+
type_strings = constants.map { |c| format(c.type) }
|
|
364
|
+
max_type_len = type_strings.map(&:length).max
|
|
365
|
+
|
|
366
|
+
# Format each constant with alignment
|
|
367
|
+
formatted = constants.zip(type_strings).map do |constant, type_str|
|
|
368
|
+
name_padding = " " * (max_name_len - constant.id.length)
|
|
369
|
+
type_padding = " " * (max_type_len - type_str.length)
|
|
370
|
+
|
|
371
|
+
"#{constant.id}#{name_padding} : #{type_str}#{type_padding} := #{format(constant.expression)};"
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
formatted.join("\n")
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
# Override format_declarations_schema to use aligned constants
|
|
378
|
+
# @param node [Model::Declarations::Schema] Schema node
|
|
379
|
+
# @return [String] Formatted schema
|
|
380
|
+
def format_declarations_schema(node)
|
|
381
|
+
indent_str = " " * @config.indent
|
|
382
|
+
preamble = format_preamble_remarks(node, indent_str)
|
|
383
|
+
schema_declarations = [
|
|
384
|
+
*if node.constants&.length&.positive?
|
|
385
|
+
[
|
|
386
|
+
"CONSTANT",
|
|
387
|
+
indent(format_constant_block(node.constants)),
|
|
388
|
+
[
|
|
389
|
+
"END_CONSTANT",
|
|
390
|
+
";",
|
|
391
|
+
].join,
|
|
392
|
+
].join("\n")
|
|
393
|
+
end,
|
|
394
|
+
*if node.types&.length&.positive?
|
|
395
|
+
node.types.map { |x| format(x) }
|
|
396
|
+
end,
|
|
397
|
+
*if node.entities&.length&.positive?
|
|
398
|
+
node.entities.map { |x| format(x) }
|
|
399
|
+
end,
|
|
400
|
+
*if node.subtype_constraints&.length&.positive?
|
|
401
|
+
node.subtype_constraints.map { |x| format(x) }
|
|
402
|
+
end,
|
|
403
|
+
*if node.functions&.length&.positive?
|
|
404
|
+
node.functions.map { |x| format(x) }
|
|
405
|
+
end,
|
|
406
|
+
*if node.rules&.length&.positive?
|
|
407
|
+
node.rules.map { |x| format(x) }
|
|
408
|
+
end,
|
|
409
|
+
*if node.procedures&.length&.positive?
|
|
410
|
+
node.procedures.map { |x| format(x) }
|
|
411
|
+
end,
|
|
412
|
+
]
|
|
413
|
+
|
|
414
|
+
[
|
|
415
|
+
format_declarations_schema_head(node),
|
|
416
|
+
*if preamble && !preamble.empty?
|
|
417
|
+
[
|
|
418
|
+
"",
|
|
419
|
+
preamble.rstrip,
|
|
420
|
+
]
|
|
421
|
+
end,
|
|
422
|
+
*if schema_declarations&.length&.positive?
|
|
423
|
+
[
|
|
424
|
+
"",
|
|
425
|
+
schema_declarations.join("\n\n"),
|
|
426
|
+
"",
|
|
427
|
+
]
|
|
428
|
+
end,
|
|
429
|
+
[
|
|
430
|
+
"END_SCHEMA",
|
|
431
|
+
";",
|
|
432
|
+
format_end_scope_remark(node),
|
|
433
|
+
].join,
|
|
434
|
+
].join("\n")
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
# Override format_declarations_function to use aligned constants
|
|
438
|
+
def format_declarations_function(node)
|
|
439
|
+
[
|
|
440
|
+
[
|
|
441
|
+
"FUNCTION",
|
|
442
|
+
" ",
|
|
443
|
+
node.id,
|
|
444
|
+
*if node.parameters&.length&.positive?
|
|
445
|
+
parameter_indent = " " * "FUNCTION #{node.id}(".length
|
|
446
|
+
[
|
|
447
|
+
"(",
|
|
448
|
+
node.parameters.map do |x|
|
|
449
|
+
format(x)
|
|
450
|
+
end.join(";\n#{parameter_indent}"),
|
|
451
|
+
")",
|
|
452
|
+
].join
|
|
453
|
+
end,
|
|
454
|
+
" ",
|
|
455
|
+
":",
|
|
456
|
+
" ",
|
|
457
|
+
format(node.return_type),
|
|
458
|
+
";",
|
|
459
|
+
].join,
|
|
460
|
+
*format_scope_body(node),
|
|
461
|
+
format_scope_footer("END_FUNCTION", node),
|
|
462
|
+
].join("\n")
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
# Override format_declarations_procedure to use aligned constants
|
|
466
|
+
def format_declarations_procedure(node)
|
|
467
|
+
[
|
|
468
|
+
[
|
|
469
|
+
"PROCEDURE",
|
|
470
|
+
" ",
|
|
471
|
+
node.id,
|
|
472
|
+
*if node.parameters&.length&.positive?
|
|
473
|
+
parameter_indent = " " * "PROCEDURE #{node.id}(".length
|
|
474
|
+
[
|
|
475
|
+
"(",
|
|
476
|
+
node.parameters.map do |x|
|
|
477
|
+
format(x)
|
|
478
|
+
end.join(";\n#{parameter_indent}"),
|
|
479
|
+
")",
|
|
480
|
+
].join
|
|
481
|
+
end,
|
|
482
|
+
";",
|
|
483
|
+
].join,
|
|
484
|
+
*format_scope_body(node),
|
|
485
|
+
format_scope_footer("END_PROCEDURE", node),
|
|
486
|
+
].join("\n")
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
# Override format_declarations_rule to use aligned constants
|
|
490
|
+
def format_declarations_rule(node)
|
|
491
|
+
[
|
|
492
|
+
[
|
|
493
|
+
"RULE",
|
|
494
|
+
" ",
|
|
495
|
+
node.id,
|
|
496
|
+
" ",
|
|
497
|
+
"FOR",
|
|
498
|
+
" ",
|
|
499
|
+
"(",
|
|
500
|
+
Array(node.applies_to).map { |x| format(x) }.join(", "),
|
|
501
|
+
")",
|
|
502
|
+
";",
|
|
503
|
+
].join,
|
|
504
|
+
*format_scope_body(node),
|
|
505
|
+
*if node.where_rules&.length&.positive?
|
|
506
|
+
[
|
|
507
|
+
"WHERE",
|
|
508
|
+
indent(node.where_rules.map { |x| format(x) }.join("\n")),
|
|
509
|
+
]
|
|
510
|
+
end,
|
|
511
|
+
*format_trailing_region_remarks(node, :where_rules).map { |x| indent(x) },
|
|
512
|
+
format_scope_footer("END_RULE", node),
|
|
513
|
+
].join("\n")
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
# Shared scope body for function, procedure, and rule declarations.
|
|
517
|
+
# These declaration types share the same internal structure:
|
|
518
|
+
# types, entities, subtype_constraints, functions, procedures,
|
|
519
|
+
# constants, variables, statements.
|
|
520
|
+
def format_scope_body(node)
|
|
521
|
+
[
|
|
522
|
+
*if node.types&.length&.positive?
|
|
523
|
+
indent(node.types.map { |x| format(x) }.join("\n"))
|
|
524
|
+
end,
|
|
525
|
+
*if node.entities&.length&.positive?
|
|
526
|
+
indent(node.entities.map { |x| format(x) }.join("\n"))
|
|
527
|
+
end,
|
|
528
|
+
*if node.subtype_constraints&.length&.positive?
|
|
529
|
+
indent(node.subtype_constraints.map { |x| format(x) }.join("\n"))
|
|
530
|
+
end,
|
|
531
|
+
*if node.functions&.length&.positive?
|
|
532
|
+
indent(node.functions.map { |x| format(x) }.join("\n"))
|
|
533
|
+
end,
|
|
534
|
+
*if node.procedures&.length&.positive?
|
|
535
|
+
indent(node.procedures.map { |x| format(x) }.join("\n"))
|
|
536
|
+
end,
|
|
537
|
+
*if node.constants&.length&.positive?
|
|
538
|
+
indent([
|
|
539
|
+
"CONSTANT",
|
|
540
|
+
indent(format_constant_block(node.constants)),
|
|
541
|
+
[
|
|
542
|
+
"END_CONSTANT",
|
|
543
|
+
";",
|
|
544
|
+
].join,
|
|
545
|
+
].join("\n"))
|
|
546
|
+
end,
|
|
547
|
+
*if node.variables&.length&.positive?
|
|
548
|
+
indent([
|
|
549
|
+
"LOCAL",
|
|
550
|
+
indent(node.variables.map { |x| format(x) }.join("\n")),
|
|
551
|
+
[
|
|
552
|
+
"END_LOCAL",
|
|
553
|
+
";",
|
|
554
|
+
].join,
|
|
555
|
+
].join("\n"))
|
|
556
|
+
end,
|
|
557
|
+
*if node.statements&.length&.positive?
|
|
558
|
+
indent(node.statements.map { |x| format(x) }.join("\n"))
|
|
559
|
+
end,
|
|
560
|
+
# Comments closing the executable body. This formatter overrides
|
|
561
|
+
# the declaration formatters, so the emitter is repeated here or
|
|
562
|
+
# trailing remarks would render only in standard output. For a
|
|
563
|
+
# RULE the body ends at WHERE, which follows this block.
|
|
564
|
+
*format_trailing_region_remarks(node, :statements).map { |x| indent(x) },
|
|
565
|
+
]
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
def format_scope_footer(keyword, node)
|
|
569
|
+
[
|
|
570
|
+
keyword,
|
|
571
|
+
";",
|
|
572
|
+
format_end_scope_remark(node),
|
|
573
|
+
].join
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
# Check if a remark was generated by this formatter's provenance output.
|
|
577
|
+
# Prevents provenance comments from accumulating on round-trip re-parses.
|
|
578
|
+
def provenance_remark?(remark)
|
|
579
|
+
return false unless remark.is_a?(Model::RemarkInfo)
|
|
580
|
+
|
|
581
|
+
text = remark.text.to_s
|
|
582
|
+
text.match?(/\A\s*(Generated by:|Format parameters:)/)
|
|
583
|
+
end
|
|
584
|
+
end
|
|
585
|
+
end
|
|
586
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Express
|
|
5
|
+
# Pretty round-trip gate (parity-ee stage 08 / eeng qualify.sh
|
|
6
|
+
# self-check): parse → format → re-parse and compare a structural
|
|
7
|
+
# fingerprint of the model. Byte identity is deliberately not
|
|
8
|
+
# required — remark placement and whitespace drift are tolerated;
|
|
9
|
+
# declaration inventory and interface shape must match.
|
|
10
|
+
class PrettyGate
|
|
11
|
+
Result = Struct.new(:path, :ok, :before, :after, :error, keyword_init: true)
|
|
12
|
+
|
|
13
|
+
def self.fingerprint(schema)
|
|
14
|
+
{
|
|
15
|
+
id: schema.id&.safe_downcase,
|
|
16
|
+
interfaces: Array(schema.interfaces).map do |i|
|
|
17
|
+
{
|
|
18
|
+
kind: i.kind,
|
|
19
|
+
schema: (i.schema.is_a?(String) ? i.schema : i.schema&.id)&.safe_downcase,
|
|
20
|
+
items: Array(i.items).map do |entry|
|
|
21
|
+
ref = entry.ref.is_a?(String) ? entry.ref : entry.ref&.id
|
|
22
|
+
[entry.id&.safe_downcase, ref&.safe_downcase]
|
|
23
|
+
end.sort,
|
|
24
|
+
}
|
|
25
|
+
end,
|
|
26
|
+
constants: ids_of(schema.constants),
|
|
27
|
+
types: ids_of(schema.types),
|
|
28
|
+
entities: ids_of(schema.entities),
|
|
29
|
+
subtype_constraints: ids_of(schema.subtype_constraints),
|
|
30
|
+
functions: ids_of(schema.functions),
|
|
31
|
+
procedures: ids_of(schema.procedures),
|
|
32
|
+
rules: ids_of(schema.rules),
|
|
33
|
+
entity_attrs: Array(schema.entities).to_h do |e|
|
|
34
|
+
[e.id.safe_downcase, Array(e.attributes).filter_map { |a| a.id&.safe_downcase }.sort]
|
|
35
|
+
end,
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.ids_of(coll)
|
|
40
|
+
Array(coll).filter_map { |d| d.id&.safe_downcase }.sort
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.check_file(path)
|
|
44
|
+
source = File.read(path)
|
|
45
|
+
original = Parser.from_exp(source, skip_references: true)
|
|
46
|
+
formatted = Formatter.format(original)
|
|
47
|
+
roundtrip = Parser.from_exp(formatted, skip_references: true)
|
|
48
|
+
|
|
49
|
+
before = original.schemas.map { |s| fingerprint(s) }
|
|
50
|
+
after = roundtrip.schemas.map { |s| fingerprint(s) }
|
|
51
|
+
Result.new(path: path, ok: before == after, before: before, after: after)
|
|
52
|
+
rescue StandardError => e
|
|
53
|
+
Result.new(path: path, ok: false, error: e)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.check_files(paths)
|
|
57
|
+
paths.map { |p| check_file(p) }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Express
|
|
5
|
+
# Resolved references are deterministic given the sources and the
|
|
6
|
+
# repository composition, so the batch path persists every
|
|
7
|
+
# SimpleReference's final base_path as an overlay next to the
|
|
8
|
+
# compiled-set artifact; warm loads re-apply them instead of
|
|
9
|
+
# re-running the {ResolveReferencesModelVisitor}.
|
|
10
|
+
module RefsOverlay
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
def write(set_path, models)
|
|
14
|
+
refs = {}
|
|
15
|
+
ModelTraversal.each_model(models) do |node, key|
|
|
16
|
+
next unless node.is_a?(Model::References::SimpleReference)
|
|
17
|
+
next if node.base_path.nil?
|
|
18
|
+
|
|
19
|
+
refs[key] = node.base_path
|
|
20
|
+
end
|
|
21
|
+
return if refs.empty?
|
|
22
|
+
|
|
23
|
+
require "json"
|
|
24
|
+
File.write("#{set_path}.refs.json", JSON.generate(refs))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Re-binds resolved references from the compiled-set refs
|
|
28
|
+
# sidecar. Returns the sidecar path when it was applied (caller
|
|
29
|
+
# then skips the resolver); nil when absent — caller falls back
|
|
30
|
+
# to resolving.
|
|
31
|
+
def apply_to(set_path, models)
|
|
32
|
+
refs_path = "#{set_path}.refs.json"
|
|
33
|
+
return nil unless File.exist?(refs_path)
|
|
34
|
+
|
|
35
|
+
require "json"
|
|
36
|
+
refs = JSON.parse(File.read(refs_path))
|
|
37
|
+
ModelTraversal.each_model(models) do |node, key|
|
|
38
|
+
next unless node.is_a?(Model::References::SimpleReference)
|
|
39
|
+
|
|
40
|
+
base_path = refs[key]
|
|
41
|
+
node.base_path = base_path unless base_path.nil?
|
|
42
|
+
end
|
|
43
|
+
refs_path
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|