hecks 3.13.0 → 4.0.0
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/examples/pizzas/adapters/fake_processor.rb +34 -0
- data/examples/pizzas/adapters/payment_signature.rb +66 -0
- data/examples/pizzas/adapters/payment_webhook.rb +87 -0
- data/examples/pizzas/bluebook/pizzas.behaviors +33 -0
- data/examples/pizzas/bluebook/pizzas.bluebook +4 -4
- data/examples/pizzas/bluebook/pizzas.hecksagon +5 -3
- data/examples/pizzas/config.ru +22 -0
- data/lib/hecks/adapters/driven/prism.rb +0 -2
- data/lib/hecks/adapters/driven.rb +0 -2
- data/lib/hecks/adapters/driving/json.rb +1 -7
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +15 -5
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -2
- data/lib/hecks/bluebook/dsl/derivation_words.rb +58 -0
- data/lib/hecks/bluebook/dsl/translation_builder.rb +6 -37
- data/lib/hecks/bluebook/expression/ast_json.rb +0 -9
- data/lib/hecks/bluebook/hecksagon.rb +1 -1
- data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +7 -10
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +4 -8
- data/lib/hecks/bluebook/meta_validator.rb +0 -11
- data/lib/hecks/bluebook/named_pattern.rb +33 -0
- data/lib/hecks/bluebook/translation.rb +18 -10
- data/lib/hecks/bluebook/translation_expression/evaluator.rb +63 -0
- data/lib/hecks/bluebook/translation_expression/parser.rb +127 -0
- data/lib/hecks/bluebook/translation_expression.rb +39 -0
- data/lib/hecks/bluebook/translation_plan.rb +70 -0
- data/lib/hecks/bluebook.rb +3 -0
- data/lib/hecks/chapters.rb +3 -3
- data/lib/hecks/cli/domain_stub.rb +1 -1
- data/lib/hecks/cli/interview_aggregate.rb +4 -4
- data/lib/hecks/composer/adapters/claude_composer.adapter +3 -0
- data/lib/hecks/composer/adapters/claude_composer.rb +83 -0
- data/lib/hecks/composer/adapters/fake_agent.adapter +3 -0
- data/lib/hecks/composer/adapters/fake_agent.rb +55 -0
- data/lib/hecks/composer/adapters/jev.adapter +3 -0
- data/lib/hecks/composer/adapters/jev.rb +66 -0
- data/lib/hecks/composer/agent.rb +113 -0
- data/lib/hecks/composer/assistant.rb +110 -0
- data/lib/hecks/composer/behavior_run.rb +53 -0
- data/lib/hecks/composer/bluebook/composer.bluebook +178 -0
- data/lib/hecks/composer/bluebook/composer.hecksagon +16 -0
- data/lib/hecks/composer/board.rb +65 -0
- data/lib/hecks/composer/board_edit/command_text.rb +39 -0
- data/lib/hecks/composer/board_edit/source.rb +84 -0
- data/lib/hecks/composer/board_edit.rb +144 -0
- data/lib/hecks/composer/check.rb +89 -0
- data/lib/hecks/composer/domains.rb +81 -0
- data/lib/hecks/composer/jobs.rb +134 -0
- data/lib/hecks/composer/layout.rb +37 -0
- data/lib/hecks/composer/live.rb +150 -0
- data/lib/hecks/composer/outline.rb +48 -0
- data/lib/hecks/composer/page.html +989 -0
- data/lib/hecks/composer/panels.rb +142 -0
- data/lib/hecks/composer/parse.rb +83 -0
- data/lib/hecks/composer/plain.rb +28 -0
- data/lib/hecks/composer/ports/composer_agent.port +7 -0
- data/lib/hecks/composer/session.rb +141 -0
- data/lib/hecks/composer/toolbox.rb +166 -0
- data/lib/hecks/composer/web.rb +156 -0
- data/lib/hecks/composer/workbench.rb +51 -0
- data/lib/hecks/composer/workspace.rb +81 -0
- data/lib/hecks/composer.rb +17 -0
- data/lib/hecks/corpus/adapters.rb +22 -0
- data/lib/hecks/corpus/rust.rb +1 -1
- data/lib/hecks/corpus/worlds.rb +19 -0
- data/lib/hecks/corpus.rb +5 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +34 -34
- data/lib/hecks/forms/app/commands.rb +2 -3
- data/lib/hecks/forms/app/queries.rb +2 -3
- data/lib/hecks/forms/app/records.rb +17 -5
- data/lib/hecks/forms/command_form_renderer.rb +42 -16
- data/lib/hecks/forms/field_controls.rb +2 -2
- data/lib/hecks/forms/field_renderer.rb +1 -1
- data/lib/hecks/forms/field_shape.rb +36 -17
- data/lib/hecks/forms/index_renderer.rb +2 -1
- data/lib/hecks/forms/page.rb +1 -1
- data/lib/hecks/forms/params.rb +0 -13
- data/lib/hecks/forms/query_form_renderer.rb +7 -6
- data/lib/hecks/forms/record_renderer.rb +11 -7
- data/lib/hecks/forms/rule_words.rb +100 -0
- data/lib/hecks/forms/value_object_shape.rb +2 -1
- data/lib/hecks/framework/bluebook/change.bluebook +2 -2
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -3
- data/lib/hecks/fuzzing/domain_generator/block_rendering.rb +1 -1
- data/lib/hecks/fuzzing/isolated_boot/worlds.rb +3 -6
- data/lib/hecks/fuzzing/replay/filters.rb +2 -6
- data/lib/hecks/gate/stages.yml +25 -0
- data/lib/hecks/grammar/evolve/seeds.rb +0 -6
- data/lib/hecks/grammar/evolve.rb +0 -3
- data/lib/hecks/grammar/translation.bluebook +1 -1
- data/lib/hecks/hecks/adapters/codebase/composing.rb +56 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +3 -1
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +0 -26
- data/lib/hecks/hecks/adapters/journal_store/examination.rb +2 -23
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +3 -11
- data/lib/hecks/hecks/adapters/journal_store.rb +0 -11
- data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +4 -11
- data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +0 -9
- data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +0 -4
- data/lib/hecks/hecks/codebase.behaviors +6 -0
- data/lib/hecks/hecks/codebase.bluebook +58 -37
- data/lib/hecks/hecks/composer.behaviors +68 -0
- data/lib/hecks/hecks/context_map.hecksagon +1 -1
- data/lib/hecks/hecks/custodian.behaviors +0 -6
- data/lib/hecks/hecks/custodian.bluebook +15 -92
- data/lib/hecks/hecks/hecks.bluebook +2 -2
- data/lib/hecks/hecks/hecks.hecksagon +2 -2
- data/lib/hecks/hecks/hecks.world +1 -1
- data/lib/hecks/hecks/rehearsal.bluebook +10 -16
- data/lib/hecks/hecks/tooling.bluebook +22 -22
- data/lib/hecks/kernel_capabilities/templates.rb +4 -4
- data/lib/hecks/kernel_capabilities.rb +1 -1
- data/lib/hecks/language/bluebook/aggregate.bluebook +1 -0
- data/lib/hecks/language/bluebook/command.bluebook +1 -0
- data/lib/hecks/language/bluebook/entity.bluebook +1 -0
- data/lib/hecks/language/bluebook/query.bluebook +1 -0
- data/lib/hecks/language/bluebook/shape.bluebook +8 -7
- data/lib/hecks/language/bluebook/vocabulary.bluebook +2 -3
- data/lib/hecks/language/hecksagon/port_operation.bluebook +1 -0
- data/lib/hecks/language/translation/translation_aggregate.bluebook +21 -24
- data/lib/hecks/ports/access_control.rb +2 -2
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +3 -41
- data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +7 -7
- data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +25 -2
- data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +4 -4
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +17 -25
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +0 -12
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +2 -22
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +0 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +9 -3
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +3 -29
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +2 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +6 -33
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -3
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +2 -4
- data/lib/hecks/ports/persistence/plugins/era/translation/expression_sql.rb +52 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +23 -29
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +0 -1
- data/lib/hecks/ports/persistence/plugins/era.rb +3 -6
- data/lib/hecks/ports.rb +0 -1
- data/lib/hecks/projection_files.rb +3 -1
- data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +1 -1
- data/lib/hecks/projections/glossary/entries.rb +10 -4
- data/lib/hecks/projections/glossary/groups.rb +42 -0
- data/lib/hecks/projections/glossary/html/page.rb +7 -2
- data/lib/hecks/projections/glossary/html/parser.rb +1 -1
- data/lib/hecks/projections/glossary/html/sections.rb +31 -11
- data/lib/hecks/projections/glossary/html.rb +1 -2
- data/lib/hecks/projections/glossary/markdown.rb +31 -28
- data/lib/hecks/projections/glossary/mermaid.rb +3 -0
- data/lib/hecks/projections/glossary/page.css +143 -153
- data/lib/hecks/projections/glossary/page.js +63 -3
- data/lib/hecks/projections/glossary/sentences/actions.rb +88 -0
- data/lib/hecks/projections/glossary/sentences/paths.rb +77 -0
- data/lib/hecks/projections/glossary/sentences/queries.rb +90 -0
- data/lib/hecks/projections/glossary/sentences/value_objects.rb +32 -5
- data/lib/hecks/projections/glossary/sentences.rb +13 -3
- data/lib/hecks/projections/glossary/slugs.rb +4 -1
- data/lib/hecks/projections/glossary.rb +2 -1
- data/lib/hecks/projections/plain_english.rb +97 -0
- data/lib/hecks/projections/rust_vocabulary/arguments.rb +2 -2
- data/lib/hecks/projections/rust_vocabulary/enum_body.rb +20 -25
- data/lib/hecks/projections/rust_vocabulary/tests.rb +2 -2
- data/lib/hecks/projections/rust_vocabulary.rb +14 -6
- data/lib/hecks/projections/site/cms_editor/color.rb +0 -6
- data/lib/hecks/projections/statements/actions.rb +99 -0
- data/lib/hecks/projections/statements/relationships.rb +86 -0
- data/lib/hecks/projections/statements.rb +15 -24
- data/lib/hecks/projector/exporter/adapters.rb +112 -0
- data/lib/hecks/projector/exporter/translations.rb +18 -35
- data/lib/hecks/projector/exporter/worlds.rb +103 -0
- data/lib/hecks/projector/exporter.rb +5 -1
- data/lib/hecks/quality_control/adapters/agent.rb +6 -7
- data/lib/hecks/quality_control/adapters/agent_profile.rb +16 -114
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +1 -1
- data/lib/hecks/quality_control/quality_control.bluebook +51 -51
- data/lib/hecks/runtime/loader/boot_steps.rb +0 -20
- data/lib/hecks/runtime/outbox.rb +2 -9
- data/lib/hecks/runtime/port_operation_interpreter.rb +1 -9
- data/lib/hecks/runtime/remote_dispatcher.rb +2 -2
- data/lib/hecks/runtime/value.rb +13 -0
- data/lib/hecks/rust_build/project_rust/target_ir.rb +23 -4
- data/lib/hecks/rust_build/wasm.rb +0 -12
- data/lib/hecks/rust_build/write_if_changed.rb +12 -12
- data/lib/hecks/rust_format.rb +77 -0
- data/lib/hecks/site/bluebook/site.bluebook +5 -5
- data/lib/hecks/sme/bluebook/sme.bluebook +12 -12
- data/lib/hecks/tickets/bluebook/tickets.bluebook +3 -3
- data/lib/hecks/tools/fuzz_sweep/findings.rb +3 -9
- data/lib/hecks/tools/fuzz_sweep.rb +1 -3
- data/lib/hecks/tools/translation_audit/verdicts.rb +3 -28
- data/lib/hecks/tools/translation_audit.rb +8 -10
- data/lib/hecks/tools/translation_scaffold/reporting.rb +1 -1
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks/vocabulary.rb +2 -1
- data/lib/hecks.rb +3 -0
- data/prebuilt/{58208399bada10b0db99928c48e38789288fc58f7b71a72b21bfa386680e32ed.marshal → 02c09c73b272c1fb5a9ae6d87bb5e5e529208e00f6b4b597dc2c0fd70a9c0964.marshal} +0 -0
- data/prebuilt/{2b59737fbdbd5f44edda0fddce2611f45d76087b3a7c782d1f1a17ea58c77948.marshal → bb84a835cf6a15136bad5ca03aa5bf93a5b92f5f72444618d3ef2412b987fb32.marshal} +0 -0
- data/prebuilt/verdicts-f1f10da14c8e8f01b4c9b7e3e2d74be8cd2bf4676364ed17fa16975d2a076d75.json +1 -0
- data/rust/Cargo.toml +40 -0
- data/rust/build/Cargo.toml +36 -0
- data/rust/build/clippy.toml +4 -0
- data/rust/build/src/adapters_pass.rs +196 -0
- data/rust/build/src/binding_pass.rs +54 -13
- data/rust/build/src/build_artifact.rs +23 -5
- data/rust/build/src/cargo_sync.rs +69 -26
- data/rust/build/src/lineage_pass.rs +101 -87
- data/rust/build/src/main.rs +11 -2
- data/rust/build/src/pipeline.rs +80 -19
- data/rust/build/src/reserved_names.rs +6 -50
- data/rust/build/src/resolve.rs +82 -35
- data/rust/build/src/rustfmt.rs +100 -0
- data/rust/build/src/seams_pass.rs +85 -16
- data/rust/build/src/subprocess.rs +30 -6
- data/rust/build/src/tmp.rs +5 -2
- data/rust/build/src/translation_pass.rs +72 -22
- data/rust/build/src/world_pass.rs +109 -0
- data/rust/clippy.toml +4 -0
- data/rust/codegen/Cargo.toml +36 -0
- data/rust/codegen/clippy.toml +4 -0
- data/rust/codegen/src/asks.rs +40 -14
- data/rust/codegen/src/attr.rs +2 -2
- data/rust/codegen/src/bridging.rs +676 -117
- data/rust/codegen/src/commands.rs +979 -373
- data/rust/codegen/src/constraints.rs +88 -25
- data/rust/codegen/src/dependency_planning.rs +128 -34
- data/rust/codegen/src/domain_generator.rs +300 -170
- data/rust/codegen/src/exemplar.rs +87 -32
- data/rust/codegen/src/expr_emitter.rs +54 -6
- data/rust/codegen/src/fielded.rs +193 -41
- data/rust/codegen/src/hecks_naming.rs +124 -16
- data/rust/codegen/src/hecks_naming_tests.rs +81 -0
- data/rust/codegen/src/json.rs +80 -44
- data/rust/codegen/src/json_codec.rs +585 -149
- data/rust/codegen/src/literal.rs +104 -138
- data/rust/codegen/src/main.rs +145 -52
- data/rust/codegen/src/manifest.rs +76 -14
- data/rust/codegen/src/mutations.rs +1212 -239
- data/rust/codegen/src/naming.rs +111 -60
- data/rust/codegen/src/optional_pass.rs +90 -28
- data/rust/codegen/src/ports.rs +5 -4
- data/rust/codegen/src/prelude.rs +139 -49
- data/rust/codegen/src/queries.rs +601 -226
- data/rust/codegen/src/reactions.rs +268 -74
- data/rust/codegen/src/read_models.rs +606 -205
- data/rust/codegen/src/reference_specs.rs +16 -3
- data/rust/codegen/src/registry.rs +128 -79
- data/rust/codegen/src/reserved_names.rs +6 -50
- data/rust/codegen/src/shared.rs +71 -22
- data/rust/codegen/src/sidecars.rs +15 -5
- data/rust/codegen/src/skip_reason.rs +8 -2
- data/rust/codegen/src/types.rs +306 -108
- data/rust/host/Cargo.lock +1 -0
- data/rust/host/Cargo.toml +40 -4
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/clippy.toml +4 -0
- data/rust/host/src/api.rs +698 -218
- data/rust/host/src/auth.rs +491 -214
- data/rust/host/src/b64.rs +91 -0
- data/rust/host/src/bin/expr_harness.rs +6 -2
- data/rust/host/src/bin/lineage_harness.rs +47 -11
- data/rust/host/src/bin/mint_harness.rs +70 -37
- data/rust/host/src/bin/validate_harness.rs +16 -8
- data/rust/host/src/boot.rs +144 -68
- data/rust/host/src/boundary_fuzz/api.rs +130 -32
- data/rust/host/src/boundary_fuzz/auth.rs +108 -23
- data/rust/host/src/boundary_fuzz/expr_json.rs +85 -11
- data/rust/host/src/boundary_fuzz/ir.rs +164 -12
- data/rust/host/src/boundary_fuzz/server.rs +283 -36
- data/rust/host/src/boundary_fuzz/web.rs +56 -8
- data/rust/host/src/checkout.rs +78 -32
- data/rust/host/src/clock.rs +8 -0
- data/rust/host/src/commerce_ir.rs +333 -95
- data/rust/host/src/crypto.rs +33 -0
- data/rust/host/src/dispatch.rs +990 -331
- data/rust/host/src/expr_json.rs +1021 -273
- data/rust/host/src/extension.rs +24 -4
- data/rust/host/src/field_hints.rs +11 -7
- data/rust/host/src/fuzz_support.rs +85 -13
- data/rust/host/src/host.rs +100 -0
- data/rust/host/src/http.rs +22 -0
- data/rust/host/src/ir.rs +326 -16
- data/rust/host/src/journal.rs +277 -176
- data/rust/host/src/lambda_client.rs +219 -53
- data/rust/host/src/lib.rs +16 -4
- data/rust/host/src/log.rs +62 -11
- data/rust/host/src/mint.rs +1153 -326
- data/rust/host/src/needs.rs +185 -44
- data/rust/host/src/payments/keystore.rs +197 -45
- data/rust/host/src/payments/roles.rs +191 -0
- data/rust/host/src/payments/tests.rs +1445 -275
- data/rust/host/src/payments.rs +409 -121
- data/rust/host/src/platform_signin/attack_tests.rs +5 -5
- data/rust/host/src/platform_signin/config.rs +11 -11
- data/rust/host/src/platform_signin/cookie.rs +2 -2
- data/rust/host/src/platform_signin/extension.rs +2 -1
- data/rust/host/src/platform_signin/handler.rs +9 -8
- data/rust/host/src/platform_signin/jti.rs +4 -2
- data/rust/host/src/platform_signin/jwks.rs +2 -1
- data/rust/host/src/platform_signin/jws.rs +2 -37
- data/rust/host/src/platform_signin/known_answer_tests.rs +5 -1
- data/rust/host/src/platform_signin/mode_tests.rs +5 -3
- data/rust/host/src/platform_signin/pages.rs +20 -20
- data/rust/host/src/platform_signin/session.rs +8 -1
- data/rust/host/src/platform_signin/settings.rs +6 -6
- data/rust/host/src/platform_signin/strict_json.rs +12 -9
- data/rust/host/src/platform_signin/verify.rs +41 -41
- data/rust/host/src/platform_signin/wiring_support.rs +13 -18
- data/rust/host/src/presentation.rs +207 -63
- data/rust/host/src/presentation_write.rs +502 -187
- data/rust/host/src/query_step.rs +69 -18
- data/rust/host/src/rate_limit.rs +541 -142
- data/rust/host/src/reference_transform.rs +77 -25
- data/rust/host/src/reference_validate.rs +443 -104
- data/rust/host/src/resend.rs +190 -55
- data/rust/host/src/secrets.rs +116 -21
- data/rust/host/src/server.rs +483 -104
- data/rust/host/src/storage_shape.rs +88 -21
- data/rust/host/src/test_pg.rs +17 -7
- data/rust/host/src/ui_schema.rs +495 -207
- data/rust/host/src/wasm_runner.rs +21 -6
- data/rust/host/src/web/commerce.rs +101 -23
- data/rust/host/src/web/newsletter/cooldown.rs +10 -3
- data/rust/host/src/web/newsletter/template.rs +26 -7
- data/rust/host/src/web/newsletter/tests.rs +112 -23
- data/rust/host/src/web/newsletter.rs +209 -59
- data/rust/host/src/web/newsletter_send.rs +251 -79
- data/rust/host/src/web/registration_receipt/tests.rs +16 -4
- data/rust/host/src/web/registration_receipt.rs +100 -24
- data/rust/host/src/web/registrations.rs +1384 -332
- data/rust/host/src/web/resend_webhook.rs +138 -80
- data/rust/host/src/web.rs +2416 -508
- data/rust/lsp/Cargo.toml +36 -0
- data/rust/lsp/clippy.toml +4 -0
- data/rust/lsp/src/json.rs +29 -22
- data/rust/lsp/src/main.rs +81 -31
- data/rust/lsp/src/outline.rs +23 -7
- data/rust/lsp/src/rpc.rs +17 -4
- data/rust/parser/Cargo.toml +36 -0
- data/rust/parser/clippy.toml +4 -0
- data/rust/parser/src/build/closed_sets.rs +6 -1
- data/rust/parser/src/build/identity.rs +4 -3
- data/rust/parser/src/build/mod.rs +1 -0
- data/rust/parser/src/build/named_pattern.rs +26 -0
- data/rust/parser/src/build/naming.rs +2 -80
- data/rust/parser/src/build/pattern_subset.rs +6 -8
- data/rust/parser/src/build/query_derive.rs +3 -1
- data/rust/parser/src/build/query_inference.rs +14 -5
- data/rust/parser/src/build/read_model.rs +4 -1
- data/rust/parser/src/build/references.rs +4 -3
- data/rust/parser/src/canonical.rs +34 -15
- data/rust/parser/src/emit.rs +187 -105
- data/rust/parser/src/expr/ast_json.rs +134 -42
- data/rust/parser/src/expr/evaluator.rs +27 -9
- data/rust/parser/src/expr/mod.rs +54 -13
- data/rust/parser/src/expr/resolver.rs +299 -92
- data/rust/parser/src/ir.rs +35 -3
- data/rust/parser/src/keywords.rs +7168 -510
- data/rust/parser/src/lex.rs +11 -25
- data/rust/parser/src/lib.rs +1 -0
- data/rust/parser/src/main.rs +65 -6
- data/rust/parser/src/parse/adapter.rs +157 -0
- data/rust/parser/src/parse/aggregate.rs +19 -10
- data/rust/parser/src/parse/chapter.rs +16 -17
- data/rust/parser/src/parse/command.rs +35 -16
- data/rust/parser/src/parse/domain_port.rs +4 -7
- data/rust/parser/src/parse/entity.rs +21 -11
- data/rust/parser/src/parse/hecksagon.rs +10 -4
- data/rust/parser/src/parse/lifecycle.rs +9 -5
- data/rust/parser/src/parse/mod.rs +43 -91
- data/rust/parser/src/parse/needs.rs +21 -12
- data/rust/parser/src/parse/policy.rs +2 -2
- data/rust/parser/src/parse/process_manager.rs +9 -11
- data/rust/parser/src/parse/query.rs +8 -4
- data/rust/parser/src/parse/read_model.rs +57 -16
- data/rust/parser/src/parse/value_object.rs +7 -2
- data/rust/parser/src/parse/world.rs +322 -0
- data/rust/parser/src/ruby_value.rs +7 -6
- data/rust/src/exemplar/json.rs +4 -4
- data/rust/src/exemplar/mutations.rs +18 -0
- data/rust/src/exemplar/read_models.rs +1 -10
- data/rust/src/kernel/attribute_shapes/composite.rs +54 -14
- data/rust/src/kernel/attribute_shapes/list.rs +2 -2
- data/rust/src/kernel/attribute_shapes/mod.rs +8 -8
- data/rust/src/kernel/attribute_shapes/scalar.rs +2 -2
- data/rust/src/kernel/cli.rs +229 -112
- data/rust/src/kernel/dispatch.rs +323 -115
- data/rust/src/kernel/dispatch_guard_tests.rs +327 -65
- data/rust/src/kernel/expr.rs +203 -86
- data/rust/src/kernel/expression_operators/arithmetic.rs +138 -25
- data/rust/src/kernel/expression_operators/comparison.rs +87 -2
- data/rust/src/kernel/expression_operators/enumeration.rs +106 -22
- data/rust/src/kernel/expression_operators/logical.rs +9 -3
- data/rust/src/kernel/expression_operators/membership.rs +3 -1
- data/rust/src/kernel/expression_operators/mod.rs +34 -21
- data/rust/src/kernel/expression_operators/pattern_match.rs +46 -11
- data/rust/src/kernel/expression_operators/positional.rs +84 -30
- data/rust/src/kernel/expression_operators/presence.rs +52 -13
- data/rust/src/kernel/expression_operators/sign_test.rs +3 -1
- data/rust/src/kernel/expression_operators/sized.rs +24 -8
- data/rust/src/kernel/expression_operators/text.rs +120 -27
- data/rust/src/kernel/expression_operators/to_string.rs +10 -4
- data/rust/src/kernel/json.rs +230 -148
- data/rust/src/kernel/mod.rs +46 -33
- data/rust/src/kernel/named_query.rs +63 -15
- data/rust/src/kernel/needs.rs +112 -25
- data/rust/src/kernel/orchestrate.rs +980 -581
- data/rust/src/kernel/orchestrate_guard_tests.rs +538 -140
- data/rust/src/kernel/pattern.rs +107 -34
- data/rust/src/kernel/query_comparators.rs +118 -41
- data/rust/src/kernel/query_ordering.rs +13 -5
- data/rust/src/kernel/read_model.rs +479 -181
- data/rust/src/kernel/reference_lookup.rs +122 -26
- data/rust/src/kernel/repository.rs +293 -66
- data/rust/src/kernel/routing.rs +58 -42
- data/rust/src/kernel/ruby_float.rs +139 -0
- data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +57 -57
- data/rust/src/kernel/vocab/entity_dispatch_order.rs +54 -54
- data/rust/src/kernel/vocab/field_hint.rs +19 -25
- data/rust/src/kernel/vocab/mod.rs +6 -6
- data/rust/src/kernel/vocab/query_comparator.rs +23 -24
- data/rust/src/kernel/vocab/refusal_template.rs +501 -297
- data/rust/src/lib.rs +50 -0
- data/rust/src/main.rs +4 -1
- data/rust/web/Cargo.toml +36 -0
- data/rust/web/clippy.toml +4 -0
- metadata +85 -15
- data/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +0 -36
- data/lib/hecks/adapters/driven/google_authentication.adapter +0 -3
- data/lib/hecks/adapters/driven/google_authentication.rb +0 -99
- data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +0 -3
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +0 -32
- data/lib/hecks/ports/authentication.port +0 -6
- data/lib/hecks/ports/authentication.rb +0 -67
- data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +0 -255
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +0 -22
- data/prebuilt/verdicts-48318ca172edd21443b1ad02801c697fff100b746e828f09db987647641a5df2.json +0 -1
- data/rust/host/src/approval.rs +0 -652
|
@@ -11,18 +11,29 @@ use crate::json::Json;
|
|
|
11
11
|
///
|
|
12
12
|
/// An aggregate with no `persisted_by` bind falls back to `world_path`'s own
|
|
13
13
|
/// `default_adapter` for the target chapter, then to `"Memory"`.
|
|
14
|
-
pub fn run(
|
|
14
|
+
pub fn run(
|
|
15
|
+
ir: &mut Json,
|
|
16
|
+
hecksagon_path: Option<&Path>,
|
|
17
|
+
world_path: Option<&Path>,
|
|
18
|
+
root: &Path,
|
|
19
|
+
) -> Result<(), String> {
|
|
15
20
|
let binds = match hecksagon_path {
|
|
16
21
|
Some(path) => {
|
|
17
|
-
let text = std::fs::read_to_string(path)
|
|
22
|
+
let text = std::fs::read_to_string(path)
|
|
23
|
+
.map_err(|e| format!("reading {}: {e}", path.display()))?;
|
|
18
24
|
persistence_binds(&text)
|
|
19
25
|
}
|
|
20
26
|
None => HashMap::new(),
|
|
21
27
|
};
|
|
22
|
-
let chapter_name = ir
|
|
28
|
+
let chapter_name = ir
|
|
29
|
+
.get("name")
|
|
30
|
+
.and_then(Json::as_str)
|
|
31
|
+
.unwrap_or_default()
|
|
32
|
+
.to_string();
|
|
23
33
|
let fallback_adapter = match world_path {
|
|
24
34
|
Some(path) => {
|
|
25
|
-
let text = std::fs::read_to_string(path)
|
|
35
|
+
let text = std::fs::read_to_string(path)
|
|
36
|
+
.map_err(|e| format!("reading {}: {e}", path.display()))?;
|
|
26
37
|
default_adapter_name(&text, &chapter_name)
|
|
27
38
|
}
|
|
28
39
|
None => None,
|
|
@@ -30,29 +41,35 @@ pub fn run(ir: &mut Json, hecksagon_path: Option<&Path>, world_path: Option<&Pat
|
|
|
30
41
|
.unwrap_or_else(|| "Memory".to_string());
|
|
31
42
|
let capable_adapters = lineage_capable_adapter_names(root)?;
|
|
32
43
|
|
|
33
|
-
// Collected
|
|
34
|
-
// `&mut` call
|
|
35
|
-
let
|
|
44
|
+
// Collected before `ir.set` below: Rust can't hold this borrow of `ir`
|
|
45
|
+
// alongside the `&mut` call.
|
|
46
|
+
let capable_aggregates: Vec<Json> = ir
|
|
36
47
|
.get("aggregates")
|
|
37
|
-
.
|
|
38
|
-
.unwrap_or(&[])
|
|
48
|
+
.map_or(&[][..], Json::each)
|
|
39
49
|
.iter()
|
|
40
50
|
.filter_map(|a| a.get("name").and_then(Json::as_str).map(str::to_string))
|
|
41
|
-
.collect();
|
|
42
|
-
|
|
43
|
-
let capable_aggregates: Vec<Json> = aggregate_names
|
|
44
|
-
.into_iter()
|
|
45
51
|
.filter(|name| {
|
|
46
|
-
let adapter_name = binds
|
|
52
|
+
let adapter_name = binds
|
|
53
|
+
.get(name.as_str())
|
|
54
|
+
.map_or(fallback_adapter.as_str(), String::as_str);
|
|
47
55
|
capable_adapters.iter().any(|a| a == adapter_name)
|
|
48
56
|
})
|
|
49
57
|
.map(|name| {
|
|
50
|
-
let storage_name =
|
|
51
|
-
Json::Object(vec![
|
|
58
|
+
let storage_name = crate::hecks_naming::snake(&name);
|
|
59
|
+
Json::Object(vec![
|
|
60
|
+
("name".to_string(), Json::String(name)),
|
|
61
|
+
("storage_name".to_string(), Json::String(storage_name)),
|
|
62
|
+
])
|
|
52
63
|
})
|
|
53
64
|
.collect();
|
|
54
65
|
|
|
55
|
-
ir.set(
|
|
66
|
+
ir.set(
|
|
67
|
+
"lineage",
|
|
68
|
+
Json::Object(vec![(
|
|
69
|
+
"capable_aggregates".to_string(),
|
|
70
|
+
Json::Array(capable_aggregates),
|
|
71
|
+
)]),
|
|
72
|
+
);
|
|
56
73
|
Ok(())
|
|
57
74
|
}
|
|
58
75
|
|
|
@@ -65,18 +82,31 @@ pub(crate) fn persistence_binds(text: &str) -> HashMap<String, String> {
|
|
|
65
82
|
continue;
|
|
66
83
|
}
|
|
67
84
|
|
|
68
|
-
let Some(call_pos) = line.find(".persisted_by(") else {
|
|
85
|
+
let Some(call_pos) = line.find(".persisted_by(") else {
|
|
86
|
+
continue;
|
|
87
|
+
};
|
|
69
88
|
|
|
70
89
|
let before = &line[..call_pos];
|
|
71
|
-
let aggregate_name: String = before
|
|
90
|
+
let aggregate_name: String = before
|
|
91
|
+
.chars()
|
|
92
|
+
.rev()
|
|
93
|
+
.take_while(|c| c.is_alphanumeric() || *c == '_')
|
|
94
|
+
.collect::<String>()
|
|
95
|
+
.chars()
|
|
96
|
+
.rev()
|
|
97
|
+
.collect();
|
|
72
98
|
if aggregate_name.is_empty() {
|
|
73
99
|
continue;
|
|
74
100
|
}
|
|
75
101
|
|
|
76
102
|
let after = &line[call_pos + ".persisted_by(".len()..];
|
|
77
|
-
let Some(open_quote) = after.find('"') else {
|
|
103
|
+
let Some(open_quote) = after.find('"') else {
|
|
104
|
+
continue;
|
|
105
|
+
};
|
|
78
106
|
let rest = &after[open_quote + 1..];
|
|
79
|
-
let Some(close_quote) = rest.find('"') else {
|
|
107
|
+
let Some(close_quote) = rest.find('"') else {
|
|
108
|
+
continue;
|
|
109
|
+
};
|
|
80
110
|
let adapter_name = &rest[..close_quote];
|
|
81
111
|
|
|
82
112
|
binds.insert(aggregate_name, adapter_name.to_string());
|
|
@@ -100,13 +130,19 @@ pub(crate) fn default_adapter_name(text: &str, chapter: &str) -> Option<String>
|
|
|
100
130
|
continue;
|
|
101
131
|
}
|
|
102
132
|
|
|
103
|
-
let Some(rest) = line.trim_start().strip_prefix("default_adapter") else {
|
|
133
|
+
let Some(rest) = line.trim_start().strip_prefix("default_adapter") else {
|
|
134
|
+
continue;
|
|
135
|
+
};
|
|
104
136
|
if !rest.starts_with(char::is_whitespace) {
|
|
105
137
|
continue;
|
|
106
138
|
}
|
|
107
|
-
let Some(open_quote) = rest.find('"') else {
|
|
139
|
+
let Some(open_quote) = rest.find('"') else {
|
|
140
|
+
continue;
|
|
141
|
+
};
|
|
108
142
|
let quoted = &rest[open_quote + 1..];
|
|
109
|
-
let Some(close_quote) = quoted.find('"') else {
|
|
143
|
+
let Some(close_quote) = quoted.find('"') else {
|
|
144
|
+
continue;
|
|
145
|
+
};
|
|
110
146
|
found = Some(quoted[..close_quote].to_string());
|
|
111
147
|
}
|
|
112
148
|
|
|
@@ -121,14 +157,18 @@ fn world_opener_name(line: &str) -> Option<String> {
|
|
|
121
157
|
|
|
122
158
|
// Where an adapter class can live: the driven adapters, and the era plugin that holds `PostgresEra`,
|
|
123
159
|
// the one adapter that declares itself lineage-capable.
|
|
124
|
-
const ADAPTER_DIRS: [&str; 2] = [
|
|
160
|
+
const ADAPTER_DIRS: [&str; 2] = [
|
|
161
|
+
"lib/hecks/adapters/driven",
|
|
162
|
+
"lib/hecks/ports/persistence/plugins/era",
|
|
163
|
+
];
|
|
125
164
|
|
|
126
165
|
// Reads each adapter's own source file rather than invoking Ruby.
|
|
127
166
|
fn lineage_capable_adapter_names(root: &Path) -> Result<Vec<String>, String> {
|
|
128
167
|
let mut names = Vec::new();
|
|
129
168
|
for relative in ADAPTER_DIRS {
|
|
130
169
|
let dir = root.join(relative);
|
|
131
|
-
let entries =
|
|
170
|
+
let entries =
|
|
171
|
+
std::fs::read_dir(&dir).map_err(|e| format!("reading {}: {e}", dir.display()))?;
|
|
132
172
|
|
|
133
173
|
for entry in entries {
|
|
134
174
|
let entry = entry.map_err(|e| format!("reading {}: {e}", dir.display()))?;
|
|
@@ -137,7 +177,8 @@ fn lineage_capable_adapter_names(root: &Path) -> Result<Vec<String>, String> {
|
|
|
137
177
|
continue;
|
|
138
178
|
}
|
|
139
179
|
|
|
140
|
-
let text = std::fs::read_to_string(&path)
|
|
180
|
+
let text = std::fs::read_to_string(&path)
|
|
181
|
+
.map_err(|e| format!("reading {}: {e}", path.display()))?;
|
|
141
182
|
if !declares_lineage_capable_true(&text) {
|
|
142
183
|
continue;
|
|
143
184
|
}
|
|
@@ -171,7 +212,10 @@ fn top_level_class_name(text: &str) -> Option<String> {
|
|
|
171
212
|
for line in text.lines() {
|
|
172
213
|
let trimmed = line.trim_start();
|
|
173
214
|
if let Some(rest) = trimmed.strip_prefix("class ") {
|
|
174
|
-
let name: String = rest
|
|
215
|
+
let name: String = rest
|
|
216
|
+
.chars()
|
|
217
|
+
.take_while(|c| c.is_alphanumeric() || *c == '_')
|
|
218
|
+
.collect();
|
|
175
219
|
if !name.is_empty() {
|
|
176
220
|
return Some(name);
|
|
177
221
|
}
|
|
@@ -180,58 +224,6 @@ fn top_level_class_name(text: &str) -> Option<String> {
|
|
|
180
224
|
None
|
|
181
225
|
}
|
|
182
226
|
|
|
183
|
-
// Hand-ported `Naming.snake` (Ruby): split acronym boundaries, then camelCase
|
|
184
|
-
// boundaries, then downcase — no regex dependency.
|
|
185
|
-
pub(crate) fn snake_case(name: &str) -> String {
|
|
186
|
-
let after_pass1 = split_acronym_boundaries(name);
|
|
187
|
-
let after_pass2 = split_camel_boundaries(&after_pass1);
|
|
188
|
-
after_pass2.to_ascii_lowercase()
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
fn split_acronym_boundaries(text: &str) -> String {
|
|
192
|
-
let chars: Vec<char> = text.chars().collect();
|
|
193
|
-
let mut out = String::with_capacity(text.len() + 4);
|
|
194
|
-
let mut i = 0;
|
|
195
|
-
while i < chars.len() {
|
|
196
|
-
// A maximal uppercase run starting at i.
|
|
197
|
-
if chars[i].is_ascii_uppercase() {
|
|
198
|
-
let mut run_end = i;
|
|
199
|
-
while run_end < chars.len() && chars[run_end].is_ascii_uppercase() {
|
|
200
|
-
run_end += 1;
|
|
201
|
-
}
|
|
202
|
-
let run_len = run_end - i;
|
|
203
|
-
let followed_by_lowercase = run_end < chars.len() && chars[run_end].is_ascii_lowercase();
|
|
204
|
-
if run_len >= 2 && followed_by_lowercase {
|
|
205
|
-
// Emit the run minus its last char, an underscore, then
|
|
206
|
-
// continue scanning from the run's own last char (which
|
|
207
|
-
// pass 2 or a plain copy picks up next iteration).
|
|
208
|
-
out.extend(&chars[i..run_end - 1]);
|
|
209
|
-
out.push('_');
|
|
210
|
-
i = run_end - 1;
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
out.push(chars[i]);
|
|
215
|
-
i += 1;
|
|
216
|
-
}
|
|
217
|
-
out
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
fn split_camel_boundaries(text: &str) -> String {
|
|
221
|
-
let chars: Vec<char> = text.chars().collect();
|
|
222
|
-
let mut out = String::with_capacity(text.len() + 4);
|
|
223
|
-
for (idx, &c) in chars.iter().enumerate() {
|
|
224
|
-
if idx > 0 {
|
|
225
|
-
let prev = chars[idx - 1];
|
|
226
|
-
if (prev.is_ascii_lowercase() || prev.is_ascii_digit()) && c.is_ascii_uppercase() {
|
|
227
|
-
out.push('_');
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
out.push(c);
|
|
231
|
-
}
|
|
232
|
-
out
|
|
233
|
-
}
|
|
234
|
-
|
|
235
227
|
#[cfg(test)]
|
|
236
228
|
mod tests {
|
|
237
229
|
use super::*;
|
|
@@ -257,7 +249,11 @@ mod tests {
|
|
|
257
249
|
("Statement", "statement"),
|
|
258
250
|
];
|
|
259
251
|
for (input, expected) in cases {
|
|
260
|
-
assert_eq!(
|
|
252
|
+
assert_eq!(
|
|
253
|
+
crate::hecks_naming::snake(input),
|
|
254
|
+
expected,
|
|
255
|
+
"snake({input:?})"
|
|
256
|
+
);
|
|
261
257
|
}
|
|
262
258
|
}
|
|
263
259
|
|
|
@@ -272,15 +268,25 @@ mod tests {
|
|
|
272
268
|
#[test]
|
|
273
269
|
fn reads_the_default_adapter_of_the_target_chapters_own_world_only() {
|
|
274
270
|
let text = "Hecks.world \"Alpha\" do\n # default_adapter \"Heki\"\n default_adapter \"PostgresEra\"\nend\n\nHecks.world(\"Beta\") do\n default_adapter \"Memory\"\nend\n";
|
|
275
|
-
assert_eq!(
|
|
276
|
-
|
|
271
|
+
assert_eq!(
|
|
272
|
+
default_adapter_name(text, "Alpha"),
|
|
273
|
+
Some("PostgresEra".to_string())
|
|
274
|
+
);
|
|
275
|
+
assert_eq!(
|
|
276
|
+
default_adapter_name(text, "Beta"),
|
|
277
|
+
Some("Memory".to_string())
|
|
278
|
+
);
|
|
277
279
|
assert_eq!(default_adapter_name(text, "Gamma"), None);
|
|
278
280
|
}
|
|
279
281
|
|
|
280
282
|
#[test]
|
|
281
283
|
fn declares_lineage_capable_true_matches_the_endless_method_form() {
|
|
282
|
-
assert!(declares_lineage_capable_true(
|
|
283
|
-
|
|
284
|
+
assert!(declares_lineage_capable_true(
|
|
285
|
+
" def self.lineage_capable? = true\n"
|
|
286
|
+
));
|
|
287
|
+
assert!(!declares_lineage_capable_true(
|
|
288
|
+
" def self.lineage_capable? = false\n"
|
|
289
|
+
));
|
|
284
290
|
assert!(!declares_lineage_capable_true("no such method here\n"));
|
|
285
291
|
}
|
|
286
292
|
|
|
@@ -290,11 +296,19 @@ mod tests {
|
|
|
290
296
|
fn finds_postgres_era_in_the_real_source_tree() {
|
|
291
297
|
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../..");
|
|
292
298
|
let names = lineage_capable_adapter_names(&root).expect("scans the adapter directories");
|
|
293
|
-
assert!(
|
|
299
|
+
assert!(
|
|
300
|
+
names.iter().any(|name| name == "PostgresEra"),
|
|
301
|
+
"lineage-capable adapters found: {names:?}"
|
|
302
|
+
);
|
|
294
303
|
}
|
|
295
304
|
|
|
296
305
|
#[test]
|
|
297
306
|
fn finds_the_top_level_class_name() {
|
|
298
|
-
assert_eq!(
|
|
307
|
+
assert_eq!(
|
|
308
|
+
top_level_class_name(
|
|
309
|
+
"module Hecks\n module Adapters\n class Postgres\n def x; end\n"
|
|
310
|
+
),
|
|
311
|
+
Some("Postgres".to_string())
|
|
312
|
+
);
|
|
299
313
|
}
|
|
300
314
|
}
|
data/rust/build/src/main.rs
CHANGED
|
@@ -2,23 +2,30 @@
|
|
|
2
2
|
//! `<domain>` is a domain directory such as `examples/pizzas`; `--wasm` also cross-compiles to
|
|
3
3
|
//! `wasm32-wasip1`, and `--no-build` generates source only.
|
|
4
4
|
|
|
5
|
+
mod adapters_pass;
|
|
5
6
|
mod build_artifact;
|
|
6
7
|
mod cargo_sync;
|
|
7
8
|
// The one JSON implementation, compiled from `hecks-codegen`'s own source: neither crate depends on
|
|
8
9
|
// the other, and a packaged workspace ships both side by side. This crate reads only part of it.
|
|
10
|
+
mod binding_pass;
|
|
9
11
|
#[allow(dead_code)]
|
|
10
12
|
#[path = "../../codegen/src/json.rs"]
|
|
11
13
|
mod json;
|
|
12
|
-
|
|
14
|
+
// The one `Hecks::Naming` port, compiled from `hecks-codegen`'s source for the same reason.
|
|
15
|
+
#[allow(dead_code)]
|
|
16
|
+
#[path = "../../codegen/src/hecks_naming.rs"]
|
|
17
|
+
mod hecks_naming;
|
|
13
18
|
mod lineage_pass;
|
|
14
19
|
mod pipeline;
|
|
15
20
|
mod reserved_names;
|
|
16
21
|
mod resolve;
|
|
17
22
|
mod root;
|
|
23
|
+
mod rustfmt;
|
|
18
24
|
mod seams_pass;
|
|
19
25
|
mod subprocess;
|
|
20
26
|
mod tmp;
|
|
21
27
|
mod translation_pass;
|
|
28
|
+
mod world_pass;
|
|
22
29
|
|
|
23
30
|
use std::process::ExitCode;
|
|
24
31
|
|
|
@@ -50,7 +57,9 @@ fn run(args: &[String]) -> Result<(), String> {
|
|
|
50
57
|
}
|
|
51
58
|
}
|
|
52
59
|
|
|
53
|
-
let domain = domain.ok_or_else(||
|
|
60
|
+
let domain = domain.ok_or_else(|| {
|
|
61
|
+
"usage: hecks-build <domain> [--wasm] [--no-build] [--out <dir>]".to_string()
|
|
62
|
+
})?;
|
|
54
63
|
let root = root::find()?;
|
|
55
64
|
|
|
56
65
|
// `--out` generates the module tree into that directory only: no `Cargo.toml` rewrite, no
|
data/rust/build/src/pipeline.rs
CHANGED
|
@@ -3,15 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
use std::path::{Path, PathBuf};
|
|
5
5
|
|
|
6
|
+
use crate::adapters_pass;
|
|
6
7
|
use crate::binding_pass;
|
|
7
8
|
use crate::build_artifact;
|
|
8
9
|
use crate::cargo_sync;
|
|
9
10
|
use crate::json::Json;
|
|
10
11
|
use crate::lineage_pass;
|
|
11
12
|
use crate::resolve;
|
|
13
|
+
use crate::rustfmt;
|
|
12
14
|
use crate::seams_pass;
|
|
13
15
|
use crate::subprocess;
|
|
14
16
|
use crate::tmp::TempDir;
|
|
17
|
+
use crate::world_pass;
|
|
15
18
|
|
|
16
19
|
pub struct Options {
|
|
17
20
|
pub build_native: bool,
|
|
@@ -53,7 +56,9 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
53
56
|
|
|
54
57
|
let bluebook_directory = domain_path.join("bluebook");
|
|
55
58
|
let bluebook_paths = resolve::bluebook_files(&bluebook_directory)?;
|
|
56
|
-
let first_bluebook = bluebook_paths
|
|
59
|
+
let first_bluebook = bluebook_paths
|
|
60
|
+
.first()
|
|
61
|
+
.ok_or_else(|| format!("{} has no .bluebook files", domain_path.display()))?;
|
|
57
62
|
let hecksagon_candidate = bluebook_directory.join(format!("{target_mod_name}.hecksagon"));
|
|
58
63
|
let hecksagon_path = hecksagon_candidate.is_file().then_some(hecksagon_candidate);
|
|
59
64
|
let world_candidate = bluebook_directory.join(format!("{target_mod_name}.world"));
|
|
@@ -92,9 +97,26 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
92
97
|
// Only the target chapter gets a `lineage` key — a framework chapter or
|
|
93
98
|
// `meta` never does, matching `derive_lineage` (Ruby) re-`JSON.parse`ing
|
|
94
99
|
// rather than chaining a live object through both passes.
|
|
95
|
-
let mut target_ir = Json::parse(&target_ir_text)
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
let mut target_ir = Json::parse(&target_ir_text)
|
|
101
|
+
.map_err(|e| format!("re-parsing target ir.json for lineage: {e}"))?;
|
|
102
|
+
lineage_pass::run(
|
|
103
|
+
&mut target_ir,
|
|
104
|
+
hecksagon_path.as_deref(),
|
|
105
|
+
world_path.as_deref(),
|
|
106
|
+
root,
|
|
107
|
+
)?;
|
|
108
|
+
binding_pass::run(
|
|
109
|
+
&mut target_ir,
|
|
110
|
+
hecksagon_path.as_deref(),
|
|
111
|
+
world_path.as_deref(),
|
|
112
|
+
|ir| {
|
|
113
|
+
// The same two places `TargetIr#adapters` scans: the source root's `lib/` and the
|
|
114
|
+
// domain's own directory.
|
|
115
|
+
let directories = [root.join("lib"), domain_path.clone()];
|
|
116
|
+
adapters_pass::declarations(&parser_bin, &directories, ir)
|
|
117
|
+
},
|
|
118
|
+
)?;
|
|
119
|
+
world_pass::run(&mut target_ir, &parser_bin, world_path.as_deref())?;
|
|
98
120
|
|
|
99
121
|
// Every other chapter the gem supplies by `attaches "Name"`, resolved through the
|
|
100
122
|
// same directory listing (`resolve::framework_members`) the Ruby
|
|
@@ -104,7 +126,9 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
104
126
|
let other_gem_chapters = resolve::other_gem_chapter_names(root)?;
|
|
105
127
|
let mut chapters: Vec<Chapter> = Vec::new();
|
|
106
128
|
for fw_name in &gem_chapter_names {
|
|
107
|
-
if other_gem_chapters.contains(fw_name)
|
|
129
|
+
if other_gem_chapters.contains(fw_name)
|
|
130
|
+
&& !framework_members.iter().any(|(name, _)| name == fw_name)
|
|
131
|
+
{
|
|
108
132
|
continue;
|
|
109
133
|
}
|
|
110
134
|
let fw_path = framework_members
|
|
@@ -114,7 +138,7 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
114
138
|
.ok_or_else(|| {
|
|
115
139
|
let mut known: Vec<&str> = framework_members.iter().map(|(n, _)| n.as_str()).collect();
|
|
116
140
|
known.extend(other_gem_chapters.iter().map(String::as_str));
|
|
117
|
-
known.
|
|
141
|
+
known.sort_unstable();
|
|
118
142
|
format!("hecks-build: attaches {fw_name:?} names no chapter the gem carries — known: {}", known.join(", "))
|
|
119
143
|
})?;
|
|
120
144
|
let fw_chapter_name = resolve::header_chapter_name(&fw_path)?;
|
|
@@ -124,7 +148,11 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
124
148
|
fw_path.display()
|
|
125
149
|
));
|
|
126
150
|
}
|
|
127
|
-
let fw_ir_text = parse_chapter(
|
|
151
|
+
let fw_ir_text = parse_chapter(
|
|
152
|
+
&parser_bin,
|
|
153
|
+
&fw_chapter_name,
|
|
154
|
+
std::slice::from_ref(&fw_path),
|
|
155
|
+
)?;
|
|
128
156
|
chapters.push(Chapter {
|
|
129
157
|
mod_name: fw_name.to_lowercase(),
|
|
130
158
|
source_label: format!("{domain} (attaches {fw_name:?})"),
|
|
@@ -138,7 +166,7 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
138
166
|
for pkg_name in &vendored_package_names {
|
|
139
167
|
let pkg_files = resolve::vendored_bluebook_files(&domain_path, pkg_name)?;
|
|
140
168
|
let pkg_chapter_name = resolve::header_chapter_name(&pkg_files[0])?;
|
|
141
|
-
let expected_chapter_name =
|
|
169
|
+
let expected_chapter_name = crate::hecks_naming::pascal(pkg_name);
|
|
142
170
|
if pkg_chapter_name != expected_chapter_name {
|
|
143
171
|
return Err(format!(
|
|
144
172
|
"hecks-build: {} declares chapter {pkg_chapter_name:?}, but attaches {pkg_name:?}, from: :vendor \
|
|
@@ -200,7 +228,10 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
200
228
|
// once every chapter is loaded; `translations` and `source_text` close the binding facts.
|
|
201
229
|
let mut member_irs = Vec::new();
|
|
202
230
|
for c in &chapters {
|
|
203
|
-
member_irs.push(
|
|
231
|
+
member_irs.push(
|
|
232
|
+
Json::parse(&c.ir_text)
|
|
233
|
+
.map_err(|e| format!("re-parsing {} ir.json for its seams: {e}", c.mod_name))?,
|
|
234
|
+
);
|
|
204
235
|
}
|
|
205
236
|
seams_pass::run(&mut target_ir, &member_irs)?;
|
|
206
237
|
binding_pass::finish(&mut target_ir, &source_files, &bluebook_directory)?;
|
|
@@ -211,8 +242,12 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
211
242
|
let grammar_files = resolve::grammar_files(root)?;
|
|
212
243
|
let meta_ir_text = parse_chapter(&parser_bin, "Bluebook", &grammar_files)?;
|
|
213
244
|
|
|
214
|
-
let out_root = opts
|
|
215
|
-
|
|
245
|
+
let out_root = opts
|
|
246
|
+
.out_dir
|
|
247
|
+
.clone()
|
|
248
|
+
.unwrap_or_else(|| root.join("rust/src/generated"));
|
|
249
|
+
std::fs::create_dir_all(&out_root)
|
|
250
|
+
.map_err(|e| format!("creating {}: {e}", out_root.display()))?;
|
|
216
251
|
|
|
217
252
|
// Scoped clearing — identical reasoning to both Ruby pipelines'
|
|
218
253
|
// own: multiple domains coexist on disk, so only this run's own
|
|
@@ -227,11 +262,21 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
227
262
|
let tmp = TempDir::new("hecks-build-codegen")?;
|
|
228
263
|
|
|
229
264
|
let meta_ir_path = tmp.path().join("meta_ir.json");
|
|
230
|
-
std::fs::write(&meta_ir_path, &meta_ir_text)
|
|
231
|
-
|
|
265
|
+
std::fs::write(&meta_ir_path, &meta_ir_text)
|
|
266
|
+
.map_err(|e| format!("writing {}: {e}", meta_ir_path.display()))?;
|
|
267
|
+
run_codegen_full(
|
|
268
|
+
&codegen_bin,
|
|
269
|
+
&[
|
|
270
|
+
out_root.to_string_lossy().to_string(),
|
|
271
|
+
"meta".to_string(),
|
|
272
|
+
META_SOURCE_LABEL.to_string(),
|
|
273
|
+
meta_ir_path.to_string_lossy().to_string(),
|
|
274
|
+
],
|
|
275
|
+
)?;
|
|
232
276
|
|
|
233
277
|
let target_ir_path = tmp.path().join("target_ir.json");
|
|
234
|
-
std::fs::write(&target_ir_path, &target_ir_text)
|
|
278
|
+
std::fs::write(&target_ir_path, &target_ir_text)
|
|
279
|
+
.map_err(|e| format!("writing {}: {e}", target_ir_path.display()))?;
|
|
235
280
|
|
|
236
281
|
let mut codegen_args = vec![
|
|
237
282
|
out_root.to_string_lossy().to_string(),
|
|
@@ -239,14 +284,13 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
239
284
|
domain.to_string(),
|
|
240
285
|
target_ir_path.to_string_lossy().to_string(),
|
|
241
286
|
];
|
|
242
|
-
let mut chapter_ir_paths = Vec::new();
|
|
243
287
|
for (idx, c) in chapters.iter().enumerate() {
|
|
244
288
|
let ir_path = tmp.path().join(format!("chapter_{idx}_ir.json"));
|
|
245
|
-
std::fs::write(&ir_path, &c.ir_text)
|
|
289
|
+
std::fs::write(&ir_path, &c.ir_text)
|
|
290
|
+
.map_err(|e| format!("writing {}: {e}", ir_path.display()))?;
|
|
246
291
|
codegen_args.push(c.mod_name.clone());
|
|
247
292
|
codegen_args.push(c.source_label.clone());
|
|
248
293
|
codegen_args.push(ir_path.to_string_lossy().to_string());
|
|
249
|
-
chapter_ir_paths.push(ir_path);
|
|
250
294
|
}
|
|
251
295
|
run_codegen_full(&codegen_bin, &codegen_args)?;
|
|
252
296
|
|
|
@@ -257,6 +301,15 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
257
301
|
cargo_sync::run(&out_root, &cargo_toml_path, &target_mod_name)?;
|
|
258
302
|
}
|
|
259
303
|
|
|
304
|
+
// `hecks project_rust` lays its Rust out with rustfmt; the tree must match it byte for byte.
|
|
305
|
+
let mut generated_dirs = vec![
|
|
306
|
+
"meta".to_string(),
|
|
307
|
+
"active".to_string(),
|
|
308
|
+
target_mod_name.clone(),
|
|
309
|
+
];
|
|
310
|
+
generated_dirs.extend(chapters.iter().map(|c| c.mod_name.clone()));
|
|
311
|
+
rustfmt::format_generated(&out_root, &generated_dirs)?;
|
|
312
|
+
|
|
260
313
|
let rust_dir = root.join("rust");
|
|
261
314
|
if opts.build_native {
|
|
262
315
|
build_artifact::build_native(&rust_dir)?;
|
|
@@ -270,9 +323,17 @@ pub fn run(root: &Path, domain: &str, opts: &Options) -> Result<(), String> {
|
|
|
270
323
|
|
|
271
324
|
// Parses via `hecks-parse chapter`. `hecks-codegen` marks the IR and writes its `ir.json` and
|
|
272
325
|
// `metadata.rs` itself, so the text goes through as `hecks-parse` printed it.
|
|
273
|
-
fn parse_chapter(
|
|
326
|
+
fn parse_chapter(
|
|
327
|
+
parser_bin: &Path,
|
|
328
|
+
chapter_name: &str,
|
|
329
|
+
files: &[PathBuf],
|
|
330
|
+
) -> Result<String, String> {
|
|
274
331
|
let parser_bin_str = parser_bin.to_string_lossy().to_string();
|
|
275
|
-
let mut args: Vec<String> = vec![
|
|
332
|
+
let mut args: Vec<String> = vec![
|
|
333
|
+
"chapter".to_string(),
|
|
334
|
+
"--chapter".to_string(),
|
|
335
|
+
chapter_name.to_string(),
|
|
336
|
+
];
|
|
276
337
|
args.extend(files.iter().map(|p| p.to_string_lossy().to_string()));
|
|
277
338
|
let arg_refs: Vec<&str> = args.iter().map(String::as_str).collect();
|
|
278
339
|
|
|
@@ -2,57 +2,13 @@
|
|
|
2
2
|
// CargoReservedName vocabularies (lib/hecks/language/bluebook/
|
|
3
3
|
// vocabulary.bluebook). Do not hand-edit — re-run hecks project_reserved_names.
|
|
4
4
|
|
|
5
|
-
/// The `RustReservedWord` vocabulary,
|
|
5
|
+
/// The `RustReservedWord` vocabulary, 51 entries.
|
|
6
6
|
pub const RUST_KEYWORDS: &[&str] = &[
|
|
7
|
-
"as",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"dyn",
|
|
13
|
-
"else",
|
|
14
|
-
"enum",
|
|
15
|
-
"extern",
|
|
16
|
-
"false",
|
|
17
|
-
"fn",
|
|
18
|
-
"for",
|
|
19
|
-
"if",
|
|
20
|
-
"impl",
|
|
21
|
-
"in",
|
|
22
|
-
"let",
|
|
23
|
-
"loop",
|
|
24
|
-
"match",
|
|
25
|
-
"mod",
|
|
26
|
-
"move",
|
|
27
|
-
"mut",
|
|
28
|
-
"pub",
|
|
29
|
-
"ref",
|
|
30
|
-
"return",
|
|
31
|
-
"self",
|
|
32
|
-
"Self",
|
|
33
|
-
"static",
|
|
34
|
-
"struct",
|
|
35
|
-
"super",
|
|
36
|
-
"trait",
|
|
37
|
-
"true",
|
|
38
|
-
"type",
|
|
39
|
-
"unsafe",
|
|
40
|
-
"use",
|
|
41
|
-
"where",
|
|
42
|
-
"while",
|
|
43
|
-
"abstract",
|
|
44
|
-
"become",
|
|
45
|
-
"box",
|
|
46
|
-
"do",
|
|
47
|
-
"final",
|
|
48
|
-
"macro",
|
|
49
|
-
"override",
|
|
50
|
-
"priv",
|
|
51
|
-
"typeof",
|
|
52
|
-
"unsized",
|
|
53
|
-
"virtual",
|
|
54
|
-
"yield",
|
|
55
|
-
"try",
|
|
7
|
+
"as", "async", "await", "break", "const", "continue", "crate", "dyn", "else", "enum", "extern",
|
|
8
|
+
"false", "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub",
|
|
9
|
+
"ref", "return", "self", "Self", "static", "struct", "super", "trait", "true", "type",
|
|
10
|
+
"unsafe", "use", "where", "while", "abstract", "become", "box", "do", "final", "macro",
|
|
11
|
+
"override", "priv", "typeof", "unsized", "virtual", "yield", "try",
|
|
56
12
|
];
|
|
57
13
|
|
|
58
14
|
/// The `CargoReservedName` vocabulary, 16 entries.
|