expressir 2.4.29-aarch64-mingw-ucrt
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.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 +690 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest"
|
|
4
|
+
require "json"
|
|
5
|
+
require "parsanol"
|
|
6
|
+
|
|
7
|
+
module Expressir
|
|
8
|
+
module Express
|
|
9
|
+
# Public-facing parser facade.
|
|
10
|
+
#
|
|
11
|
+
# Three concerns were split out (TODO.bugs/09):
|
|
12
|
+
# - Grammar rules → {Grammar::Parser} (~250 Parsanol rules)
|
|
13
|
+
# - Schema-block splitting → {SchemaBlockScanner}
|
|
14
|
+
# - I/O orchestration → this class (from_file, from_exp, etc.)
|
|
15
|
+
#
|
|
16
|
+
# The facade delegates grammar work to Grammar::Parser and block
|
|
17
|
+
# extraction to SchemaBlockScanner. All public methods remain
|
|
18
|
+
# backward-compatible.
|
|
19
|
+
class Parser
|
|
20
|
+
# Threshold for using memory-bounded fresh parse (bytes)
|
|
21
|
+
LARGE_FILE_THRESHOLD = 1024 * 1024 # 1 MB
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
# Delegate grammar-level queries to Grammar::Parser.
|
|
25
|
+
def native_available? = Grammar::Parser.native_available?
|
|
26
|
+
def cached_parser = Grammar::Parser.cached_parser
|
|
27
|
+
def cached_grammar_json = Grammar::Parser.cached_grammar_json
|
|
28
|
+
def cached_schema_grammar_json = Grammar::Parser.cached_schema_grammar_json
|
|
29
|
+
def parse_native(source) = Grammar::Parser.parse_native(source)
|
|
30
|
+
def clear_parser_cache = Grammar::Parser.clear_parser_cache
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# UTF-8 BOM byte sequence (EF BB BF). Some editors prepend this
|
|
34
|
+
# to EXPRESS files; the parser fails because SCHEMA isn't at byte 0.
|
|
35
|
+
def self.strip_bom(source)
|
|
36
|
+
bytes = source.b
|
|
37
|
+
return source unless bytes.bytesize >= 3 &&
|
|
38
|
+
bytes.getbyte(0) == 0xEF &&
|
|
39
|
+
bytes.getbyte(1) == 0xBB &&
|
|
40
|
+
bytes.getbyte(2) == 0xBF
|
|
41
|
+
|
|
42
|
+
bytes.byteslice(3..).force_encoding(source.encoding)
|
|
43
|
+
end
|
|
44
|
+
private_class_method :strip_bom
|
|
45
|
+
|
|
46
|
+
# Parses Express file into an Express model.
|
|
47
|
+
# @param file [String] Express file path
|
|
48
|
+
# @param skip_references [Boolean] skip resolving references
|
|
49
|
+
# @param include_source [Boolean] attach original source code to model elements
|
|
50
|
+
# @param use_native [Boolean] use native parser (default: true when available)
|
|
51
|
+
# @param use_core [Boolean] use the Rust core parse path
|
|
52
|
+
# (default: true when the expressir-core extension is available;
|
|
53
|
+
# produces a byte-identical model to the Ruby path — see
|
|
54
|
+
# parser_core_parity_spec)
|
|
55
|
+
# @return [Model::ExpFile] ExpFile containing parsed schemas
|
|
56
|
+
# @raise [Error::SchemaParseFailure] if the schema file fails to parse
|
|
57
|
+
def self.from_file(file, skip_references: nil, include_source: nil,
|
|
58
|
+
root_path: nil, use_native: nil,
|
|
59
|
+
use_core: nil) # rubocop:disable Metrics/AbcSize
|
|
60
|
+
use_core = Core::NATIVE_AVAILABLE if use_core.nil?
|
|
61
|
+
if use_core && Core::NATIVE_AVAILABLE
|
|
62
|
+
return from_file_core(file, skip_references: skip_references,
|
|
63
|
+
include_source: include_source,
|
|
64
|
+
root_path: root_path)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
Expressir::Benchmark.measure_file(file) do
|
|
68
|
+
source = strip_bom(File.read(file))
|
|
69
|
+
|
|
70
|
+
schema_file = root_path ? Pathname.new(file.to_s).relative_path_from(root_path).to_s : file.to_s
|
|
71
|
+
|
|
72
|
+
use_native = Grammar::Parser.native_available? if use_native.nil?
|
|
73
|
+
|
|
74
|
+
begin
|
|
75
|
+
ast = if use_native && Grammar::Parser.native_available?
|
|
76
|
+
begin
|
|
77
|
+
Grammar::Parser.parse_native(source)
|
|
78
|
+
rescue StandardError
|
|
79
|
+
Grammar::Parser.cached_parser.parse source
|
|
80
|
+
end
|
|
81
|
+
else
|
|
82
|
+
Grammar::Parser.cached_parser.parse source
|
|
83
|
+
end
|
|
84
|
+
rescue Parsanol::ParseFailed => e
|
|
85
|
+
raise Error::SchemaParseFailure.new(schema_file, e)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
exp_file = ::Expressir::Express::Builder.build_with_remarks(ast, source: source,
|
|
89
|
+
include_source: include_source)
|
|
90
|
+
|
|
91
|
+
transfer_header_to_schema(exp_file, source)
|
|
92
|
+
|
|
93
|
+
exp_file.path = schema_file
|
|
94
|
+
exp_file.schemas.each do |schema|
|
|
95
|
+
schema.file = schema_file
|
|
96
|
+
schema.file_basename = File.basename(schema_file, ".exp")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
unless skip_references
|
|
100
|
+
Expressir::Benchmark.measure_references do
|
|
101
|
+
ResolveReferencesModelVisitor.new.visit(exp_file)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
exp_file
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Parses Express files into an Express model.
|
|
110
|
+
# @param files [Array<String>] Express file paths
|
|
111
|
+
# @param skip_references [Boolean] skip resolving references
|
|
112
|
+
# @param include_source [Boolean] attach original source code to model elements
|
|
113
|
+
# @param use_native [Boolean] use native parser (default: true when available)
|
|
114
|
+
# @yield [filename, schemas, error] Optional block called for each file
|
|
115
|
+
# @return [Model::Repository] Repository containing all parsed ExpFiles
|
|
116
|
+
def self.from_files(files, skip_references: nil, include_source: nil,
|
|
117
|
+
root_path: nil, use_native: nil, max_processes: nil,
|
|
118
|
+
compiled_set: nil, &progress)
|
|
119
|
+
set_path = compiled_set || ENV.fetch("EXPRESSIR_COMPILED_SET", nil)
|
|
120
|
+
if set_path && core_set_available?
|
|
121
|
+
repo = from_compiled_set(set_path, files,
|
|
122
|
+
skip_references: skip_references,
|
|
123
|
+
include_source: include_source,
|
|
124
|
+
root_path: root_path)
|
|
125
|
+
return repo if repo
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# EXPRESSIR_BATCH=0 escapes the native batch workers: their
|
|
129
|
+
# Rust threads crash the process under some loads (SIGILL in
|
|
130
|
+
# the mpmc recv park — see GH batch-crash report); sequential
|
|
131
|
+
# parsing is slower but proven stable.
|
|
132
|
+
batch_disabled = ENV["EXPRESSIR_BATCH"] == "0"
|
|
133
|
+
all_exp_files = if batch_available? && !batch_disabled && files.size > 1
|
|
134
|
+
from_files_batch(
|
|
135
|
+
files, include_source: include_source,
|
|
136
|
+
root_path: root_path,
|
|
137
|
+
max_processes: max_processes,
|
|
138
|
+
compiled_set_out: set_path
|
|
139
|
+
) do |file, exp_file, error|
|
|
140
|
+
progress&.call(file, exp_file&.schemas, error)
|
|
141
|
+
end
|
|
142
|
+
elsif ParallelFiles.sequential?(files, max_processes)
|
|
143
|
+
parse_files_sequentially(
|
|
144
|
+
files, skip_references: skip_references, include_source: include_source,
|
|
145
|
+
root_path: root_path, use_native: use_native
|
|
146
|
+
) do |file, exp_file, error|
|
|
147
|
+
progress&.call(file, exp_file&.schemas, error)
|
|
148
|
+
end
|
|
149
|
+
else
|
|
150
|
+
ParallelFiles.run(
|
|
151
|
+
files,
|
|
152
|
+
max_processes: max_processes,
|
|
153
|
+
parse: lambda do |file|
|
|
154
|
+
from_file(file, skip_references: true, root_path: root_path,
|
|
155
|
+
use_native: use_native)
|
|
156
|
+
end,
|
|
157
|
+
) do |file, exp_file, error|
|
|
158
|
+
progress&.call(file, exp_file&.schemas, error)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
repository = build_repository(all_exp_files, skip_references: skip_references)
|
|
163
|
+
if set_path && !skip_references && !File.exist?(set_path) &&
|
|
164
|
+
!all_exp_files.include?(nil)
|
|
165
|
+
if core_set_available?
|
|
166
|
+
write_compiled_set(set_path, files, all_exp_files, root_path)
|
|
167
|
+
else
|
|
168
|
+
warn "expressir: compiled-set write to #{set_path} skipped: " \
|
|
169
|
+
"the expressir-core native extension is unavailable"
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
if set_path && !skip_references && File.exist?(set_path)
|
|
173
|
+
files = all_exp_files.compact
|
|
174
|
+
RefsOverlay.write(set_path, files)
|
|
175
|
+
graph = Model::Indexes::ItemGraph.new(repository)
|
|
176
|
+
repository.item_graph = graph
|
|
177
|
+
require "json"
|
|
178
|
+
File.write("#{set_path}.graph.json", JSON.generate(graph.tables))
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
repository
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Core path: the Rust extension parses and emits the model hash
|
|
185
|
+
# directly (lutaml wire shape); Ruby hydrates, then remark
|
|
186
|
+
# attachment runs on the source as usual.
|
|
187
|
+
def self.from_file_core(file, skip_references: nil,
|
|
188
|
+
include_source: nil, root_path: nil, &block)
|
|
189
|
+
unless Core::NATIVE_AVAILABLE
|
|
190
|
+
raise Error::StreamingUnsupportedError,
|
|
191
|
+
"core parse requires the native extension"
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
Expressir::Benchmark.measure_file(file) do
|
|
195
|
+
source = strip_bom(File.read(file))
|
|
196
|
+
schema_file = root_path ? Pathname.new(file.to_s).relative_path_from(root_path).to_s : file.to_s
|
|
197
|
+
|
|
198
|
+
exp_file =
|
|
199
|
+
begin
|
|
200
|
+
Core.parse_to_model(source, schema_file).tap(&:wire_parents)
|
|
201
|
+
rescue NotImplementedError
|
|
202
|
+
begin
|
|
203
|
+
Model::ExpFile.from_hash(
|
|
204
|
+
Core.parse_to_model_hash(source, schema_file),
|
|
205
|
+
)&.tap(&:wire_parents)
|
|
206
|
+
rescue StandardError => e
|
|
207
|
+
raise Error::SchemaParseFailure.new(schema_file, e)
|
|
208
|
+
end
|
|
209
|
+
rescue StandardError => e
|
|
210
|
+
raise Error::SchemaParseFailure.new(schema_file, e)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
finalize_loaded_file(exp_file, source, schema_file,
|
|
214
|
+
include_source: include_source)
|
|
215
|
+
|
|
216
|
+
unless skip_references
|
|
217
|
+
Expressir::Benchmark.measure_references do
|
|
218
|
+
ResolveReferencesModelVisitor.new.visit(exp_file)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
exp_file
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
private_class_method :from_file_core
|
|
226
|
+
|
|
227
|
+
# Shared post-parse steps for every core-path file: remark
|
|
228
|
+
# attachment, header-remark transfer, and path wiring.
|
|
229
|
+
def self.finalize_loaded_file(exp_file, source, schema_file,
|
|
230
|
+
include_source: nil)
|
|
231
|
+
RemarkAttacher.new(source).attach(exp_file) if source && include_source != false
|
|
232
|
+
|
|
233
|
+
transfer_header_to_schema(exp_file, source)
|
|
234
|
+
|
|
235
|
+
exp_file.path = schema_file
|
|
236
|
+
exp_file.schemas.each do |schema|
|
|
237
|
+
schema.file = schema_file
|
|
238
|
+
schema.file_basename = File.basename(schema_file, ".exp")
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
private_class_method :finalize_loaded_file
|
|
242
|
+
|
|
243
|
+
# Whether the native batch compiler is usable: the extension is
|
|
244
|
+
# loaded and exposes BatchStream.
|
|
245
|
+
def self.batch_available?
|
|
246
|
+
Core::NATIVE_AVAILABLE &&
|
|
247
|
+
::Expressir::Core.const_defined?(:BatchStream, false)
|
|
248
|
+
end
|
|
249
|
+
private_class_method :batch_available?
|
|
250
|
+
|
|
251
|
+
# Whether the compiled-set artifact APIs are exposed.
|
|
252
|
+
def self.core_set_available?
|
|
253
|
+
Core::NATIVE_AVAILABLE && ::Expressir::Core.const_defined?(:Set, false)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Concurrent core-path parse: workers compile in the background
|
|
257
|
+
# while this thread hydrates, attaches remarks, and reports
|
|
258
|
+
# progress per file. Results keep the input order; a file that
|
|
259
|
+
# fails to parse is nil-padded exactly like the other paths.
|
|
260
|
+
def self.from_files_batch(files, include_source: nil, root_path: nil,
|
|
261
|
+
max_processes: nil, compiled_set_out: nil,
|
|
262
|
+
&progress)
|
|
263
|
+
schema_file_for = lambda do |file|
|
|
264
|
+
root_path ? Pathname.new(file.to_s).relative_path_from(root_path).to_s : file.to_s
|
|
265
|
+
end
|
|
266
|
+
wire_paths = files.map { |f| schema_file_for.call(f) }
|
|
267
|
+
physical = wire_paths.zip(files.map(&:to_s)).to_h
|
|
268
|
+
|
|
269
|
+
results = {}
|
|
270
|
+
jobs = files.map { |f| [f.to_s, schema_file_for.call(f)] }
|
|
271
|
+
# Outcomes arrive in completion order; files are finalized and
|
|
272
|
+
# reported in input order (the contract every other path keeps).
|
|
273
|
+
pending = {}
|
|
274
|
+
stream = ::Expressir::Core::BatchStream.start(jobs, max_processes.to_i)
|
|
275
|
+
cursor = 0
|
|
276
|
+
while (item = stream.next)
|
|
277
|
+
wire_path, model, error = item
|
|
278
|
+
if error
|
|
279
|
+
# Unreadable sources raise like every other path; parse
|
|
280
|
+
# failures nil-pad and report.
|
|
281
|
+
raise Errno::ENOENT, error if error.start_with?("read ")
|
|
282
|
+
|
|
283
|
+
pending[wire_path] = [nil, error]
|
|
284
|
+
else
|
|
285
|
+
pending[wire_path] = [model, nil]
|
|
286
|
+
end
|
|
287
|
+
while (entry = pending[wire_paths[cursor]])
|
|
288
|
+
pending.delete(wire_paths[cursor])
|
|
289
|
+
ordered_path = wire_paths[cursor]
|
|
290
|
+
file = physical[ordered_path]
|
|
291
|
+
loaded, load_error = entry
|
|
292
|
+
if loaded
|
|
293
|
+
source = strip_bom(File.read(file))
|
|
294
|
+
loaded.wire_parents
|
|
295
|
+
finalize_loaded_file(loaded, source, ordered_path,
|
|
296
|
+
include_source: include_source)
|
|
297
|
+
results[ordered_path] = loaded
|
|
298
|
+
yield(file, loaded, nil)
|
|
299
|
+
else
|
|
300
|
+
results[ordered_path] = nil
|
|
301
|
+
yield(file, nil,
|
|
302
|
+
Error::SchemaParseFailure.new(ordered_path,
|
|
303
|
+
RuntimeError.new(load_error)))
|
|
304
|
+
end
|
|
305
|
+
cursor += 1
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
if compiled_set_out && !results.value?(nil)
|
|
310
|
+
stream.write_set(compiled_set_out, physical,
|
|
311
|
+
Expressir::Version::VERSION)
|
|
312
|
+
RemarkOverlay.write(compiled_set_out, results.values.compact)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
wire_paths.map { |wire_path| results[wire_path] }
|
|
316
|
+
end
|
|
317
|
+
private_class_method :from_files_batch
|
|
318
|
+
|
|
319
|
+
# Warm start from a compiled-set artifact. Returns nil (caller
|
|
320
|
+
# falls back to compiling) when the artifact is unreadable or no
|
|
321
|
+
# longer matches the sources. Remarks are re-attached from the
|
|
322
|
+
# source files and references are resolved as usual — everything
|
|
323
|
+
# not carried by the wire is deterministic and cheap to rebuild.
|
|
324
|
+
def self.from_compiled_set(path, files, skip_references: nil,
|
|
325
|
+
include_source: nil, root_path: nil, &progress)
|
|
326
|
+
schema_file_for = lambda do |file|
|
|
327
|
+
root_path ? Pathname.new(file.to_s).relative_path_from(root_path).to_s : file.to_s
|
|
328
|
+
end
|
|
329
|
+
physical = files.to_h { |f| [schema_file_for.call(f), f.to_s] }
|
|
330
|
+
|
|
331
|
+
set = begin
|
|
332
|
+
::Expressir::Core::Set.open(path)
|
|
333
|
+
rescue StandardError
|
|
334
|
+
nil
|
|
335
|
+
end
|
|
336
|
+
return nil if set.nil?
|
|
337
|
+
return nil unless set.matches_sources(physical) == true
|
|
338
|
+
|
|
339
|
+
models = []
|
|
340
|
+
while (pair = set.next)
|
|
341
|
+
wire_path, model = pair
|
|
342
|
+
file = physical[wire_path]
|
|
343
|
+
# The artifact wire is pre-remark; the overlay carries them
|
|
344
|
+
# (plus header remarks and remark-derived structures), so the
|
|
345
|
+
# RemarkAttacher never runs on a warm load.
|
|
346
|
+
model.wire_parents
|
|
347
|
+
finalize_loaded_file(model, nil, wire_path,
|
|
348
|
+
include_source: include_source)
|
|
349
|
+
models << model
|
|
350
|
+
progress&.call(file || wire_path, model.schemas, nil)
|
|
351
|
+
end
|
|
352
|
+
RemarkOverlay.apply(path, models)
|
|
353
|
+
|
|
354
|
+
repository = build_repository(models, skip_references: true)
|
|
355
|
+
graph_path = "#{path}.graph.json"
|
|
356
|
+
if File.exist?(graph_path)
|
|
357
|
+
require "json"
|
|
358
|
+
repository.item_graph =
|
|
359
|
+
Model::Indexes::ItemGraph.from_tables(JSON.parse(File.read(graph_path)))
|
|
360
|
+
end
|
|
361
|
+
if skip_references || RefsOverlay.apply_to(path, models)
|
|
362
|
+
# Either explicitly skipping resolution or the compiled-set
|
|
363
|
+
# refs sidecar already re-bound the references.
|
|
364
|
+
else
|
|
365
|
+
Expressir::Benchmark.measure_references do
|
|
366
|
+
ResolveReferencesModelVisitor.new.visit(repository)
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
repository
|
|
370
|
+
end
|
|
371
|
+
private_class_method :from_compiled_set
|
|
372
|
+
|
|
373
|
+
def self.parse_files_sequentially(files, skip_references: nil,
|
|
374
|
+
include_source: nil, root_path: nil, use_native: nil, &block)
|
|
375
|
+
all_exp_files = []
|
|
376
|
+
|
|
377
|
+
files.each do |file|
|
|
378
|
+
exp_file = from_file(file, skip_references: true,
|
|
379
|
+
root_path: root_path, use_native: use_native)
|
|
380
|
+
all_exp_files << exp_file
|
|
381
|
+
|
|
382
|
+
yield(file, exp_file, nil) if block
|
|
383
|
+
rescue StandardError => e
|
|
384
|
+
# Nil-pad so results align with files by index, exactly like the
|
|
385
|
+
# parallel path does.
|
|
386
|
+
all_exp_files << nil if e.is_a?(Error::SchemaParseFailure)
|
|
387
|
+
yield(file, nil, e) if block
|
|
388
|
+
raise unless e.is_a?(Error::SchemaParseFailure)
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
all_exp_files
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
# Artifact write for the non-batch paths (single file,
|
|
395
|
+
# EXPRESSIR_BATCH=0, small sequential sets): serializes the
|
|
396
|
+
# parsed models through Core.write_set, producing the same
|
|
397
|
+
# artifact shape the batch path writes natively. The wire is
|
|
398
|
+
# pre-remark — RemarkOverlay.write carries the remark-derived
|
|
399
|
+
# attributes, exactly as it does for the batch path.
|
|
400
|
+
def self.write_compiled_set(set_path, files, exp_files, root_path)
|
|
401
|
+
require "digest"
|
|
402
|
+
require "json"
|
|
403
|
+
schema_file_for = lambda do |file|
|
|
404
|
+
root_path ? Pathname.new(file.to_s).relative_path_from(root_path).to_s : file.to_s
|
|
405
|
+
end
|
|
406
|
+
entries = files.zip(exp_files).map do |file, exp_file|
|
|
407
|
+
[schema_file_for.call(file),
|
|
408
|
+
Digest::SHA256.file(file.to_s).hexdigest,
|
|
409
|
+
JSON.generate(strip_remark_wire(exp_file.to_hash))]
|
|
410
|
+
end
|
|
411
|
+
::Expressir::Core.write_set(set_path, entries, Expressir::Version::VERSION)
|
|
412
|
+
RemarkOverlay.write(set_path, exp_files)
|
|
413
|
+
end
|
|
414
|
+
private_class_method :write_compiled_set
|
|
415
|
+
|
|
416
|
+
# Deep copy of a serialized model without the RemarkOverlay
|
|
417
|
+
# attributes: the artifact wire carries only the parsed model;
|
|
418
|
+
# untagged remarks are plain hashes that the Rust hydrator
|
|
419
|
+
# cannot instantiate, and every remark-derived value belongs to
|
|
420
|
+
# the overlay anyway.
|
|
421
|
+
def self.strip_remark_wire(node)
|
|
422
|
+
case node
|
|
423
|
+
when Hash
|
|
424
|
+
node.each_with_object({}) do |(key, value), out|
|
|
425
|
+
out[key] = strip_remark_wire(value) unless RemarkOverlay::CAPTURED.include?(key)
|
|
426
|
+
end
|
|
427
|
+
when Array
|
|
428
|
+
node.map { |value| strip_remark_wire(value) }
|
|
429
|
+
else
|
|
430
|
+
node
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
private_class_method :strip_remark_wire
|
|
434
|
+
|
|
435
|
+
def self.build_repository(all_exp_files, skip_references: nil)
|
|
436
|
+
repository = Model::Repository.new(files: all_exp_files)
|
|
437
|
+
|
|
438
|
+
unless skip_references
|
|
439
|
+
Expressir::Benchmark.measure_references do
|
|
440
|
+
ResolveReferencesModelVisitor.new.visit(repository)
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
repository
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
# Parses Express content string into an Express model.
|
|
448
|
+
# @param content [String] EXPRESS source code
|
|
449
|
+
# @param skip_references [Boolean] skip resolving references
|
|
450
|
+
# @param include_source [Boolean] attach original source code to model elements
|
|
451
|
+
# @param use_native [Boolean] use native parser (default: true when available)
|
|
452
|
+
# @param use_streaming [Boolean] unsupported on current parsanol;
|
|
453
|
+
# passing true raises {Error::StreamingUnsupportedError}. The
|
|
454
|
+
# streaming paths return when parsanol exposes a stable
|
|
455
|
+
# parse_with_builder (see parsanol-ruby#52 and the TODO.max-perf/02
|
|
456
|
+
# notes).
|
|
457
|
+
# @return [Model::ExpFile] Parsed ExpFile
|
|
458
|
+
# @raise [Error::SchemaParseFailure] if the content fails to parse
|
|
459
|
+
def self.from_exp(content, skip_references: nil, include_source: nil,
|
|
460
|
+
use_native: nil, use_streaming: false)
|
|
461
|
+
content = strip_bom(content)
|
|
462
|
+
if use_streaming
|
|
463
|
+
raise Error::StreamingUnsupportedError
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
use_native = Grammar::Parser.native_available? if use_native.nil?
|
|
467
|
+
|
|
468
|
+
begin
|
|
469
|
+
ast = if use_native && Grammar::Parser.native_available?
|
|
470
|
+
Grammar::Parser.parse_native(content)
|
|
471
|
+
else
|
|
472
|
+
Grammar::Parser.cached_parser.parse(content)
|
|
473
|
+
end
|
|
474
|
+
rescue Parsanol::ParseFailed, StandardError => e
|
|
475
|
+
raise Error::SchemaParseFailure.new("(from string)", e)
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
exp_file = ::Expressir::Express::Builder.build_with_remarks(ast,
|
|
479
|
+
source: content,
|
|
480
|
+
include_source: include_source)
|
|
481
|
+
|
|
482
|
+
transfer_header_to_schema(exp_file, content)
|
|
483
|
+
|
|
484
|
+
exp_file.schemas.each do |schema|
|
|
485
|
+
schema.file = nil
|
|
486
|
+
schema.file_basename = nil
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
unless skip_references
|
|
490
|
+
Expressir::Benchmark.measure_references do
|
|
491
|
+
ResolveReferencesModelVisitor.new.visit(exp_file)
|
|
492
|
+
end
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
exp_file
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
# Transfer file-level untagged remarks that appear before the first
|
|
499
|
+
# SCHEMA keyword to the first schema's +header+ attribute so they are
|
|
500
|
+
# accessible via +schema.header+ and through Liquid drops.
|
|
501
|
+
def self.transfer_header_to_schema(exp_file, source = nil)
|
|
502
|
+
return unless exp_file.untagged_remarks&.any?
|
|
503
|
+
return unless exp_file.schemas&.any?
|
|
504
|
+
return unless source
|
|
505
|
+
|
|
506
|
+
schema_pos = source.b.index(/\bSCHEMA\b/)
|
|
507
|
+
return unless schema_pos
|
|
508
|
+
|
|
509
|
+
header_remarks = exp_file.untagged_remarks.select do |r|
|
|
510
|
+
r.source_offset && r.source_offset < schema_pos
|
|
511
|
+
end
|
|
512
|
+
return unless header_remarks.any?
|
|
513
|
+
|
|
514
|
+
header_text = header_remarks.map(&:text).join("\n")
|
|
515
|
+
exp_file.schemas.first.header = header_text
|
|
516
|
+
exp_file.untagged_remarks -= header_remarks
|
|
517
|
+
end
|
|
518
|
+
private_class_method :transfer_header_to_schema
|
|
519
|
+
private_class_method :parse_files_sequentially
|
|
520
|
+
private_class_method :build_repository
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
end
|