From da220d2e96cecee01a20ff01f316bc16119f1b58 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Wed, 26 Aug 2026 16:16:15 +0000 Subject: [PATCH 01/30] Two independently-green PRs met on main and the corpus went red: restore exhaustiveness over the two abort-side dispositions MAIN IS RED, and the finding is HOW rather than what. This is a SEMANTIC MERGE CONFLICT between two PRs that were each correct and each green, and NEITHER IS AT FAULT: #9227 cd7cf33a33a adds dag/gunbc/build_target.dag, which MATCHES over ClaimDisposition #9263 a968415a008 adds PanickedBeforeVerdict and NotAttemptedAfterAbort TO ClaimDisposition Neither PR touches the other's file. There is no textual conflict, no merge-tree signal, and both merged cleanly. One grows a coproduct, the other adds a match over it, and main refuses at strict preparation the moment they meet: dag/gunbc/build_target.dag:177:3: error: non-exhaustive match: missing variant(s) PanickedBeforeVerdict, NotAttemptedAfterAbort dag/gunbc/build_target.dag:378:3: error: non-exhaustive match: missing variant(s) PanickedBeforeVerdict, NotAttemptedAfterAbort #9263 was genuinely green on its own head (witnesses/build/floor all success, 03:38-04:56Z) and merged at 15:16Z against a main that had meanwhile acquired the match. So this is not a PR that merged on a missing check. NO PER-PR GATE CAN CATCH THIS CLASS BY CONSTRUCTION, because each PR is green against the base it was tested on; the combination is what is untested. That is worth recording separately from this repair, because the repair will look routine in six hours and the gap will not have moved. The compiler catching it the instant the two met is fail-closed working correctly. It is the only thing that did catch it. THE MAPPING IS DECIDED BY THE PARTITION THESE MATCHES ALREADY DRAW, not by severity. blaze_test_status_of_claim_disposition already sorts on DID THE CLAIM RUN -- RuntimeErrored is FAILED because it ran and blew up, while RouteGap, HostToolUnresolved and ObservationUnreadable are all INCOMPLETE because they never ran. So: PanickedBeforeVerdict -> TestStatusFailed it executed and died NotAttemptedAfterAbort -> TestStatusIncomplete it never executed INCOMPLETE is the honest arm here rather than the soft one. Rendering a claim that never ran as FAILED asserts that an assertion failed when no assertion ever executed -- the execution-provenance loss DESIGN forbids, where a stage refused before it ran must not inhabit the same carrier as a stage that ran and found a defect. In claim_disposition_verdict both are StandingUnsatisfied, for the same reason read the other way: neither is a claim that satisfied its standing, and admitting an unattempted claim as satisfied would let an aborted run report a standing it never tested. Verified by compiling dag/gunbc/build_target.dag as an entry. Co-Authored-By: Claude Opus 5 (1M context) --- dag/gunbc/build_target.dag | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/dag/gunbc/build_target.dag b/dag/gunbc/build_target.dag index e625bf11bb4..adc1c30bcd7 100644 --- a/dag/gunbc/build_target.dag +++ b/dag/gunbc/build_target.dag @@ -14,6 +14,7 @@ import v2.workflow.floor_terminal_ledger { Passed, Failed, KnownRedHeld, KnownRedNowPassing, BudgetRefusedBeforeVerdict, PassedOverBudget, BudgetTerminalWithoutSafetyCause, HostToolUnresolvedBeforeVerdict, RouteGapBeforeVerdict, RuntimeErroredBeforeVerdict, ObservationUnreadableBeforeVerdict, + PanickedBeforeVerdict, NotAttemptedAfterAbort, } import std.types { String, Bool, NonEmptyStr } import std.integer { Int } @@ -173,6 +174,10 @@ type StandingVerdict // witness passed, so nothing is broken in the tree — what is broken is the ROSTER, which still // enrols it as expected-red. Admitting it would let a stale enrolment survive indefinitely, // because the only signal it ever produces is this one. +// `PanickedBeforeVerdict` and `NotAttemptedAfterAbort` are both UNSATISFIED, for the same reason +// read in opposite directions: one claim executed and died, the other never executed at all, and +// neither is a claim that satisfied its standing. Admitting an unattempted claim as satisfied +// would be the fail-open — it would let an aborted run report a standing it never tested. fn claim_disposition_verdict(d: ClaimDisposition) -> StandingVerdict { match d { Passed => StandingSatisfied {} @@ -193,6 +198,10 @@ fn claim_disposition_verdict(d: ClaimDisposition) -> StandingVerdict { StandingUnsatisfied { cause: FloorDispositionUnsatisfied { disposition: RuntimeErroredBeforeVerdict {} } } ObservationUnreadableBeforeVerdict => StandingUnsatisfied { cause: FloorDispositionUnsatisfied { disposition: ObservationUnreadableBeforeVerdict {} } } + PanickedBeforeVerdict => + StandingUnsatisfied { cause: FloorDispositionUnsatisfied { disposition: PanickedBeforeVerdict {} } } + NotAttemptedAfterAbort => + StandingUnsatisfied { cause: FloorDispositionUnsatisfied { disposition: NotAttemptedAfterAbort {} } } } } @@ -374,6 +383,14 @@ fn required_gate_decision(a: AggregateStanding) -> RequiredGateDecision { // remedies differ, so this collapse would be a defect in a carrier; it is admissible in an // export because the distinguishing fact stays on the `TestStanding` the export was computed // from, one dereference away, and the export is never fed back into a decision. +// The two abort-side arms are placed by the partition this match already draws — DID THE CLAIM +// RUN — and not by severity. `PanickedBeforeVerdict` is `RuntimeErroredBeforeVerdict`'s neighbour: +// the claim executed and died, so `FAILED`. `NotAttemptedAfterAbort` is `RouteGapBeforeVerdict`'s: +// the claim never executed, so `INCOMPLETE`. `INCOMPLETE` here is the HONEST arm rather than the +// soft one — rendering a claim that never ran as `FAILED` asserts that an assertion failed when no +// assertion ever executed, which is exactly the execution-provenance loss DESIGN forbids, since a +// stage refused before it ran must not inhabit the same carrier as a stage that ran and found a +// defect. fn blaze_test_status_of_claim_disposition(d: ClaimDisposition) -> BlazeTestStatus { match d { Passed => TestStatusPassed {} @@ -387,6 +404,8 @@ fn blaze_test_status_of_claim_disposition(d: ClaimDisposition) -> BlazeTestStatu RouteGapBeforeVerdict => TestStatusIncomplete {} RuntimeErroredBeforeVerdict => TestStatusFailed {} ObservationUnreadableBeforeVerdict => TestStatusIncomplete {} + PanickedBeforeVerdict => TestStatusFailed {} + NotAttemptedAfterAbort => TestStatusIncomplete {} } } From 324ea9045d696ba10704778473dfb92392d305d3 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 26 Aug 2026 16:20:24 +0000 Subject: [PATCH 02/30] Prove required record fields cannot be omitted --- ...red_record_field_omission_witness_test.dag | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 dag/test/claim/required_record_field_omission_witness_test.dag diff --git a/dag/test/claim/required_record_field_omission_witness_test.dag b/dag/test/claim/required_record_field_omission_witness_test.dag new file mode 100644 index 00000000000..020832984d1 --- /dev/null +++ b/dag/test/claim/required_record_field_omission_witness_test.dag @@ -0,0 +1,33 @@ +module test.claim.required_record_field_omission_witness + +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +data required_record_field_omission_witness_note: String = "Construction control for the v1 NodeOccurrenceIdentity carrier. The negative and positive sources differ only in whether the required `identity` field is supplied. The negative must be refused by the production compile path; the positive prevents a parser, resolver, or harness failure shared by both sources from satisfying that assertion vacuously. This establishes the structural mechanism the carrier relies on before the carrier changes Node: omitting a required record field cannot compile, while supplying every required field can." + +fn required_record_field_omitted_compiles() -> Bool { + compile_dag_rust_emit_check( + "module required_field_red\ntype Pair { identity: Int, label: String }\ndata pair: Pair = Pair { label: \"red\" }\n", + "src/required_field_red.rs", + [], + [] + ) +} + +fn required_record_fields_supplied_compile() -> Bool { + compile_dag_rust_emit_check( + "module required_field_green\ntype Pair { identity: Int, label: String }\ndata pair: Pair = Pair { identity: 1, label: \"green\" }\n", + "src/required_field_green.rs", + [], + [] + ) +} + +test fn omitted_required_record_field_refuses() -> Bool { + !required_record_field_omitted_compiles() +} + +test fn complete_required_record_literal_accepts() -> Bool { + required_record_fields_supplied_compile() +} From 6f8638fc80bd9eef94c180445fa3ab4dd65ba221 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Wed, 26 Aug 2026 16:20:26 +0000 Subject: [PATCH 03/30] witness: make the ran/never-ran split executable for the two new dispositions The arm-by-arm policy roster enumerated every ClaimDisposition BY HAND, so the two arms this PR adds would have landed with no executing evidence -- the exact specification-without-execution gap DESIGN names, one rung up from the non-exhaustive match that caused the outage. Both dispositions join the roster, and a dedicated witness pins the split that decides them: PanickedBeforeVerdict exports FAILED beside RuntimeErrored (the claim ran and died), NotAttemptedAfterAbort exports INCOMPLETE beside RouteGap (the claim never ran). The INCOMPLETE half is the assertion that earns its keep -- it goes red on precisely the collapse that is tempting to make, where a claim that never executed is reported as one whose assertion failed. Co-Authored-By: Claude Opus 5 (1M context) --- .../claim/bazel_target_model_witness_test.dag | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/dag/test/claim/bazel_target_model_witness_test.dag b/dag/test/claim/bazel_target_model_witness_test.dag index 0cf85570e19..642ee669804 100644 --- a/dag/test/claim/bazel_target_model_witness_test.dag +++ b/dag/test/claim/bazel_target_model_witness_test.dag @@ -26,6 +26,7 @@ import v2.workflow.floor_terminal_ledger { Passed, Failed, KnownRedHeld, KnownRedNowPassing, BudgetRefusedBeforeVerdict, PassedOverBudget, BudgetTerminalWithoutSafetyCause, HostToolUnresolvedBeforeVerdict, RouteGapBeforeVerdict, RuntimeErroredBeforeVerdict, ObservationUnreadableBeforeVerdict, + PanickedBeforeVerdict, NotAttemptedAfterAbort, } import gunbc.build_target { TargetKind, BuildRule, TestRule, AggregateAlias, @@ -284,6 +285,8 @@ test fn w_claim_disposition_policy_is_stated_arm_by_arm() -> Bool { && !verdict_holds(v: claim_disposition_verdict(d: RouteGapBeforeVerdict {})) && !verdict_holds(v: claim_disposition_verdict(d: RuntimeErroredBeforeVerdict {})) && !verdict_holds(v: claim_disposition_verdict(d: ObservationUnreadableBeforeVerdict {})) + && !verdict_holds(v: claim_disposition_verdict(d: PanickedBeforeVerdict {})) + && !verdict_holds(v: claim_disposition_verdict(d: NotAttemptedAfterAbort {})) } // THE REFUSED ARM CARRIES THE DISPOSITION IT REFUSED, which is exactly what the deleted `Bool` @@ -474,3 +477,21 @@ test fn w_export_maps_budget_and_unreached_arms_apart() -> Bool { && (blaze_test_status_of_test_standing(t: TestReportedByBazel { status: TestStatusFlaky {} }) == TestStatusFlaky {}) && (blaze_test_status_of_test_standing(t: TestRunByFloor { disposition: Passed {} }) == TestStatusPassed {}) } + +// THE TWO ABORT-SIDE ARMS ARE SPLIT BY WHETHER THE CLAIM RAN, NOT BY SEVERITY, and this witness is +// what makes that split executable rather than a comment. A panic means the claim executed and +// died, so it exports as `FAILED` beside `RuntimeErroredBeforeVerdict`. An unattempted claim never +// executed at all, so it exports as `INCOMPLETE` beside `RouteGapBeforeVerdict`. +// +// The `INCOMPLETE` half is the assertion that earns its keep. Exporting a claim that never ran as +// `FAILED` would report that an assertion failed when no assertion executed — a verdict fabricated +// for an observation nobody made — so this witness goes red on exactly the collapse that is +// tempting to make, and the disposition-level pairing beneath it keeps the two from being merged +// in the other direction either. +test fn w_export_splits_panic_from_unattempted_by_whether_the_claim_ran() -> Bool { + (blaze_test_status_of_claim_disposition(d: PanickedBeforeVerdict {}) == TestStatusFailed {}) + && (blaze_test_status_of_claim_disposition(d: RuntimeErroredBeforeVerdict {}) == TestStatusFailed {}) + && (blaze_test_status_of_claim_disposition(d: NotAttemptedAfterAbort {}) == TestStatusIncomplete {}) + && !verdict_holds(v: claim_disposition_verdict(d: PanickedBeforeVerdict {})) + && !verdict_holds(v: claim_disposition_verdict(d: NotAttemptedAfterAbort {})) +} From 6c14c47c94a0d20efb05ed4d72da5a6664019696 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Wed, 26 Aug 2026 16:32:26 +0000 Subject: [PATCH 04/30] ci: re-push to trigger a dispatch that never arrived The 16:20 push and the 16:27 ready-flip should each have fired a witnesses run -- witnesses.yml lists both synchronize and ready_for_review, and carries no draft guard -- and neither produced a run of any kind. Not queued, not failed, not startup_failure: absent. The fleet was dispatching normally throughout that window, so this is specific to this ref rather than the outage pattern seen earlier today. Co-Authored-By: Claude Opus 5 (1M context) From b07e24b9e2656915279e5fc2fd9781408ef1e0aa Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 26 Aug 2026 16:33:52 +0000 Subject: [PATCH 05/30] Pin the existing successful-tree stamp order --- .../tests/namespace_occurrence_serde.rs | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/v1/stage0/tests/namespace_occurrence_serde.rs b/src/v1/stage0/tests/namespace_occurrence_serde.rs index b04ed4ed36b..313a99adcc1 100644 --- a/src/v1/stage0/tests/namespace_occurrence_serde.rs +++ b/src/v1/stage0/tests/namespace_occurrence_serde.rs @@ -110,6 +110,68 @@ fn occurrence_transport_round_trips_with_node_identity_and_paths() { assert!(!parsed.occurrence_transport.index.entries.is_empty()); assert!(!parsed.occurrence_transport.declarations.is_empty()); assert!(!parsed.occurrence_transport.references.is_empty()); + assert_eq!( + occurrence_identity_view(&parsed.occurrence_transport), + ( + vec![ + (0, (vec![], 0)), + (1, (vec![0], 1)), + (2, (vec![0, 1], 2)), + (3, (vec![0, 1, 2], 3)), + (4, (vec![0, 1], 4)), + (5, (vec![0, 1], 5)), + (6, (vec![0], 6)), + (7, (vec![0, 6], 7)), + (8, (vec![0, 6, 7], 8)), + (9, (vec![0, 6], 9)), + (10, (vec![0, 6, 9], 10)), + (11, (vec![0, 6, 9, 10], 11)), + (12, (vec![0, 6], 12)), + ], + vec![ + ( + 0, + OccurrenceCategory::NamespaceSegmentOccurrence, + (vec![], 0) + ), + (1, OccurrenceCategory::CallableOccurrence, (vec![0], 1)), + ( + 2, + OccurrenceCategory::LexicalValueOccurrence, + (vec![0, 1], 2) + ), + (6, OccurrenceCategory::CallableOccurrence, (vec![0], 6)), + ( + 7, + OccurrenceCategory::LexicalValueOccurrence, + (vec![0, 6], 7) + ), + ], + vec![ + (3, OccurrenceCategory::TypeOccurrence, (vec![0, 1, 2], 3)), + ( + 4, + OccurrenceCategory::LexicalValueOccurrence, + (vec![0, 1], 4) + ), + (5, OccurrenceCategory::TypeOccurrence, (vec![0, 1], 5)), + (8, OccurrenceCategory::TypeOccurrence, (vec![0, 6, 7], 8)), + (9, OccurrenceCategory::CallableOccurrence, (vec![0, 6], 9)), + ( + 10, + OccurrenceCategory::CallableOccurrence, + (vec![0, 6, 9], 10) + ), + ( + 11, + OccurrenceCategory::LexicalValueOccurrence, + (vec![0, 6, 9, 10], 11) + ), + (12, OccurrenceCategory::TypeOccurrence, (vec![0, 6], 12)), + ], + ), + "successful-tree stamp population, ids, roles, containment and traversal order changed" + ); let encoded = serde_json::to_vec(&parsed).expect("serialize occurrence parse result"); let decoded: Rc = From 1277fc7025ff28ea16a4e5fca4a9c5e74c4d662b Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 26 Aug 2026 16:46:58 +0000 Subject: [PATCH 06/30] Name the required-field refusal in the carrier control --- ...red_record_field_omission_witness_test.dag | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/dag/test/claim/required_record_field_omission_witness_test.dag b/dag/test/claim/required_record_field_omission_witness_test.dag index 020832984d1..13f2eaefd79 100644 --- a/dag/test/claim/required_record_field_omission_witness_test.dag +++ b/dag/test/claim/required_record_field_omission_witness_test.dag @@ -1,17 +1,15 @@ module test.claim.required_record_field_omission_witness -import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } +import gunbc.compile_diagnostic_census { CompileDiagnosticCensus, CensusObserved, CensusNotRunnable } +import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } -data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly +data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree -data required_record_field_omission_witness_note: String = "Construction control for the v1 NodeOccurrenceIdentity carrier. The negative and positive sources differ only in whether the required `identity` field is supplied. The negative must be refused by the production compile path; the positive prevents a parser, resolver, or harness failure shared by both sources from satisfying that assertion vacuously. This establishes the structural mechanism the carrier relies on before the carrier changes Node: omitting a required record field cannot compile, while supplying every required field can." +data required_record_field_omission_witness_note: String = "Construction control for the v1 NodeOccurrenceIdentity carrier. The negative and positive sources differ only in whether the required `identity` field is supplied. The negative observes exactly one blocking MissingField row whose subject is identity; a bare false is insufficient because it cannot separate this wall from an unrelated earlier failure. The positive production compile prevents a parser, resolver, or harness failure shared by both sources from satisfying the assertion vacuously. compile_dag_diagnostic_census reads the live checkout while resolving its synthetic source, so this carrier declares ReadsLiveTree truthfully and is declined by the required floor today; direct execution is the honest rung until the floor's DeclinedLiveTree arm retires." -fn required_record_field_omitted_compiles() -> Bool { - compile_dag_rust_emit_check( - "module required_field_red\ntype Pair { identity: Int, label: String }\ndata pair: Pair = Pair { label: \"red\" }\n", - "src/required_field_red.rs", - [], - [] +fn required_record_field_omission_census() -> CompileDiagnosticCensus { + compile_dag_diagnostic_census( + "module required_field_red\ntype Pair { identity: Int, label: String }\ndata pair: Pair = Pair { label: \"red\" }\n" ) } @@ -25,7 +23,19 @@ fn required_record_fields_supplied_compile() -> Bool { } test fn omitted_required_record_field_refuses() -> Bool { - !required_record_field_omitted_compiles() + match required_record_field_omission_census() { + CensusObserved { rows: rows } => + match first(rows) { + Present { value: row } => + count(rows) == 1 + && row.diagnostic_class == "MissingField" + && row.subject_name == "identity" + && row.blocking + && row.count == 1 + Absent => false + } + CensusNotRunnable { cause: _ } => false + } } test fn complete_required_record_literal_accepts() -> Bool { From 1bc049dcc9ac0cee87af55c8e2da20dd6e4ee942 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 26 Aug 2026 17:18:38 +0000 Subject: [PATCH 07/30] Enroll required-field refusal hermetically --- ...red_record_field_omission_witness_test.dag | 70 +++++++++++++------ 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/dag/test/claim/required_record_field_omission_witness_test.dag b/dag/test/claim/required_record_field_omission_witness_test.dag index 13f2eaefd79..6554386f06f 100644 --- a/dag/test/claim/required_record_field_omission_witness_test.dag +++ b/dag/test/claim/required_record_field_omission_witness_test.dag @@ -1,43 +1,69 @@ module test.claim.required_record_field_omission_witness -import gunbc.compile_diagnostic_census { CompileDiagnosticCensus, CensusObserved, CensusNotRunnable } -import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } +import tools.multi_module_compile_fixture { + MultiModuleCompileFixture, + MultiModuleCompileFixtureOutcome, + FixtureInstrumentRefused, + FixtureCompileRefused, + FixtureCompileCompleted, + fixture_source, + compile_fixture, + fixture_blocking_rows, + fixture_rows_of_class, +} + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly -data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree +data required_record_field_omission_witness_note: String = "Construction control for the v1 NodeOccurrenceIdentity carrier. The negative and positive manifests differ only in whether the required `occurrence_identity` field is supplied. The negative reaches the isolated v1-to-Rust compiler and observes exactly one blocking MissingField row naming occurrence_identity; FixtureInstrumentRefused cannot impersonate that refusal. The positive reaches Rust emission with no diagnostics and a nonempty artifact population. Both measured arms carry nonempty source and compiler digests, binding the receipt to the ordered manifest and running transform. This instrument does not assert interpreter behavior or any non-Rust render target." -data required_record_field_omission_witness_note: String = "Construction control for the v1 NodeOccurrenceIdentity carrier. The negative and positive sources differ only in whether the required `identity` field is supplied. The negative observes exactly one blocking MissingField row whose subject is identity; a bare false is insufficient because it cannot separate this wall from an unrelated earlier failure. The positive production compile prevents a parser, resolver, or harness failure shared by both sources from satisfying the assertion vacuously. compile_dag_diagnostic_census reads the live checkout while resolving its synthetic source, so this carrier declares ReadsLiveTree truthfully and is declined by the required floor today; direct execution is the honest rung until the floor's DeclinedLiveTree arm retires." +fn required_record_field_fixture(source: String) -> MultiModuleCompileFixtureOutcome { + compile_fixture(MultiModuleCompileFixture { + sources: [fixture_source("required_field/entry.dag", source)], + entry: "required_field/entry.dag", + }) +} -fn required_record_field_omission_census() -> CompileDiagnosticCensus { - compile_dag_diagnostic_census( - "module required_field_red\ntype Pair { identity: Int, label: String }\ndata pair: Pair = Pair { label: \"red\" }\n" +fn required_record_field_omission_run() -> MultiModuleCompileFixtureOutcome { + required_record_field_fixture( + source: "module required_field.entry\ntype Pair { occurrence_identity: Int, label: String }\ndata pair: Pair = Pair { label: \"red\" }\n" ) } -fn required_record_fields_supplied_compile() -> Bool { - compile_dag_rust_emit_check( - "module required_field_green\ntype Pair { identity: Int, label: String }\ndata pair: Pair = Pair { identity: 1, label: \"green\" }\n", - "src/required_field_green.rs", - [], - [] +fn required_record_fields_supplied_run() -> MultiModuleCompileFixtureOutcome { + required_record_field_fixture( + source: "module required_field.entry\ntype Pair { occurrence_identity: Int, label: String }\ndata pair: Pair = Pair { occurrence_identity: 1, label: \"green\" }\n" ) } test fn omitted_required_record_field_refuses() -> Bool { - match required_record_field_omission_census() { - CensusObserved { rows: rows } => - match first(rows) { + match required_record_field_omission_run() { + FixtureCompileRefused { module_count: _, diagnostics: rows, source_digest: source_digest, compiler_digest: compiler_digest } => + let blocking = fixture_blocking_rows(rows) + let missing = fixture_rows_of_class(rows, "MissingField") + match first(missing) { Present { value: row } => - count(rows) == 1 - && row.diagnostic_class == "MissingField" - && row.subject_name == "identity" - && row.blocking + count(blocking) == 1 + && count(missing) == 1 + && row.subject_name == "occurrence_identity" && row.count == 1 + && count(source_digest as String) > 0 + && count(compiler_digest as String) > 0 Absent => false } - CensusNotRunnable { cause: _ } => false + FixtureCompileCompleted { module_count: _, emitted_files: _, diagnostics: _, source_digest: _, compiler_digest: _ } => false + FixtureInstrumentRefused { cause: _ } => false } } test fn complete_required_record_literal_accepts() -> Bool { - required_record_fields_supplied_compile() + match required_record_fields_supplied_run() { + FixtureCompileCompleted { module_count: _, emitted_files: files, diagnostics: rows, source_digest: source_digest, compiler_digest: compiler_digest } => + count(rows) == 0 + && count(files) > 0 + && count(source_digest as String) > 0 + && count(compiler_digest as String) > 0 + FixtureCompileRefused { module_count: _, diagnostics: _, source_digest: _, compiler_digest: _ } => false + FixtureInstrumentRefused { cause: _ } => false + } } From a0ecdaa4bd166542db52f2dc037cac85a70889be Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 26 Aug 2026 17:53:16 +0000 Subject: [PATCH 08/30] Revert "Merge remote-tracking branch 'origin/session/cool-swift-307-exhaustive' into HEAD" This reverts commit 9f56a4e308ecb41d0521b5692f230d0c5d16b88d, reversing changes made to 1bc049dcc9ac0cee87af55c8e2da20dd6e4ee942. --- dag/gunbc/build_target.dag | 19 ----------------- .../claim/bazel_target_model_witness_test.dag | 21 ------------------- 2 files changed, 40 deletions(-) diff --git a/dag/gunbc/build_target.dag b/dag/gunbc/build_target.dag index adc1c30bcd7..e625bf11bb4 100644 --- a/dag/gunbc/build_target.dag +++ b/dag/gunbc/build_target.dag @@ -14,7 +14,6 @@ import v2.workflow.floor_terminal_ledger { Passed, Failed, KnownRedHeld, KnownRedNowPassing, BudgetRefusedBeforeVerdict, PassedOverBudget, BudgetTerminalWithoutSafetyCause, HostToolUnresolvedBeforeVerdict, RouteGapBeforeVerdict, RuntimeErroredBeforeVerdict, ObservationUnreadableBeforeVerdict, - PanickedBeforeVerdict, NotAttemptedAfterAbort, } import std.types { String, Bool, NonEmptyStr } import std.integer { Int } @@ -174,10 +173,6 @@ type StandingVerdict // witness passed, so nothing is broken in the tree — what is broken is the ROSTER, which still // enrols it as expected-red. Admitting it would let a stale enrolment survive indefinitely, // because the only signal it ever produces is this one. -// `PanickedBeforeVerdict` and `NotAttemptedAfterAbort` are both UNSATISFIED, for the same reason -// read in opposite directions: one claim executed and died, the other never executed at all, and -// neither is a claim that satisfied its standing. Admitting an unattempted claim as satisfied -// would be the fail-open — it would let an aborted run report a standing it never tested. fn claim_disposition_verdict(d: ClaimDisposition) -> StandingVerdict { match d { Passed => StandingSatisfied {} @@ -198,10 +193,6 @@ fn claim_disposition_verdict(d: ClaimDisposition) -> StandingVerdict { StandingUnsatisfied { cause: FloorDispositionUnsatisfied { disposition: RuntimeErroredBeforeVerdict {} } } ObservationUnreadableBeforeVerdict => StandingUnsatisfied { cause: FloorDispositionUnsatisfied { disposition: ObservationUnreadableBeforeVerdict {} } } - PanickedBeforeVerdict => - StandingUnsatisfied { cause: FloorDispositionUnsatisfied { disposition: PanickedBeforeVerdict {} } } - NotAttemptedAfterAbort => - StandingUnsatisfied { cause: FloorDispositionUnsatisfied { disposition: NotAttemptedAfterAbort {} } } } } @@ -383,14 +374,6 @@ fn required_gate_decision(a: AggregateStanding) -> RequiredGateDecision { // remedies differ, so this collapse would be a defect in a carrier; it is admissible in an // export because the distinguishing fact stays on the `TestStanding` the export was computed // from, one dereference away, and the export is never fed back into a decision. -// The two abort-side arms are placed by the partition this match already draws — DID THE CLAIM -// RUN — and not by severity. `PanickedBeforeVerdict` is `RuntimeErroredBeforeVerdict`'s neighbour: -// the claim executed and died, so `FAILED`. `NotAttemptedAfterAbort` is `RouteGapBeforeVerdict`'s: -// the claim never executed, so `INCOMPLETE`. `INCOMPLETE` here is the HONEST arm rather than the -// soft one — rendering a claim that never ran as `FAILED` asserts that an assertion failed when no -// assertion ever executed, which is exactly the execution-provenance loss DESIGN forbids, since a -// stage refused before it ran must not inhabit the same carrier as a stage that ran and found a -// defect. fn blaze_test_status_of_claim_disposition(d: ClaimDisposition) -> BlazeTestStatus { match d { Passed => TestStatusPassed {} @@ -404,8 +387,6 @@ fn blaze_test_status_of_claim_disposition(d: ClaimDisposition) -> BlazeTestStatu RouteGapBeforeVerdict => TestStatusIncomplete {} RuntimeErroredBeforeVerdict => TestStatusFailed {} ObservationUnreadableBeforeVerdict => TestStatusIncomplete {} - PanickedBeforeVerdict => TestStatusFailed {} - NotAttemptedAfterAbort => TestStatusIncomplete {} } } diff --git a/dag/test/claim/bazel_target_model_witness_test.dag b/dag/test/claim/bazel_target_model_witness_test.dag index 642ee669804..0cf85570e19 100644 --- a/dag/test/claim/bazel_target_model_witness_test.dag +++ b/dag/test/claim/bazel_target_model_witness_test.dag @@ -26,7 +26,6 @@ import v2.workflow.floor_terminal_ledger { Passed, Failed, KnownRedHeld, KnownRedNowPassing, BudgetRefusedBeforeVerdict, PassedOverBudget, BudgetTerminalWithoutSafetyCause, HostToolUnresolvedBeforeVerdict, RouteGapBeforeVerdict, RuntimeErroredBeforeVerdict, ObservationUnreadableBeforeVerdict, - PanickedBeforeVerdict, NotAttemptedAfterAbort, } import gunbc.build_target { TargetKind, BuildRule, TestRule, AggregateAlias, @@ -285,8 +284,6 @@ test fn w_claim_disposition_policy_is_stated_arm_by_arm() -> Bool { && !verdict_holds(v: claim_disposition_verdict(d: RouteGapBeforeVerdict {})) && !verdict_holds(v: claim_disposition_verdict(d: RuntimeErroredBeforeVerdict {})) && !verdict_holds(v: claim_disposition_verdict(d: ObservationUnreadableBeforeVerdict {})) - && !verdict_holds(v: claim_disposition_verdict(d: PanickedBeforeVerdict {})) - && !verdict_holds(v: claim_disposition_verdict(d: NotAttemptedAfterAbort {})) } // THE REFUSED ARM CARRIES THE DISPOSITION IT REFUSED, which is exactly what the deleted `Bool` @@ -477,21 +474,3 @@ test fn w_export_maps_budget_and_unreached_arms_apart() -> Bool { && (blaze_test_status_of_test_standing(t: TestReportedByBazel { status: TestStatusFlaky {} }) == TestStatusFlaky {}) && (blaze_test_status_of_test_standing(t: TestRunByFloor { disposition: Passed {} }) == TestStatusPassed {}) } - -// THE TWO ABORT-SIDE ARMS ARE SPLIT BY WHETHER THE CLAIM RAN, NOT BY SEVERITY, and this witness is -// what makes that split executable rather than a comment. A panic means the claim executed and -// died, so it exports as `FAILED` beside `RuntimeErroredBeforeVerdict`. An unattempted claim never -// executed at all, so it exports as `INCOMPLETE` beside `RouteGapBeforeVerdict`. -// -// The `INCOMPLETE` half is the assertion that earns its keep. Exporting a claim that never ran as -// `FAILED` would report that an assertion failed when no assertion executed — a verdict fabricated -// for an observation nobody made — so this witness goes red on exactly the collapse that is -// tempting to make, and the disposition-level pairing beneath it keeps the two from being merged -// in the other direction either. -test fn w_export_splits_panic_from_unattempted_by_whether_the_claim_ran() -> Bool { - (blaze_test_status_of_claim_disposition(d: PanickedBeforeVerdict {}) == TestStatusFailed {}) - && (blaze_test_status_of_claim_disposition(d: RuntimeErroredBeforeVerdict {}) == TestStatusFailed {}) - && (blaze_test_status_of_claim_disposition(d: NotAttemptedAfterAbort {}) == TestStatusIncomplete {}) - && !verdict_holds(v: claim_disposition_verdict(d: PanickedBeforeVerdict {})) - && !verdict_holds(v: claim_disposition_verdict(d: NotAttemptedAfterAbort {})) -} From a17db424081eef5e3005aa7adb46b572026196de Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 01:25:25 +0000 Subject: [PATCH 09/30] Carry occurrence identity through v1 Node construction --- src/v1/00_core.dag | 153 +-- src/v1/02_parse.dag | 983 +++++++++++------- src/v1/04_env.dag | 10 +- src/v1/04_infer.dag | 270 ++--- src/v1/04_items.dag | 10 +- src/v1/04_method.dag | 4 +- src/v1/04_patterns.dag | 16 +- src/v1/04_resolve.dag | 123 +-- src/v1/04_service.dag | 6 +- src/v1/04_types.dag | 56 +- src/v1/05_emit.dag | 4 +- src/v1/05_emit_rust.dag | 8 +- src/v1/compile.dag | 5 +- .../transport_roster_closure_witness_test.dag | 24 +- 14 files changed, 959 insertions(+), 713 deletions(-) diff --git a/src/v1/00_core.dag b/src/v1/00_core.dag index 0fcb5c02332..6ab31d603b5 100644 --- a/src/v1/00_core.dag +++ b/src/v1/00_core.dag @@ -10,6 +10,8 @@ import std.syntax { import std.algebra { CollectionSizeEffect, CostShape, AlgebraFieldTemplate } import std.induction { SubValueRelation } import std.occurrence_identity { + NodeOccurrenceIdentity, + OccurrenceSynthetic, AuthoredTokenOrdinalSpace, authored_token_ordinal_space_initial, authored_token_ordinal_space_from_allocator, @@ -547,6 +549,7 @@ type DeclaredFuncEnv { } type Node { + occurrence_identity: NodeOccurrenceIdentity name: String ident: Int? span: SourceSpan @@ -581,8 +584,9 @@ fn empty_node_list() -> List { [] } -fn make_expr_node(expr_data: ExprData, children: List, inferred: InferredNode?, span: SourceSpan) -> Node { +fn make_expr_node(occurrence_identity: NodeOccurrenceIdentity, expr_data: ExprData, children: List, inferred: InferredNode?, span: SourceSpan) -> Node { Node { + occurrence_identity: occurrence_identity, name: "", span: span, ident_span: none, children: children, connective: NoConnective, @@ -593,8 +597,9 @@ fn make_expr_node(expr_data: ExprData, children: List, inferred: InferredN } } -fn make_named_expr_node(name: String, expr_data: ExprData, children: List, inferred: InferredNode?, span: SourceSpan, name_span: SourceSpan) -> Node { +fn make_named_expr_node(occurrence_identity: NodeOccurrenceIdentity, name: String, expr_data: ExprData, children: List, inferred: InferredNode?, span: SourceSpan, name_span: SourceSpan) -> Node { Node { + occurrence_identity: occurrence_identity, name: name, span: span, ident_span: default_ident_span(name: name, span: name_span), children: children, connective: NoConnective, @@ -605,8 +610,9 @@ fn make_named_expr_node(name: String, expr_data: ExprData, children: List, } } -fn make_pattern_binder_declaration_node(name: String, span: SourceSpan) -> Node { +fn make_pattern_binder_declaration_node(occurrence_identity: NodeOccurrenceIdentity, name: String, span: SourceSpan) -> Node { make_named_expr_node( + occurrence_identity: occurrence_identity, name: name, expr_data: NoExprData, children: [], @@ -616,8 +622,9 @@ fn make_pattern_binder_declaration_node(name: String, span: SourceSpan) -> Node ) } -fn make_expr_error_node(kind: ExprErrorKind, message: String, span: SourceSpan) -> Node { +fn make_expr_error_node(occurrence_identity: NodeOccurrenceIdentity, kind: ExprErrorKind, message: String, span: SourceSpan) -> Node { Node { + occurrence_identity: occurrence_identity, name: "", span: span, ident_span: none, children: [], connective: NoConnective, params: [], inferred: Present { value: CompilerError { message: message, span: span } }, @@ -628,9 +635,10 @@ fn make_expr_error_node(kind: ExprErrorKind, message: String, span: SourceSpan) } } -fn make_arg_node(name: String?, value: Node, span: SourceSpan, name_span: SourceSpan) -> Node { +fn make_arg_node(occurrence_identity: NodeOccurrenceIdentity, name: String?, value: Node, span: SourceSpan, name_span: SourceSpan) -> Node { let arg_name = match name { Present { value: n } => n Absent => "" } Node { + occurrence_identity: occurrence_identity, name: arg_name, span: span, ident_span: default_ident_span(name: arg_name, span: name_span), children: [value], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, @@ -640,9 +648,10 @@ fn make_arg_node(name: String?, value: Node, span: SourceSpan, name_span: Source } } -fn make_arm_node(pattern: MatchPattern, guard: Node?, body: Node, span: SourceSpan) -> Node { +fn make_arm_node(occurrence_identity: NodeOccurrenceIdentity, pattern: MatchPattern, guard: Node?, body: Node, span: SourceSpan) -> Node { let children = match guard { Present { value: g } => [g, body] Absent => [body] } Node { + occurrence_identity: occurrence_identity, name: "", span: span, ident_span: none, children: children, connective: NoConnective, params: [], inferred: none, return_cardinality: Required, @@ -653,8 +662,9 @@ fn make_arm_node(pattern: MatchPattern, guard: Node?, body: Node, span: SourceSp } } -fn make_resource_use_node(name: String, resource: Node, span: SourceSpan, name_span: SourceSpan) -> Node { +fn make_resource_use_node(occurrence_identity: NodeOccurrenceIdentity, name: String, resource: Node, span: SourceSpan, name_span: SourceSpan) -> Node { Node { + occurrence_identity: occurrence_identity, name: name, span: span, ident_span: default_ident_span(name: name, span: name_span), children: [resource], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, @@ -669,12 +679,13 @@ fn resource_use_name_at(n: Node, source_indices: Map) -> S fn resource_use_resource(n: Node) -> Node { match n.children |> first { Present { value: v } => v - Absent => make_expr_error_node(kind: InternalExprError, message: "malformed resource-use: missing resource", span: n.span) + Absent => make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: "malformed resource-use: missing resource", span: n.span) } } -fn make_field_init_node(name: String, value: Node, span: SourceSpan, name_span: SourceSpan) -> Node { +fn make_field_init_node(occurrence_identity: NodeOccurrenceIdentity, name: String, value: Node, span: SourceSpan, name_span: SourceSpan) -> Node { Node { + occurrence_identity: occurrence_identity, name: name, span: span, ident_span: default_ident_span(name: name, span: name_span), children: [value], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, @@ -684,8 +695,9 @@ fn make_field_init_node(name: String, value: Node, span: SourceSpan, name_span: } } -fn make_field_binding_node(field_name: String, binding: MatchPattern, span: SourceSpan, name_span: SourceSpan) -> Node { +fn make_field_binding_node(occurrence_identity: NodeOccurrenceIdentity, field_name: String, binding: MatchPattern, span: SourceSpan, name_span: SourceSpan) -> Node { Node { + occurrence_identity: occurrence_identity, name: field_name, span: span, ident_span: default_ident_span(name: field_name, span: name_span), children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], @@ -700,8 +712,9 @@ fn field_binding_pattern(n: Node) -> MatchPattern { match n.match_pattern { Present { value: p } => p Absent => Wildcard } } -fn make_text_part_node(text: String, span: SourceSpan) -> Node { +fn make_text_part_node(occurrence_identity: NodeOccurrenceIdentity, text: String, span: SourceSpan) -> Node { Node { + occurrence_identity: occurrence_identity, name: "", span: span, ident_span: none, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, @@ -712,8 +725,9 @@ fn make_text_part_node(text: String, span: SourceSpan) -> Node { } } -fn make_interp_part_node(expr: Node, span: SourceSpan) -> Node { +fn make_interp_part_node(occurrence_identity: NodeOccurrenceIdentity, expr: Node, span: SourceSpan) -> Node { Node { + occurrence_identity: occurrence_identity, name: "", span: span, ident_span: none, children: [expr], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, @@ -723,9 +737,10 @@ fn make_interp_part_node(expr: Node, span: SourceSpan) -> Node { } } -fn make_param_node(name: String, type_expr: Node, default_value: Node?, span: SourceSpan, name_span: SourceSpan) -> Node { +fn make_param_node(occurrence_identity: NodeOccurrenceIdentity, name: String, type_expr: Node, default_value: Node?, span: SourceSpan, name_span: SourceSpan) -> Node { let children = match default_value { Present { value: dv } => [type_expr, dv] Absent => [type_expr] } Node { + occurrence_identity: occurrence_identity, name: name, span: span, ident_span: default_ident_span(name: name, span: name_span), children: children, connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], @@ -734,9 +749,10 @@ fn make_param_node(name: String, type_expr: Node, default_value: Node?, span: So } } -fn make_resolved_param_node(name: String, type_expr: Node, default_value: Node?, properties: List, span: SourceSpan, name_span: SourceSpan) -> Node { +fn make_resolved_param_node(occurrence_identity: NodeOccurrenceIdentity, name: String, type_expr: Node, default_value: Node?, properties: List, span: SourceSpan, name_span: SourceSpan) -> Node { let children = match default_value { Present { value: dv } => [type_expr, dv] Absent => [type_expr] } Node { + occurrence_identity: occurrence_identity, name: name, span: span, ident_span: default_ident_span(name: name, span: name_span), children: children, connective: NoConnective, params: [], inferred: Present { value: Resolved { node: type_expr } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: properties, @@ -781,7 +797,7 @@ fn has_child_named(n: Node, name: String, source_indices: Map Node { match n.children |> first { Present { value: v } => v - Absent => make_expr_error_node(kind: InternalExprError, message: "malformed param: missing type_expr", span: n.span) + Absent => make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: "malformed param: missing type_expr", span: n.span) } } @@ -793,16 +809,13 @@ fn param_node_default_value(n: Node) -> Node? { fn param_node_span(n: Node) -> SourceSpan { n.span } -fn make_field_node(name: String, type_expr: Node, cardinality: Cardinality, default_value: Node?, from_key: String?, span: SourceSpan, name_span: SourceSpan) -> Node { +fn make_field_node(occurrence_identity: NodeOccurrenceIdentity, name: String, type_expr: Node, cardinality: Cardinality, default_value: Node?, from_key_properties: List, span: SourceSpan, name_span: SourceSpan) -> Node { let children = match default_value { Present { value: dv } => [type_expr, dv] Absent => [type_expr] } - let props = match from_key { - Present { value: fk } => [make_field_init_node(name: "from_key", value: Node { name: fk, span: no_span(), ident_span: default_ident_span(name: fk, span: no_span()), children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, span: no_span(), name_span: no_span())] - Absent => [] - } Node { + occurrence_identity: occurrence_identity, name: name, span: span, ident_span: default_ident_span(name: name, span: name_span), children: children, connective: NoConnective, params: [], inferred: none, return_cardinality: cardinality, - uses: [], body: none, transport: none, properties: concat(props, type_expr.properties), + uses: [], body: none, transport: none, properties: concat(from_key_properties, type_expr.properties), type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } @@ -813,7 +826,7 @@ fn field_node_name_at(n: Node, source_indices: Map) -> Str fn field_node_type_expr(n: Node) -> Node { match n.children |> first { Present { value: v } => v - Absent => make_expr_error_node(kind: InternalExprError, message: "malformed field: missing type_expr", span: n.span) + Absent => make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: "malformed field: missing type_expr", span: n.span) } } @@ -834,8 +847,9 @@ fn field_node_from_key(n: Node, source_indices: Map) -> St fn field_node_span(n: Node) -> SourceSpan { n.span } -fn make_variant_node(name: String, fields: List, span: SourceSpan, name_span: SourceSpan) -> Node { +fn make_variant_node(occurrence_identity: NodeOccurrenceIdentity, name: String, fields: List, span: SourceSpan, name_span: SourceSpan) -> Node { Node { + occurrence_identity: occurrence_identity, name: name, span: span, ident_span: default_ident_span(name: name, span: name_span), children: fields, connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], @@ -1005,7 +1019,7 @@ fn is_property_contraction(func_name: String) -> Bool { fn expr_child_at(texpr: Node, index: Int, role: String) -> Node { match texpr.children |> skip(index) |> first { Present { value: v } => v - Absent => make_expr_error_node(kind: InternalExprError, message: concat("malformed node: missing ", role), span: texpr.span) + Absent => make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: concat("malformed node: missing ", role), span: texpr.span) } } @@ -1017,7 +1031,7 @@ fn arg_name_at(n: Node, source_indices: Map) -> String? { fn arg_value(n: Node) -> Node { match n.children |> first { Present { value: v } => v - Absent => make_expr_error_node(kind: InternalExprError, message: "malformed arg: missing value", span: n.span) + Absent => make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: "malformed arg: missing value", span: n.span) } } @@ -1032,7 +1046,7 @@ fn arm_guard(n: Node) -> Node? { fn arm_body(n: Node) -> Node { match n.children |> last { Present { value: v } => v - Absent => make_expr_error_node(kind: InternalExprError, message: "malformed arm: missing body", span: n.span) + Absent => make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: "malformed arm: missing body", span: n.span) } } @@ -1043,7 +1057,7 @@ fn field_init_node_name_at(n: Node, source_indices: Map) - fn field_init_node_value(n: Node) -> Node { match n.children |> first { Present { value: v } => v - Absent => make_expr_error_node(kind: InternalExprError, message: "malformed field-init: missing value", span: n.span) + Absent => make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: "malformed field-init: missing value", span: n.span) } } @@ -1273,8 +1287,9 @@ data transport_headers_key: String = "headers" data transport_auth_basic_key: String = "auth_basic" data transport_tls_key: String = "tls" -fn make_transport_node(properties: List, children: List, body: Node?, span: SourceSpan) -> Node { +fn make_transport_node(occurrence_identity: NodeOccurrenceIdentity, properties: List, children: List, body: Node?, span: SourceSpan) -> Node { Node { + occurrence_identity: occurrence_identity, name: "", span: span, ident_span: none, children: children, connective: NoConnective, params: [], inferred: none, return_cardinality: Required, @@ -1284,46 +1299,46 @@ fn make_transport_node(properties: List, children: List, body: Node? } } -fn local_transport_node(span: SourceSpan) -> Node { - make_transport_node(properties: [], children: [], body: none, span: span) +fn local_transport_node(occurrence_identity: NodeOccurrenceIdentity, span: SourceSpan) -> Node { + make_transport_node(occurrence_identity: occurrence_identity, properties: [], children: [], body: none, span: span) } -fn rest_transport_node(base_url: Node, auth_props: List, headers: List, method: Node?, path: Node?, query: Node?, request_body: Node?, response_format: Node?, span: SourceSpan) -> Node { +fn rest_transport_node(occurrence_identity: NodeOccurrenceIdentity, base_url: Node, auth_props: List, headers: List, method: Node?, path: Node?, query: Node?, request_body: Node?, response_format: Node?, span: SourceSpan) -> Node { let zero_span = no_span() - let url_field = make_field_init_node(name: transport_url_key, value: base_url, span: zero_span, name_span: zero_span) + let url_field = make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: transport_url_key, value: base_url, span: zero_span, name_span: zero_span) let method_props = match method { - Present { value: m } => [make_field_init_node(name: transport_method_key, value: m, span: zero_span, name_span: zero_span)] + Present { value: m } => [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: transport_method_key, value: m, span: zero_span, name_span: zero_span)] Absent => [] } let path_props = match path { - Present { value: p } => [make_field_init_node(name: transport_path_template_key, value: p, span: zero_span, name_span: zero_span)] + Present { value: p } => [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: transport_path_template_key, value: p, span: zero_span, name_span: zero_span)] Absent => [] } let query_props = match query { - Present { value: q } => [make_field_init_node(name: transport_query_key, value: q, span: zero_span, name_span: zero_span)] + Present { value: q } => [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: transport_query_key, value: q, span: zero_span, name_span: zero_span)] Absent => [] } let body_props = match request_body { - Present { value: b } => [make_field_init_node(name: transport_body_key, value: b, span: zero_span, name_span: zero_span)] + Present { value: b } => [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: transport_body_key, value: b, span: zero_span, name_span: zero_span)] Absent => [] } let rf_props = match response_format { - Present { value: rf } => [make_field_init_node(name: transport_response_format_key, value: rf, span: zero_span, name_span: zero_span)] + Present { value: rf } => [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: transport_response_format_key, value: rf, span: zero_span, name_span: zero_span)] Absent => [] } let props = concat([url_field], method_props, path_props, query_props, body_props, rf_props, auth_props, headers) - make_transport_node(properties: props, children: [], body: none, span: span) + make_transport_node(occurrence_identity: occurrence_identity, properties: props, children: [], body: none, span: span) } -fn shell_transport_node(argv: List, env: List, stdin: Node?, span: SourceSpan) -> Node { - let shell_marker = Node { name: "", span: span, ident_span: none, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } +fn shell_transport_node(occurrence_identity: NodeOccurrenceIdentity, argv: List, env: List, stdin: Node?, span: SourceSpan) -> Node { + let shell_marker = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: span, ident_span: none, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let zero_span = no_span() let stdin_props = match stdin { - Present { value: s } => [make_field_init_node(name: transport_stdin_key, value: s, span: zero_span, name_span: zero_span)] + Present { value: s } => [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: transport_stdin_key, value: s, span: zero_span, name_span: zero_span)] Absent => [] } let all_props = concat(env, stdin_props) - Node { + Node { occurrence_identity: occurrence_identity, name: "", span: span, ident_span: none, children: argv, connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: Present { value: shell_marker }, transport: none, properties: all_props, @@ -1332,14 +1347,14 @@ fn shell_transport_node(argv: List, env: List, stdin: Node?, span: S } } -fn file_transport_node(base_path: Node, verb: Node?, span: SourceSpan) -> Node { - let path_field = make_field_init_node(name: transport_path_key, value: base_path, span: no_span(), name_span: no_span()) +fn file_transport_node(occurrence_identity: NodeOccurrenceIdentity, base_path: Node, verb: Node?, span: SourceSpan) -> Node { + let path_field = make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: transport_path_key, value: base_path, span: no_span(), name_span: no_span()) let props = match verb { Present { value: verb_expr } => - [path_field, make_field_init_node(name: transport_verb_key, value: verb_expr, span: no_span(), name_span: no_span())] + [path_field, make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: transport_verb_key, value: verb_expr, span: no_span(), name_span: no_span())] Absent => [path_field] } - make_transport_node(properties: props, children: [], body: none, span: span) + make_transport_node(occurrence_identity: occurrence_identity, properties: props, children: [], body: none, span: span) } fn find_property(props: List, prop_name: String, source_indices: Map) -> Node? { @@ -1596,7 +1611,7 @@ fn transport_env(t: Node, source_indices: Map) -> List Node) -> Node { - Node { + Node { occurrence_identity: node.occurrence_identity, name: node.name, ident: node.ident, span: node.span, ident_span: node.ident_span, children: node.children |> map(child => transform(child)), connective: node.connective, @@ -1729,21 +1744,21 @@ fn service_config_field_for_property_name(name: String) -> ServiceConfigField? { // site, not as a literal frozen into a dependency's module. fn service_config_properties(endpoint: Node, auth: Node?, auth_input: Node?, auth_source: Node?, rate_limit: Node?) -> List { let zero_span = no_span() - let ep_prop = [make_field_init_node(name: service_config_field_property_name(field: SvcEndpoint), value: endpoint, span: zero_span, name_span: zero_span)] + let ep_prop = [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: service_config_field_property_name(field: SvcEndpoint), value: endpoint, span: zero_span, name_span: zero_span)] let auth_prop = match auth { - Present { value: a } => [make_field_init_node(name: service_config_field_property_name(field: SvcAuth), value: a, span: zero_span, name_span: zero_span)] + Present { value: a } => [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: service_config_field_property_name(field: SvcAuth), value: a, span: zero_span, name_span: zero_span)] Absent => [] } let auth_input_prop = match auth_input { - Present { value: ai } => [make_field_init_node(name: service_config_field_property_name(field: SvcAuthInput), value: ai, span: zero_span, name_span: zero_span)] + Present { value: ai } => [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: service_config_field_property_name(field: SvcAuthInput), value: ai, span: zero_span, name_span: zero_span)] Absent => [] } let auth_source_prop = match auth_source { - Present { value: src } => [make_field_init_node(name: service_config_field_property_name(field: SvcAuthSource), value: src, span: zero_span, name_span: zero_span)] + Present { value: src } => [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: service_config_field_property_name(field: SvcAuthSource), value: src, span: zero_span, name_span: zero_span)] Absent => [] } let rate_prop = match rate_limit { - Present { value: r } => [make_field_init_node(name: service_config_field_property_name(field: SvcRateLimit), value: r, span: zero_span, name_span: zero_span)] + Present { value: r } => [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: service_config_field_property_name(field: SvcRateLimit), value: r, span: zero_span, name_span: zero_span)] Absent => [] } concat(ep_prop, auth_prop, auth_input_prop, auth_source_prop, rate_prop) @@ -1773,8 +1788,8 @@ fn service_config_auth_source(n: Node, source_indices: Map find_property(props: n.properties, prop_name: "svc_auth_source", source_indices: source_indices) } -fn module_node(name: String, imports: List, items: List, span: SourceSpan) -> Node { - Node { +fn module_node(occurrence_identity: NodeOccurrenceIdentity, name: String, imports: List, items: List, span: SourceSpan) -> Node { + Node { occurrence_identity: occurrence_identity, name: name, span: span, ident_span: default_ident_span(name: name, span: span), children: items, connective: NoConnective, params: imports, inferred: none, return_cardinality: Required, @@ -1784,11 +1799,11 @@ fn module_node(name: String, imports: List, items: List, span: Sourc } } -fn import_node(module_path: String, is_all: Bool, specific_names: List, span: SourceSpan, name_span: SourceSpan) -> Node { +fn import_node(occurrence_identity: NodeOccurrenceIdentity, module_path: String, is_all: Bool, specific_names: List, span: SourceSpan, name_span: SourceSpan) -> Node { let wildcard_marker = if is_all { - Present { value: Node { name: "", span: span, ident_span: none, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } + Present { value: Node { occurrence_identity: OccurrenceSynthetic, name: "", span: span, ident_span: none, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } } else { none } - Node { + Node { occurrence_identity: occurrence_identity, name: module_path, span: span, ident_span: Present { value: name_span }, children: specific_names, connective: NoConnective, params: [], inferred: none, return_cardinality: Required, @@ -1814,23 +1829,23 @@ fn module_items(n: Node) -> List { n.children } -fn leaf_node_with_span(name: String, span: SourceSpan) -> Node { - Node { name: name, span: span, ident_span: default_ident_span(name: name, span: span), children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } +fn leaf_node_with_span(occurrence_identity: NodeOccurrenceIdentity, name: String, span: SourceSpan) -> Node { + Node { occurrence_identity: occurrence_identity, name: name, span: span, ident_span: default_ident_span(name: name, span: span), children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn kernel_span(name: String) -> SourceSpan { SourceSpan { file: concat(""), start: 0, end: string_length(s: name) } } -data unit_type: Node = Node { name: "Unit", span: kernel_span(name: "Unit"), ident_span: Present { value: kernel_span(name: "Unit") }, children: [], connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } -data bool_type: Node = Node { name: "Bool", span: kernel_span(name: "Bool"), ident_span: Present { value: kernel_span(name: "Bool") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } -data string_type: Node = Node { name: "String", span: kernel_span(name: "String"), ident_span: Present { value: kernel_span(name: "String") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } -data hash_type: Node = Node { name: "Hash", span: kernel_span(name: "Hash"), ident_span: Present { value: kernel_span(name: "Hash") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } -data int_type: Node = Node { name: "Int", span: kernel_span(name: "Int"), ident_span: Present { value: kernel_span(name: "Int") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } -data float_type: Node = Node { name: "Float", span: kernel_span(name: "Float"), ident_span: Present { value: kernel_span(name: "Float") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } -data none_type: Node = Node { name: "None", span: kernel_span(name: "None"), ident_span: Present { value: kernel_span(name: "None") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } +data unit_type: Node = Node { occurrence_identity: OccurrenceSynthetic, name: "Unit", span: kernel_span(name: "Unit"), ident_span: Present { value: kernel_span(name: "Unit") }, children: [], connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } +data bool_type: Node = Node { occurrence_identity: OccurrenceSynthetic, name: "Bool", span: kernel_span(name: "Bool"), ident_span: Present { value: kernel_span(name: "Bool") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } +data string_type: Node = Node { occurrence_identity: OccurrenceSynthetic, name: "String", span: kernel_span(name: "String"), ident_span: Present { value: kernel_span(name: "String") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } +data hash_type: Node = Node { occurrence_identity: OccurrenceSynthetic, name: "Hash", span: kernel_span(name: "Hash"), ident_span: Present { value: kernel_span(name: "Hash") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } +data int_type: Node = Node { occurrence_identity: OccurrenceSynthetic, name: "Int", span: kernel_span(name: "Int"), ident_span: Present { value: kernel_span(name: "Int") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } +data float_type: Node = Node { occurrence_identity: OccurrenceSynthetic, name: "Float", span: kernel_span(name: "Float"), ident_span: Present { value: kernel_span(name: "Float") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } +data none_type: Node = Node { occurrence_identity: OccurrenceSynthetic, name: "None", span: kernel_span(name: "None"), ident_span: Present { value: kernel_span(name: "None") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } data tuple_type_name: String = "Tuple" -data error_type: Node = Node { name: "", span: no_span(), ident_span: none, children: [], connective: NoConnective, params: [], inferred: Present { value: CompilerError { message: "unresolved type", span: no_span() } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: ExprError { kind: SemanticExprError, message: "unresolved type" } } +data error_type: Node = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: no_span(), ident_span: none, children: [], connective: NoConnective, params: [], inferred: Present { value: CompilerError { message: "unresolved type", span: no_span() } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: ExprError { kind: SemanticExprError, message: "unresolved type" } } fn make_file_span(file: String, start: Int, end: Int) -> SourceSpan { SourceSpan { file: file, start: start, end: end } @@ -2006,11 +2021,11 @@ fn pre_intern_tokens(tokens: List, table: InternTable) -> InternTable { } fn with_optional_cardinality(n: Node) -> Node { - Node { name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, children: n.children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: CardOptional, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: n.is_self_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } + Node { occurrence_identity: n.occurrence_identity, name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, children: n.children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: CardOptional, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: n.is_self_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } } fn with_required_cardinality(n: Node) -> Node { - Node { name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, children: n.children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: Required, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: n.is_self_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } + Node { occurrence_identity: n.occurrence_identity, name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, children: n.children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: Required, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: n.is_self_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } } fn join_optional_cardinality(left: Cardinality, right: Cardinality) -> Cardinality { diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index 565eff129c2..04dc87a998e 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -52,6 +52,8 @@ import v1.std.core { } import std.occurrence_identity { AuthoredTokenOrdinalSpace, + NodeOccurrenceIdentity, + OccurrenceSynthetic, OccurrenceId, OccurrenceIdAllocator, OccurrenceIdAllocResult, @@ -73,6 +75,7 @@ import std.occurrence_identity { occurrence_id_allocator_initial, occurrence_id_allocator_advance_to, alloc_occurrence_id, + node_occurrence_identity_minted, } import std.algebra { FreeMonoid, Empty, Cons } @@ -170,6 +173,30 @@ type ParsedOccurrenceRole | ParsedOccurrenceDeclaration { category: OccurrenceCategory } | ParsedOccurrenceReference { category: OccurrenceCategory } +// The parser's sole ordinary authored-occurrence mint. ParseContext is persistent: +// callers publish mint.ctx only on the branch whose Node survives, so a refused or +// speculative branch discards its advanced allocator together with that branch. +type ParsedNodeIdentityMint { + identity: NodeOccurrenceIdentity + ctx: ParseContext +} + +fn mint_parsed_node_identity(ctx: ParseContext) -> ParsedNodeIdentityMint { + let allocated = alloc_occurrence_id( + alloc: parse_context_occurrence_allocator(ctx: ctx) + ) + ParsedNodeIdentityMint { + identity: node_occurrence_identity_minted(id: allocated.id), + ctx: parse_context_with_occurrence_state( + ctx: ctx, + occurrence_allocator: Present { value: allocated.alloc }, + occurrence_index: ctx.occurrence_index, + declaration_occurrences: ctx.declaration_occurrences, + reference_occurrences: ctx.reference_occurrences + ), + } +} + fn parse_context_occurrence_allocator(ctx: ParseContext) -> OccurrenceIdAllocator { match ctx.occurrence_allocator { Present { value: allocator } => allocator @@ -236,7 +263,7 @@ fn parse_context_with_intern_table( } fn parsed_node_with_ident(node: Node, ident: Int) -> Node { - Node { + Node { occurrence_identity: node.occurrence_identity, name: node.name, ident: Present { value: ident }, span: node.span, @@ -285,6 +312,102 @@ type FieldResult { field: Node, tokens: TokenStream, ctx: ParseContext, err: Err type FieldInitResult { field: Node, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type AdmitCallersResult { props: List, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type ResUseResult { resource_use: Node, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } +type ParsedPropertiesResult { properties: List, ctx: ParseContext } +type ParsedPropertyResult { property: Node, ctx: ParseContext } +type ParsedNodesResult { nodes: List, ctx: ParseContext } + +fn parsed_expr_result( + tokens: TokenStream, + ctx: ParseContext, + build: fn(NodeOccurrenceIdentity) -> Node +) -> ExprResult { + let minted = mint_parsed_node_identity(ctx: ctx) + ExprResult { + expr: build(minted.identity), + tokens: tokens, + ctx: minted.ctx, + err: none, + } +} + +fn parsed_sole_constructor_properties(ctx: ParseContext, enabled: Bool, span: SourceSpan) -> ParsedPropertiesResult { + if enabled { + let value_mint = mint_parsed_node_identity(ctx: ctx) + let property_mint = mint_parsed_node_identity(ctx: value_mint.ctx) + ParsedPropertiesResult { + properties: [make_field_init_node( + occurrence_identity: property_mint.identity, + name: "sole_constructor", + value: make_expr_node(occurrence_identity: value_mint.identity, expr_data: ExprLiteral { value: LitBool { value: true } }, children: [], inferred: none, span: span), + span: span, + name_span: no_span() + )], + ctx: property_mint.ctx, + } + } else { + ParsedPropertiesResult { properties: [], ctx: ctx } + } +} + +fn mint_parsed_bool_property(ctx: ParseContext, name: String, span: SourceSpan) -> ParsedPropertyResult { + let value_mint = mint_parsed_node_identity(ctx: ctx) + let property_mint = mint_parsed_node_identity(ctx: value_mint.ctx) + ParsedPropertyResult { + property: make_field_init_node( + occurrence_identity: property_mint.identity, + name: name, + value: make_expr_node(occurrence_identity: value_mint.identity, expr_data: ExprLiteral { value: LitBool { value: true } }, children: [], inferred: none, span: span), + span: span, + name_span: span + ), + ctx: property_mint.ctx, + } +} + +fn mint_parsed_optional_int_property(ctx: ParseContext, name: String, value: Int?, span: SourceSpan) -> ParsedPropertiesResult { + match value { + Present { value: n } => { + let value_mint = mint_parsed_node_identity(ctx: ctx) + let property_mint = mint_parsed_node_identity(ctx: value_mint.ctx) + ParsedPropertiesResult { + properties: [make_field_init_node(occurrence_identity: property_mint.identity, name: name, value: make_expr_node(occurrence_identity: value_mint.identity, expr_data: ExprLiteral { value: LitInt { value: n } }, children: [], inferred: none, span: span), span: span, name_span: span)], + ctx: property_mint.ctx, + } + } + Absent => ParsedPropertiesResult { properties: [], ctx: ctx } + } +} + +fn mint_parsed_string_part_nodes(parts: List, ctx: ParseContext, span: SourceSpan, acc: List) -> ParsedNodesResult { + match parts |> first { + Present { value: part } => { + let minted = mint_parsed_node_identity(ctx: ctx) + let node = match part { + Text { value: text } => make_text_part_node(occurrence_identity: minted.identity, text: text, span: span) + Interpolation { expr: expr } => make_interp_part_node(occurrence_identity: minted.identity, expr: expr, span: span) + } + mint_parsed_string_part_nodes(parts: parts |> skip(1), ctx: minted.ctx, span: span, acc: list_push(acc, node)) + } + Absent => ParsedNodesResult { nodes: acc, ctx: ctx } + } +} + +// Predicate values are structurally inside their field-init wrapper, so this +// helper mints the child first and the enclosing occurrence second. +fn parsed_predicate_result( + tokens: TokenStream, + ctx: ParseContext, + build: fn(NodeOccurrenceIdentity, NodeOccurrenceIdentity) -> Node +) -> PredResult { + let value_mint = mint_parsed_node_identity(ctx: ctx) + let predicate_mint = mint_parsed_node_identity(ctx: value_mint.ctx) + PredResult { + predicate: build(value_mint.identity, predicate_mint.identity), + tokens: tokens, + ctx: predicate_mint.ctx, + err: none, + } +} type ItemPrefixResult { name: String @@ -335,11 +458,11 @@ type ArgsResult { args: List, tokens: TokenStream, ctx: ParseContext, err: type StmtsResult { stmts: List, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type ExprsResult { exprs: List, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type ArmsResult { arms: List, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } -type ModsResult { modifiers: List, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } +type ModsResult { properties: List, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type BindingsResult { field_bindings: List, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } fn parse_recovery_expr(span: SourceSpan, message: String) -> Node { - make_expr_error_node(kind: ParseRecoveryError, message: message, span: span) + make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: ParseRecoveryError, message: message, span: span) } fn parse_recovery_placeholder() -> Node { @@ -351,7 +474,7 @@ fn parse_recovery_placeholder() -> Node { type OptRetResult { inferred: InferredNode?, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type GuardResult { guard: Node?, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } -type FromKeyResult { from_key: String?, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } +type FromKeyResult { properties: List, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type PostfixResult { expr: Node, changed: Bool, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type ParserParam { name: String, span: SourceSpan } @@ -955,12 +1078,12 @@ fn parser_result_witness(expr: Node, source_indices: Map) } } -fn leaf_type_node(name: String, span: SourceSpan) -> Node { - Node { name: name, span: span, ident_span: if name == "" { none } else { Present { value: span } }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } +fn leaf_type_node(occurrence_identity: NodeOccurrenceIdentity, name: String, span: SourceSpan) -> Node { + Node { occurrence_identity: occurrence_identity, name: name, span: span, ident_span: if name == "" { none } else { Present { value: span } }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } -fn literal_width_nat_type_node(value: Int, span: SourceSpan) -> Node { - Node { name: "", span: span, ident_span: none, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: ExprLiteral { value: LitInt { value: value } } } +fn literal_width_nat_type_node(occurrence_identity: NodeOccurrenceIdentity, value: Int, span: SourceSpan) -> Node { + Node { occurrence_identity: occurrence_identity, name: "", span: span, ident_span: none, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: ExprLiteral { value: LitInt { value: value } } } } fn parse_type_angle_arg(tokens: TokenStream, ctx: ParseContext) -> TypeResult { @@ -972,9 +1095,10 @@ fn parse_type_angle_arg(tokens: TokenStream, ctx: ParseContext) -> TypeResult { Present { value: ShLitInt } => { let r = parse_int_literal_value(tokens: tokens) if has_err(err: r.err) { - TypeResult { type_expr: leaf_type_node(name: "", span: span), tokens: r.tokens, ctx: ctx, err: r.err } + TypeResult { type_expr: leaf_type_node(occurrence_identity: OccurrenceSynthetic, name: "", span: span), tokens: r.tokens, ctx: ctx, err: r.err } } else { - TypeResult { type_expr: literal_width_nat_type_node(value: r.value, span: span), tokens: r.tokens, ctx: ctx, err: none } + let minted = mint_parsed_node_identity(ctx: ctx) + TypeResult { type_expr: literal_width_nat_type_node(occurrence_identity: minted.identity, value: r.value, span: span), tokens: r.tokens, ctx: minted.ctx, err: none } } } _ => parse_type_expr(tokens: tokens, ctx: ctx) @@ -997,12 +1121,12 @@ fn node_inferred_to_outputs(rt: Node, source_indices: Map) let all_children_typed = rt.children |> all(ch => match ch.inferred { Present { value: Resolved { node: _ } } => true _ => false }) if all_children_typed { rt.children - |> map(ch => make_field_node(name: authored_name_at(source_indices: source_indices, node: ch), type_expr: child_inferred_or_empty(ch: ch), cardinality: Required, default_value: ch.body, from_key: none, span: ch.span, name_span: node_name_span(n: ch))) + |> map(ch => make_field_node(occurrence_identity: OccurrenceSynthetic, name: authored_name_at(source_indices: source_indices, node: ch), type_expr: child_inferred_or_empty(ch: ch), cardinality: Required, default_value: ch.body, from_key_properties: [], span: ch.span, name_span: node_name_span(n: ch))) } else { [] } } else { - [make_field_node(name: "value", type_expr: rt, cardinality: Required, default_value: none, from_key: none, span: rt.span, name_span: no_span())] + [make_field_node(occurrence_identity: OccurrenceSynthetic, name: "value", type_expr: rt, cardinality: Required, default_value: none, from_key_properties: [], span: rt.span, name_span: no_span())] } } @@ -1575,23 +1699,23 @@ fn parse_module(tokens: TokenStream, ctx: ParseContext) -> ModuleResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) let r = expect(tokens: tokens, expected: ExpectKeyword { text: "module" }) - if has_err(err: r.err) { return ModuleResult { module: module_node(name: "", imports: [], items: [], span: start_span), tokens: r.tokens, ctx: ctx, err: r.err } } + if has_err(err: r.err) { return ModuleResult { module: module_node(occurrence_identity: OccurrenceSynthetic, name: "", imports: [], items: [], span: start_span), tokens: r.tokens, ctx: ctx, err: r.err } } let tokens = r.tokens let r = parse_dotted_ident(tokens: tokens) - if has_err(err: r.err) { return ModuleResult { module: module_node(name: "", imports: [], items: [], span: start_span), tokens: r.tokens, ctx: ctx, err: r.err } } + if has_err(err: r.err) { return ModuleResult { module: module_node(occurrence_identity: OccurrenceSynthetic, name: "", imports: [], items: [], span: start_span), tokens: r.tokens, ctx: ctx, err: r.err } } let mod_name = r.name let mod_name_span = r.span let tokens = skip_newlines(tokens: r.tokens) let r = parse_imports(tokens: tokens, ctx: ctx) - if has_err(err: r.err) { return ModuleResult { module: module_node(name: "", imports: [], items: [], span: start_span), tokens: r.tokens, ctx: r.ctx, err: r.err } } + if has_err(err: r.err) { return ModuleResult { module: module_node(occurrence_identity: OccurrenceSynthetic, name: "", imports: [], items: [], span: start_span), tokens: r.tokens, ctx: r.ctx, err: r.err } } let imports = r.imports let tokens = r.tokens let ctx = r.ctx let r = parse_items(tokens: tokens, ctx: ctx) - if has_err(err: r.err) { return ModuleResult { module: module_node(name: "", imports: [], items: [], span: start_span), tokens: r.tokens, ctx: r.ctx, err: r.err } } + if has_err(err: r.err) { return ModuleResult { module: module_node(occurrence_identity: OccurrenceSynthetic, name: "", imports: [], items: [], span: start_span), tokens: r.tokens, ctx: r.ctx, err: r.err } } let items = r.items let tokens = r.tokens let ctx = r.ctx @@ -1601,7 +1725,8 @@ fn parse_module(tokens: TokenStream, ctx: ParseContext) -> ModuleResult { ctx: ctx, intern_table: mod_ir.table ) - let base_mod = Node { + let minted = mint_parsed_node_identity(ctx: ctx) + let base_mod = Node { occurrence_identity: minted.identity, name: mod_name, span: start_span, ident_span: Present { value: mod_name_span }, children: items, connective: NoConnective, @@ -1611,7 +1736,7 @@ fn parse_module(tokens: TokenStream, ctx: ParseContext) -> ModuleResult { has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let mod = parsed_node_with_ident(node: base_mod, ident: mod_ir.id) - ModuleResult { module: mod, tokens: tokens, ctx: ctx, err: none } + ModuleResult { module: mod, tokens: tokens, ctx: minted.ctx, err: none } } fn parse_imports(tokens: TokenStream, ctx: ParseContext) -> ImportsResult { @@ -1646,7 +1771,7 @@ fn parse_items_acc(tokens: TokenStream, ctx: ParseContext, acc: List) -> I fn parse_import(tokens: TokenStream, ctx: ParseContext) -> ImportResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let err_import = import_node(module_path: "", is_all: false, specific_names: [], span: start_span, name_span: start_span) + let err_import = import_node(occurrence_identity: OccurrenceSynthetic, module_path: "", is_all: false, specific_names: [], span: start_span, name_span: start_span) let r = expect(tokens: tokens, expected: ExpectKeyword { text: "import" }) if has_err(err: r.err) { return ImportResult { import: err_import, tokens: r.tokens, ctx: ctx, err: r.err } } let tokens = r.tokens @@ -1678,20 +1803,22 @@ fn parse_import(tokens: TokenStream, ctx: ParseContext) -> ImportResult { let r = expect(tokens: tokens, expected: ExpectRBrace) if has_err(err: r.err) { return ImportResult { import: err_import, tokens: r.tokens, ctx: ctx, err: r.err } } let tokens = skip_newlines(tokens: r.tokens) - let base_imp = import_node(module_path: mod_path, is_all: false, specific_names: names, span: start_span, name_span: mod_path_span) + let minted = mint_parsed_node_identity(ctx: ctx) + let base_imp = import_node(occurrence_identity: minted.identity, module_path: mod_path, is_all: false, specific_names: names, span: start_span, name_span: mod_path_span) let imp_ir = intern(table: ctx.intern_table, s: mod_path) let ctx = parse_context_with_intern_table( - ctx: ctx, + ctx: minted.ctx, intern_table: imp_ir.table ) let imp = parsed_node_with_ident(node: base_imp, ident: imp_ir.id) ImportResult { import: imp, tokens: tokens, ctx: ctx, err: none } EatUnchanged { tokens: __eu } => let tokens = skip_newlines(tokens: tokens) - let base_imp = import_node(module_path: mod_path, is_all: true, specific_names: [], span: start_span, name_span: mod_path_span) + let minted = mint_parsed_node_identity(ctx: ctx) + let base_imp = import_node(occurrence_identity: minted.identity, module_path: mod_path, is_all: true, specific_names: [], span: start_span, name_span: mod_path_span) let imp_ir = intern(table: ctx.intern_table, s: mod_path) let ctx = parse_context_with_intern_table( - ctx: ctx, + ctx: minted.ctx, intern_table: imp_ir.table ) let imp = parsed_node_with_ident(node: base_imp, ident: imp_ir.id) @@ -1703,8 +1830,8 @@ fn parse_import_names(tokens: TokenStream, ctx: ParseContext) -> NamesResult { parse_import_names_acc(tokens: tokens, ctx: ctx, acc: []) } -fn parsed_name_leaf(name: String, span: SourceSpan) -> Node { - leaf_node_with_span(name: name, span: span) +fn parsed_name_leaf(occurrence_identity: NodeOccurrenceIdentity, name: String, span: SourceSpan) -> Node { + leaf_node_with_span(occurrence_identity: occurrence_identity, name: name, span: span) } fn parse_import_names_acc(tokens: TokenStream, ctx: ParseContext, acc: List) -> NamesResult { @@ -1714,11 +1841,12 @@ fn parse_import_names_acc(tokens: TokenStream, ctx: ParseContext, acc: List __ec EatUnchanged { tokens: _ } => tokens }) - parse_import_names_acc(tokens: tokens, ctx: ctx, acc: list_push(acc, name_node)) + parse_import_names_acc(tokens: tokens, ctx: minted.ctx, acc: list_push(acc, name_node)) } } @@ -1739,7 +1867,7 @@ fn parse_item(tokens: TokenStream, ctx: ParseContext) -> ItemResult { let form = find_item_form(forms: dag_syntax_spec.item_forms, keyword: kw) match form { Present { value: f } => parse_item_by_form(tokens: tokens, ctx: ctx, form: f) - Absent => ItemResult { item: Node { name: "", span: span, ident_span: Present { value: span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: "expected item declaration (alias, type, fn, func, service, resource, data, extern, pattern, interface)", span: span) } } + Absent => ItemResult { item: Node { occurrence_identity: OccurrenceSynthetic, name: "", span: span, ident_span: Present { value: span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: "expected item declaration (alias, type, fn, func, service, resource, data, extern, pattern, interface)", span: span) } } } } @@ -1792,7 +1920,7 @@ fn parse_item_prefix(tokens: TokenStream, ctx: ParseContext, form: ItemForm) -> fn parse_item_by_form(tokens: TokenStream, ctx: ParseContext, form: ItemForm) -> ItemResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect(tokens: tokens, expected: ExpectKeyword { text: form.keyword }) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } let tokens = r.tokens @@ -1826,22 +1954,18 @@ fn parse_item_by_form(tokens: TokenStream, ctx: ParseContext, form: ItemForm) -> fn field_to_child_node(field: Node, source_indices: Map) -> Node { let ret_type = field_node_type_expr(n: field) - let props = match field_node_from_key(n: field, source_indices: source_indices) { - Present { value: key } => [make_field_init_node(name: "from_key", value: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: key } }, children: [], inferred: none, span: field.span), span: field.span, name_span: no_span())] - Absent => [] - } - Node { name: field_node_name_at(n: field, source_indices: source_indices), span: field.span, ident_span: field.ident_span, + Node { occurrence_identity: field.occurrence_identity, name: field_node_name_at(n: field, source_indices: source_indices), span: field.span, ident_span: field.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: ret_type } }, return_cardinality: field_node_cardinality(n: field), uses: [], body: field_node_default_value(n: field), - transport: none, properties: props, + transport: none, properties: field.properties, type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn variant_to_child_node(variant: Node, source_indices: Map) -> Node { let fields = variant_node_fields(n: variant) let children = fields |> map(f => field_to_child_node(field: f, source_indices: source_indices)) - Node { name: variant_node_name_at(n: variant, source_indices: source_indices), span: variant.span, ident_span: variant.ident_span, + Node { occurrence_identity: variant.occurrence_identity, name: variant_node_name_at(n: variant, source_indices: source_indices), span: variant.span, ident_span: variant.ident_span, children: children, connective: if fields |> count > 0 { Conj } else { NoConnective }, params: [], inferred: none, return_cardinality: Required, @@ -1852,17 +1976,17 @@ fn variant_to_child_node(variant: Node, source_indices: Map, span: SourceSpan, source_indices: Map) -> InferredNode? { if outputs |> count > 0 { - Present { value: Resolved { node: Node { name: "", span: span, ident_span: none, children: map(outputs, f => field_to_child_node(field: f, source_indices: source_indices)), connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } } + Present { value: Resolved { node: Node { occurrence_identity: OccurrenceSynthetic, name: "", span: span, ident_span: none, children: map(outputs, f => field_to_child_node(field: f, source_indices: source_indices)), connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } } } else { none } } -fn make_operation_node(name: String, ident_span: SourceSpan?, inputs: List, outputs: List, response_props: List, mock_props: List, exit_props: List, modifier_props: List, transport: Node?, span: SourceSpan, source_indices: Map) -> Node { +fn make_operation_node(occurrence_identity: NodeOccurrenceIdentity, name: String, ident_span: SourceSpan?, inputs: List, outputs: List, response_props: List, mock_props: List, exit_props: List, modifier_props: List, transport: Node?, span: SourceSpan, source_indices: Map) -> Node { let all_props = concat(modifier_props, response_props, exit_props, mock_props) - Node { name: name, span: span, ident_span: ident_span, + Node { occurrence_identity: occurrence_identity, name: name, span: span, ident_span: ident_span, children: [], - params: inputs |> map(f => make_param_node( + params: inputs |> map(f => make_param_node(occurrence_identity: f.occurrence_identity, name: field_node_name_at(n: f, source_indices: source_indices), type_expr: field_node_type_expr(n: f), default_value: field_node_default_value(n: f), span: f.span, name_span: node_name_span(n: f) )), @@ -1873,10 +1997,10 @@ fn make_operation_node(name: String, ident_span: SourceSpan?, inputs: List is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } -fn make_capability_node(name: String, ident_span: SourceSpan?, inputs: List, outputs: List, span: SourceSpan, source_indices: Map) -> Node { - Node { name: name, span: span, ident_span: ident_span, +fn make_capability_node(occurrence_identity: NodeOccurrenceIdentity, name: String, ident_span: SourceSpan?, inputs: List, outputs: List, span: SourceSpan, source_indices: Map) -> Node { + Node { occurrence_identity: occurrence_identity, name: name, span: span, ident_span: ident_span, children: [], - params: inputs |> map(f => make_param_node( + params: inputs |> map(f => make_param_node(occurrence_identity: f.occurrence_identity, name: field_node_name_at(n: f, source_indices: source_indices), type_expr: field_node_type_expr(n: f), default_value: field_node_default_value(n: f), span: f.span, name_span: node_name_span(n: f) )), @@ -1889,14 +2013,14 @@ fn make_capability_node(name: String, ident_span: SourceSpan?, inputs: List ItemResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect(tokens: tokens, expected: ExpectKeyword { text: "type" }) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } parse_type_after_kw(tokens: r.tokens, ctx: ctx, start_span: start_span) } fn parse_type_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: SourceSpan) -> ItemResult { - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect_ident(tokens: tokens) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -1914,24 +2038,27 @@ fn parse_type_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: Sourc match eat(tokens: tokens, expected: ExpectLBrace) { EatConsumed { token: _, tokens: __ec } => let r = parse_field_list(tokens: skip_newlines(tokens: __ec), ctx: ctx) - let named_dummy = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let named_dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: r.ctx, err: r.err } } let tokens = skip_newlines(tokens: r.tokens) let ctx = r.ctx let r2 = expect(tokens: tokens, expected: ExpectRBrace) if has_err(err: r2.err) { return ItemResult { item: named_dummy, tokens: r2.tokens, ctx: ctx, err: r2.err } } let type_children = r.fields |> map(f => field_to_child_node(field: f, source_indices: ctx.source_indices)) - let sole_ctor_prop = if is_sole_constructor { [make_field_init_node(name: "sole_constructor", value: make_expr_node(expr_data: ExprLiteral { value: LitBool { value: true } }, children: [], inferred: none, span: start_span), span: start_span, name_span: no_span())] } else { [] } - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: type_children, connective: Conj, params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: sole_ctor_prop, type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: r2.tokens), ctx: ctx, err: none } + let sole = parsed_sole_constructor_properties(ctx: ctx, enabled: is_sole_constructor, span: start_span) + let minted = mint_parsed_node_identity(ctx: sole.ctx) + let item = Node { occurrence_identity: minted.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: type_children, connective: Conj, params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: sole.properties, type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + ItemResult { item: item, tokens: skip_newlines(tokens: r2.tokens), ctx: minted.ctx, err: none } EatUnchanged { tokens: __eu } => match eat(tokens: tokens, expected: ExpectEq) { EatConsumed { token: _, tokens: __ec } => let tokens = skip_newlines(tokens: __ec) parse_type_body_after_eq(tokens: tokens, ctx: ctx, name: name, name_span: name_span, start_span: start_span, type_params: type_params, is_sole_constructor: is_sole_constructor) EatUnchanged { tokens: __eu } => - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], connective: NoConnective, params: type_params, inferred: Present { value: Resolved { node: leaf_type_node(name: name, span: name_span) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: __eu, ctx: ctx, err: none } + let type_mint = mint_parsed_node_identity(ctx: ctx) + let item_mint = mint_parsed_node_identity(ctx: type_mint.ctx) + let item = Node { occurrence_identity: item_mint.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], connective: NoConnective, params: type_params, inferred: Present { value: Resolved { node: leaf_type_node(occurrence_identity: type_mint.identity, name: name, span: name_span) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + ItemResult { item: item, tokens: __eu, ctx: item_mint.ctx, err: none } } } } @@ -1941,7 +2068,7 @@ fn parse_type_body_from_prefix(prefix: ItemPrefixResult, start_span: SourceSpan) let name_span = prefix.name_span let type_params = prefix.type_params let ctx = prefix.ctx - let named_dummy = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let named_dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let raw_tokens = skip_newlines(tokens: prefix.tokens) let is_sole_constructor = tok_is_ident_text(tok: token_stream_first(stream: raw_tokens), text: "sole_constructor") let tokens = type_body_tokens_after_modifiers(tokens: raw_tokens) @@ -1955,17 +2082,20 @@ fn parse_type_body_from_prefix(prefix: ItemPrefixResult, start_span: SourceSpan) let r2 = expect(tokens: tokens, expected: ExpectRBrace) if has_err(err: r2.err) { return ItemResult { item: named_dummy, tokens: r2.tokens, ctx: ctx, err: r2.err } } let type_children = r.fields |> map(f => field_to_child_node(field: f, source_indices: ctx.source_indices)) - let sole_ctor_prop = if is_sole_constructor { [make_field_init_node(name: "sole_constructor", value: make_expr_node(expr_data: ExprLiteral { value: LitBool { value: true } }, children: [], inferred: none, span: start_span), span: start_span, name_span: no_span())] } else { [] } - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: type_children, connective: Conj, params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: sole_ctor_prop, type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: r2.tokens), ctx: ctx, err: none } + let sole = parsed_sole_constructor_properties(ctx: ctx, enabled: is_sole_constructor, span: start_span) + let minted = mint_parsed_node_identity(ctx: sole.ctx) + let item = Node { occurrence_identity: minted.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: type_children, connective: Conj, params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: sole.properties, type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + ItemResult { item: item, tokens: skip_newlines(tokens: r2.tokens), ctx: minted.ctx, err: none } EatUnchanged { tokens: __eu } => match eat(tokens: tokens, expected: ExpectEq) { EatConsumed { token: _, tokens: __ec } => let tokens = skip_newlines(tokens: __ec) parse_type_body_after_eq(tokens: tokens, ctx: ctx, name: name, name_span: name_span, start_span: start_span, type_params: type_params, is_sole_constructor: is_sole_constructor) EatUnchanged { tokens: __eu } => - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], connective: NoConnective, params: type_params, inferred: Present { value: Resolved { node: leaf_type_node(name: name, span: name_span) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: __eu, ctx: ctx, err: none } + let type_mint = mint_parsed_node_identity(ctx: ctx) + let item_mint = mint_parsed_node_identity(ctx: type_mint.ctx) + let item = Node { occurrence_identity: item_mint.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], connective: NoConnective, params: type_params, inferred: Present { value: Resolved { node: leaf_type_node(occurrence_identity: type_mint.identity, name: name, span: name_span) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + ItemResult { item: item, tokens: __eu, ctx: item_mint.ctx, err: none } } } } @@ -2019,17 +2149,16 @@ fn alias_rhs_is_anonymous_record(te: Node) -> Bool { && te.type_annotation == none } -fn type_item_from_alias_rhs(name: String, name_span: SourceSpan, start_span: SourceSpan, type_params: List, te: Node, is_sole_constructor: Bool) -> Node { +fn type_item_from_alias_rhs(occurrence_identity: NodeOccurrenceIdentity, name: String, name_span: SourceSpan, start_span: SourceSpan, type_params: List, te: Node, sole_constructor_properties: List) -> Node { if alias_rhs_is_anonymous_record(te: te) { - let sole_ctor_prop = if is_sole_constructor { [make_field_init_node(name: "sole_constructor", value: make_expr_node(expr_data: ExprLiteral { value: LitBool { value: true } }, children: [], inferred: none, span: start_span), span: start_span, name_span: no_span())] } else { [] } - Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: te.children, connective: Conj, params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: sole_ctor_prop, type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: occurrence_identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: te.children, connective: Conj, params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: sole_constructor_properties, type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } else { - Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], connective: NoConnective, params: type_params, inferred: Present { value: Resolved { node: te } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: occurrence_identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], connective: NoConnective, params: type_params, inferred: Present { value: Resolved { node: te } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: sole_constructor_properties, type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } } fn parse_type_body_after_eq(tokens: TokenStream, ctx: ParseContext, name: String, name_span: SourceSpan, start_span: SourceSpan, type_params: List, is_sole_constructor: Bool) -> ItemResult { - let dummy = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } match eat(tokens: tokens, expected: ExpectPipe) { EatConsumed { token: _, tokens: __lead } => @@ -2044,8 +2173,9 @@ fn parse_type_body_after_eq(tokens: TokenStream, ctx: ParseContext, name: String let rest = parse_more_variants_acc(tokens: rv.tokens, ctx: rv.ctx, acc: [rv.variant]) if has_err(err: rest.err) { return ItemResult { item: dummy, tokens: rest.tokens, ctx: rest.ctx, err: rest.err } } let type_children = rest.variants |> map(v => variant_to_child_node(variant: v, source_indices: ctx.source_indices)) - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: type_children, connective: Disj, params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: rest.tokens), ctx: rest.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: rest.ctx) + let item = Node { occurrence_identity: minted.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: type_children, connective: Disj, params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + ItemResult { item: item, tokens: skip_newlines(tokens: rest.tokens), ctx: minted.ctx, err: none } EatUnchanged { tokens: _ } => if tok_is_ident(tok: token_stream_first(stream: tokens)) { let r = parse_dotted_ident(tokens: tokens) @@ -2062,23 +2192,28 @@ fn parse_type_body_after_eq(tokens: TokenStream, ctx: ParseContext, name: String if has_err(err: rest.err) { return ItemResult { item: dummy, tokens: rest.tokens, ctx: rest.ctx, err: rest.err } } let variants = rest.variants let type_children = variants |> map(v => variant_to_child_node(variant: v, source_indices: ctx.source_indices)) - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: type_children, connective: Disj, params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: rest.tokens), ctx: rest.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: rest.ctx) + let item = Node { occurrence_identity: minted.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: type_children, connective: Disj, params: type_params, inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + ItemResult { item: item, tokens: skip_newlines(tokens: rest.tokens), ctx: minted.ctx, err: none } } else { let r = finish_type_expr_from_name(tokens: tokens, ctx: ctx, type_name: first_name, start_span: first_name_span) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: r.ctx, err: r.err } } let wr = try_where_clause(tokens: r.tokens, ctx: r.ctx, base_te: r.type_expr, start_span: start_span) if has_err(err: wr.err) { return ItemResult { item: dummy, tokens: wr.tokens, ctx: wr.ctx, err: wr.err } } - let item = type_item_from_alias_rhs(name: name, name_span: name_span, start_span: start_span, type_params: type_params, te: wr.type_expr, is_sole_constructor: is_sole_constructor) - ItemResult { item: item, tokens: skip_newlines(tokens: wr.tokens), ctx: wr.ctx, err: none } + let sole = parsed_sole_constructor_properties(ctx: wr.ctx, enabled: is_sole_constructor, span: start_span) + let minted = mint_parsed_node_identity(ctx: sole.ctx) + let item = type_item_from_alias_rhs(occurrence_identity: minted.identity, name: name, name_span: name_span, start_span: start_span, type_params: type_params, te: wr.type_expr, sole_constructor_properties: sole.properties) + ItemResult { item: item, tokens: skip_newlines(tokens: wr.tokens), ctx: minted.ctx, err: none } } } else { let r = parse_type_expr(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: r.ctx, err: r.err } } let wr = try_where_clause(tokens: r.tokens, ctx: r.ctx, base_te: r.type_expr, start_span: start_span) if has_err(err: wr.err) { return ItemResult { item: dummy, tokens: wr.tokens, ctx: wr.ctx, err: wr.err } } - let item = type_item_from_alias_rhs(name: name, name_span: name_span, start_span: start_span, type_params: type_params, te: wr.type_expr, is_sole_constructor: is_sole_constructor) - ItemResult { item: item, tokens: skip_newlines(tokens: wr.tokens), ctx: wr.ctx, err: none } + let sole = parsed_sole_constructor_properties(ctx: wr.ctx, enabled: is_sole_constructor, span: start_span) + let minted = mint_parsed_node_identity(ctx: sole.ctx) + let item = type_item_from_alias_rhs(occurrence_identity: minted.identity, name: name, name_span: name_span, start_span: start_span, type_params: type_params, te: wr.type_expr, sole_constructor_properties: sole.properties) + ItemResult { item: item, tokens: skip_newlines(tokens: wr.tokens), ctx: minted.ctx, err: none } } } } @@ -2089,9 +2224,11 @@ fn try_where_clause(tokens: TokenStream, ctx: ParseContext, base_te: Node, start AdvanceOk { token: _, tokens: rest } => let r = parse_predicates(tokens: rest, ctx: ctx) if has_err(err: r.err) { return TypeResult { type_expr: base_te, tokens: r.tokens, ctx: r.ctx, err: r.err } } - let predicate_node = Node { name: "", span: start_span, ident_span: none, children: r.predicates, connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let refined = Node { name: "", span: start_span, ident_span: none, children: [base_te], connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: Present { value: predicate_node }, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - TypeResult { type_expr: refined, tokens: r.tokens, ctx: r.ctx, err: none } + let predicate_mint = mint_parsed_node_identity(ctx: r.ctx) + let refined_mint = mint_parsed_node_identity(ctx: predicate_mint.ctx) + let predicate_node = Node { occurrence_identity: predicate_mint.identity, name: "", span: start_span, ident_span: none, children: r.predicates, connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let refined = Node { occurrence_identity: refined_mint.identity, name: "", span: start_span, ident_span: none, children: [base_te], connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: Present { value: predicate_node }, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + TypeResult { type_expr: refined, tokens: r.tokens, ctx: refined_mint.ctx, err: none } AdvanceEof => TypeResult { type_expr: base_te, tokens: tokens, ctx: ctx, err: none } } } else { @@ -2117,7 +2254,7 @@ fn parse_predicates_acc(tokens: TokenStream, ctx: ParseContext, acc: List) fn parse_single_predicate(tokens: TokenStream, ctx: ParseContext) -> PredResult { let zero_span = no_span() - let dummy_pred = make_field_init_node(name: "", value: make_expr_node(expr_data: ExprLiteral { value: LitBool { value: false } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span) + let dummy_pred = make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: "", value: make_expr_node(occurrence_identity: OccurrenceSynthetic, expr_data: ExprLiteral { value: LitBool { value: false } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span) let r = expect_name(tokens: tokens) if has_err(err: r.err) { return PredResult { predicate: dummy_pred, tokens: r.tokens, ctx: ctx, err: r.err } } let pred_name = r.name @@ -2132,48 +2269,44 @@ fn parse_single_predicate(tokens: TokenStream, ctx: ParseContext) -> PredResult if has_err(err: r2.err) { return PredResult { predicate: dummy_pred, tokens: r2.tokens, ctx: ctx, err: r2.err } } let r3 = expect(tokens: r2.tokens, expected: ExpectRParen) if has_err(err: r3.err) { return PredResult { predicate: dummy_pred, tokens: r3.tokens, ctx: ctx, err: r3.err } } - PredResult { predicate: make_field_init_node(name: "Pattern", value: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: r2.value } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span), tokens: r3.tokens, ctx: ctx, err: none } + parsed_predicate_result(tokens: r3.tokens, ctx: ctx, build: (value_identity, predicate_identity) => make_field_init_node(occurrence_identity: predicate_identity, name: "Pattern", value: make_expr_node(occurrence_identity: value_identity, expr_data: ExprLiteral { value: LitStr { value: r2.value } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span)) } "format" => { let r2 = expect_ident(tokens: tokens) if has_err(err: r2.err) { return PredResult { predicate: dummy_pred, tokens: r2.tokens, ctx: ctx, err: r2.err } } let r3 = expect(tokens: r2.tokens, expected: ExpectRParen) if has_err(err: r3.err) { return PredResult { predicate: dummy_pred, tokens: r3.tokens, ctx: ctx, err: r3.err } } - PredResult { predicate: make_field_init_node(name: "Format", value: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: r2.name } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span), tokens: r3.tokens, ctx: ctx, err: none } + parsed_predicate_result(tokens: r3.tokens, ctx: ctx, build: (value_identity, predicate_identity) => make_field_init_node(occurrence_identity: predicate_identity, name: "Format", value: make_expr_node(occurrence_identity: value_identity, expr_data: ExprLiteral { value: LitStr { value: r2.name } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span)) } "brand" => { let r2 = parse_string_literal_value(tokens: tokens) if has_err(err: r2.err) { return PredResult { predicate: dummy_pred, tokens: r2.tokens, ctx: ctx, err: r2.err } } let r3 = expect(tokens: r2.tokens, expected: ExpectRParen) if has_err(err: r3.err) { return PredResult { predicate: dummy_pred, tokens: r3.tokens, ctx: ctx, err: r3.err } } - PredResult { predicate: make_field_init_node(name: "Brand", value: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: r2.value } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span), tokens: r3.tokens, ctx: ctx, err: none } + parsed_predicate_result(tokens: r3.tokens, ctx: ctx, build: (value_identity, predicate_identity) => make_field_init_node(occurrence_identity: predicate_identity, name: "Brand", value: make_expr_node(occurrence_identity: value_identity, expr_data: ExprLiteral { value: LitStr { value: r2.value } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span)) } "content" => { let r2 = expect_ident(tokens: tokens) if has_err(err: r2.err) { return PredResult { predicate: dummy_pred, tokens: r2.tokens, ctx: ctx, err: r2.err } } let r3 = expect(tokens: r2.tokens, expected: ExpectRParen) if has_err(err: r3.err) { return PredResult { predicate: dummy_pred, tokens: r3.tokens, ctx: ctx, err: r3.err } } - PredResult { predicate: make_field_init_node(name: "ContentEncoding", value: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: r2.name } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span), tokens: r3.tokens, ctx: ctx, err: none } + parsed_predicate_result(tokens: r3.tokens, ctx: ctx, build: (value_identity, predicate_identity) => make_field_init_node(occurrence_identity: predicate_identity, name: "ContentEncoding", value: make_expr_node(occurrence_identity: value_identity, expr_data: ExprLiteral { value: LitStr { value: r2.name } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span)) } "domain" => { let r2 = expect_ident(tokens: tokens) if has_err(err: r2.err) { return PredResult { predicate: dummy_pred, tokens: r2.tokens, ctx: ctx, err: r2.err } } let r3 = expect(tokens: r2.tokens, expected: ExpectRParen) if has_err(err: r3.err) { return PredResult { predicate: dummy_pred, tokens: r3.tokens, ctx: ctx, err: r3.err } } - PredResult { predicate: make_field_init_node(name: "Domain", value: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: r2.name } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span), tokens: r3.tokens, ctx: ctx, err: none } + parsed_predicate_result(tokens: r3.tokens, ctx: ctx, build: (value_identity, predicate_identity) => make_field_init_node(occurrence_identity: predicate_identity, name: "Domain", value: make_expr_node(occurrence_identity: value_identity, expr_data: ExprLiteral { value: LitStr { value: r2.name } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span)) } "range" => { let r2 = parse_named_int_args(tokens: tokens, ctx: ctx) if has_err(err: r2.err) { return PredResult { predicate: dummy_pred, tokens: r2.tokens, ctx: r2.ctx, err: r2.err } } let r3 = expect(tokens: r2.tokens, expected: ExpectRParen) if has_err(err: r3.err) { return PredResult { predicate: dummy_pred, tokens: r3.tokens, ctx: r2.ctx, err: r3.err } } - let min_fields = if r2.min_val != none { - [make_field_init_node(name: "min", value: make_expr_node(expr_data: ExprLiteral { value: LitInt { value: r2.min_val.value } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span)] - } else { [] } - let max_fields = if r2.max_val != none { - [make_field_init_node(name: "max", value: make_expr_node(expr_data: ExprLiteral { value: LitInt { value: r2.max_val.value } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span)] - } else { [] } - PredResult { predicate: make_field_init_node(name: "range", value: make_expr_node(expr_data: ExprRecordLit { parent_enum: none }, children: concat(min_fields, max_fields), inferred: none, span: zero_span), span: zero_span, name_span: zero_span), tokens: r3.tokens, ctx: r2.ctx, err: none } + let min = mint_parsed_optional_int_property(ctx: r2.ctx, name: "min", value: r2.min_val, span: zero_span) + let max = mint_parsed_optional_int_property(ctx: min.ctx, name: "max", value: r2.max_val, span: zero_span) + parsed_predicate_result(tokens: r3.tokens, ctx: max.ctx, build: (value_identity, predicate_identity) => make_field_init_node(occurrence_identity: predicate_identity, name: "range", value: make_expr_node(occurrence_identity: value_identity, expr_data: ExprRecordLit { parent_enum: none }, children: concat(min.properties, max.properties), inferred: none, span: zero_span), span: zero_span, name_span: zero_span)) } _ => PredResult { predicate: dummy_pred, tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: concat("unknown where predicate `", pred_name, "`"), span: token_span(tok: token_stream_first(stream: tokens))) } } @@ -2181,9 +2314,9 @@ fn parse_single_predicate(tokens: TokenStream, ctx: ParseContext) -> PredResult EatUnchanged { tokens: __eu } => match pred_name { "non_empty" => - PredResult { predicate: make_field_init_node(name: "non_empty", value: make_expr_node(expr_data: ExprLiteral { value: LitBool { value: true } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span), tokens: tokens, ctx: ctx, err: none } + parsed_predicate_result(tokens: tokens, ctx: ctx, build: (value_identity, predicate_identity) => make_field_init_node(occurrence_identity: predicate_identity, name: "non_empty", value: make_expr_node(occurrence_identity: value_identity, expr_data: ExprLiteral { value: LitBool { value: true } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span)) _ => - PredResult { predicate: make_field_init_node(name: pred_name, value: make_expr_node(expr_data: ExprLiteral { value: LitBool { value: true } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span), tokens: tokens, ctx: ctx, err: none } + parsed_predicate_result(tokens: tokens, ctx: ctx, build: (value_identity, predicate_identity) => make_field_init_node(occurrence_identity: predicate_identity, name: pred_name, value: make_expr_node(occurrence_identity: value_identity, expr_data: ExprLiteral { value: LitBool { value: true } }, children: [], inferred: none, span: zero_span), span: zero_span, name_span: zero_span)) } } } @@ -2224,15 +2357,6 @@ fn parse_positional_variant_type_fields(tokens: TokenStream, ctx: ParseContext) let tokens = skip_newlines(tokens: tokens) let r = parse_type_expr(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return FieldsResult { fields: [], tokens: r.tokens, ctx: r.ctx, err: r.err } } - let field = make_field_node( - name: "0", - type_expr: r.type_expr, - cardinality: Required, - default_value: none, - from_key: none, - span: r.type_expr.span, - name_span: kernel_span(name: "0") - ) match eat(tokens: r.tokens, expected: ExpectComma) { EatConsumed { token: comma_tok, tokens: __ec } => FieldsResult { @@ -2242,7 +2366,17 @@ fn parse_positional_variant_type_fields(tokens: TokenStream, ctx: ParseContext) err: Present { value: parse_error(msg: "positional variant payload accepts a single type only (comma-separated fields not supported yet)", span: token_span(tok: Present { value: comma_tok })) } } EatUnchanged { tokens: __eu } => - FieldsResult { fields: [field], tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let field = make_field_node(occurrence_identity: minted.identity, + name: "0", + type_expr: r.type_expr, + cardinality: Required, + default_value: none, + from_key_properties: [], + span: r.type_expr.span, + name_span: kernel_span(name: "0") + ) + FieldsResult { fields: [field], tokens: r.tokens, ctx: minted.ctx, err: none } } } @@ -2251,24 +2385,27 @@ fn parse_variant_fields(tokens: TokenStream, ctx: ParseContext, vname: String, v match eat(tokens: tokens, expected: ExpectLBrace) { EatConsumed { token: _, tokens: __ec } => let r = parse_field_list(tokens: skip_newlines(tokens: __ec), ctx: ctx) - if has_err(err: r.err) { return VariantResult { variant: make_variant_node(name: vname, fields: [], span: start_span, name_span: vname_span), tokens: r.tokens, ctx: r.ctx, err: r.err } } + if has_err(err: r.err) { return VariantResult { variant: make_variant_node(occurrence_identity: OccurrenceSynthetic, name: vname, fields: [], span: start_span, name_span: vname_span), tokens: r.tokens, ctx: r.ctx, err: r.err } } let tokens = skip_newlines(tokens: r.tokens) let r2 = expect(tokens: tokens, expected: ExpectRBrace) - if has_err(err: r2.err) { return VariantResult { variant: make_variant_node(name: vname, fields: [], span: start_span, name_span: vname_span), tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - let v = make_variant_node(name: vname, fields: r.fields, span: start_span, name_span: vname_span) - VariantResult { variant: v, tokens: r2.tokens, ctx: r.ctx, err: none } + if has_err(err: r2.err) { return VariantResult { variant: make_variant_node(occurrence_identity: OccurrenceSynthetic, name: vname, fields: [], span: start_span, name_span: vname_span), tokens: r2.tokens, ctx: r.ctx, err: r2.err } } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let v = make_variant_node(occurrence_identity: minted.identity, name: vname, fields: r.fields, span: start_span, name_span: vname_span) + VariantResult { variant: v, tokens: r2.tokens, ctx: minted.ctx, err: none } EatUnchanged { tokens: __eu } => match eat(tokens: tokens, expected: ExpectLParen) { EatConsumed { token: _, tokens: __ec } => let r = parse_positional_variant_type_fields(tokens: __ec, ctx: ctx) - if has_err(err: r.err) { return VariantResult { variant: make_variant_node(name: vname, fields: [], span: start_span, name_span: vname_span), tokens: r.tokens, ctx: r.ctx, err: r.err } } + if has_err(err: r.err) { return VariantResult { variant: make_variant_node(occurrence_identity: OccurrenceSynthetic, name: vname, fields: [], span: start_span, name_span: vname_span), tokens: r.tokens, ctx: r.ctx, err: r.err } } let r2 = expect(tokens: r.tokens, expected: ExpectRParen) - if has_err(err: r2.err) { return VariantResult { variant: make_variant_node(name: vname, fields: [], span: start_span, name_span: vname_span), tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - let v = make_variant_node(name: vname, fields: r.fields, span: start_span, name_span: vname_span) - VariantResult { variant: v, tokens: r2.tokens, ctx: r.ctx, err: none } + if has_err(err: r2.err) { return VariantResult { variant: make_variant_node(occurrence_identity: OccurrenceSynthetic, name: vname, fields: [], span: start_span, name_span: vname_span), tokens: r2.tokens, ctx: r.ctx, err: r2.err } } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let v = make_variant_node(occurrence_identity: minted.identity, name: vname, fields: r.fields, span: start_span, name_span: vname_span) + VariantResult { variant: v, tokens: r2.tokens, ctx: minted.ctx, err: none } EatUnchanged { tokens: __eu2 } => - let v = make_variant_node(name: vname, fields: [], span: vname_span, name_span: vname_span) - VariantResult { variant: v, tokens: tokens, ctx: ctx, err: none } + let minted = mint_parsed_node_identity(ctx: ctx) + let v = make_variant_node(occurrence_identity: minted.identity, name: vname, fields: [], span: vname_span, name_span: vname_span) + VariantResult { variant: v, tokens: tokens, ctx: minted.ctx, err: none } } } } @@ -2300,25 +2437,26 @@ fn parse_type_expr(tokens: TokenStream, ctx: ParseContext) -> TypeResult { match sh { Present { value: ShLBrace } => { let r = parse_field_list(tokens: skip_newlines(tokens: token_stream_advance(stream: tokens, n: 1)), ctx: ctx) - if has_err(err: r.err) { return TypeResult { type_expr: leaf_type_node(name: "", span: span), tokens: r.tokens, ctx: r.ctx, err: r.err } } + if has_err(err: r.err) { return TypeResult { type_expr: leaf_type_node(occurrence_identity: OccurrenceSynthetic, name: "", span: span), tokens: r.tokens, ctx: r.ctx, err: r.err } } let tokens = skip_newlines(tokens: r.tokens) let r2 = expect(tokens: tokens, expected: ExpectRBrace) - if has_err(err: r2.err) { return TypeResult { type_expr: leaf_type_node(name: "", span: span), tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - let te = Node { name: "", span: span, ident_span: none, children: map(r.fields, f => field_to_child_node(field: f, source_indices: ctx.source_indices)), connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - TypeResult { type_expr: te, tokens: r2.tokens, ctx: r.ctx, err: none } + if has_err(err: r2.err) { return TypeResult { type_expr: leaf_type_node(occurrence_identity: OccurrenceSynthetic, name: "", span: span), tokens: r2.tokens, ctx: r.ctx, err: r2.err } } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let te = Node { occurrence_identity: minted.identity, name: "", span: span, ident_span: none, children: map(r.fields, f => field_to_child_node(field: f, source_indices: ctx.source_indices)), connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + TypeResult { type_expr: te, tokens: r2.tokens, ctx: minted.ctx, err: none } } Present { value: ShKeyword } => { if tok.value.text == "fn" { parse_callable_type_expr(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, start_span: span) } else { - TypeResult { type_expr: leaf_type_node(name: "", span: span), tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: "expected type expression", span: span) } } + TypeResult { type_expr: leaf_type_node(occurrence_identity: OccurrenceSynthetic, name: "", span: span), tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: "expected type expression", span: span) } } } } Present { value: ShIdent } => { let r = parse_dotted_ident(tokens: tokens) if has_err(err: r.err) { return TypeResult { - type_expr: leaf_type_node(name: "", span: span), + type_expr: leaf_type_node(occurrence_identity: OccurrenceSynthetic, name: "", span: span), tokens: r.tokens, ctx: ctx, err: r.err @@ -2326,13 +2464,13 @@ fn parse_type_expr(tokens: TokenStream, ctx: ParseContext) -> TypeResult { } finish_type_expr_from_name(tokens: r.tokens, ctx: ctx, type_name: r.name, start_span: r.span) } - _ => TypeResult { type_expr: leaf_type_node(name: "", span: span), tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: "expected type expression", span: span) } } + _ => TypeResult { type_expr: leaf_type_node(occurrence_identity: OccurrenceSynthetic, name: "", span: span), tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: "expected type expression", span: span) } } } } fn parse_callable_type_expr(tokens: TokenStream, ctx: ParseContext, start_span: SourceSpan) -> TypeResult { - let dummy_te = leaf_type_node(name: "", span: start_span) + let dummy_te = leaf_type_node(occurrence_identity: OccurrenceSynthetic, name: "", span: start_span) let r = expect(tokens: tokens, expected: ExpectLParen) if has_err(err: r.err) { return TypeResult { type_expr: dummy_te, tokens: r.tokens, ctx: ctx, err: r.err } } let tokens = skip_newlines(tokens: r.tokens) @@ -2354,31 +2492,33 @@ fn parse_callable_type_expr(tokens: TokenStream, ctx: ParseContext, start_span: let ret = parse_type_expr(tokens: r3.tokens, ctx: params_result.ctx) if has_err(err: ret.err) { return TypeResult { type_expr: dummy_te, tokens: ret.tokens, ctx: ret.ctx, err: ret.err } } - let te = Node { name: "Callable", span: start_span, ident_span: Present { value: start_span }, children: [], connective: Arrow, params: params_result.params, inferred: Present { value: Resolved { node: ret.type_expr } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - maybe_optional(tokens: ret.tokens, ctx: ret.ctx, te: te, start_span: start_span) + let minted = mint_parsed_node_identity(ctx: ret.ctx) + let te = Node { occurrence_identity: minted.identity, name: "Callable", span: start_span, ident_span: Present { value: start_span }, children: [], connective: Arrow, params: params_result.params, inferred: Present { value: Resolved { node: ret.type_expr } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + maybe_optional(tokens: ret.tokens, ctx: minted.ctx, te: te, start_span: start_span) } fn parse_callable_param_types(tokens: TokenStream, ctx: ParseContext, acc: List) -> ParamsResult { let r = parse_type_expr(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ParamsResult { params: [], tokens: r.tokens, ctx: r.ctx, err: r.err } } - let param = make_param_node(name: "", type_expr: r.type_expr, default_value: none, span: r.type_expr.span, name_span: r.type_expr.span) + let minted = mint_parsed_node_identity(ctx: r.ctx) + let param = make_param_node(occurrence_identity: minted.identity, name: "", type_expr: r.type_expr, default_value: none, span: r.type_expr.span, name_span: r.type_expr.span) let acc = list_push(acc, param) match eat(tokens: r.tokens, expected: ExpectComma) { EatConsumed { token: _, tokens: __ec } => let tokens = skip_newlines(tokens: __ec) if tok_is_rparen(tok: token_stream_first(stream: tokens)) { - ParamsResult { params: acc, tokens: tokens, ctx: r.ctx, err: none } + ParamsResult { params: acc, tokens: tokens, ctx: minted.ctx, err: none } } else { - parse_callable_param_types(tokens: tokens, ctx: r.ctx, acc: acc) + parse_callable_param_types(tokens: tokens, ctx: minted.ctx, acc: acc) } EatUnchanged { tokens: __eu } => - ParamsResult { params: acc, tokens: r.tokens, ctx: r.ctx, err: none } + ParamsResult { params: acc, tokens: r.tokens, ctx: minted.ctx, err: none } } } fn finish_type_expr_from_name(tokens: TokenStream, ctx: ParseContext, type_name: String, start_span: SourceSpan) -> TypeResult { - let dummy_te = leaf_type_node(name: type_name, span: start_span) + let dummy_te = leaf_type_node(occurrence_identity: OccurrenceSynthetic, name: type_name, span: start_span) match eat(tokens: tokens, expected: ExpectLt) { EatConsumed { token: _, tokens: __ec } => let r = parse_type_angle_arg(tokens: __ec, ctx: ctx) @@ -2389,11 +2529,13 @@ fn finish_type_expr_from_name(tokens: TokenStream, ctx: ParseContext, type_name: if has_err(err: type_args.err) { return TypeResult { type_expr: dummy_te, tokens: type_args.tokens, ctx: type_args.ctx, err: type_args.err } } let r3 = expect(tokens: type_args.tokens, expected: ExpectGt) if has_err(err: r3.err) { return TypeResult { type_expr: dummy_te, tokens: r3.tokens, ctx: type_args.ctx, err: r3.err } } - let te = Node { name: type_name, span: start_span, ident_span: Present { value: start_span }, children: type_args.args, connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - maybe_optional(tokens: r3.tokens, ctx: type_args.ctx, te: te, start_span: start_span) + let minted = mint_parsed_node_identity(ctx: type_args.ctx) + let te = Node { occurrence_identity: minted.identity, name: type_name, span: start_span, ident_span: Present { value: start_span }, children: type_args.args, connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + maybe_optional(tokens: r3.tokens, ctx: minted.ctx, te: te, start_span: start_span) EatUnchanged { tokens: __eu } => - let te = leaf_type_node(name: type_name, span: start_span) - maybe_optional(tokens: tokens, ctx: ctx, te: te, start_span: start_span) + let minted = mint_parsed_node_identity(ctx: ctx) + let te = leaf_type_node(occurrence_identity: minted.identity, name: type_name, span: start_span) + maybe_optional(tokens: tokens, ctx: minted.ctx, te: te, start_span: start_span) } } @@ -2418,13 +2560,16 @@ fn collect_type_param_names(tokens: TokenStream, ctx: ParseContext, params: List if tok_is_ident(tok: token_stream_first(stream: tokens)) { let r = expect_ident(tokens: tokens) let span = r.span - let param = make_param_node(name: r.name, type_expr: leaf_type_node(name: r.name, span: span), default_value: none, span: span, name_span: span) + let type_mint = mint_parsed_node_identity(ctx: ctx) + let type_expr = leaf_type_node(occurrence_identity: type_mint.identity, name: r.name, span: span) + let param_mint = mint_parsed_node_identity(ctx: type_mint.ctx) + let param = make_param_node(occurrence_identity: param_mint.identity, name: r.name, type_expr: type_expr, default_value: none, span: span, name_span: span) let next_params = list_push(params, param) match eat(tokens: r.tokens, expected: ExpectComma) { EatConsumed { token: _, tokens: __ec } => - collect_type_param_names(tokens: __ec, ctx: ctx, params: next_params) + collect_type_param_names(tokens: __ec, ctx: param_mint.ctx, params: next_params) EatUnchanged { tokens: __eu } => - TypeParamsResult { params: next_params, tokens: r.tokens, ctx: ctx } + TypeParamsResult { params: next_params, tokens: r.tokens, ctx: param_mint.ctx } } } else { TypeParamsResult { params: params, tokens: tokens, ctx: ctx } @@ -2452,7 +2597,7 @@ fn collect_type_args(tokens: TokenStream, ctx: ParseContext, args: List) - fn maybe_optional(tokens: TokenStream, ctx: ParseContext, te: Node, start_span: SourceSpan) -> TypeResult { match eat(tokens: tokens, expected: ExpectQuestion) { EatConsumed { token: _, tokens: __ec } => - let ote = Node { name: te.name, span: te.span, ident_span: te.ident_span, children: te.children, connective: te.connective, params: te.params, inferred: te.inferred, return_cardinality: CardOptional, uses: te.uses, body: te.body, transport: te.transport, properties: te.properties, type_annotation: te.type_annotation, is_self_recursive: te.is_self_recursive, has_non_tail_self_call: te.has_non_tail_self_call, match_pattern: te.match_pattern, expr_data: te.expr_data } + let ote = Node { occurrence_identity: te.occurrence_identity, name: te.name, span: te.span, ident_span: te.ident_span, children: te.children, connective: te.connective, params: te.params, inferred: te.inferred, return_cardinality: CardOptional, uses: te.uses, body: te.body, transport: te.transport, properties: te.properties, type_annotation: te.type_annotation, is_self_recursive: te.is_self_recursive, has_non_tail_self_call: te.has_non_tail_self_call, match_pattern: te.match_pattern, expr_data: te.expr_data } TypeResult { type_expr: ote, tokens: __ec, ctx: ctx, err: none } EatUnchanged { tokens: __eu } => TypeResult { type_expr: te, tokens: tokens, ctx: ctx, err: none } @@ -2484,7 +2629,7 @@ fn parse_field_list_acc(tokens: TokenStream, ctx: ParseContext, acc: List) fn parse_field(tokens: TokenStream, ctx: ParseContext) -> FieldResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy_field = make_field_node(name: "", type_expr: leaf_type_node(name: "", span: start_span), cardinality: Required, default_value: none, from_key: none, span: start_span, name_span: start_span) + let dummy_field = make_field_node(occurrence_identity: OccurrenceSynthetic, name: "", type_expr: leaf_type_node(occurrence_identity: OccurrenceSynthetic, name: "", span: start_span), cardinality: Required, default_value: none, from_key_properties: [], span: start_span, name_span: start_span) let r = expect_name(tokens: tokens) if has_err(err: r.err) { return FieldResult { field: dummy_field, tokens: r.tokens, ctx: ctx, err: r.err } } let name = r.name @@ -2504,7 +2649,7 @@ fn parse_field(tokens: TokenStream, ctx: ParseContext) -> FieldResult { let ctx = wr.ctx let from_r = parse_optional_from_key(tokens: tokens, ctx: ctx) - let from_key = from_r.from_key + let from_key_properties = from_r.properties let tokens = from_r.tokens let ctx = from_r.ctx @@ -2512,17 +2657,19 @@ fn parse_field(tokens: TokenStream, ctx: ParseContext) -> FieldResult { EatConsumed { token: _, tokens: __ec } => let r4 = parse_expr(tokens: __ec, ctx: ctx) if has_err(err: r4.err) { return FieldResult { field: dummy_field, tokens: r4.tokens, ctx: r4.ctx, err: r4.err } } - let f = make_field_node( + let minted = mint_parsed_node_identity(ctx: r4.ctx) + let f = make_field_node(occurrence_identity: minted.identity, name: name, type_expr: te, cardinality: te.return_cardinality, - default_value: Present { value: r4.expr }, from_key: from_key, span: start_span, name_span: name_span + default_value: Present { value: r4.expr }, from_key_properties: from_key_properties, span: start_span, name_span: name_span ) - FieldResult { field: f, tokens: r4.tokens, ctx: r4.ctx, err: none } + FieldResult { field: f, tokens: r4.tokens, ctx: minted.ctx, err: none } EatUnchanged { tokens: __eu } => - let f = make_field_node( + let minted = mint_parsed_node_identity(ctx: ctx) + let f = make_field_node(occurrence_identity: minted.identity, name: name, type_expr: te, cardinality: te.return_cardinality, - default_value: none, from_key: from_key, span: start_span, name_span: name_span + default_value: none, from_key_properties: from_key_properties, span: start_span, name_span: name_span ) - FieldResult { field: f, tokens: tokens, ctx: ctx, err: none } + FieldResult { field: f, tokens: tokens, ctx: minted.ctx, err: none } } } @@ -2537,37 +2684,41 @@ fn parse_optional_from_key(tokens: TokenStream, ctx: ParseContext) -> FromKeyRes match sh2 { Present { value: ShLitStr } => { let key = tok2.value.text - FromKeyResult { from_key: Present { value: key }, tokens: token_stream_advance(stream: tokens, n: 2), ctx: ctx, err: none } + let value_mint = mint_parsed_node_identity(ctx: ctx) + let property_mint = mint_parsed_node_identity(ctx: value_mint.ctx) + let value = make_named_expr_node(occurrence_identity: value_mint.identity, name: key, expr_data: NoExprData, children: [], inferred: none, span: token_span(tok: tok2.value), name_span: token_span(tok: tok2.value)) + let property = make_field_init_node(occurrence_identity: property_mint.identity, name: "from_key", value: value, span: token_span(tok: tok.value), name_span: token_span(tok: tok.value)) + FromKeyResult { properties: [property], tokens: token_stream_advance(stream: tokens, n: 2), ctx: property_mint.ctx, err: none } } _ => - FromKeyResult { from_key: none, tokens: tokens, ctx: ctx, err: none } + FromKeyResult { properties: [], tokens: tokens, ctx: ctx, err: none } } } else { - FromKeyResult { from_key: none, tokens: tokens, ctx: ctx, err: none } + FromKeyResult { properties: [], tokens: tokens, ctx: ctx, err: none } } } _ => - FromKeyResult { from_key: none, tokens: tokens, ctx: ctx, err: none } + FromKeyResult { properties: [], tokens: tokens, ctx: ctx, err: none } } } fn parse_fn_def(tokens: TokenStream, ctx: ParseContext) -> ItemResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect(tokens: tokens, expected: ExpectKeyword { text: "fn" }) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } parse_fn_after_kw(tokens: r.tokens, ctx: ctx, start_span: start_span) } fn parse_fn_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: SourceSpan) -> ItemResult { - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect_ident(tokens: tokens) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } let name = r.name let name_span = r.span let tokens = r.tokens - let named_dummy = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let named_dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = parse_params(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: r.ctx, err: r.err } } @@ -2585,12 +2736,13 @@ fn parse_fn_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: SourceS if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: r.ctx, err: r.err } } let body = r.expr - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: params, + let minted = mint_parsed_node_identity(ctx: r.ctx) + let item = Node { occurrence_identity: minted.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: params, inferred: inferred, return_cardinality: Required, uses: [], body: Present { value: body }, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: r.tokens), ctx: r.ctx, err: none } + ItemResult { item: item, tokens: skip_newlines(tokens: r.tokens), ctx: minted.ctx, err: none } } fn admit_callers_property_nonempty(field: Node) -> Bool { @@ -2628,7 +2780,7 @@ fn parse_fn_body_from_prefix(prefix: ItemPrefixResult, start_span: SourceSpan) - let ctx = prefix.ctx let all_params = concat(type_params, params) - let named_dummy = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: all_params, inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let named_dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: all_params, inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let tokens = skip_newlines(tokens: prefix.tokens) let admit_r = parse_optional_admit_callers(tokens: tokens, ctx: ctx) @@ -2649,17 +2801,18 @@ fn parse_fn_body_from_prefix(prefix: ItemPrefixResult, start_span: SourceSpan) - if has_err(err: body_result.err) { return ItemResult { item: named_dummy, tokens: body_result.tokens, ctx: body_result.ctx, err: body_result.err } } let body = body_result.expr - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: all_params, + let minted = mint_parsed_node_identity(ctx: body_result.ctx) + let item = Node { occurrence_identity: minted.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: all_params, inferred: inferred, return_cardinality: Required, uses: [], body: Present { value: body }, connective: NoConnective, transport: none, properties: admit_props, type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: body_result.tokens), ctx: body_result.ctx, err: none } + ItemResult { item: item, tokens: skip_newlines(tokens: body_result.tokens), ctx: minted.ctx, err: none } } fn parse_func_def(tokens: TokenStream, ctx: ParseContext) -> ItemResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let kw = tok_keyword_text(tok: token_stream_first(stream: tokens)) let r = if kw == "func" { expect(tokens: tokens, expected: ExpectKeyword { text: "func" }) } else if kw == "pattern" { expect(tokens: tokens, expected: ExpectKeyword { text: "pattern" }) } @@ -2674,14 +2827,14 @@ fn parse_func_def(tokens: TokenStream, ctx: ParseContext) -> ItemResult { } fn parse_block_item_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: SourceSpan, form: ItemForm) -> ItemResult { - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect_ident(tokens: tokens) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } let name = r.name let name_span = r.span let tokens = r.tokens - let named_dummy = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let named_dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = parse_params(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: r.ctx, err: r.err } } @@ -2706,12 +2859,13 @@ fn parse_block_item_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: r.ctx, err: r.err } } let body = r.expr - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: params, + let minted = mint_parsed_node_identity(ctx: r.ctx) + let item = Node { occurrence_identity: minted.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: params, inferred: inferred, return_cardinality: Required, uses: uses, body: Present { value: body }, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: r.tokens), ctx: r.ctx, err: none } + ItemResult { item: item, tokens: skip_newlines(tokens: r.tokens), ctx: minted.ctx, err: none } } fn parse_block_body_from_prefix(prefix: ItemPrefixResult, start_span: SourceSpan) -> ItemResult { @@ -2721,28 +2875,30 @@ fn parse_block_body_from_prefix(prefix: ItemPrefixResult, start_span: SourceSpan let inferred = prefix.inferred let uses = prefix.uses let ctx = prefix.ctx - let named_dummy = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let named_dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = parse_item_block_body(tokens: skip_newlines(tokens: prefix.tokens), ctx: ctx) if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: r.ctx, err: r.err } } let body = r.expr - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: params, + let minted = mint_parsed_node_identity(ctx: r.ctx) + let item = Node { occurrence_identity: minted.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: params, inferred: inferred, return_cardinality: Required, uses: uses, body: Present { value: body }, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: r.tokens), ctx: r.ctx, err: none } + ItemResult { item: item, tokens: skip_newlines(tokens: r.tokens), ctx: minted.ctx, err: none } } fn parse_no_body_from_prefix(prefix: ItemPrefixResult, start_span: SourceSpan) -> ItemResult { - let item = Node { + let minted = mint_parsed_node_identity(ctx: prefix.ctx) + let item = Node { occurrence_identity: minted.identity, name: prefix.name, span: start_span, ident_span: Present { value: prefix.name_span }, children: [], params: prefix.params, inferred: prefix.inferred, return_cardinality: Required, uses: prefix.uses, body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: prefix.tokens, ctx: prefix.ctx, err: none } + ItemResult { item: item, tokens: prefix.tokens, ctx: minted.ctx, err: none } } fn parse_uses_clause(tokens: TokenStream, ctx: ParseContext) -> UsesResult { @@ -2780,7 +2936,7 @@ fn parse_uses_list_acc(tokens: TokenStream, ctx: ParseContext, acc: List) fn parse_uses_entry(tokens: TokenStream, ctx: ParseContext) -> ResUseResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = make_resource_use_node(name: "", resource: leaf_type_node(name: "", span: start_span), span: start_span, name_span: start_span) + let dummy = make_resource_use_node(occurrence_identity: OccurrenceSynthetic, name: "", resource: leaf_type_node(occurrence_identity: OccurrenceSynthetic, name: "", span: start_span), span: start_span, name_span: start_span) let r = expect_ident(tokens: tokens) if has_err(err: r.err) { return ResUseResult { resource_use: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } let name = r.name @@ -2798,17 +2954,19 @@ fn parse_uses_entry(tokens: TokenStream, ctx: ParseContext) -> ResUseResult { if has_err(err: ar.err) { return ResUseResult { resource_use: dummy, tokens: ar.tokens, ctx: ar.ctx, err: ar.err } } let r4 = expect(tokens: ar.tokens, expected: ExpectRParen) if has_err(err: r4.err) { return ResUseResult { resource_use: dummy, tokens: r4.tokens, ctx: ar.ctx, err: r4.err } } - let res_node = Node { name: r3.type_expr.name, span: r3.type_expr.span, ident_span: r3.type_expr.ident_span, children: r3.type_expr.children, + let res_node = Node { occurrence_identity: r3.type_expr.occurrence_identity, name: r3.type_expr.name, span: r3.type_expr.span, ident_span: r3.type_expr.ident_span, children: r3.type_expr.children, params: r3.type_expr.params, inferred: r3.type_expr.inferred, return_cardinality: r3.type_expr.return_cardinality, uses: r3.type_expr.uses, body: r3.type_expr.body, connective: r3.type_expr.connective, transport: r3.type_expr.transport, properties: ar.fields, type_annotation: r3.type_expr.type_annotation, is_self_recursive: r3.type_expr.is_self_recursive, has_non_tail_self_call: r3.type_expr.has_non_tail_self_call, match_pattern: r3.type_expr.match_pattern, expr_data: r3.type_expr.expr_data } - let ru = make_resource_use_node(name: name, resource: res_node, span: start_span, name_span: r.span) - ResUseResult { resource_use: ru, tokens: r4.tokens, ctx: ar.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: ar.ctx) + let ru = make_resource_use_node(occurrence_identity: minted.identity, name: name, resource: res_node, span: start_span, name_span: r.span) + ResUseResult { resource_use: ru, tokens: r4.tokens, ctx: minted.ctx, err: none } EatUnchanged { tokens: __eu } => - let ru = make_resource_use_node(name: name, resource: r3.type_expr, span: start_span, name_span: r.span) - ResUseResult { resource_use: ru, tokens: r3.tokens, ctx: r3.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r3.ctx) + let ru = make_resource_use_node(occurrence_identity: minted.identity, name: name, resource: r3.type_expr, span: start_span, name_span: r.span) + ResUseResult { resource_use: ru, tokens: r3.tokens, ctx: minted.ctx, err: none } } } @@ -2830,13 +2988,14 @@ fn parse_resource_config_acc(tokens: TokenStream, ctx: ParseContext, acc: List - parse_resource_config_acc(tokens: skip_newlines(tokens: __ec), ctx: r3.ctx, acc: acc) + parse_resource_config_acc(tokens: skip_newlines(tokens: __ec), ctx: minted.ctx, acc: acc) EatUnchanged { tokens: __eu } => - ResConfigResult { fields: acc, tokens: r3.tokens, ctx: r3.ctx, err: none } + ResConfigResult { fields: acc, tokens: r3.tokens, ctx: minted.ctx, err: none } } } @@ -2853,14 +3012,14 @@ fn parse_optional_inferred(tokens: TokenStream, ctx: ParseContext) -> OptRetResu fn parse_service_def(tokens: TokenStream, ctx: ParseContext) -> ItemResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect(tokens: tokens, expected: ExpectKeyword { text: "service" }) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } parse_service_after_kw(tokens: r.tokens, ctx: ctx, start_span: start_span) } fn parse_service_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: SourceSpan) -> ItemResult { - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r_ns = expect_name(tokens: tokens) if has_err(err: r_ns.err) { return ItemResult { item: dummy, tokens: r_ns.tokens, ctx: ctx, err: r_ns.err } } @@ -2868,7 +3027,7 @@ fn parse_service_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: So let r = parse_dotted_ident_rest(tokens: r_ns.tokens, acc: namespace_root, span: r_ns.span) let name = r.name let svc_name_span = r.span - let named_dummy = Node { name: name, span: start_span, ident_span: Present { value: svc_name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let named_dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: svc_name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect(tokens: r.tokens, expected: ExpectLBrace) if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -2881,25 +3040,28 @@ fn parse_service_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: So let r2 = expect(tokens: tokens, expected: ExpectRBrace) if has_err(err: r2.err) { return ItemResult { item: named_dummy, tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - let ns_prop = make_field_init_node(name: "namespace_root", value: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: namespace_root } }, children: [], inferred: none, span: start_span), span: start_span, name_span: no_span()) + let ns_value_mint = mint_parsed_node_identity(ctx: r.ctx) + let ns_property_mint = mint_parsed_node_identity(ctx: ns_value_mint.ctx) + let item_mint = mint_parsed_node_identity(ctx: ns_property_mint.ctx) + let ns_prop = make_field_init_node(occurrence_identity: ns_property_mint.identity, name: "namespace_root", value: make_expr_node(occurrence_identity: ns_value_mint.identity, expr_data: ExprLiteral { value: LitStr { value: namespace_root } }, children: [], inferred: none, span: start_span), span: start_span, name_span: no_span()) let svc_props = match r.config { Present { value: cfg } => service_config_properties(endpoint: cfg.endpoint, auth: cfg.auth, auth_input: cfg.auth_input, auth_source: cfg.auth_source, rate_limit: cfg.rate_limit) Absent => [] } - let item = Node { name: name, span: start_span, ident_span: Present { value: svc_name_span }, + let item = Node { occurrence_identity: item_mint.identity, name: name, span: start_span, ident_span: Present { value: svc_name_span }, children: r.operations, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: Present { value: r.transport }, properties: concat([ns_prop], svc_props), type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: r2.tokens), ctx: r.ctx, err: none } + ItemResult { item: item, tokens: skip_newlines(tokens: r2.tokens), ctx: item_mint.ctx, err: none } } fn parse_service_body(tokens: TokenStream, ctx: ParseContext) -> ServiceBodyResult { parse_service_entries( tokens: tokens, ctx: ctx, config: none, - transport: local_transport_node(span: token_span(tok: token_stream_first(stream: tokens))), + transport: local_transport_node(occurrence_identity: OccurrenceSynthetic, span: token_span(tok: token_stream_first(stream: tokens))), operations: [] ) } @@ -2957,7 +3119,7 @@ fn parse_config_fields(tokens: TokenStream, ctx: ParseContext, endpoint: Node?, let cfg = ServiceConfig { endpoint: match endpoint { Present { value: e } => e - Absent => make_expr_node(expr_data: ExprLiteral { value: LitStr { value: "" } }, children: [], inferred: none, span: no_span()) + Absent => make_expr_node(occurrence_identity: OccurrenceSynthetic, expr_data: ExprLiteral { value: LitStr { value: "" } }, children: [], inferred: none, span: no_span()) }, auth: auth, auth_input: auth_input, @@ -2966,7 +3128,7 @@ fn parse_config_fields(tokens: TokenStream, ctx: ParseContext, endpoint: Node?, } ConfigResult { config: cfg, tokens: tokens, ctx: ctx, err: none } } else { - let dummy_cfg = ServiceConfig { endpoint: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: "" } }, children: [], inferred: none, span: no_span()), auth: none, auth_input: none, auth_source: none, rate_limit: none } + let dummy_cfg = ServiceConfig { endpoint: make_expr_node(occurrence_identity: OccurrenceSynthetic, expr_data: ExprLiteral { value: LitStr { value: "" } }, children: [], inferred: none, span: no_span()), auth: none, auth_input: none, auth_source: none, rate_limit: none } let r = expect_ident(tokens: tokens) if has_err(err: r.err) { return ConfigResult { config: dummy_cfg, tokens: r.tokens, ctx: ctx, err: r.err } } let fname = r.name @@ -2992,7 +3154,7 @@ fn parse_config_fields(tokens: TokenStream, ctx: ParseContext, endpoint: Node?, fn parse_transport_binding(tokens: TokenStream, ctx: ParseContext) -> TransportResult { let span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = local_transport_node(span: span) + let dummy = local_transport_node(occurrence_identity: OccurrenceSynthetic, span: span) let tok = token_stream_first(stream: tokens) let tok_text = match tok { Present { value: t } => t.text Absent => "" } let sh = match tok { Present { value: t } => Present { value: t.shape } Absent => none } @@ -3038,13 +3200,14 @@ fn parse_rest_binding_body(tokens: TokenStream, ctx: ParseContext) -> TransportR fn parse_rest_fields(tokens: TokenStream, ctx: ParseContext, base_url: Node?, method: Node?, path_template: Node?, query: Node?, request_body: Node?, response_format: Node?, headers: List) -> TransportResult { let tokens = skip_newlines(tokens: tokens) let span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = local_transport_node(span: span) + let dummy = local_transport_node(occurrence_identity: OccurrenceSynthetic, span: span) if tok_is_rbrace(tok: token_stream_first(stream: tokens)) || tok_is_eof(tok: token_stream_first(stream: tokens)) { let bu = match base_url { Present { value: e } => e - Absent => make_expr_node(expr_data: ExprLiteral { value: LitStr { value: "" } }, children: [], inferred: none, span: no_span()) + Absent => make_expr_node(occurrence_identity: OccurrenceSynthetic, expr_data: ExprLiteral { value: LitStr { value: "" } }, children: [], inferred: none, span: no_span()) } - TransportResult { transport: rest_transport_node(base_url: bu, auth_props: [], headers: headers, method: method, path: path_template, query: query, request_body: request_body, response_format: response_format, span: span), tokens: tokens, ctx: ctx, err: none } + let minted = mint_parsed_node_identity(ctx: ctx) + TransportResult { transport: rest_transport_node(occurrence_identity: minted.identity, base_url: bu, auth_props: [], headers: headers, method: method, path: path_template, query: query, request_body: request_body, response_format: response_format, span: span), tokens: tokens, ctx: minted.ctx, err: none } } else { let r = expect_ident(tokens: tokens) if has_err(err: r.err) { return TransportResult { transport: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -3075,8 +3238,9 @@ fn parse_rest_fields(tokens: TokenStream, ctx: ParseContext, base_url: Node?, me } parse_rest_fields(tokens: tokens, ctx: ctx, base_url: base_url, method: method, path_template: path_template, query: query, request_body: request_body, response_format: response_format, headers: h) } else if fname == transport_auth_basic_key || fname == transport_tls_key { - let field = make_field_init_node(name: fname, value: r3.expr, span: no_span(), name_span: no_span()) - parse_rest_fields(tokens: tokens, ctx: ctx, base_url: base_url, method: method, path_template: path_template, query: query, request_body: request_body, response_format: response_format, headers: concat(headers, [field])) + let minted = mint_parsed_node_identity(ctx: ctx) + let field = make_field_init_node(occurrence_identity: minted.identity, name: fname, value: r3.expr, span: no_span(), name_span: no_span()) + parse_rest_fields(tokens: tokens, ctx: minted.ctx, base_url: base_url, method: method, path_template: path_template, query: query, request_body: request_body, response_format: response_format, headers: concat(headers, [field])) } else { TransportResult { transport: dummy, tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: concat("transport rest has no field `", fname, "`; the declared fields are `base_url`, `method`, `path`, `query`, `body`, `response_format`, `headers`, `auth_basic` and `tls`"), span: r.span) } } } @@ -3090,9 +3254,10 @@ fn parse_shell_binding_body(tokens: TokenStream, ctx: ParseContext) -> Transport fn parse_shell_fields(tokens: TokenStream, ctx: ParseContext, argv: List, stdin: Node?) -> TransportResult { let tokens = skip_newlines(tokens: tokens) let span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = local_transport_node(span: span) + let dummy = local_transport_node(occurrence_identity: OccurrenceSynthetic, span: span) if tok_is_rbrace(tok: token_stream_first(stream: tokens)) || tok_is_eof(tok: token_stream_first(stream: tokens)) { - TransportResult { transport: shell_transport_node(argv: argv, env: [], stdin: stdin, span: span), tokens: tokens, ctx: ctx, err: none } + let minted = mint_parsed_node_identity(ctx: ctx) + TransportResult { transport: shell_transport_node(occurrence_identity: minted.identity, argv: argv, env: [], stdin: stdin, span: span), tokens: tokens, ctx: minted.ctx, err: none } } else { let r = expect_ident(tokens: tokens) if has_err(err: r.err) { return TransportResult { transport: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -3128,11 +3293,12 @@ fn parse_file_binding_body(tokens: TokenStream, ctx: ParseContext) -> TransportR fn parse_file_fields(tokens: TokenStream, ctx: ParseContext, base_path: Node?, verb: Node?) -> TransportResult { let tokens = skip_newlines(tokens: tokens) let span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = local_transport_node(span: span) + let dummy = local_transport_node(occurrence_identity: OccurrenceSynthetic, span: span) if tok_is_rbrace(tok: token_stream_first(stream: tokens)) || tok_is_eof(tok: token_stream_first(stream: tokens)) { match base_path { Present { value: bp } => - TransportResult { transport: file_transport_node(base_path: bp, verb: verb, span: span), tokens: tokens, ctx: ctx, err: none } + let minted = mint_parsed_node_identity(ctx: ctx) + TransportResult { transport: file_transport_node(occurrence_identity: minted.identity, base_path: bp, verb: verb, span: span), tokens: tokens, ctx: minted.ctx, err: none } Absent => TransportResult { transport: dummy, tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: "transport file declares no `path:` field; a file transport must name the path it reads or writes", span: span) } } } @@ -3158,7 +3324,7 @@ fn parse_file_fields(tokens: TokenStream, ctx: ParseContext, base_path: Node?, v fn parse_operation_def(tokens: TokenStream, ctx: ParseContext) -> OpResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy_op = make_operation_node(name: "", ident_span: none, inputs: [], outputs: [], response_props: [], mock_props: [], exit_props: [], modifier_props: [], transport: none, span: start_span, source_indices: ctx.source_indices) + let dummy_op = make_operation_node(occurrence_identity: OccurrenceSynthetic, name: "", ident_span: none, inputs: [], outputs: [], response_props: [], mock_props: [], exit_props: [], modifier_props: [], transport: none, span: start_span, source_indices: ctx.source_indices) let r = expect(tokens: tokens, expected: ExpectKeyword { text: "operation" }) if has_err(err: r.err) { return OpResult { operation: dummy_op, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -3176,10 +3342,9 @@ fn parse_operation_def(tokens: TokenStream, ctx: ParseContext) -> OpResult { } fn parse_operation_v2_inline(tokens: TokenStream, ctx: ParseContext, name: String, name_span: SourceSpan, start_span: SourceSpan) -> OpResult { - let dummy_op = make_operation_node(name: "", ident_span: none, inputs: [], outputs: [], response_props: [], mock_props: [], exit_props: [], modifier_props: [], transport: none, span: start_span, source_indices: ctx.source_indices) + let dummy_op = make_operation_node(occurrence_identity: OccurrenceSynthetic, name: "", ident_span: none, inputs: [], outputs: [], response_props: [], mock_props: [], exit_props: [], modifier_props: [], transport: none, span: start_span, source_indices: ctx.source_indices) let mods_r = parse_operation_modifiers(tokens: tokens, ctx: ctx) - let modifiers = mods_r.modifiers - let mod_props = modifiers_to_props(modifiers: modifiers, span: start_span) + let mod_props = mods_r.properties let tokens = mods_r.tokens let ctx = mods_r.ctx @@ -3188,6 +3353,7 @@ fn parse_operation_v2_inline(tokens: TokenStream, ctx: ParseContext, name: Strin let r = parse_field_list(tokens: skip_newlines(tokens: r.tokens), ctx: ctx) if has_err(err: r.err) { return OpResult { operation: dummy_op, tokens: r.tokens, ctx: r.ctx, err: r.err } } let inputs = r.fields + let ctx = r.ctx let r = expect(tokens: skip_newlines(tokens: r.tokens), expected: ExpectRParen) if has_err(err: r.err) { return OpResult { operation: dummy_op, tokens: r.tokens, ctx: ctx, err: r.err } } let tokens = r.tokens @@ -3211,17 +3377,19 @@ fn parse_operation_v2_inline(tokens: TokenStream, ctx: ParseContext, name: Strin let tokens = skip_newlines(tokens: mock_r.tokens) let ctx = mock_r.ctx + let minted = mint_parsed_node_identity(ctx: ctx) let op = make_operation_node( + occurrence_identity: minted.identity, name: name, ident_span: Present { value: name_span }, inputs: inputs, outputs: outputs, response_props: resp_r.responses, mock_props: mock_r.mocks, exit_props: [], modifier_props: mod_props, transport: none, span: start_span, source_indices: ctx.source_indices ) - OpResult { operation: op, tokens: tokens, ctx: ctx, err: none } + OpResult { operation: op, tokens: tokens, ctx: minted.ctx, err: none } } fn parse_operation_v1_body(tokens: TokenStream, ctx: ParseContext, name: String, name_span: SourceSpan, start_span: SourceSpan) -> OpResult { - let dummy_op = make_operation_node(name: "", ident_span: none, inputs: [], outputs: [], response_props: [], mock_props: [], exit_props: [], modifier_props: [], transport: none, span: start_span, source_indices: ctx.source_indices) + let dummy_op = make_operation_node(occurrence_identity: OccurrenceSynthetic, name: "", ident_span: none, inputs: [], outputs: [], response_props: [], mock_props: [], exit_props: [], modifier_props: [], transport: none, span: start_span, source_indices: ctx.source_indices) let r = expect(tokens: tokens, expected: ExpectLBrace) if has_err(err: r.err) { return OpResult { operation: dummy_op, tokens: r.tokens, ctx: ctx, err: r.err } } let tokens = skip_newlines(tokens: r.tokens) @@ -3235,14 +3403,16 @@ fn parse_operation_v1_body(tokens: TokenStream, ctx: ParseContext, name: String, let r3 = expect(tokens: skip_newlines(tokens: r2.tokens), expected: ExpectRBrace) if has_err(err: r3.err) { return OpResult { operation: dummy_op, tokens: r3.tokens, ctx: r2.ctx, err: r3.err } } + let minted = mint_parsed_node_identity(ctx: r2.ctx) let op = make_operation_node( + occurrence_identity: minted.identity, name: name, ident_span: Present { value: name_span }, inputs: r2.inputs, outputs: r2.outputs, response_props: r2.response_props, mock_props: r2.mock_props, exit_props: r2.exit_props, modifier_props: r2.modifier_props, transport: r2.transport, span: start_span, source_indices: ctx.source_indices ) - OpResult { operation: op, tokens: skip_newlines(tokens: r3.tokens), ctx: r2.ctx, err: none } + OpResult { operation: op, tokens: skip_newlines(tokens: r3.tokens), ctx: minted.ctx, err: none } } fn parse_op_body_entries( @@ -3279,14 +3449,14 @@ fn parse_op_body_entries( if has_err(err: r3.err) { return OpBodyResult { inputs: inputs, outputs: outputs, modifier_props: modifier_props, transport: transport, exit_props: exit_props, response_props: response_props, mock_props: mock_props, tokens: r3.tokens, ctx: r2.ctx, err: r3.err } } parse_op_body_entries(tokens: r3.tokens, ctx: r2.ctx, inputs: inputs, outputs: r2.fields, modifier_props: modifier_props, transport: transport, exit_props: exit_props, response_props: response_props, mock_props: mock_props) } else if kw_text == "idempotent" { - let prop = modifier_to_prop(name: "idempotent", span: span) - parse_op_body_entries(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, inputs: inputs, outputs: outputs, modifier_props: list_push(modifier_props, prop), transport: transport, exit_props: exit_props, response_props: response_props, mock_props: mock_props) + let minted = mint_parsed_bool_property(ctx: ctx, name: "idempotent", span: span) + parse_op_body_entries(tokens: token_stream_advance(stream: tokens, n: 1), ctx: minted.ctx, inputs: inputs, outputs: outputs, modifier_props: list_push(modifier_props, minted.property), transport: transport, exit_props: exit_props, response_props: response_props, mock_props: mock_props) } else if kw_text == "readonly" { - let prop = modifier_to_prop(name: "readonly", span: span) - parse_op_body_entries(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, inputs: inputs, outputs: outputs, modifier_props: list_push(modifier_props, prop), transport: transport, exit_props: exit_props, response_props: response_props, mock_props: mock_props) + let minted = mint_parsed_bool_property(ctx: ctx, name: "readonly", span: span) + parse_op_body_entries(tokens: token_stream_advance(stream: tokens, n: 1), ctx: minted.ctx, inputs: inputs, outputs: outputs, modifier_props: list_push(modifier_props, minted.property), transport: transport, exit_props: exit_props, response_props: response_props, mock_props: mock_props) } else if kw_text == "hermetic" { - let prop = modifier_to_prop(name: "hermetic", span: span) - parse_op_body_entries(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, inputs: inputs, outputs: outputs, modifier_props: list_push(modifier_props, prop), transport: transport, exit_props: exit_props, response_props: response_props, mock_props: mock_props) + let minted = mint_parsed_bool_property(ctx: ctx, name: "hermetic", span: span) + parse_op_body_entries(tokens: token_stream_advance(stream: tokens, n: 1), ctx: minted.ctx, inputs: inputs, outputs: outputs, modifier_props: list_push(modifier_props, minted.property), transport: transport, exit_props: exit_props, response_props: response_props, mock_props: mock_props) } else { mk_result } @@ -3332,18 +3502,6 @@ fn parse_op_body_entries( } } -fn modifier_to_prop(name: String, span: SourceSpan) -> Node { - make_field_init_node(name: name, value: make_expr_node(expr_data: ExprLiteral { value: LitBool { value: true } }, children: [], inferred: none, span: span), span: span, name_span: span) -} - -fn modifiers_to_props(modifiers: List, span: SourceSpan) -> List { - modifiers |> map(m => match m { - Idempotent => modifier_to_prop(name: "idempotent", span: span) - Readonly => modifier_to_prop(name: "readonly", span: span) - Hermetic => modifier_to_prop(name: "hermetic", span: span) - }) -} - fn status_expr_to_str(expr: Node, source_indices: Map) -> String { match expr.expr_data { ExprLiteral { value: v } => match v { @@ -3449,10 +3607,11 @@ fn parse_exit_entries_acc(tokens: TokenStream, ctx: ParseContext, acc: List __ec EatUnchanged { tokens: _ } => desc_tokens }) - parse_exit_entries_acc(tokens: tokens, ctx: r3.ctx, acc: list_push(acc, entry)) + parse_exit_entries_acc(tokens: tokens, ctx: minted.ctx, acc: list_push(acc, entry)) } } @@ -3460,16 +3619,19 @@ fn parse_operation_modifiers(tokens: TokenStream, ctx: ParseContext) -> ModsResu parse_operation_modifiers_acc(tokens: tokens, ctx: ctx, acc: []) } -fn parse_operation_modifiers_acc(tokens: TokenStream, ctx: ParseContext, acc: List) -> ModsResult { +fn parse_operation_modifiers_acc(tokens: TokenStream, ctx: ParseContext, acc: List) -> ModsResult { let kw = tok_keyword_text(tok: token_stream_first(stream: tokens)) if kw == "idempotent" { - parse_operation_modifiers_acc(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, acc: list_push(acc, Idempotent)) + let minted = mint_parsed_bool_property(ctx: ctx, name: "idempotent", span: token_span(tok: token_stream_first(stream: tokens))) + parse_operation_modifiers_acc(tokens: token_stream_advance(stream: tokens, n: 1), ctx: minted.ctx, acc: list_push(acc, minted.property)) } else if kw == "readonly" { - parse_operation_modifiers_acc(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, acc: list_push(acc, Readonly)) + let minted = mint_parsed_bool_property(ctx: ctx, name: "readonly", span: token_span(tok: token_stream_first(stream: tokens))) + parse_operation_modifiers_acc(tokens: token_stream_advance(stream: tokens, n: 1), ctx: minted.ctx, acc: list_push(acc, minted.property)) } else if kw == "hermetic" { - parse_operation_modifiers_acc(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, acc: list_push(acc, Hermetic)) + let minted = mint_parsed_bool_property(ctx: ctx, name: "hermetic", span: token_span(tok: token_stream_first(stream: tokens))) + parse_operation_modifiers_acc(tokens: token_stream_advance(stream: tokens, n: 1), ctx: minted.ctx, acc: list_push(acc, minted.property)) } else { - ModsResult { modifiers: acc, tokens: tokens, ctx: ctx, err: none } + ModsResult { properties: acc, tokens: tokens, ctx: ctx, err: none } } } @@ -3480,27 +3642,27 @@ fn parse_status_pattern(tokens: TokenStream, ctx: ParseContext) -> ExprResult { match sh { Present { value: ShLitInt } => { let n_opt = parse_int(s: tok.value.text) - let n = match n_opt { Present { value: v } => v Absent => { return ExprResult { expr: make_expr_error_node(kind: InternalExprError, message: concat("internal: ShLitInt token text not parseable as int: '", tok.value.text, "'"), span: span), tokens: tokens, ctx: ctx, err: none } } } + let n = match n_opt { Present { value: v } => v Absent => { return ExprResult { expr: make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: concat("internal: ShLitInt token text not parseable as int: '", tok.value.text, "'"), span: span), tokens: tokens, ctx: ctx, err: none } } } let next_tok = token_stream_first(stream: token_stream_advance(stream: tokens, n: 1)) match next_tok { Present { value: t } => { if is_ident_shape(shape: t.shape) && t.text == "xx" { - ExprResult { expr: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: "{n}xx" } }, children: [], inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 2), ctx: ctx, err: none } + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 2), ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLiteral { value: LitStr { value: "{n}xx" } }, children: [], inferred: none, span: span)) } else { - ExprResult { expr: make_expr_node(expr_data: ExprLiteral { value: LitInt { value: n } }, children: [], inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLiteral { value: LitInt { value: n } }, children: [], inferred: none, span: span)) } } Absent => { - ExprResult { expr: make_expr_node(expr_data: ExprLiteral { value: LitInt { value: n } }, children: [], inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLiteral { value: LitInt { value: n } }, children: [], inferred: none, span: span)) } } } Present { value: ShIdent } => { let id = tok.value.text - ExprResult { expr: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: id } }, children: [], inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLiteral { value: LitStr { value: id } }, children: [], inferred: none, span: span)) } _ => { - ExprResult { expr: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: "_" } }, children: [], inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLiteral { value: LitStr { value: "_" } }, children: [], inferred: none, span: span)) } } } @@ -3543,10 +3705,11 @@ fn parse_response_entries_acc(tokens: TokenStream, ctx: ParseContext, acc: List< let status_str = status_expr_to_str(expr: status, source_indices: ctx.source_indices) let type_name = node_to_name_str(n: r3.type_expr, source_indices: ctx.source_indices) let prop_name = concat("response_", status_str) - let entry = make_field_init_node(name: prop_name, value: make_named_expr_node(name: type_name, expr_data: ExprVar { binding_kind: none }, children: [], inferred: none, span: r3.type_expr.span, name_span: r3.type_expr.span), span: r3.type_expr.span, name_span: no_span()) + let minted = mint_parsed_node_identity(ctx: r3.ctx) + let entry = make_field_init_node(occurrence_identity: minted.identity, name: prop_name, value: make_named_expr_node(occurrence_identity: r3.type_expr.occurrence_identity, name: type_name, expr_data: ExprVar { binding_kind: none }, children: [], inferred: none, span: r3.type_expr.span, name_span: r3.type_expr.span), span: r3.type_expr.span, name_span: no_span()) let e = eat(tokens: r3.tokens, expected: ExpectComma) let tokens = skip_newlines(tokens: match e { EatConsumed { token: _, tokens: __ec } => __ec EatUnchanged { tokens: _ } => r3.tokens }) - parse_response_entries_acc(tokens: tokens, ctx: r3.ctx, acc: list_push(acc, entry)) + parse_response_entries_acc(tokens: tokens, ctx: minted.ctx, acc: list_push(acc, entry)) } } @@ -3594,29 +3757,30 @@ fn parse_mock_response_entries_acc(tokens: TokenStream, ctx: ParseContext, acc: } let status_str = status_expr_to_str(expr: status, source_indices: ctx.source_indices) let prop_name = concat("mock_", status_str) - let entry = make_field_init_node(name: prop_name, value: body, span: no_span(), name_span: no_span()) + let minted = mint_parsed_node_identity(ctx: r3.ctx) + let entry = make_field_init_node(occurrence_identity: minted.identity, name: prop_name, value: body, span: no_span(), name_span: no_span()) let e = eat(tokens: desc_tokens, expected: ExpectComma) let tokens = skip_newlines(tokens: match e { EatConsumed { token: _, tokens: __ec } => __ec EatUnchanged { tokens: _ } => desc_tokens }) - parse_mock_response_entries_acc(tokens: tokens, ctx: r3.ctx, acc: list_push(acc, entry)) + parse_mock_response_entries_acc(tokens: tokens, ctx: minted.ctx, acc: list_push(acc, entry)) } } fn parse_resource_def(tokens: TokenStream, ctx: ParseContext) -> ItemResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect(tokens: tokens, expected: ExpectKeyword { text: "resource" }) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } parse_resource_after_kw(tokens: r.tokens, ctx: ctx, start_span: start_span) } fn parse_resource_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: SourceSpan) -> ItemResult { - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect_ident(tokens: tokens) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } let name = r.name let name_span = r.span - let named_dummy = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let named_dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect(tokens: r.tokens, expected: ExpectLBrace) if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -3627,13 +3791,14 @@ fn parse_resource_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: S let r2 = expect(tokens: skip_newlines(tokens: r.tokens), expected: ExpectRBrace) if has_err(err: r2.err) { return ItemResult { item: named_dummy, tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, + let minted = mint_parsed_node_identity(ctx: r.ctx) + let item = Node { occurrence_identity: minted.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: r.capabilities, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: r.properties, type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: r2.tokens), ctx: r.ctx, err: none } + ItemResult { item: item, tokens: skip_newlines(tokens: r2.tokens), ctx: minted.ctx, err: none } } fn parse_resource_entries(tokens: TokenStream, ctx: ParseContext, properties: List, capabilities: List) -> ResPropResult { @@ -3678,8 +3843,9 @@ fn parse_resource_entries(tokens: TokenStream, ctx: ParseContext, properties: Li if has_err(err: r2.err) { return ResPropResult { properties: properties, capabilities: capabilities, tokens: r2.tokens, ctx: ctx, err: r2.err } } let r3 = parse_expr(tokens: r2.tokens, ctx: ctx) if has_err(err: r3.err) { return ResPropResult { properties: properties, capabilities: capabilities, tokens: r3.tokens, ctx: r3.ctx, err: r3.err } } - let fi = make_field_init_node(name: fname, value: r3.expr, span: no_span(), name_span: r.span) - parse_resource_entries(tokens: skip_newlines(tokens: r3.tokens), ctx: r3.ctx, properties: list_push(properties, fi), capabilities: capabilities) + let minted = mint_parsed_node_identity(ctx: r3.ctx) + let fi = make_field_init_node(occurrence_identity: minted.identity, name: fname, value: r3.expr, span: no_span(), name_span: r.span) + parse_resource_entries(tokens: skip_newlines(tokens: r3.tokens), ctx: minted.ctx, properties: list_push(properties, fi), capabilities: capabilities) } else { ResPropResult { properties: properties, capabilities: capabilities, tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: "unexpected token in resource block", span: span) } } } @@ -3712,7 +3878,7 @@ fn skip_until_rbrace(tokens: TokenStream) -> UnitResult { fn parse_capability(tokens: TokenStream, ctx: ParseContext) -> CapResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy_cap = make_capability_node(name: "", ident_span: none, inputs: [], outputs: [], span: start_span, source_indices: ctx.source_indices) + let dummy_cap = make_capability_node(occurrence_identity: OccurrenceSynthetic, name: "", ident_span: none, inputs: [], outputs: [], span: start_span, source_indices: ctx.source_indices) let r = expect(tokens: tokens, expected: ExpectKeyword { text: "capability" }) if has_err(err: r.err) { return CapResult { capability: dummy_cap, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -3729,8 +3895,9 @@ fn parse_capability(tokens: TokenStream, ctx: ParseContext) -> CapResult { if has_err(err: io.err) { return CapResult { capability: dummy_cap, tokens: io.tokens, ctx: io.ctx, err: io.err } } let r3 = expect(tokens: skip_newlines(tokens: io.tokens), expected: ExpectRBrace) if has_err(err: r3.err) { return CapResult { capability: dummy_cap, tokens: r3.tokens, ctx: io.ctx, err: r3.err } } - let cap = make_capability_node(name: name, ident_span: Present { value: name_span }, inputs: io.inputs, outputs: io.outputs, span: start_span, source_indices: ctx.source_indices) - CapResult { capability: cap, tokens: skip_newlines(tokens: r3.tokens), ctx: io.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: io.ctx) + let cap = make_capability_node(occurrence_identity: minted.identity, name: name, ident_span: Present { value: name_span }, inputs: io.inputs, outputs: io.outputs, span: start_span, source_indices: ctx.source_indices) + CapResult { capability: cap, tokens: skip_newlines(tokens: r3.tokens), ctx: minted.ctx, err: none } } else if tok_is_lparen(tok: token_stream_first(stream: tokens)) { let r2 = expect(tokens: tokens, expected: ExpectLParen) if has_err(err: r2.err) { return CapResult { capability: dummy_cap, tokens: r2.tokens, ctx: ctx, err: r2.err } } @@ -3745,11 +3912,13 @@ fn parse_capability(tokens: TokenStream, ctx: ParseContext) -> CapResult { Present { value: Resolved { node: rt } } => node_inferred_to_outputs(rt: rt, source_indices: ret.ctx.source_indices) _ => [] } - let cap = make_capability_node(name: name, ident_span: Present { value: name_span }, inputs: inputs, outputs: outputs, span: start_span, source_indices: ctx.source_indices) - CapResult { capability: cap, tokens: skip_newlines(tokens: ret.tokens), ctx: ret.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: ret.ctx) + let cap = make_capability_node(occurrence_identity: minted.identity, name: name, ident_span: Present { value: name_span }, inputs: inputs, outputs: outputs, span: start_span, source_indices: ctx.source_indices) + CapResult { capability: cap, tokens: skip_newlines(tokens: ret.tokens), ctx: minted.ctx, err: none } } else { - let cap = make_capability_node(name: name, ident_span: Present { value: name_span }, inputs: [], outputs: [], span: start_span, source_indices: ctx.source_indices) - CapResult { capability: cap, tokens: skip_newlines(tokens: tokens), ctx: ctx, err: none } + let minted = mint_parsed_node_identity(ctx: ctx) + let cap = make_capability_node(occurrence_identity: minted.identity, name: name, ident_span: Present { value: name_span }, inputs: [], outputs: [], span: start_span, source_indices: ctx.source_indices) + CapResult { capability: cap, tokens: skip_newlines(tokens: tokens), ctx: minted.ctx, err: none } } } @@ -3787,20 +3956,20 @@ fn parse_io_blocks_acc(tokens: TokenStream, ctx: ParseContext, inputs: List ItemResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect(tokens: tokens, expected: ExpectKeyword { text: "data" }) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } parse_data_after_kw(tokens: r.tokens, ctx: ctx, start_span: start_span) } fn parse_alias_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: SourceSpan) -> ItemResult { - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect_ident(tokens: tokens) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } let name = r.name let name_span = r.span - let named_dummy = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let named_dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect(tokens: r.tokens, expected: ExpectEq) if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -3809,9 +3978,12 @@ fn parse_alias_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: Sour if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: ctx, err: r.err } } let target_path = r.name - let target_prop = make_field_init_node( + let value_mint = mint_parsed_node_identity(ctx: ctx) + let property_mint = mint_parsed_node_identity(ctx: value_mint.ctx) + let item_mint = mint_parsed_node_identity(ctx: property_mint.ctx) + let target_prop = make_field_init_node(occurrence_identity: property_mint.identity, name: "namespace_alias_target", - value: make_expr_node( + value: make_expr_node(occurrence_identity: value_mint.identity, expr_data: ExprLiteral { value: LitStr { value: target_path } }, children: [], inferred: none, @@ -3821,24 +3993,24 @@ fn parse_alias_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: Sour name_span: no_span() ) - let item = Node { + let item = Node { occurrence_identity: item_mint.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [target_prop], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: r.tokens), ctx: ctx, err: none } + ItemResult { item: item, tokens: skip_newlines(tokens: r.tokens), ctx: item_mint.ctx, err: none } } fn parse_data_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: SourceSpan) -> ItemResult { - let dummy = Node { name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let dummy = Node { occurrence_identity: OccurrenceSynthetic, name: "", span: start_span, ident_span: none, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect_ident(tokens: tokens) if has_err(err: r.err) { return ItemResult { item: dummy, tokens: r.tokens, ctx: ctx, err: r.err } } let name = r.name let name_span = r.span - let named_dummy = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let named_dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let r = expect(tokens: r.tokens, expected: ExpectColon) if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -3846,6 +4018,7 @@ fn parse_data_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: Sourc let r = parse_type_expr(tokens: r.tokens, ctx: ctx) if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: r.ctx, err: r.err } } let te = r.type_expr + let ctx = r.ctx let r = expect(tokens: r.tokens, expected: ExpectEq) if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -3853,12 +4026,13 @@ fn parse_data_after_kw(tokens: TokenStream, ctx: ParseContext, start_span: Sourc let r = parse_expr(tokens: r.tokens, ctx: ctx) if has_err(err: r.err) { return ItemResult { item: named_dummy, tokens: r.tokens, ctx: r.ctx, err: r.err } } - let item = Node { name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], + let minted = mint_parsed_node_identity(ctx: r.ctx) + let item = Node { occurrence_identity: minted.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: [], inferred: none, return_cardinality: Required, uses: [], body: Present { value: r.expr }, connective: NoConnective, transport: none, properties: [], type_annotation: Present { value: te }, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - ItemResult { item: item, tokens: skip_newlines(tokens: r.tokens), ctx: r.ctx, err: none } + ItemResult { item: item, tokens: skip_newlines(tokens: r.tokens), ctx: minted.ctx, err: none } } fn parse_params(tokens: TokenStream, ctx: ParseContext) -> ParamsResult { @@ -3902,7 +4076,7 @@ fn parse_param_list_acc(tokens: TokenStream, ctx: ParseContext, acc: List) fn parse_param(tokens: TokenStream, ctx: ParseContext) -> ParamResult { let start_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy_param = make_param_node(name: "", type_expr: leaf_type_node(name: "", span: start_span), default_value: none, span: start_span, name_span: start_span) + let dummy_param = make_param_node(occurrence_identity: OccurrenceSynthetic, name: "", type_expr: leaf_type_node(occurrence_identity: OccurrenceSynthetic, name: "", span: start_span), default_value: none, span: start_span, name_span: start_span) let r = expect_name(tokens: tokens) if has_err(err: r.err) { return ParamResult { param: dummy_param, tokens: r.tokens, ctx: ctx, err: r.err } } let name = r.name @@ -3924,17 +4098,19 @@ fn parse_param(tokens: TokenStream, ctx: ParseContext) -> ParamResult { EatConsumed { token: _, tokens: __ec } => let r4 = parse_expr(tokens: __ec, ctx: ctx) if has_err(err: r4.err) { return ParamResult { param: dummy_param, tokens: r4.tokens, ctx: r4.ctx, err: r4.err } } - let p = make_param_node( + let minted = mint_parsed_node_identity(ctx: r4.ctx) + let p = make_param_node(occurrence_identity: minted.identity, name: name, type_expr: type_expr, default_value: Present { value: r4.expr }, span: start_span, name_span: name_span ) - ParamResult { param: p, tokens: r4.tokens, ctx: r4.ctx, err: none } + ParamResult { param: p, tokens: r4.tokens, ctx: minted.ctx, err: none } EatUnchanged { tokens: __eu } => - let p = make_param_node( + let minted = mint_parsed_node_identity(ctx: ctx) + let p = make_param_node(occurrence_identity: minted.identity, name: name, type_expr: type_expr, default_value: none, span: start_span, name_span: name_span ) - ParamResult { param: p, tokens: tokens, ctx: ctx, err: none } + ParamResult { param: p, tokens: tokens, ctx: minted.ctx, err: none } } } @@ -3980,7 +4156,7 @@ fn heads_skip_block_tokens(tokens: TokenStream, depth: Int) -> HeadsBlockSkipRes data census_heads_body_stand_in_message: String = "pool census heads-only: function body stripped -- refuse to interpret" fn census_heads_body_stand_in() -> Node { - make_expr_error_node( + make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: CensusHeadsBodyStripped, message: census_heads_body_stand_in_message, span: no_span() @@ -4027,7 +4203,7 @@ fn parse_block(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if count(stmts) == 1 { ExprResult { expr: first(stmts).value, tokens: r.tokens, ctx: ctx, err: none } } else { - ExprResult { expr: make_expr_node(expr_data: ExprBlock, children: stmts, inferred: none, span: block_span), tokens: r.tokens, ctx: ctx, err: none } + parsed_expr_result(tokens: r.tokens, ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprBlock, children: stmts, inferred: none, span: block_span)) } } @@ -4116,15 +4292,16 @@ fn parse_constrained_assignment(tokens: TokenStream, ctx: ParseContext) -> ExprR if has_err(err: r2.err) { return ExprResult { expr: dummy_expr, tokens: r2.tokens, ctx: cr.ctx, err: r2.err } } let r3 = parse_expr(tokens: r2.tokens, ctx: cr.ctx) if has_err(err: r3.err) { return r3 } - let node = make_named_expr_node(name: name, expr_data: ExprLet, children: [r3.expr], inferred: none, span: span, name_span: name_span) - let node = Node { name: node.name, span: node.span, ident_span: node.ident_span, children: node.children, - params: node.params, inferred: node.inferred, return_cardinality: node.return_cardinality, - uses: node.uses, body: node.body, - connective: node.connective, transport: node.transport, properties: cr.constraints, - type_annotation: node.type_annotation, is_self_recursive: node.is_self_recursive, - has_non_tail_self_call: node.has_non_tail_self_call, match_pattern: node.match_pattern, - expr_data: node.expr_data } - ExprResult { expr: node, tokens: r3.tokens, ctx: r3.ctx, err: none } + parsed_expr_result( + tokens: r3.tokens, + ctx: r3.ctx, + build: identity => Node { occurrence_identity: identity, name: name, span: span, + ident_span: Present { value: name_span }, children: [r3.expr], params: [], + inferred: none, return_cardinality: Required, uses: [], body: none, + connective: NoConnective, transport: none, properties: cr.constraints, + type_annotation: none, is_self_recursive: false, + has_non_tail_self_call: false, match_pattern: none, expr_data: ExprLet } + ) } fn peek_text_is(tokens: TokenStream, expected: String) -> Bool { @@ -4155,13 +4332,16 @@ fn parse_node_decl(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let ret = parse_optional_inferred(tokens: r3.tokens, ctx: r3.ctx) if has_err(err: ret.err) { return ExprResult { expr: dummy_expr, tokens: ret.tokens, ctx: ret.ctx, err: ret.err } } let type_ann = match e_colon { EatConsumed { token: _, tokens: _ } => Present { value: r3.expr } EatUnchanged { tokens: _ } => none } - let node = Node { name: name, span: span, ident_span: Present { value: name_span }, children: [r3.expr], - connective: NoConnective, params: [], inferred: ret.inferred, return_cardinality: Required, - uses: [], body: none, transport: none, properties: cr.constraints, - type_annotation: type_ann, is_self_recursive: false, - has_non_tail_self_call: false, match_pattern: none, - expr_data: ExprLet } - ExprResult { expr: node, tokens: ret.tokens, ctx: ret.ctx, err: none } + parsed_expr_result( + tokens: ret.tokens, + ctx: ret.ctx, + build: identity => Node { occurrence_identity: identity, name: name, span: span, + ident_span: Present { value: name_span }, children: [r3.expr], + connective: NoConnective, params: [], inferred: ret.inferred, + return_cardinality: Required, uses: [], body: none, transport: none, + properties: cr.constraints, type_annotation: type_ann, is_self_recursive: false, + has_non_tail_self_call: false, match_pattern: none, expr_data: ExprLet } + ) } fn parse_bare_assignment(tokens: TokenStream, ctx: ParseContext) -> ExprResult { @@ -4177,18 +4357,16 @@ fn parse_bare_assignment(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if has_err(err: r3.err) { return r3 } let cr = try_constraint_annotations(tokens: r3.tokens, ctx: r3.ctx) if has_err(err: cr.err) { return ExprResult { expr: dummy_expr, tokens: cr.tokens, ctx: cr.ctx, err: cr.err } } - let node = make_named_expr_node(name: name, expr_data: ExprLet, children: [r3.expr], inferred: none, span: span, name_span: name_span) - if count(cr.constraints) > 0 { - let node = Node { name: node.name, span: node.span, ident_span: node.ident_span, children: node.children, params: node.params, - inferred: node.inferred, return_cardinality: node.return_cardinality, uses: node.uses, - body: node.body, connective: node.connective, - transport: node.transport, properties: cr.constraints, type_annotation: node.type_annotation, - is_self_recursive: node.is_self_recursive, has_non_tail_self_call: node.has_non_tail_self_call, - match_pattern: node.match_pattern, expr_data: node.expr_data } - ExprResult { expr: node, tokens: cr.tokens, ctx: cr.ctx, err: none } - } else { - ExprResult { expr: node, tokens: cr.tokens, ctx: cr.ctx, err: none } - } + parsed_expr_result( + tokens: cr.tokens, + ctx: cr.ctx, + build: identity => Node { occurrence_identity: identity, name: name, span: span, + ident_span: Present { value: name_span }, children: [r3.expr], params: [], + inferred: none, return_cardinality: Required, uses: [], body: none, + connective: NoConnective, transport: none, properties: cr.constraints, + type_annotation: none, is_self_recursive: false, + has_non_tail_self_call: false, match_pattern: none, expr_data: ExprLet } + ) } fn parse_expr(tokens: TokenStream, ctx: ParseContext) -> ExprResult { @@ -4227,8 +4405,9 @@ fn parse_expr_loop(tokens: TokenStream, ctx: ParseContext, lhs: Node, min_bp: In if is_dot_shape(shape: op_shape) { let r = expect_name(tokens: rest) if has_err(err: r.err) { return ExprResult { expr: lhs, tokens: r.tokens, ctx: ctx, err: r.err } } - let new_lhs = make_named_expr_node(name: r.name, expr_data: ExprFieldAccess { summary: none }, children: [lhs], inferred: none, span: loop_span, name_span: r.span) - parse_expr_loop(tokens: r.tokens, ctx: ctx, lhs: new_lhs, min_bp: min_bp) + let minted = mint_parsed_node_identity(ctx: ctx) + let new_lhs = make_named_expr_node(occurrence_identity: minted.identity, name: r.name, expr_data: ExprFieldAccess { summary: none }, children: [lhs], inferred: none, span: loop_span, name_span: r.span) + parse_expr_loop(tokens: r.tokens, ctx: minted.ctx, lhs: new_lhs, min_bp: min_bp) } else if is_pipe_arrow_shape(shape: op_shape) { let r = parse_pipe_rhs(tokens: rest, ctx: ctx, receiver: lhs, span: loop_span) if has_err(err: r.err) { return ExprResult { expr: r.expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } @@ -4240,8 +4419,9 @@ fn parse_expr_loop(tokens: TokenStream, ctx: ParseContext, lhs: Node, min_bp: In let binop_opt = find_operator_binop(ops: dag_syntax_spec.operators, symbol: op_tok.text) match binop_opt { Present { value: binop } => { - let new_lhs = make_expr_node(expr_data: ExprBinOp { op: binop, algebra_field: none }, children: [lhs, r.expr], inferred: none, span: loop_span) - parse_expr_loop(tokens: r.tokens, ctx: r.ctx, lhs: new_lhs, min_bp: min_bp) + let minted = mint_parsed_node_identity(ctx: r.ctx) + let new_lhs = make_expr_node(occurrence_identity: minted.identity, expr_data: ExprBinOp { op: binop, algebra_field: none }, children: [lhs, r.expr], inferred: none, span: loop_span) + parse_expr_loop(tokens: r.tokens, ctx: minted.ctx, lhs: new_lhs, min_bp: min_bp) } Absent => ExprResult { expr: lhs, tokens: r.tokens, ctx: r.ctx, err: Present { value: parse_error(msg: concat("unknown binary operator: ", op_tok.text), span: loop_span) } } } @@ -4274,9 +4454,9 @@ fn parse_pipe_rhs(tokens: TokenStream, ctx: ParseContext, receiver: Node, span: if tok_is_lparen(tok: token_stream_first(stream: tokens)) { let r2 = parse_call_args(tokens: tokens, ctx: ctx) if has_err(err: r2.err) { return ExprResult { expr: dummy_expr, tokens: r2.tokens, ctx: r2.ctx, err: r2.err } } - ExprResult { expr: make_named_expr_node(name: method, expr_data: ExprMethodCall { method_semantics: none }, children: concat([receiver], r2.args |> map(na => make_arg_node(name: arg_name_at(n: na, source_indices: ctx.source_indices), value: arg_value(n: na), span: na.span, name_span: node_name_span(n: na)))), inferred: none, span: span, name_span: r.span), tokens: r2.tokens, ctx: r2.ctx, err: none } + parsed_expr_result(tokens: r2.tokens, ctx: r2.ctx, build: identity => make_named_expr_node(occurrence_identity: identity, name: method, expr_data: ExprMethodCall { method_semantics: none }, children: concat([receiver], r2.args |> map(na => make_arg_node(occurrence_identity: na.occurrence_identity, name: arg_name_at(n: na, source_indices: ctx.source_indices), value: arg_value(n: na), span: na.span, name_span: node_name_span(n: na)))), inferred: none, span: span, name_span: r.span)) } else { - ExprResult { expr: make_named_expr_node(name: method, expr_data: ExprMethodCall { method_semantics: none }, children: [receiver], inferred: none, span: span, name_span: r.span), tokens: tokens, ctx: ctx, err: none } + parsed_expr_result(tokens: tokens, ctx: ctx, build: identity => make_named_expr_node(occurrence_identity: identity, name: method, expr_data: ExprMethodCall { method_semantics: none }, children: [receiver], inferred: none, span: span, name_span: r.span)) } } @@ -4288,12 +4468,12 @@ fn parse_prefix(tokens: TokenStream, ctx: ParseContext) -> ExprResult { Present { value: ShBang } => { let r = parse_expr_bp(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, min_bp: 12) if has_err(err: r.err) { return ExprResult { expr: r.expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } - ExprResult { expr: make_expr_node(expr_data: ExprUnaryOp { op: Not }, children: [r.expr], inferred: none, span: span), tokens: r.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprUnaryOp { op: Not }, children: [r.expr], inferred: none, span: span)) } Present { value: ShMinus } => { let r = parse_expr_bp(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, min_bp: 12) if has_err(err: r.err) { return ExprResult { expr: r.expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } - ExprResult { expr: make_expr_node(expr_data: ExprUnaryOp { op: Neg }, children: [r.expr], inferred: none, span: span), tokens: r.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprUnaryOp { op: Neg }, children: [r.expr], inferred: none, span: span)) } _ => parse_primary(tokens: tokens, ctx: ctx) } @@ -4310,12 +4490,11 @@ fn parse_caret_expr(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let spelling = next.value.text let end_span = token_span(tok: next) let lit_span = make_file_span(file: span.file, start: span.start, end: end_span.end) - ExprResult { - expr: make_expr_node(expr_data: ExprLiteral { value: LitSymbol { value: spelling } }, children: [], inferred: none, span: lit_span), + parsed_expr_result( tokens: token_stream_advance(stream: after_caret, n: 1), ctx: ctx, - err: none - } + build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLiteral { value: LitSymbol { value: spelling } }, children: [], inferred: none, span: lit_span) + ) } Present { value: ShLParen } => { let r = parse_expr(tokens: token_stream_advance(stream: after_caret, n: 1), ctx: ctx) @@ -4324,9 +4503,11 @@ fn parse_caret_expr(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let r2 = expect(tokens: tokens, expected: ExpectRParen) if has_err(err: r2.err) { return ExprResult { expr: dummy_expr, tokens: r2.tokens, ctx: r.ctx, err: r2.err } } let call_span = make_file_span(file: span.file, start: span.start, end: r2.token.span.end) - let callee = make_named_expr_node(name: "discriminant", expr_data: ExprVar { binding_kind: none }, children: [], inferred: none, span: call_span, name_span: kernel_span(name: "discriminant")) - let call = make_call_expr(lhs: callee, args: [r.expr], span: call_span, source_indices: ctx.source_indices) - ExprResult { expr: call, tokens: r2.tokens, ctx: ctx, err: none } + let callee_mint = mint_parsed_node_identity(ctx: r.ctx) + let callee = make_named_expr_node(occurrence_identity: callee_mint.identity, name: "discriminant", expr_data: ExprVar { binding_kind: none }, children: [], inferred: none, span: call_span, name_span: kernel_span(name: "discriminant")) + let call_mint = mint_parsed_node_identity(ctx: callee_mint.ctx) + let call = make_call_expr(occurrence_identity: call_mint.identity, lhs: callee, args: [r.expr], span: call_span, source_indices: ctx.source_indices) + ExprResult { expr: call, tokens: r2.tokens, ctx: call_mint.ctx, err: none } } _ => { let found = match next_shape { @@ -4353,7 +4534,7 @@ fn parse_primary(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let lit_val = lookup(dag_syntax_spec.keyword_literals, key: kw_text) match lit_val { Present { value: lv } => { - ExprResult { expr: make_expr_node(expr_data: ExprLiteral { value: lv }, children: [], inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLiteral { value: lv }, children: [], inferred: none, span: span)) } Absent => { if kw_text == "match" { parse_match(tokens: tokens, ctx: ctx) } @@ -4381,16 +4562,16 @@ fn parse_primary(tokens: TokenStream, ctx: ParseContext) -> ExprResult { } Present { value: ShLitInt } => { let n_opt = parse_int(s: tok.value.text) - let n = match n_opt { Present { value: v } => v Absent => { return ExprResult { expr: make_expr_error_node(kind: InternalExprError, message: concat("internal: ShLitInt token text not parseable as int: '", tok.value.text, "'"), span: span), tokens: tokens, ctx: ctx, err: none } } } - ExprResult { expr: make_expr_node(expr_data: ExprLiteral { value: LitInt { value: n } }, children: [], inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + let n = match n_opt { Present { value: v } => v Absent => { return ExprResult { expr: make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: concat("internal: ShLitInt token text not parseable as int: '", tok.value.text, "'"), span: span), tokens: tokens, ctx: ctx, err: none } } } + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLiteral { value: LitInt { value: n } }, children: [], inferred: none, span: span)) } Present { value: ShLitFloat } => { let f = tok.value.text - ExprResult { expr: make_expr_node(expr_data: ExprLiteral { value: LitFloat { value: f } }, children: [], inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLiteral { value: LitFloat { value: f } }, children: [], inferred: none, span: span)) } Present { value: ShLitStr } => { let s = tok.value.text - ExprResult { expr: make_expr_node(expr_data: ExprLiteral { value: LitStr { value: s } }, children: [], inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLiteral { value: LitStr { value: s } }, children: [], inferred: none, span: span)) } Present { value: ShStrBegin } => parse_string_interp(tokens: tokens, ctx: ctx) Present { value: ShCaret } => parse_caret_expr(tokens: tokens, ctx: ctx) @@ -4427,7 +4608,7 @@ fn parse_lambda_body(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if count(r.stmts) == 1 { ExprResult { expr: first(r.stmts).value, tokens: r.tokens, ctx: r.ctx, err: none } } else { - ExprResult { expr: make_expr_node(expr_data: ExprBlock, children: r.stmts, inferred: none, span: span), tokens: r.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprBlock, children: r.stmts, inferred: none, span: span)) } } else { parse_expr(tokens: tokens, ctx: ctx) @@ -4453,12 +4634,12 @@ fn parse_ident_expr(tokens: TokenStream, ctx: ParseContext, name: String) -> Exp if tok_is_fat_arrow(tok: token_stream_first(stream: tokens)) { let r = parse_lambda_body(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx) if has_err(err: r.err) { return r } - ExprResult { expr: make_expr_node(expr_data: ExprLambda, children: concat([r.expr], [parsed_name_leaf(name: name, span: span)]), inferred: none, span: span), tokens: r.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLambda, children: concat([r.expr], [parsed_name_leaf(name: name, span: span)]), inferred: none, span: span)) } else { if is_uppercase_start(name: name) && tok_is_lbrace(tok: token_stream_first(stream: tokens)) { parse_record_literal(tokens: tokens, ctx: ctx, name: name, span: span) } else { - ExprResult { expr: make_named_expr_node(name: name, expr_data: ExprVar { binding_kind: none }, children: [], inferred: none, span: span, name_span: span), tokens: tokens, ctx: ctx, err: none } + parsed_expr_result(tokens: tokens, ctx: ctx, build: identity => make_named_expr_node(occurrence_identity: identity, name: name, expr_data: ExprVar { binding_kind: none }, children: [], inferred: none, span: span, name_span: span)) } } } @@ -4488,8 +4669,9 @@ fn try_postfix(tokens: TokenStream, ctx: ParseContext, lhs: Node, min_bp: Int) - } else { let r = parse_call_args(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return PostfixResult { expr: lhs, changed: false, tokens: r.tokens, ctx: r.ctx, err: r.err } } - let call_expr = make_call_expr(lhs: lhs, args: r.args, span: span, source_indices: ctx.source_indices) - PostfixResult { expr: call_expr, changed: true, tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let call_expr = make_call_expr(occurrence_identity: minted.identity, lhs: lhs, args: r.args, span: span, source_indices: ctx.source_indices) + PostfixResult { expr: call_expr, changed: true, tokens: r.tokens, ctx: minted.ctx, err: none } } } Present { value: ShIdent } => { @@ -4499,7 +4681,8 @@ fn try_postfix(tokens: TokenStream, ctx: ParseContext, lhs: Node, min_bp: Int) - } else { let r = parse_type_expr(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx) if has_err(err: r.err) { return PostfixResult { expr: lhs, changed: false, tokens: r.tokens, ctx: r.ctx, err: r.err } } - PostfixResult { expr: make_expr_node(expr_data: ExprCast, children: [lhs, r.type_expr], inferred: none, span: span), changed: true, tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + PostfixResult { expr: make_expr_node(occurrence_identity: minted.identity, expr_data: ExprCast, children: [lhs, r.type_expr], inferred: none, span: span), changed: true, tokens: r.tokens, ctx: minted.ctx, err: none } } } else { PostfixResult { expr: lhs, changed: false, tokens: tokens, ctx: ctx, err: none } @@ -4600,13 +4783,14 @@ fn parse_constraint_list(tokens: TokenStream, ctx: ParseContext, acc: List let kw_name = tok.value.text let r = parse_expr(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx) if has_err(err: r.err) { return ConstraintsResult { constraints: [], tokens: r.tokens, ctx: r.ctx, err: r.err } } - let fi = make_field_init_node(name: kw_name, value: r.expr, span: no_span(), name_span: no_span()) + let minted = mint_parsed_node_identity(ctx: r.ctx) + let fi = make_field_init_node(occurrence_identity: minted.identity, name: kw_name, value: r.expr, span: no_span(), name_span: no_span()) let acc = list_push(acc, fi) match eat(tokens: r.tokens, expected: ExpectComma) { EatConsumed { token: _, tokens: __ec } => - parse_constraint_list(tokens: __ec, ctx: r.ctx, acc: acc) + parse_constraint_list(tokens: __ec, ctx: minted.ctx, acc: acc) EatUnchanged { tokens: __eu } => - ConstraintsResult { constraints: acc, tokens: r.tokens, ctx: r.ctx, err: none } + ConstraintsResult { constraints: acc, tokens: r.tokens, ctx: minted.ctx, err: none } } } @@ -4618,11 +4802,11 @@ fn try_constraint_annotations(tokens: TokenStream, ctx: ParseContext) -> Constra } } -fn make_call_expr(lhs: Node, args: List, span: SourceSpan, source_indices: Map) -> Node { +fn make_call_expr(occurrence_identity: NodeOccurrenceIdentity, lhs: Node, args: List, span: SourceSpan, source_indices: Map) -> Node { match lhs.expr_data { - ExprVar { binding_kind: _ } => make_named_expr_node(name: expr_var_name_at(texpr: lhs, source_indices: source_indices), expr_data: ExprCall { call_semantics: none, descent_evidence: none }, children: args, inferred: none, span: lhs.span, name_span: node_name_span(n: lhs)) - ExprFieldAccess { summary: _ } => make_named_expr_node(name: field_access_field_at(texpr: lhs, source_indices: source_indices), expr_data: ExprMethodCall { method_semantics: none }, children: concat([first(lhs.children).value], args), inferred: none, span: lhs.span, name_span: node_name_span(n: lhs)) - _ => make_named_expr_node(name: "", expr_data: ExprCall { call_semantics: none, descent_evidence: none }, children: args, inferred: none, span: lhs.span, name_span: no_span()) + ExprVar { binding_kind: _ } => make_named_expr_node(occurrence_identity: occurrence_identity, name: expr_var_name_at(texpr: lhs, source_indices: source_indices), expr_data: ExprCall { call_semantics: none, descent_evidence: none }, children: args, inferred: none, span: lhs.span, name_span: node_name_span(n: lhs)) + ExprFieldAccess { summary: _ } => make_named_expr_node(occurrence_identity: occurrence_identity, name: field_access_field_at(texpr: lhs, source_indices: source_indices), expr_data: ExprMethodCall { method_semantics: none }, children: concat([first(lhs.children).value], args), inferred: none, span: lhs.span, name_span: node_name_span(n: lhs)) + _ => make_named_expr_node(occurrence_identity: occurrence_identity, name: "", expr_data: ExprCall { call_semantics: none, descent_evidence: none }, children: args, inferred: none, span: lhs.span, name_span: no_span()) } } @@ -4643,11 +4827,11 @@ fn parse_index_or_slice(tokens: TokenStream, ctx: ParseContext, base: Node, span let end_expr = r.expr let r = expect(tokens: r.tokens, expected: ExpectRBracket) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: ctx, err: r.err } } - ExprResult { expr: make_expr_node(expr_data: ExprSlice, children: [base, first_expr, end_expr], inferred: none, span: span), tokens: r.tokens, ctx: ctx, err: none } + parsed_expr_result(tokens: r.tokens, ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprSlice, children: [base, first_expr, end_expr], inferred: none, span: span)) } else { let r = expect(tokens: tokens, expected: ExpectRBracket) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: ctx, err: r.err } } - ExprResult { expr: make_expr_node(expr_data: ExprIndex, children: [base, first_expr], inferred: none, span: span), tokens: r.tokens, ctx: ctx, err: none } + parsed_expr_result(tokens: r.tokens, ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprIndex, children: [base, first_expr], inferred: none, span: span)) } } @@ -4693,7 +4877,7 @@ fn parse_arg_list_acc(tokens: TokenStream, ctx: ParseContext, acc: List) - fn parse_single_arg(tokens: TokenStream, ctx: ParseContext) -> ArgResult { let span = token_span(tok: token_stream_first(stream: tokens)) - let dummy_arg = make_arg_node(name: none, value: parse_recovery_placeholder(), span: span, name_span: span) + let dummy_arg = make_arg_node(occurrence_identity: OccurrenceSynthetic, name: none, value: parse_recovery_placeholder(), span: span, name_span: span) let tok = token_stream_first(stream: tokens) let is_name_token = tok_is_ident(tok: tok) || tok_is_keyword_name(tok: tok) if is_name_token { @@ -4701,24 +4885,28 @@ fn parse_single_arg(tokens: TokenStream, ctx: ParseContext) -> ArgResult { if has_err(err: name_r.err) { let r = parse_expr(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ArgResult { arg: dummy_arg, tokens: r.tokens, ctx: r.ctx, err: r.err } } - let arg = make_arg_node(name: none, value: r.expr, span: span, name_span: span) - ArgResult { arg: arg, tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let arg = make_arg_node(occurrence_identity: minted.identity, name: none, value: r.expr, span: span, name_span: span) + ArgResult { arg: arg, tokens: r.tokens, ctx: minted.ctx, err: none } } else if tok_is_colon(tok: token_stream_first(stream: name_r.tokens)) { let r = parse_expr(tokens: token_stream_advance(stream: name_r.tokens, n: 1), ctx: ctx) if has_err(err: r.err) { return ArgResult { arg: dummy_arg, tokens: r.tokens, ctx: r.ctx, err: r.err } } - let arg = make_arg_node(name: Present { value: name_r.name }, value: r.expr, span: span, name_span: name_r.span) - ArgResult { arg: arg, tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let arg = make_arg_node(occurrence_identity: minted.identity, name: Present { value: name_r.name }, value: r.expr, span: span, name_span: name_r.span) + ArgResult { arg: arg, tokens: r.tokens, ctx: minted.ctx, err: none } } else { let r = parse_expr(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ArgResult { arg: dummy_arg, tokens: r.tokens, ctx: r.ctx, err: r.err } } - let arg = make_arg_node(name: none, value: r.expr, span: span, name_span: span) - ArgResult { arg: arg, tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let arg = make_arg_node(occurrence_identity: minted.identity, name: none, value: r.expr, span: span, name_span: span) + ArgResult { arg: arg, tokens: r.tokens, ctx: minted.ctx, err: none } } } else { let r = parse_expr(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ArgResult { arg: dummy_arg, tokens: r.tokens, ctx: r.ctx, err: r.err } } - let arg = make_arg_node(name: none, value: r.expr, span: span, name_span: span) - ArgResult { arg: arg, tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let arg = make_arg_node(occurrence_identity: minted.identity, name: none, value: r.expr, span: span, name_span: span) + ArgResult { arg: arg, tokens: r.tokens, ctx: minted.ctx, err: none } } } @@ -4742,7 +4930,7 @@ fn parse_match(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let r = expect(tokens: skip_newlines(tokens: r.tokens), expected: ExpectRBrace) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: ctx, err: r.err } } - ExprResult { expr: make_expr_node(expr_data: ExprMatch, children: concat([scrutinee], arms), inferred: none, span: span), tokens: r.tokens, ctx: ctx, err: none } + parsed_expr_result(tokens: r.tokens, ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprMatch, children: concat([scrutinee], arms), inferred: none, span: span)) } fn parse_expr_no_brace(tokens: TokenStream, ctx: ParseContext) -> ExprResult { @@ -4763,10 +4951,11 @@ fn parse_expr_bp_no_brace(tokens: TokenStream, ctx: ParseContext, min_bp: Int) - let stopped_at_infix = match infix_bp(tokens: parsed.tokens) { Present { value: _ } => true Absent => false } if leading_ident_brace && !has_err(err: parsed.err) && !tok_is_lbrace(tok: token_stream_first(stream: parsed.tokens)) && !stopped_at_infix { let span = token_span(tok: tok) - let lhs = make_named_expr_node(name: tok.value.text, expr_data: ExprVar { binding_kind: none }, children: [], inferred: none, span: span, name_span: span) + let minted = mint_parsed_node_identity(ctx: ctx) + let lhs = make_named_expr_node(occurrence_identity: minted.identity, name: tok.value.text, expr_data: ExprVar { binding_kind: none }, children: [], inferred: none, span: span, name_span: span) parse_expr_loop_no_brace( tokens: token_stream_advance(stream: tokens, n: 1), - ctx: ctx, + ctx: minted.ctx, lhs: lhs, min_bp: min_bp ) @@ -4787,8 +4976,9 @@ fn parse_expr_loop_no_brace(tokens: TokenStream, ctx: ParseContext, lhs: Node, m let r = parse_call_args(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ExprResult { expr: lhs, tokens: r.tokens, ctx: r.ctx, err: r.err } } let span = token_span(tok: token_stream_first(stream: tokens)) - let new_lhs = make_call_expr(lhs: lhs, args: r.args, span: span, source_indices: ctx.source_indices) - parse_expr_loop_no_brace(tokens: r.tokens, ctx: r.ctx, lhs: new_lhs, min_bp: min_bp) + let minted = mint_parsed_node_identity(ctx: r.ctx) + let new_lhs = make_call_expr(occurrence_identity: minted.identity, lhs: lhs, args: r.args, span: span, source_indices: ctx.source_indices) + parse_expr_loop_no_brace(tokens: r.tokens, ctx: minted.ctx, lhs: new_lhs, min_bp: min_bp) } else if tok_is_lbracket(tok: token_stream_first(stream: tokens)) && 21 >= min_bp { let span = token_span(tok: token_stream_first(stream: tokens)) let r = parse_index_or_slice(tokens: tokens, ctx: ctx, base: lhs, span: span) @@ -4807,8 +4997,9 @@ fn parse_expr_loop_no_brace(tokens: TokenStream, ctx: ParseContext, lhs: Node, m if is_dot_shape(shape: op_shape) { let r = expect_name(tokens: rest) if has_err(err: r.err) { return ExprResult { expr: lhs, tokens: r.tokens, ctx: ctx, err: r.err } } - let new_lhs = make_named_expr_node(name: r.name, expr_data: ExprFieldAccess { summary: none }, children: [lhs], inferred: none, span: loop_span, name_span: r.span) - parse_expr_loop_no_brace(tokens: r.tokens, ctx: ctx, lhs: new_lhs, min_bp: min_bp) + let minted = mint_parsed_node_identity(ctx: ctx) + let new_lhs = make_named_expr_node(occurrence_identity: minted.identity, name: r.name, expr_data: ExprFieldAccess { summary: none }, children: [lhs], inferred: none, span: loop_span, name_span: r.span) + parse_expr_loop_no_brace(tokens: r.tokens, ctx: minted.ctx, lhs: new_lhs, min_bp: min_bp) } else if is_pipe_arrow_shape(shape: op_shape) { let r = parse_pipe_rhs(tokens: rest, ctx: ctx, receiver: lhs, span: loop_span) if has_err(err: r.err) { return ExprResult { expr: r.expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } @@ -4820,8 +5011,9 @@ fn parse_expr_loop_no_brace(tokens: TokenStream, ctx: ParseContext, lhs: Node, m let binop_opt = find_operator_binop(ops: dag_syntax_spec.operators, symbol: op_tok.text) match binop_opt { Present { value: binop } => { - let new_lhs = make_expr_node(expr_data: ExprBinOp { op: binop, algebra_field: none }, children: [lhs, r.expr], inferred: none, span: loop_span) - parse_expr_loop_no_brace(tokens: r.tokens, ctx: r.ctx, lhs: new_lhs, min_bp: min_bp) + let minted = mint_parsed_node_identity(ctx: r.ctx) + let new_lhs = make_expr_node(occurrence_identity: minted.identity, expr_data: ExprBinOp { op: binop, algebra_field: none }, children: [lhs, r.expr], inferred: none, span: loop_span) + parse_expr_loop_no_brace(tokens: r.tokens, ctx: minted.ctx, lhs: new_lhs, min_bp: min_bp) } Absent => ExprResult { expr: lhs, tokens: r.tokens, ctx: r.ctx, err: Present { value: parse_error(msg: concat("unknown binary operator: ", op_tok.text), span: loop_span) } } } @@ -4855,7 +5047,7 @@ fn parse_match_arms_acc(tokens: TokenStream, ctx: ParseContext, acc: List) fn parse_match_arm(tokens: TokenStream, ctx: ParseContext) -> ArmResult { let arm_span = token_span(tok: token_stream_first(stream: tokens)) - let dummy_arm = make_arm_node(pattern: Wildcard, guard: none, body: parse_recovery_placeholder(), span: no_span()) + let dummy_arm = make_arm_node(occurrence_identity: OccurrenceSynthetic, pattern: Wildcard, guard: none, body: parse_recovery_placeholder(), span: no_span()) let r = parse_pattern(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ArmResult { arm: dummy_arm, tokens: r.tokens, ctx: r.ctx, err: r.err } } let pat = r.pattern @@ -4879,8 +5071,9 @@ fn parse_match_arm(tokens: TokenStream, ctx: ParseContext) -> ArmResult { } if has_err(err: r.err) { return ArmResult { arm: dummy_arm, tokens: r.tokens, ctx: r.ctx, err: r.err } } - let arm = make_arm_node(pattern: pat, guard: guard, body: r.expr, span: arm_span) - ArmResult { arm: arm, tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let arm = make_arm_node(occurrence_identity: minted.identity, pattern: pat, guard: guard, body: r.expr, span: arm_span) + ArmResult { arm: arm, tokens: r.tokens, ctx: minted.ctx, err: none } } fn parse_match_arm_body(tokens: TokenStream, ctx: ParseContext) -> ExprResult { @@ -4893,7 +5086,7 @@ fn parse_match_arm_body(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if count(r.stmts) == 1 { ExprResult { expr: first(r.stmts).value, tokens: r.tokens, ctx: r.ctx, err: none } } else { - ExprResult { expr: make_expr_node(expr_data: ExprBlock, children: r.stmts, inferred: none, span: span), tokens: r.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprBlock, children: r.stmts, inferred: none, span: span)) } } else { parse_expr(tokens: tokens, ctx: ctx) @@ -5023,12 +5216,13 @@ fn parse_pattern(tokens: TokenStream, ctx: ParseContext) -> PatternResult { } else if is_variant_pattern_start(name: n) { parse_variant_pattern(tokens: r.tokens, ctx: ctx, name: n) } else { + let minted = mint_parsed_node_identity(ctx: ctx) PatternResult { pattern: Bind { - declaration: make_pattern_binder_declaration_node(name: n, span: r.span) + declaration: make_pattern_binder_declaration_node(occurrence_identity: minted.identity, name: n, span: r.span) }, tokens: r.tokens, - ctx: ctx, + ctx: minted.ctx, err: none } } @@ -5069,8 +5263,9 @@ fn parse_variant_pattern(tokens: TokenStream, ctx: ParseContext, name: String) - if has_err(err: r.err) { return PatternResult { pattern: Wildcard, tokens: r.tokens, ctx: r.ctx, err: r.err } } let r2 = expect(tokens: r.tokens, expected: ExpectRParen) if has_err(err: r2.err) { return PatternResult { pattern: Wildcard, tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - let fb = make_field_binding_node(field_name: "0", binding: r.pattern, span: span, name_span: kernel_span(name: "0")) - PatternResult { pattern: VariantPattern { name: name, parent_enum: none, field_bindings: [fb] }, tokens: r2.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let fb = make_field_binding_node(occurrence_identity: minted.identity, field_name: "0", binding: r.pattern, span: span, name_span: kernel_span(name: "0")) + PatternResult { pattern: VariantPattern { name: name, parent_enum: none, field_bindings: [fb] }, tokens: r2.tokens, ctx: minted.ctx, err: none } } else { PatternResult { pattern: VariantPattern { name: name, parent_enum: none, field_bindings: [] }, tokens: tokens, ctx: ctx, err: none } } @@ -5098,15 +5293,18 @@ fn parse_variant_bindings_brace_acc(tokens: TokenStream, ctx: ParseContext, acc: if has_err(err: r2.err) { return BindingsResult { field_bindings: [], tokens: r2.tokens, ctx: r2.ctx, err: r2.err } } let e2 = eat(tokens: r2.tokens, expected: ExpectComma) let tokens = skip_newlines(tokens: match e2 { EatConsumed { token: _, tokens: __ec } => __ec EatUnchanged { tokens: _ } => r2.tokens }) - let fb = make_field_binding_node(field_name: field_name, binding: r2.pattern, span: bind_span, name_span: field_name_span) - parse_variant_bindings_brace_acc(tokens: tokens, ctx: r2.ctx, acc: list_push(acc, fb)) + let minted = mint_parsed_node_identity(ctx: r2.ctx) + let fb = make_field_binding_node(occurrence_identity: minted.identity, field_name: field_name, binding: r2.pattern, span: bind_span, name_span: field_name_span) + parse_variant_bindings_brace_acc(tokens: tokens, ctx: minted.ctx, acc: list_push(acc, fb)) EatUnchanged { tokens: __eu } => let e2 = eat(tokens: tokens, expected: ExpectComma) let tokens = skip_newlines(tokens: match e2 { EatConsumed { token: _, tokens: __ec } => __ec EatUnchanged { tokens: _ } => tokens }) - let fb = make_field_binding_node( + let declaration_mint = mint_parsed_node_identity(ctx: ctx) + let field_mint = mint_parsed_node_identity(ctx: declaration_mint.ctx) + let fb = make_field_binding_node(occurrence_identity: field_mint.identity, field_name: field_name, binding: Bind { - declaration: make_pattern_binder_declaration_node( + declaration: make_pattern_binder_declaration_node(occurrence_identity: declaration_mint.identity, name: field_name, span: field_name_span ) @@ -5114,7 +5312,7 @@ fn parse_variant_bindings_brace_acc(tokens: TokenStream, ctx: ParseContext, acc: span: bind_span, name_span: field_name_span ) - parse_variant_bindings_brace_acc(tokens: tokens, ctx: ctx, acc: list_push(acc, fb)) + parse_variant_bindings_brace_acc(tokens: tokens, ctx: field_mint.ctx, acc: list_push(acc, fb)) } } } @@ -5141,14 +5339,14 @@ fn parse_if(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if tok_is_keyword(tok: token_stream_first(stream: tokens), kw: "if") { let r2 = parse_if(tokens: tokens, ctx: ctx) if has_err(err: r2.err) { return ExprResult { expr: r2.expr, tokens: r2.tokens, ctx: r2.ctx, err: r2.err } } - ExprResult { expr: make_expr_node(expr_data: ExprIf, children: [condition, then_branch, r2.expr], inferred: none, span: span), tokens: r2.tokens, ctx: r2.ctx, err: none } + parsed_expr_result(tokens: r2.tokens, ctx: r2.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprIf, children: [condition, then_branch, r2.expr], inferred: none, span: span)) } else { let r2 = parse_block(tokens: tokens, ctx: ctx) if has_err(err: r2.err) { return ExprResult { expr: r2.expr, tokens: r2.tokens, ctx: r2.ctx, err: r2.err } } - ExprResult { expr: make_expr_node(expr_data: ExprIf, children: [condition, then_branch, r2.expr], inferred: none, span: span), tokens: r2.tokens, ctx: r2.ctx, err: none } + parsed_expr_result(tokens: r2.tokens, ctx: r2.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprIf, children: [condition, then_branch, r2.expr], inferred: none, span: span)) } EatUnchanged { tokens: __eu } => - ExprResult { expr: make_expr_node(expr_data: ExprIf, children: [condition, then_branch], inferred: none, span: span), tokens: tokens, ctx: ctx, err: none } + parsed_expr_result(tokens: tokens, ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprIf, children: [condition, then_branch], inferred: none, span: span)) } } @@ -5181,20 +5379,21 @@ fn parse_let(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if has_err(err: r2.err) { return ExprResult { expr: dummy_expr, tokens: r2.tokens, ctx: tr.ctx, err: r2.err } } let r3 = parse_required_expression_after_separator(tokens: r2.tokens, ctx: tr.ctx) if has_err(err: r3.err) { return r3 } - let node = Node { + let minted = mint_parsed_node_identity(ctx: r3.ctx) + let node = Node { occurrence_identity: minted.identity, name: name, span: span, ident_span: Present { value: name_span }, children: [r3.expr], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: Present { value: tr.type_expr }, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: ExprLet } - ExprResult { expr: node, tokens: r3.tokens, ctx: r3.ctx, err: none } + ExprResult { expr: node, tokens: r3.tokens, ctx: minted.ctx, err: none } EatUnchanged { tokens: __eu } => let r2 = expect(tokens: __eu, expected: ExpectEq) if has_err(err: r2.err) { return ExprResult { expr: dummy_expr, tokens: r2.tokens, ctx: ctx, err: r2.err } } let r3 = parse_required_expression_after_separator(tokens: r2.tokens, ctx: ctx) if has_err(err: r3.err) { return r3 } - ExprResult { expr: make_named_expr_node(name: name, expr_data: ExprLet, children: [r3.expr], inferred: none, span: span, name_span: name_span), tokens: r3.tokens, ctx: r3.ctx, err: none } + parsed_expr_result(tokens: r3.tokens, ctx: r3.ctx, build: identity => make_named_expr_node(occurrence_identity: identity, name: name, expr_data: ExprLet, children: [r3.expr], inferred: none, span: span, name_span: name_span)) } } @@ -5206,7 +5405,7 @@ fn parse_return(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let r = parse_required_expression_after_separator(tokens: r.tokens, ctx: ctx) if has_err(err: r.err) { return r } - ExprResult { expr: make_expr_node(expr_data: ExprReturn, children: [r.expr], inferred: none, span: span), tokens: r.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprReturn, children: [r.expr], inferred: none, span: span)) } fn parse_for(tokens: TokenStream, ctx: ParseContext) -> ExprResult { @@ -5231,8 +5430,9 @@ fn parse_for(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if has_err(err: r.err) { return ExprResult { expr: r.expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } let body = r.expr - let for_expr = make_named_expr_node(name: var_name, expr_data: ExprForEach, children: [collection, body], inferred: none, span: span, name_span: var_name_span) - ExprResult { expr: for_expr, tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let for_expr = make_named_expr_node(occurrence_identity: minted.identity, name: var_name, expr_data: ExprForEach, children: [collection, body], inferred: none, span: span, name_span: var_name_span) + ExprResult { expr: for_expr, tokens: r.tokens, ctx: minted.ctx, err: none } } fn field_access_chain_span(texpr: Node) -> SourceSpan { @@ -5262,7 +5462,7 @@ fn parse_record_literal_named(tokens: TokenStream, ctx: ParseContext, name: Stri let r2 = expect(tokens: tokens, expected: ExpectRBrace) if has_err(err: r2.err) { return ExprResult { expr: dummy_expr, tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - ExprResult { expr: make_named_expr_node(name: name, expr_data: ExprRecordLit { parent_enum: none }, children: r.fields, inferred: none, span: span, name_span: name_span), tokens: r2.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r2.tokens, ctx: r.ctx, build: identity => make_named_expr_node(occurrence_identity: identity, name: name, expr_data: ExprRecordLit { parent_enum: none }, children: r.fields, inferred: none, span: span, name_span: name_span)) } fn parse_field_init_list(tokens: TokenStream, ctx: ParseContext) -> FieldInitsResult { @@ -5285,7 +5485,7 @@ fn parse_field_init_list_acc(tokens: TokenStream, ctx: ParseContext, acc: List FieldInitResult { let zero_span = no_span() let span = token_span(tok: token_stream_first(stream: tokens)) - let dummy_fi = make_field_init_node(name: "", value: parse_recovery_placeholder(), span: zero_span, name_span: zero_span) + let dummy_fi = make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: "", value: parse_recovery_placeholder(), span: zero_span, name_span: zero_span) let tok = token_stream_first(stream: tokens) if tok_is_ident(tok: tok) || tok_is_keyword_name(tok: tok) { let name_r = expect_name(tokens: tokens) @@ -5294,11 +5494,15 @@ fn parse_field_init(tokens: TokenStream, ctx: ParseContext) -> FieldInitResult { if tok_is_colon(tok: token_stream_first(stream: name_r.tokens)) { let r = parse_expr(tokens: token_stream_advance(stream: name_r.tokens, n: 1), ctx: ctx) if has_err(err: r.err) { return FieldInitResult { field: dummy_fi, tokens: r.tokens, ctx: r.ctx, err: r.err } } - let fi = make_field_init_node(name: n, value: r.expr, span: span, name_span: name_r.span) - FieldInitResult { field: fi, tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let fi = make_field_init_node(occurrence_identity: minted.identity, name: n, value: r.expr, span: span, name_span: name_r.span) + FieldInitResult { field: fi, tokens: r.tokens, ctx: minted.ctx, err: none } } else { - let fi = make_field_init_node(name: n, value: make_named_expr_node(name: n, expr_data: ExprVar { binding_kind: none }, children: [], inferred: none, span: span, name_span: name_r.span), span: span, name_span: name_r.span) - FieldInitResult { field: fi, tokens: name_r.tokens, ctx: ctx, err: none } + let value_mint = mint_parsed_node_identity(ctx: ctx) + let value = make_named_expr_node(occurrence_identity: value_mint.identity, name: n, expr_data: ExprVar { binding_kind: none }, children: [], inferred: none, span: span, name_span: name_r.span) + let field_mint = mint_parsed_node_identity(ctx: value_mint.ctx) + let fi = make_field_init_node(occurrence_identity: field_mint.identity, name: n, value: value, span: span, name_span: name_r.span) + FieldInitResult { field: fi, tokens: name_r.tokens, ctx: field_mint.ctx, err: none } } } else if tok_is_lit_str(tok: tok) && peek_is_colon_after_ident(tokens: tokens) { let str_name = match tok { @@ -5307,13 +5511,15 @@ fn parse_field_init(tokens: TokenStream, ctx: ParseContext) -> FieldInitResult { } let r = parse_expr(tokens: token_stream_advance(stream: tokens, n: 2), ctx: ctx) if has_err(err: r.err) { return FieldInitResult { field: dummy_fi, tokens: r.tokens, ctx: r.ctx, err: r.err } } - let fi = make_field_init_node(name: str_name, value: r.expr, span: span, name_span: no_span()) - FieldInitResult { field: fi, tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let fi = make_field_init_node(occurrence_identity: minted.identity, name: str_name, value: r.expr, span: span, name_span: no_span()) + FieldInitResult { field: fi, tokens: r.tokens, ctx: minted.ctx, err: none } } else { let r = parse_expr(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return FieldInitResult { field: dummy_fi, tokens: r.tokens, ctx: r.ctx, err: r.err } } - let fi = make_field_init_node(name: "_", value: r.expr, span: span, name_span: no_span()) - FieldInitResult { field: fi, tokens: r.tokens, ctx: r.ctx, err: none } + let minted = mint_parsed_node_identity(ctx: r.ctx) + let fi = make_field_init_node(occurrence_identity: minted.identity, name: "_", value: r.expr, span: span, name_span: no_span()) + FieldInitResult { field: fi, tokens: r.tokens, ctx: minted.ctx, err: none } } } @@ -5329,7 +5535,7 @@ fn parse_list_literal(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let r2 = expect(tokens: skip_newlines(tokens: r.tokens), expected: ExpectRBracket) if has_err(err: r2.err) { return ExprResult { expr: dummy_expr, tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - ExprResult { expr: make_expr_node(expr_data: ExprListLit, children: r.exprs, inferred: none, span: span), tokens: r2.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r2.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprListLit, children: r.exprs, inferred: none, span: span)) } fn parse_expr_list_until(tokens: TokenStream, ctx: ParseContext, end_expected: ExpectedToken) -> ExprsResult { @@ -5361,13 +5567,13 @@ fn parse_paren_expr(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let tokens = skip_newlines(tokens: r.tokens) if tok_is_rparen(tok: token_stream_first(stream: tokens)) { - ExprResult { expr: make_expr_node(expr_data: ExprRecordLit { parent_enum: none }, children: [], inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprRecordLit { parent_enum: none }, children: [], inferred: none, span: span)) } else { let lambda_r = try_lambda_params(tokens: tokens, ctx: ctx) if lambda_r.is_lambda { let r = parse_lambda_body(tokens: lambda_r.tokens, ctx: lambda_r.ctx) if has_err(err: r.err) { return ExprResult { expr: r.expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } - ExprResult { expr: make_expr_node(expr_data: ExprLambda, children: concat([r.expr], lambda_r.params |> map(p => parsed_name_leaf(name: p.name, span: p.span))), inferred: none, span: span), tokens: r.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLambda, children: concat([r.expr], lambda_r.params |> map(p => parsed_name_leaf(name: p.name, span: p.span))), inferred: none, span: span)) } else { let r = parse_expr(tokens: lambda_r.tokens, ctx: lambda_r.ctx) if has_err(err: r.err) { return ExprResult { expr: r.expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } @@ -5392,7 +5598,7 @@ fn parse_fn_lambda(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let tokens = skip_newlines(tokens: r3.tokens) let body_r = parse_brace_expr(tokens: tokens, ctx: params_r.ctx) if has_err(err: body_r.err) { return body_r } - ExprResult { expr: make_expr_node(expr_data: ExprLambda, children: concat([body_r.expr], params_r.params |> map(p => parsed_name_leaf(name: p.name, span: p.span))), inferred: none, span: span), tokens: body_r.tokens, ctx: body_r.ctx, err: none } + parsed_expr_result(tokens: body_r.tokens, ctx: body_r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLambda, children: concat([body_r.expr], params_r.params |> map(p => parsed_name_leaf(name: p.name, span: p.span))), inferred: none, span: span)) } fn collect_fn_lambda_params(tokens: TokenStream, ctx: ParseContext, acc: List) -> IdentCollectResult { @@ -5510,10 +5716,11 @@ fn parse_interp_parts(tokens: TokenStream, ctx: ParseContext, parts: List map(p => match p { Text { value: v } => make_text_part_node(text: v, span: span) Interpolation { expr: e } => make_interp_part_node(expr: e, span: span) }), inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + let children = mint_parsed_string_part_nodes(parts: final_parts, ctx: ctx, span: span, acc: []) + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 1), ctx: children.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprStringInterp, children: children.nodes, inferred: none, span: span)) } _ => - ExprResult { expr: make_expr_node(expr_data: ExprStringInterp, children: new_parts |> map(p => match p { Text { value: v } => make_text_part_node(text: v, span: span) Interpolation { expr: e } => make_interp_part_node(expr: e, span: span) }), inferred: none, span: span), tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: interp_body_error_message(err: none), span: span) } } + ExprResult { expr: make_expr_node(occurrence_identity: OccurrenceSynthetic, expr_data: ExprStringInterp, children: new_parts |> map(p => match p { Text { value: v } => make_text_part_node(occurrence_identity: OccurrenceSynthetic, text: v, span: span) Interpolation { expr: e } => make_interp_part_node(occurrence_identity: OccurrenceSynthetic, expr: e, span: span) }), inferred: none, span: span), tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: interp_body_error_message(err: none), span: span) } } } } @@ -5524,7 +5731,7 @@ fn parse_brace_expr(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let tok = token_stream_first(stream: tokens) if tok_is_rbrace(tok: tok) { - ExprResult { expr: make_expr_node(expr_data: ExprRecordLit { parent_enum: none }, children: [], inferred: none, span: span), tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + parsed_expr_result(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprRecordLit { parent_enum: none }, children: [], inferred: none, span: span)) } else { let sh = match tok { Present { value: t } => Present { value: t.shape } Absent => none } match sh { @@ -5539,7 +5746,7 @@ fn parse_brace_expr(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if count(r.stmts) == 1 { ExprResult { expr: first(r.stmts).value, tokens: r2.tokens, ctx: r.ctx, err: none } } else { - ExprResult { expr: make_expr_node(expr_data: ExprBlock, children: r.stmts, inferred: none, span: span), tokens: r2.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r2.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprBlock, children: r.stmts, inferred: none, span: span)) } } else { if tok_is_keyword_name(tok: tok) && peek_is_colon_after_ident(tokens: tokens) { @@ -5548,7 +5755,7 @@ fn parse_brace_expr(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let tokens = skip_newlines(tokens: r.tokens) let r2 = expect(tokens: tokens, expected: ExpectRBrace) if has_err(err: r2.err) { return ExprResult { expr: dummy_expr, tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - ExprResult { expr: make_expr_node(expr_data: ExprRecordLit { parent_enum: none }, children: r.fields, inferred: none, span: span), tokens: r2.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r2.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprRecordLit { parent_enum: none }, children: r.fields, inferred: none, span: span)) } else { let r = parse_expr(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } @@ -5567,14 +5774,14 @@ fn parse_brace_expr(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let tokens = skip_newlines(tokens: r.tokens) let r2 = expect(tokens: tokens, expected: ExpectRBrace) if has_err(err: r2.err) { return ExprResult { expr: dummy_expr, tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - ExprResult { expr: make_expr_node(expr_data: ExprRecordLit { parent_enum: none }, children: r.fields, inferred: none, span: span), tokens: r2.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r2.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprRecordLit { parent_enum: none }, children: r.fields, inferred: none, span: span)) } else if tok_is_lit_str(tok: tok) && peek_is_colon_after_ident(tokens: tokens) { let r = parse_field_init_list(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } let tokens = skip_newlines(tokens: r.tokens) let r2 = expect(tokens: tokens, expected: ExpectRBrace) if has_err(err: r2.err) { return ExprResult { expr: dummy_expr, tokens: r2.tokens, ctx: r.ctx, err: r2.err } } - ExprResult { expr: make_expr_node(expr_data: ExprRecordLit { parent_enum: none }, children: r.fields, inferred: none, span: span), tokens: r2.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r2.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprRecordLit { parent_enum: none }, children: r.fields, inferred: none, span: span)) } else { let r = parse_stmts(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } @@ -5584,7 +5791,7 @@ fn parse_brace_expr(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if count(r.stmts) == 1 { ExprResult { expr: first(r.stmts).value, tokens: r2.tokens, ctx: r.ctx, err: none } } else { - ExprResult { expr: make_expr_node(expr_data: ExprBlock, children: r.stmts, inferred: none, span: span), tokens: r2.tokens, ctx: r.ctx, err: none } + parsed_expr_result(tokens: r2.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprBlock, children: r.stmts, inferred: none, span: span)) } } } diff --git a/src/v1/04_env.dag b/src/v1/04_env.dag index eac4c75c6ac..3029154ddb7 100644 --- a/src/v1/04_env.dag +++ b/src/v1/04_env.dag @@ -1,5 +1,7 @@ module v1.compiler.infer_env +import std.occurrence_identity { OccurrenceSynthetic } + import v1.std.core { Node, NewlineIndex, InternTable, empty_intern_table, merge_intern_tables, intern, intern_find, intern_str, source_text_at, authored_name_at, find_child_named, Cardinality, Connective, ExprData, InferredNode, kernel_span, module_path_segments, param_node_name_at, param_node_type_expr, CompilerDiagnostic, AmbiguousReference, UnresolvedType } import v1.compiler.type_head_exposure { TypeHeadExposure } @@ -725,7 +727,7 @@ fn qualify_borrowed_type_names(n: Node, owner_module_path: String, env: TypeEnv, } else { let qname = concat(mp, ".", name) Node { - name: qname, span: n.span, ident_span: Present { value: kernel_span(name: qname) }, + occurrence_identity: OccurrenceSynthetic, name: qname, span: n.span, ident_span: Present { value: kernel_span(name: qname) }, children: qualified_children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, @@ -740,7 +742,7 @@ fn qualify_borrowed_type_names(n: Node, owner_module_path: String, env: TypeEnv, fn node_with_children(n: Node, children: List) -> Node { Node { - name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, + occurrence_identity: OccurrenceSynthetic, name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, children: children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, @@ -752,7 +754,7 @@ fn node_with_children(n: Node, children: List) -> Node { fn node_with_inferred(n: Node, inferred: InferredNode?) -> Node { Node { - name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, + occurrence_identity: OccurrenceSynthetic, name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, children: n.children, connective: n.connective, params: n.params, inferred: inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, @@ -1068,7 +1070,7 @@ fn env_with_type_variable_bindings(env: TypeEnv, tp_names: List) -> Type fold(tp_names, init: env, f: (e, tp_name) => let tp_binding = TypeBinding { name: tp_name, - resolved: Node { name: tp_name, span: kernel_span(name: tp_name), ident_span: Present { value: kernel_span(name: tp_name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: tp_name } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: OccurrenceSynthetic, name: tp_name, span: kernel_span(name: tp_name), ident_span: Present { value: kernel_span(name: tp_name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: tp_name } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, provenance: SubValueUnknown } TypeEnv { module_path: e.module_path, diff --git a/src/v1/04_infer.dag b/src/v1/04_infer.dag index b85f378c3d9..56d8c004850 100644 --- a/src/v1/04_infer.dag +++ b/src/v1/04_infer.dag @@ -1,4 +1,6 @@ module v1.compiler.infer + +import std.occurrence_identity { NodeOccurrenceIdentity, OccurrenceSynthetic } import std.types { SourceSpan, NonEmptyStr, container_param_name, container_template_algebra, kernel_type_set, is_kernel_type } import std.content_hash { ContentHash, @@ -492,7 +494,7 @@ fn build_item_inductive_fields(items: List, recursive_type_set: Set Node { Node { - name: name, span: span, ident_span: ident_span, children: [], + occurrence_identity: OccurrenceSynthetic, name: name, span: span, ident_span: ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: nominal_leaf_type(name: name) } }, return_cardinality: Required, @@ -551,11 +553,11 @@ fn ok_infer(texpr: Node) -> InferResult { } fn semantic_expr_error_node(message: String, span: SourceSpan) -> Node { - make_expr_error_node(kind: SemanticExprError, message: message, span: span) + make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: SemanticExprError, message: message, span: span) } fn internal_expr_error_node(message: String, span: SourceSpan) -> Node { - make_expr_error_node(kind: InternalExprError, message: message, span: span) + make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: message, span: span) } fn lookup_variant_parent_enum(scope: InferScope, name: String) -> String? { @@ -1277,7 +1279,7 @@ fn record_lit_instantiated_fields(type_name: String?, expected: Node?, scope: In let template_fields = decl.children Present { value: template_fields |> map(sf => Node { - name: sf.name, span: sf.span, ident_span: sf.ident_span, + occurrence_identity: OccurrenceSynthetic, name: sf.name, span: sf.span, ident_span: sf.ident_span, children: sf.children, connective: sf.connective, params: sf.params, inferred: Present { value: Resolved { node: substitute_generics(n: field_substitution_carrier(sf: sf, source_indices: scope.type_env.source_indices), subst: subst, source_indices: scope.type_env.source_indices) } }, return_cardinality: sf.return_cardinality, uses: sf.uses, body: sf.body, @@ -3817,7 +3819,7 @@ fn optional_cast_diags( } fn type_variable_node(id: String) -> Node { - Node { name: "", span: no_span(), ident_span: none, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: id } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: OccurrenceSynthetic, name: "", span: no_span(), ident_span: none, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: id } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn is_type_variable(inferred: InferredNode) -> Bool { @@ -3874,7 +3876,7 @@ fn annotate_pattern_parent_enums(pattern: MatchPattern, scrutinee_subject: Patte let annotated_bindings = bindings |> map(binding => let field_lookup = lookup_field_in_variant(variant: variant_subject, field_name: field_binding_name_at(n: binding, source_indices: scope.type_env.source_indices), module_name: scope.module_name, source_indices: scope.type_env.source_indices) let field_subject = lookup_result_subject(result: field_lookup) - make_field_binding_node(field_name: field_binding_name_at(n: binding, source_indices: scope.type_env.source_indices), binding: annotate_pattern_parent_enums(pattern: field_binding_pattern(n: binding), scrutinee_subject: field_subject, scope: scope), span: binding.span, name_span: node_name_span(n: binding)) + make_field_binding_node(occurrence_identity: binding.occurrence_identity, field_name: field_binding_name_at(n: binding, source_indices: scope.type_env.source_indices), binding: annotate_pattern_parent_enums(pattern: field_binding_pattern(n: binding), scrutinee_subject: field_subject, scope: scope), span: binding.span, name_span: node_name_span(n: binding)) ) match inferred_parent { Present { value: parent_name } => @@ -4050,7 +4052,7 @@ fn extract_fold_init_info(method_name: String?, method_args: List, min_arg match init_arg { Present { value: ia } => let init_result = infer_expr(texpr: arg_value(n: ia), scope: scope, expected: expected) - Present { value: ArgInferResult { typed_arg: make_arg_node(name: arg_name_at(n: ia, source_indices: scope.type_env.source_indices), value: init_result.typed, span: ia.span, name_span: ia.span), diagnostics: init_result.diagnostics } } + Present { value: ArgInferResult { typed_arg: make_arg_node(occurrence_identity: ia.occurrence_identity, name: arg_name_at(n: ia, source_indices: scope.type_env.source_indices), value: init_result.typed, span: ia.span, name_span: ia.span), diagnostics: init_result.diagnostics } } Absent => none } } else { none } @@ -4086,11 +4088,11 @@ fn infer_method_args_with_fold(method_name: String?, method_args: List, fo } } else if is_fold && fold_info != none { let fold_params = [ - make_param_node(name: "acc", type_expr: fold_acc_type, default_value: none, span: no_span(), name_span: no_span()), - make_param_node(name: "elem", type_expr: element_type, default_value: none, span: no_span(), name_span: no_span()) + make_param_node(occurrence_identity: OccurrenceSynthetic, name: "acc", type_expr: fold_acc_type, default_value: none, span: no_span(), name_span: no_span()), + make_param_node(occurrence_identity: OccurrenceSynthetic, name: "elem", type_expr: element_type, default_value: none, span: no_span(), name_span: no_span()) ] let fold_callable = Node { - name: "", span: no_span(), ident_span: none, children: [], + occurrence_identity: OccurrenceSynthetic, name: "", span: no_span(), ident_span: none, children: [], connective: NoConnective, params: fold_params, inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, @@ -4114,7 +4116,7 @@ fn infer_method_args_with_fold(method_name: String?, method_args: List, fo lambda_param_provenance: prov_map } let ar = infer_expr(texpr: lam_value, scope: fold_scope, expected: Present { value: fold_callable }) - ArgInferResult { typed_arg: make_arg_node(name: arg_name_at(n: a, source_indices: scope.type_env.source_indices), value: ar.typed, span: a.span, name_span: a.span), diagnostics: ar.diagnostics } + ArgInferResult { typed_arg: make_arg_node(occurrence_identity: a.occurrence_identity, name: arg_name_at(n: a, source_indices: scope.type_env.source_indices), value: ar.typed, span: a.span, name_span: a.span), diagnostics: ar.diagnostics } } else { let nf_lam_value = arg_value(n: a) let nf_prov_map = match elem_provenance { @@ -4140,14 +4142,14 @@ fn infer_method_args_with_fold(method_name: String?, method_args: List, fo ContractUnavailable => let ar = infer_expr(texpr: nf_lam_value, scope: nf_scope, expected: none) let contract_diag = categorized_error(message: "no declared argument contract is available for this method call; refusing rather than substituting the receiver element type", span: a.span, module_name: nf_scope.module_name, category: "method-arg-contract-unavailable") - ArgInferResult { typed_arg: make_arg_node(name: arg_name_at(n: a, source_indices: nf_scope.type_env.source_indices), value: ar.typed, span: a.span, name_span: a.span), diagnostics: concat(ar.diagnostics, [contract_diag]) } + ArgInferResult { typed_arg: make_arg_node(occurrence_identity: a.occurrence_identity, name: arg_name_at(n: a, source_indices: nf_scope.type_env.source_indices), value: ar.typed, span: a.span, name_span: a.span), diagnostics: concat(ar.diagnostics, [contract_diag]) } ContractKnown { types: declared_types } => match declared_types |> skip(idx) |> first { Present { value: declared_type } => infer_arg_with_element_type(arg: a, element_type: declared_type, scope: nf_scope) Absent => let ar = infer_expr(texpr: nf_lam_value, scope: nf_scope, expected: none) let contract_diag = categorized_error(message: "no declared argument contract is available at this parameter position; refusing rather than substituting the receiver element type", span: a.span, module_name: nf_scope.module_name, category: "method-arg-contract-unavailable") - ArgInferResult { typed_arg: make_arg_node(name: arg_name_at(n: a, source_indices: nf_scope.type_env.source_indices), value: ar.typed, span: a.span, name_span: a.span), diagnostics: concat(ar.diagnostics, [contract_diag]) } + ArgInferResult { typed_arg: make_arg_node(occurrence_identity: a.occurrence_identity, name: arg_name_at(n: a, source_indices: nf_scope.type_env.source_indices), value: ar.typed, span: a.span, name_span: a.span), diagnostics: concat(ar.diagnostics, [contract_diag]) } } } } @@ -4175,7 +4177,7 @@ fn empty_override_map() -> Map { fn infer_arg_with_element_type(arg: Node, element_type: Node, scope: InferScope) -> ArgInferResult { let ar = infer_expr(texpr: arg_value(n: arg), scope: scope, expected: Present { value: element_type }) - ArgInferResult { typed_arg: make_arg_node(name: arg_name_at(n: arg, source_indices: scope.type_env.source_indices), value: ar.typed, span: arg.span, name_span: arg.span), diagnostics: ar.diagnostics } + ArgInferResult { typed_arg: make_arg_node(occurrence_identity: a.occurrence_identity, name: arg_name_at(n: arg, source_indices: scope.type_env.source_indices), value: ar.typed, span: arg.span, name_span: arg.span), diagnostics: ar.diagnostics } } fn binding_is_namespace_root_nominal(binding: TypeBinding) -> Bool { @@ -4214,7 +4216,7 @@ fn qualified_value_projection(texpr: Node, scope: InferScope, span: SourceSpan) env: scope.type_env, excluded: empty_map() ) - Present { value: ok_infer(texpr: make_named_expr_node( + Present { value: ok_infer(texpr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: spine.dotted, expr_data: ExprVar { binding_kind: Present { value: FunctionValueBinding } }, children: [], @@ -4238,7 +4240,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu match texpr.expr_data { ExprLiteral { value: lit } => let span = texpr.span - ok_infer(texpr: make_expr_node(expr_data: ExprLiteral { value: lit }, children: [], inferred: Present { value: Resolved { node: infer_literal_node(lit: lit) } }, span: span)) + ok_infer(texpr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprLiteral { value: lit }, children: [], inferred: Present { value: Resolved { node: infer_literal_node(lit: lit) } }, span: span)) ExprError { kind: kind, message: message } => let span = texpr.span @@ -4248,7 +4250,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu _ => [] } InferResult { - typed: make_expr_error_node(kind: kind, message: message, span: span), + typed: make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: kind, message: message, span: span), diagnostics: diagnostics } @@ -4263,7 +4265,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu let scope_parent = lookup_variant_parent_enum(scope: scope, name: name) match scope_parent { Present { value: scope_enum } => - ok_infer(texpr: make_named_expr_node( + ok_infer(texpr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: name, expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: scope_enum } } }, children: [], @@ -4273,7 +4275,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu )) Absent => let binding_kind = infer_var_binding_kind(scope: scope, name: name) - ok_infer(texpr: make_named_expr_node( + ok_infer(texpr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: name, expr_data: ExprVar { binding_kind: Present { value: binding_kind } }, children: [], @@ -4287,7 +4289,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu FuncSigResolved { sig: fsig } => match (fsig.params |> count) == 0 { true => - ok_infer(texpr: make_named_expr_node( + ok_infer(texpr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: [], @@ -4296,7 +4298,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu name_span: span )) false => - ok_infer(texpr: make_named_expr_node( + ok_infer(texpr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: name, expr_data: ExprVar { binding_kind: Present { value: FunctionValueBinding } }, children: [], @@ -4313,7 +4315,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu let scope_parent = lookup_variant_parent_enum(scope: scope, name: name) match scope_parent { Present { value: scope_enum } => - ok_infer(texpr: make_named_expr_node( + ok_infer(texpr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: name, expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: scope_enum } } }, children: [], @@ -4323,7 +4325,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu )) Absent => let binding_kind = infer_var_binding_kind(scope: scope, name: name) - ok_infer(texpr: make_named_expr_node( + ok_infer(texpr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: name, expr_data: ExprVar { binding_kind: Present { value: binding_kind } }, children: [], @@ -4336,7 +4338,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu let expected_variant_enum = expected_variant_owner_instantiation(expected: expected, name: name, scope: scope) match expected_variant_enum { Present { value: exp_enum } => - ok_infer(texpr: make_named_expr_node( + ok_infer(texpr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: name, expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: authored_name_at(source_indices: scope.type_env.source_indices, node: exp_enum) } } }, children: [], @@ -4349,7 +4351,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu if (var_ambiguity_cands |> count) > 0 { ambiguous_reference_refusal(name: name, candidates: var_ambiguity_cands, span: span, scope: scope) } else { - let err_texpr = make_named_expr_node( + let err_texpr = make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: name, expr_data: ExprVar { binding_kind: none }, children: [], @@ -4393,7 +4395,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu let resolved_base_is_error = if resolved_base.inferred != none { is_compiler_error(inferred: resolved_base.inferred.value) } else { false } if resolved_base_is_error { InferResult { - typed: make_expr_error_node(kind: SemanticExprError, message: "error type cascade", span: span), + typed: make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: SemanticExprError, message: "error type cascade", span: span), diagnostics: concat(base_diags, resolved_base_diags) } } else { @@ -4406,7 +4408,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu Present { value: s } => Present { value: s } Absent => field_summary_for_type(base_type: resolved_base, env: scope.type_env, field: field_name) } - let fa_texpr = make_named_expr_node( + let fa_texpr = make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: field_name, expr_data: ExprFieldAccess { summary: field_summary }, children: [base_typed], @@ -4421,7 +4423,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu Absent => let base_is_type_var = is_deferred_field_access_base(n: resolved_base, env: scope.type_env) if base_is_type_var { - let fa_texpr = make_named_expr_node( + let fa_texpr = make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: field_name, expr_data: ExprFieldAccess { summary: Present { value: FieldSummary { access_style: StoredField, value_shape: PlainValue } } }, children: [base_typed], @@ -4436,7 +4438,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } else { match check_service_field_access_node(base_type: base_rt, field: field_name, service_registry: scope.service_registry, source_indices: scope.type_env.source_indices) { Present { value: svc_type } => - let fa_texpr = make_named_expr_node( + let fa_texpr = make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: field_name, expr_data: ExprFieldAccess { summary: Present { value: FieldSummary { access_style: StoredField, value_shape: PlainValue } } }, children: [base_typed], @@ -4450,7 +4452,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } Absent => let error_message = concat("no field '", field_name, "' on type '", authored_name_at(source_indices: scope.type_env.source_indices, node: resolved_base), "'") - let fa_texpr = make_expr_error_node(kind: SemanticExprError, message: error_message, span: span) + let fa_texpr = make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: SemanticExprError, message: error_message, span: span) InferResult { typed: fa_texpr, diagnostics: concat(concat(base_diags, resolved_base_diags), [inference_error( @@ -4505,7 +4507,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu let call_elem_provenance = derive_element_provenance(coll_expr: first_result.typed, elem_type: elem_type, scope: scope) let remaining_results = infer_method_args_with_fold(method_name: call_method_name, method_args: call_method_args, fold_info: call_fold_info, fold_acc_type: call_fold_acc_type, element_type: elem_type, elem_provenance: call_elem_provenance, arg_contract: MethodUnresolved, scope: scope) concat( - [ArgInferResult { typed_arg: make_arg_node(name: arg_name_at(n: first_arg, source_indices: scope.type_env.source_indices), value: first_result.typed, span: first_arg.span, name_span: first_arg.span), diagnostics: first_result.diagnostics }], + [ArgInferResult { typed_arg: make_arg_node(occurrence_identity: first_arg.occurrence_identity, name: arg_name_at(n: first_arg, source_indices: scope.type_env.source_indices), value: first_result.typed, span: first_arg.span, name_span: first_arg.span), diagnostics: first_result.diagnostics }], remaining_results ) Absent => @@ -4534,7 +4536,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu unify_generics(formal: formal_raw, actual: resolved_type(n: ar.typed), generic_names: generic_names, source_indices: scope.type_env.source_indices, acc: st.subst) } ArgGenericFoldState { - results: concat(st.results, [ArgInferResult { typed_arg: make_arg_node(name: arg_name_at(n: a, source_indices: scope.type_env.source_indices), value: ar.typed, span: a.span, name_span: a.span), diagnostics: ar.diagnostics }]), + results: concat(st.results, [ArgInferResult { typed_arg: make_arg_node(occurrence_identity: a.occurrence_identity, name: arg_name_at(n: a, source_indices: scope.type_env.source_indices), value: ar.typed, span: a.span, name_span: a.span), diagnostics: ar.diagnostics }]), subst: next_subst } ) @@ -4593,7 +4595,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu scope: scope ) InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: Resolved { node: resolved_type } }, @@ -4672,7 +4674,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } let final_receiver = if returns_receiver_self && is_fully_resolved(n: bridge_result_type, source_indices: scope.type_env.source_indices) && !is_fully_resolved(n: first_arg_type, source_indices: scope.type_env.source_indices) { Node { - name: receiver.name, span: receiver.span, ident_span: receiver.ident_span, + occurrence_identity: OccurrenceSynthetic, name: receiver.name, span: receiver.span, ident_span: receiver.ident_span, children: bridge_result_type.children, connective: receiver.connective, params: receiver.params, inferred: Present { value: Resolved { node: bridge_result_type } }, @@ -4683,9 +4685,9 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu match_pattern: receiver.match_pattern, expr_data: receiver.expr_data } } else { receiver } - let remaining_arg_nodes = remaining |> map(ta => make_arg_node(name: arg_name_at(n: ta, source_indices: scope.type_env.source_indices), value: arg_value(n: ta), span: span, name_span: span)) + let remaining_arg_nodes = remaining |> map(ta => make_arg_node(occurrence_identity: ta.occurrence_identity, name: arg_name_at(n: ta, source_indices: scope.type_env.source_indices), value: arg_value(n: ta), span: span, name_span: span)) InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprMethodCall { method_semantics: method_resolution.semantics }, children: concat([final_receiver], remaining_arg_nodes), inferred: Present { value: Resolved { node: bridge_result_type } }, @@ -4700,7 +4702,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu Present { value: exp } => if node_is_keyed_collection(n: exp, source_indices: scope.type_env.source_indices) { InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: Resolved { node: exp } }, @@ -4714,7 +4716,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu match bare_m { Present { value: map_t } => InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: Resolved { node: map_t } }, @@ -4725,7 +4727,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } Absent => InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: CompilerError { message: "empty_map(): Map kernel container profile missing (compiler misconfigured)", span: span } }, @@ -4740,7 +4742,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu match bare_m { Present { value: map_t } => InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: Resolved { node: map_t } }, @@ -4751,7 +4753,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } Absent => InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: CompilerError { message: "empty_map(): Map kernel container profile missing (compiler misconfigured)", span: span } }, @@ -4768,7 +4770,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu Present { value: exp } => if node_is_set_collection(n: exp, source_indices: scope.type_env.source_indices) { InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: Resolved { node: exp } }, @@ -4782,7 +4784,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu match bare_s { Present { value: set_t } => InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: Resolved { node: set_t } }, @@ -4793,7 +4795,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } Absent => InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: CompilerError { message: "empty_set(): Set kernel container profile missing (compiler misconfigured)", span: span } }, @@ -4808,7 +4810,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu match bare_s { Present { value: set_t } => InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: Resolved { node: set_t } }, @@ -4819,7 +4821,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } Absent => InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: CompilerError { message: "empty_set(): Set kernel container profile missing (compiler misconfigured)", span: span } }, @@ -4839,7 +4841,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu Present { value: PlainCallSemantics } } InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: call_semantics, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: Resolved { node: bt } }, @@ -4865,7 +4867,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu _ => error_type } InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: if callee_is_body_binding { FunctionValueCallSemantics } else { PlainCallSemantics } }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: Resolved { node: resolved_type } }, @@ -4910,7 +4912,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } } InferResult { - typed: make_named_expr_node( + typed: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: typed_arg_nodes, inferred: Present { value: Resolved { node: resolved_type } }, @@ -4942,7 +4944,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu Absent => none Present { value: _ } => Present { value: infer_expr( - texpr: make_named_expr_node( + texpr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: dotted, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, children: mc_args, @@ -5019,7 +5021,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu let mc_template_diags = method_tv_mc.diagnostics let method_semantics = if method_resolution.semantics != none { method_resolution.semantics } else { Present { value: PlainMethodSemantics } } let typed_mc_arg_nodes = typed_mc_args - let mc_texpr = make_named_expr_node( + let mc_texpr = make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: method_name, expr_data: ExprMethodCall { method_semantics: method_semantics }, children: concat([recv_typed], typed_mc_arg_nodes), inferred: Present { value: Resolved { node: result_type } }, @@ -5064,7 +5066,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } let guard_diags = if guard_result != none { guard_unwrapped.diagnostics } else { [] } ArmInferResult { - typed_arm: make_arm_node( + typed_arm: make_arm_node(occurrence_identity: arm_node.occurrence_identity, pattern: typed_pattern, guard: if guard_result != none { Present { value: guard_unwrapped.typed } } else { none }, body: body_typed, @@ -5111,7 +5113,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } let guard_diags = if guard_result != none { guard_unwrapped.diagnostics } else { [] } ArmInferResult { - typed_arm: make_arm_node( + typed_arm: make_arm_node(occurrence_identity: arm_node.occurrence_identity, pattern: typed_pattern, guard: if guard_result != none { Present { value: guard_unwrapped.typed } } else { none }, body: body_typed, @@ -5147,7 +5149,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu PatternDynamic { span: _ } => [] PatternLookupBlocked => [] } - let match_texpr = make_expr_node(expr_data: ExprMatch, children: concat([scrut_typed], typed_arms), inferred: Present { value: Resolved { node: result_type } }, span: span) + let match_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprMatch, children: concat([scrut_typed], typed_arms), inferred: Present { value: Resolved { node: result_type } }, span: span) InferResult { typed: match_texpr, diagnostics: concat(scrut_diags, arm_diags, empty_arms_diags, exhaustiveness_diags) @@ -5200,13 +5202,13 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu module_name: scope.module_name )] } - let if_texpr = make_expr_node(expr_data: ExprIf, children: [cond_typed, then_typed, else_typed], inferred: Present { value: Resolved { node: unified } }, span: span) + let if_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprIf, children: [cond_typed, then_typed, else_typed], inferred: Present { value: Resolved { node: unified } }, span: span) InferResult { typed: if_texpr, diagnostics: concat(cond_diags, then_diags, else_diags, branch_diags) } Absent => - let if_texpr2 = make_expr_node(expr_data: ExprIf, children: [cond_typed, then_typed], inferred: Present { value: Resolved { node: unit_type } }, span: span) + let if_texpr2 = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprIf, children: [cond_typed, then_typed], inferred: Present { value: Resolved { node: unit_type } }, span: span) InferResult { typed: if_texpr2, diagnostics: concat(cond_diags, then_diags) @@ -5245,7 +5247,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } else { [] } let val_diags = concat(val_result.diagnostics, val_annotation_diags) if body_expr == none { - let let_texpr = make_named_expr_node(name: let_name, expr_data: ExprLet, children: [val_typed], inferred: Present { value: Resolved { node: val_type } }, span: span, name_span: node_name_span(n: texpr)) + let let_texpr = make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: let_name, expr_data: ExprLet, children: [val_typed], inferred: Present { value: Resolved { node: val_type } }, span: span, name_span: node_name_span(n: texpr)) InferResult { typed: let_texpr, diagnostics: val_diags @@ -5255,7 +5257,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu let body_result = infer_expr(texpr: body_expr.value, scope: extended, expected: expected) let body_typed = body_result.typed let body_diags = body_result.diagnostics - let let_texpr2 = make_named_expr_node(name: let_name, expr_data: ExprLet, children: [val_typed, body_typed], inferred: body_typed.inferred, span: span, name_span: node_name_span(n: texpr)) + let let_texpr2 = make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: let_name, expr_data: ExprLet, children: [val_typed, body_typed], inferred: body_typed.inferred, span: span, name_span: node_name_span(n: texpr)) InferResult { typed: let_texpr2, diagnostics: concat(val_diags, body_diags) @@ -5265,7 +5267,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu ExprRecordLit { parent_enum: _ } => let span = texpr.span let field_inits = texpr.children - infer_record_lit(type_name: record_lit_type_name_at(texpr: texpr, source_indices: scope.type_env.source_indices), field_inits: field_inits, span: span, name_span: node_name_span(n: texpr), scope: scope, expected: expected) + infer_record_lit(occurrence_identity: texpr.occurrence_identity, type_name: record_lit_type_name_at(texpr: texpr, source_indices: scope.type_env.source_indices), field_inits: field_inits, span: span, name_span: node_name_span(n: texpr), scope: scope, expected: expected) ExprListLit => let span = texpr.span @@ -5325,7 +5327,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } } else { [] } let list_k = list_kernel_ty_from_element(element: elem_type_node) - let ll_texpr = make_expr_node(expr_data: ExprListLit, children: typed_elements, inferred: Present { value: Resolved { node: list_k.ty } }, span: span) + let ll_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprListLit, children: typed_elements, inferred: Present { value: Resolved { node: list_k.ty } }, span: span) InferResult { typed: ll_texpr, diagnostics: concat(concat(elem_diags, empty_list_diags), list_k.miss_diags) @@ -5342,7 +5344,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu let right_typed = right_result.typed let right_diags = right_result.diagnostics let binop_info = infer_binop_type_node(op: op, left_type: resolved_type(n: left_typed), source_indices: scope.type_env.source_indices) - let bo_texpr = make_expr_node(expr_data: ExprBinOp { op: op, algebra_field: binop_info.algebra_field }, children: [left_typed, right_typed], inferred: Present { value: Resolved { node: binop_info.result_type } }, span: span) + let bo_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprBinOp { op: op, algebra_field: binop_info.algebra_field }, children: [left_typed, right_typed], inferred: Present { value: Resolved { node: binop_info.result_type } }, span: span) InferResult { typed: bo_texpr, diagnostics: concat(left_diags, right_diags) @@ -5358,7 +5360,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu Not => bool_type Neg => resolved_type(n: operand_typed) } - let uo_texpr = make_expr_node(expr_data: ExprUnaryOp { op: op }, children: [operand_typed], inferred: Present { value: Resolved { node: result_type } }, span: span) + let uo_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprUnaryOp { op: op }, children: [operand_typed], inferred: Present { value: Resolved { node: result_type } }, span: span) InferResult { typed: uo_texpr, diagnostics: operand_diags @@ -5439,7 +5441,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu Absent => none } Node { - name: pn.name, ident: pn.ident, span: pn.span, ident_span: pn.ident_span, children: pn.children, + occurrence_identity: OccurrenceSynthetic, name: pn.name, ident: pn.ident, span: pn.span, ident_span: pn.ident_span, children: pn.children, connective: pn.connective, params: pn.params, inferred: param_type, return_cardinality: pn.return_cardinality, uses: pn.uses, body: pn.body, transport: pn.transport, properties: pn.properties, type_annotation: pn.type_annotation, @@ -5447,7 +5449,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu match_pattern: pn.match_pattern, expr_data: pn.expr_data } ) - let lam_texpr = make_expr_node( + let lam_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprLambda, children: concat([body_typed], typed_param_nodes), inferred: body_typed.inferred, @@ -5467,7 +5469,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu match part_node.children |> first { Present { value: inner } => let r = infer_expr(texpr: inner, scope: scope, expected: none) - make_interp_part_node(expr: r.typed, span: part_node.span) + make_interp_part_node(occurrence_identity: part_node.occurrence_identity, expr: r.typed, span: part_node.span) Absent => part_node } } @@ -5484,7 +5486,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } } ) - let si_texpr = make_expr_node(expr_data: ExprStringInterp, children: typed_part_nodes, inferred: Present { value: Resolved { node: string_type } }, span: span) + let si_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprStringInterp, children: typed_part_nodes, inferred: Present { value: Resolved { node: string_type } }, span: span) InferResult { typed: si_texpr, diagnostics: interp_diags @@ -5499,13 +5501,13 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu typed_stmts: [], diag_chunks: [], last_type: unit_type, expected: expected ) - let blk_texpr = make_expr_node(expr_data: ExprBlock, children: state.typed_stmts, inferred: Present { value: Resolved { node: state.last_type } }, span: span) + let blk_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprBlock, children: state.typed_stmts, inferred: Present { value: Resolved { node: state.last_type } }, span: span) InferResult { typed: blk_texpr, diagnostics: flat_map(state.diag_chunks, c => c) } } else { - ok_infer(texpr: make_expr_node(expr_data: ExprBlock, children: [], inferred: Present { value: Resolved { node: unit_type } }, span: span)) + ok_infer(texpr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprBlock, children: [], inferred: Present { value: Resolved { node: unit_type } }, span: span)) } ExprCast => @@ -5537,7 +5539,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu module_name: scope.module_name, type_env: scope.type_env ) - let cast_texpr = make_expr_node(expr_data: ExprCast, children: [inner_typed, target_type], inferred: Present { value: Resolved { node: target_type } }, span: span) + let cast_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprCast, children: [inner_typed, target_type], inferred: Present { value: Resolved { node: target_type } }, span: span) InferResult { typed: cast_texpr, diagnostics: concat(concat(concat(concat(inner_diags, cast_diags), cast_optional_diags), cast_sole_ctor_diags), cast_refinement_diags) @@ -5557,7 +5559,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu let body_result = infer_expr(texpr: body_expr, scope: body_scope, expected: none) let body_typed = body_result.typed let body_diags = body_result.diagnostics - let fe_texpr = make_named_expr_node(name: variable, expr_data: ExprForEach, children: [coll_typed, body_typed], inferred: body_typed.inferred, span: span, name_span: node_name_span(n: texpr)) + let fe_texpr = make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: variable, expr_data: ExprForEach, children: [coll_typed, body_typed], inferred: body_typed.inferred, span: span, name_span: node_name_span(n: texpr)) InferResult { typed: fe_texpr, diagnostics: concat(coll_diags, body_diags) @@ -5600,7 +5602,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu Present { value: checked } => checked.diagnostics Absent => [] } - let idx_texpr = make_expr_node(expr_data: ExprIndex, children: [base_typed, index_typed], inferred: idx_inferred, span: span) + let idx_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprIndex, children: [base_typed, index_typed], inferred: idx_inferred, span: span) InferResult { typed: idx_texpr, diagnostics: concat(base_diags, index_diags, index_access_diags) @@ -5656,7 +5658,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu Present { value: checked } => checked.diagnostics Absent => [] } - let slc_texpr = make_expr_node(expr_data: ExprSlice, children: [base_typed, start_typed, end_typed], inferred: slc_inferred, span: span) + let slc_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprSlice, children: [base_typed, start_typed, end_typed], inferred: slc_inferred, span: span) InferResult { typed: slc_texpr, diagnostics: concat(base_diags, start_diags, end_diags, slice_access_diags) @@ -5666,7 +5668,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu let span = texpr.span let inner_expr = return_value(texpr: texpr) let inner_result = infer_expr(texpr: inner_expr, scope: scope, expected: expected) - let ret_texpr = make_expr_node(expr_data: ExprReturn, children: [inner_result.typed], inferred: inner_result.typed.inferred, span: span) + let ret_texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprReturn, children: [inner_result.typed], inferred: inner_result.typed.inferred, span: span) InferResult { typed: ret_texpr, diagnostics: inner_result.diagnostics @@ -5675,7 +5677,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu _ => let span = texpr.span InferResult { - typed: make_expr_error_node(kind: InternalExprError, message: "unhandled expression variant in infer_expr", span: span), + typed: make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: InternalExprError, message: "unhandled expression variant in infer_expr", span: span), diagnostics: [inference_error( message: "unhandled expression variant in infer_expr", span: span, @@ -5710,13 +5712,14 @@ fn infer_variant_constructor_call(func_name: String, call_args: List, span } } Absent => let payload_expr = arg_value(n: arg) - let payload_init = make_field_init_node( + let payload_init = make_field_init_node(occurrence_identity: arg.occurrence_identity, name: "0", value: payload_expr, span: payload_expr.span, name_span: kernel_span(name: "0") ) Present { value: infer_record_lit( + occurrence_identity: texpr.occurrence_identity, type_name: Present { value: func_name }, field_inits: [payload_init], span: span, @@ -6051,7 +6054,7 @@ fn map_literal_expected_keyed_node(type_name: String?, expected: Node?, scope: I } } -fn infer_map_literal(map_node: Node, field_inits: List, span: SourceSpan, scope: InferScope) -> InferResult { +fn infer_map_literal(occurrence_identity: NodeOccurrenceIdentity, map_node: Node, field_inits: List, span: SourceSpan, scope: InferScope) -> InferResult { let value_expected = match map_node.children |> skip(n: 1) |> first { Present { value: v } => Present { value: v } Absent => none @@ -6059,7 +6062,7 @@ fn infer_map_literal(map_node: Node, field_inits: List, span: SourceSpan, let fi_results = field_inits |> map(fi => let ar = infer_expr(texpr: field_init_node_value(n: fi), scope: scope, expected: value_expected) FieldInferResult { - typed_field: make_field_init_node( + typed_field: make_field_init_node(occurrence_identity: fi.occurrence_identity, name: field_init_node_name_at(n: fi, source_indices: scope.type_env.source_indices), value: ar.typed, span: fi.span, @@ -6070,7 +6073,7 @@ fn infer_map_literal(map_node: Node, field_inits: List, span: SourceSpan, } ) InferResult { - typed: make_expr_node( + typed: make_expr_node(occurrence_identity: occurrence_identity, expr_data: ExprRecordLit { parent_enum: none }, children: fi_results |> map(fir => fir.typed_field), inferred: Present { value: Resolved { node: map_node } }, @@ -6080,12 +6083,13 @@ fn infer_map_literal(map_node: Node, field_inits: List, span: SourceSpan, } } -fn infer_record_lit(type_name: String?, field_inits: List, span: SourceSpan, name_span: SourceSpan, scope: InferScope, expected: Node?) -> InferResult { +fn infer_record_lit(occurrence_identity: NodeOccurrenceIdentity, type_name: String?, field_inits: List, span: SourceSpan, name_span: SourceSpan, scope: InferScope, expected: Node?) -> InferResult { match map_literal_expected_keyed_node(type_name: type_name, expected: expected, scope: scope) { Present { value: map_node } => - infer_map_literal(map_node: map_node, field_inits: field_inits, span: span, scope: scope) + infer_map_literal(occurrence_identity: occurrence_identity, map_node: map_node, field_inits: field_inits, span: span, scope: scope) Absent => infer_record_lit_structural( + occurrence_identity: occurrence_identity, type_name: type_name, field_inits: field_inits, span: span, @@ -6096,7 +6100,7 @@ fn infer_record_lit(type_name: String?, field_inits: List, span: SourceSpa } } -fn infer_record_lit_structural(type_name: String?, field_inits: List, span: SourceSpan, name_span: SourceSpan, scope: InferScope, expected: Node?) -> InferResult { +fn infer_record_lit_structural(occurrence_identity: NodeOccurrenceIdentity, type_name: String?, field_inits: List, span: SourceSpan, name_span: SourceSpan, scope: InferScope, expected: Node?) -> InferResult { let instantiated_struct_fields = record_lit_instantiated_fields(type_name: type_name, expected: expected, scope: scope) let expected_struct_fields = if instantiated_struct_fields == none { record_lit_fields_from_expected(type_name: type_name, expected: expected, scope: scope) @@ -6311,7 +6315,7 @@ fn infer_record_lit_structural(type_name: String?, field_inits: List, span Absent => [] } FieldInferResult { - typed_field: make_field_init_node(name: fi_name, value: ar_typed, span: fi.span, name_span: node_name_span(n: fi)), + typed_field: make_field_init_node(occurrence_identity: fi.occurrence_identity, name: fi_name, value: ar_typed, span: fi.span, name_span: node_name_span(n: fi)), infer_result: ar, diagnostics: concat(concat(concat(ar_diags, field_type_diags), unknown_field_diags), bare_none_field_construction_diags( fi: fi, @@ -6327,20 +6331,20 @@ fn infer_record_lit_structural(type_name: String?, field_inits: List, span if type_name == none { let child_nodes = fi_infer_results |> map(fir => Node { - name: field_init_node_name_at(n: fir.typed_field, source_indices: scope.type_env.source_indices), span: fir.typed_field.span, ident_span: fir.typed_field.ident_span, + occurrence_identity: OccurrenceSynthetic, name: field_init_node_name_at(n: fir.typed_field, source_indices: scope.type_env.source_indices), span: fir.typed_field.span, ident_span: fir.typed_field.ident_span, children: [], connective: NoConnective, params: [], inferred: fir.infer_result.typed.inferred, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } ) let anon_node = Node { - name: "", span: no_span(), ident_span: none, + occurrence_identity: OccurrenceSynthetic, name: "", span: no_span(), ident_span: none, children: child_nodes, connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let typed_field_nodes = typed_fields - let texpr = make_expr_node(expr_data: ExprRecordLit { parent_enum: none }, children: typed_field_nodes, inferred: Present { value: Resolved { node: anon_node } }, span: span) + let texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprRecordLit { parent_enum: none }, children: typed_field_nodes, inferred: Present { value: Resolved { node: anon_node } }, span: span) InferResult { typed: texpr, diagnostics: concat(fi_diags, alias_struct_diags) @@ -6407,7 +6411,7 @@ fn infer_record_lit_structural(type_name: String?, field_inits: List, span let sole_ctor_diags = sole_constructor_construction_diags(type_name: type_name.value, span: span, scope: scope) let typed_field_nodes2 = typed_fields let rl_name = match type_name { Present { value: tn_val } => tn_val Absent => "" } - let texpr = make_named_expr_node( + let texpr = make_named_expr_node(occurrence_identity: occurrence_identity, name: rl_name, expr_data: ExprRecordLit { parent_enum: local_variant_parent }, children: typed_field_nodes2, @@ -7421,15 +7425,15 @@ fn annotate_descent(body: Node, ctx: DescentContext) -> Node { per_field_vars: ctx.per_field_vars, body_locals: ctx.body_locals } - make_arg_node(name: arg_name_at(n: child, source_indices: ctx.type_env.source_indices), value: annotate_descent(body: arg_val, ctx: lambda_ctx), span: child.span, name_span: child.span) + make_arg_node(occurrence_identity: child.occurrence_identity, name: arg_name_at(n: child, source_indices: ctx.type_env.source_indices), value: annotate_descent(body: arg_val, ctx: lambda_ctx), span: child.span, name_span: child.span) } else { - make_arg_node(name: arg_name_at(n: child, source_indices: ctx.type_env.source_indices), value: annotate_descent(body: arg_val, ctx: ctx), span: child.span, name_span: child.span) + make_arg_node(occurrence_identity: child.occurrence_identity, name: arg_name_at(n: child, source_indices: ctx.type_env.source_indices), value: annotate_descent(body: arg_val, ctx: ctx), span: child.span, name_span: child.span) } - _ => make_arg_node(name: arg_name_at(n: child, source_indices: ctx.type_env.source_indices), value: annotate_descent(body: arg_val, ctx: ctx), span: child.span, name_span: child.span) + _ => make_arg_node(occurrence_identity: child.occurrence_identity, name: arg_name_at(n: child, source_indices: ctx.type_env.source_indices), value: annotate_descent(body: arg_val, ctx: ctx), span: child.span, name_span: child.span) } ) Node { - name: body.name, span: body.span, ident_span: body.ident_span, + occurrence_identity: OccurrenceSynthetic, name: body.name, span: body.span, ident_span: body.ident_span, children: annotated_children, connective: body.connective, params: body.params, inferred: body.inferred, return_cardinality: body.return_cardinality, uses: body.uses, body: body.body, transport: body.transport, @@ -7616,10 +7620,10 @@ fn annotate_descent(body: Node, ctx: DescentContext) -> Node { } else { ctx } } let annotated_body = annotate_descent(body: arm_body(n: arm_node), ctx: descent_ctx_shadowing_names(ctx: arm_ctx, names: descent_pattern_bound_names(pattern: arm_pattern(n: arm_node)))) - make_arm_node(pattern: arm_pattern(n: arm_node), guard: arm_guard(n: arm_node), body: annotated_body, span: arm_node.span) + make_arm_node(occurrence_identity: arm_node.occurrence_identity, pattern: arm_pattern(n: arm_node), guard: arm_guard(n: arm_node), body: annotated_body, span: arm_node.span) ) Node { - name: body.name, span: body.span, ident_span: body.ident_span, + occurrence_identity: OccurrenceSynthetic, name: body.name, span: body.span, ident_span: body.ident_span, children: concat([annotated_scrut], annotated_arms), connective: body.connective, params: body.params, inferred: body.inferred, return_cardinality: body.return_cardinality, @@ -7674,7 +7678,7 @@ fn annotate_descent(body: Node, ctx: DescentContext) -> Node { Absent => [annotated_value] } Node { - name: body.name, span: body.span, ident_span: body.ident_span, + occurrence_identity: OccurrenceSynthetic, name: body.name, span: body.span, ident_span: body.ident_span, children: annotated_children, connective: body.connective, params: body.params, inferred: body.inferred, return_cardinality: body.return_cardinality, uses: body.uses, body: body.body, transport: body.transport, @@ -7730,7 +7734,7 @@ fn annotate_descent(body: Node, ctx: DescentContext) -> Node { BlockAnnotateAcc { ctx: next_ctx, children: concat(acc.children, [annotated]) } ) Node { - name: body.name, span: body.span, ident_span: body.ident_span, + occurrence_identity: OccurrenceSynthetic, name: body.name, span: body.span, ident_span: body.ident_span, children: threaded.children, connective: body.connective, params: body.params, inferred: body.inferred, return_cardinality: body.return_cardinality, uses: body.uses, body: body.body, transport: body.transport, @@ -7836,13 +7840,13 @@ fn annotate_descent(body: Node, ctx: DescentContext) -> Node { let arg_val = arg_value(n: arg_node) let is_lambda = match arg_val.expr_data { ExprLambda => true _ => false } if is_lambda { - make_arg_node(name: match arg_name_at(n: arg_node, source_indices: ctx.type_env.source_indices) { Present { value: n } => Present { value: n } Absent => none }, value: annotate_descent(body: arg_val, ctx: inner_ctx), span: arg_node.span, name_span: arg_node.span) + make_arg_node(occurrence_identity: arg_node.occurrence_identity, name: match arg_name_at(n: arg_node, source_indices: ctx.type_env.source_indices) { Present { value: n } => Present { value: n } Absent => none }, value: annotate_descent(body: arg_val, ctx: inner_ctx), span: arg_node.span, name_span: arg_node.span) } else { - make_arg_node(name: match arg_name_at(n: arg_node, source_indices: ctx.type_env.source_indices) { Present { value: n } => Present { value: n } Absent => none }, value: annotate_descent(body: arg_val, ctx: ctx), span: arg_node.span, name_span: arg_node.span) + make_arg_node(occurrence_identity: arg_node.occurrence_identity, name: match arg_name_at(n: arg_node, source_indices: ctx.type_env.source_indices) { Present { value: n } => Present { value: n } Absent => none }, value: annotate_descent(body: arg_val, ctx: ctx), span: arg_node.span, name_span: arg_node.span) } ) Node { - name: body.name, span: body.span, ident_span: body.ident_span, + occurrence_identity: OccurrenceSynthetic, name: body.name, span: body.span, ident_span: body.ident_span, children: concat([annotated_receiver], annotated_args), connective: body.connective, params: body.params, inferred: body.inferred, return_cardinality: body.return_cardinality, @@ -7889,7 +7893,7 @@ fn annotate_descent(body: Node, ctx: DescentContext) -> Node { let annotated_coll = annotate_descent(body: coll, ctx: ctx) let annotated_body = annotate_descent(body: fe_body, ctx: inner_ctx) Node { - name: body.name, span: body.span, ident_span: body.ident_span, + occurrence_identity: OccurrenceSynthetic, name: body.name, span: body.span, ident_span: body.ident_span, children: [annotated_coll, annotated_body], connective: body.connective, params: body.params, inferred: body.inferred, return_cardinality: body.return_cardinality, uses: body.uses, body: body.body, transport: body.transport, @@ -8604,7 +8608,7 @@ fn infer_property_values(props: List, scope: InferScope) -> InferPropertie let val_result = infer_expr(texpr: val, scope: scope, expected: none) PropertyInferenceResult { prop: Node { - name: p.name, span: p.span, ident_span: p.ident_span, + occurrence_identity: OccurrenceSynthetic, name: p.name, span: p.span, ident_span: p.ident_span, children: [val_result.typed], connective: p.connective, params: p.params, inferred: p.inferred, return_cardinality: p.return_cardinality, uses: p.uses, body: p.body, transport: p.transport, properties: p.properties, @@ -8713,7 +8717,7 @@ fn infer_service_config_properties(props: List, scope: InferScope) -> Infe let val_result = infer_expr(texpr: val, scope: scope, expected: none) PropertyInferenceResult { prop: Node { - name: p.name, span: p.span, ident_span: p.ident_span, + occurrence_identity: OccurrenceSynthetic, name: p.name, span: p.span, ident_span: p.ident_span, children: [val_result.typed], connective: p.connective, params: p.params, inferred: p.inferred, return_cardinality: p.return_cardinality, uses: p.uses, body: p.body, transport: p.transport, properties: p.properties, @@ -8752,7 +8756,7 @@ fn infer_transport_node(transport: Node?, scope: InferScope) -> InferTransportRe let prop_result = infer_property_values(props: t.properties, scope: scope) InferTransportResult { transport: Present { value: Node { - name: t.name, span: t.span, ident_span: t.ident_span, + occurrence_identity: OccurrenceSynthetic, name: t.name, span: t.span, ident_span: t.ident_span, children: t.children, connective: t.connective, params: t.params, inferred: t.inferred, return_cardinality: t.return_cardinality, uses: t.uses, body: t.body, transport: t.transport, properties: prop_result.props, @@ -8779,7 +8783,7 @@ fn infer_item(item: Node, scope: InferScope) -> TypedItemResult { if item.connective != NoConnective && item.transport == none { TypedItemResult { item: Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: item.children |> map(c => infer_item(item: c, scope: scope).item), params: item.params, + occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: item.children |> map(c => infer_item(item: c, scope: scope).item), params: item.params, inferred: Present { value: Resolved { node: unit_type } }, return_cardinality: item.return_cardinality, uses: item.uses, body: none, connective: item.connective, transport: typed_transport, properties: typed_properties, type_annotation: typed_anno, @@ -8823,7 +8827,7 @@ fn infer_item(item: Node, scope: InferScope) -> TypedItemResult { } else { body_typed } TypedItemResult { item: Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: item.children |> map(c => infer_item(item: c, scope: scope).item), params: item.params, + occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: item.children |> map(c => infer_item(item: c, scope: scope).item), params: item.params, inferred: inferred_ret, return_cardinality: item.return_cardinality, uses: item.uses, body: Present { value: annotated_body }, connective: NoConnective, transport: typed_transport, properties: typed_properties, type_annotation: typed_anno, @@ -8858,7 +8862,7 @@ fn infer_item(item: Node, scope: InferScope) -> TypedItemResult { ) TypedItemResult { item: Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: [], params: [], + occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: [], params: [], inferred: item.inferred, return_cardinality: item.return_cardinality, uses: [], body: Present { value: body_typed }, connective: NoConnective, transport: typed_transport, properties: typed_properties, type_annotation: typed_anno, @@ -8880,7 +8884,7 @@ fn infer_item(item: Node, scope: InferScope) -> TypedItemResult { let inferred_ret = if item.type_annotation != none { Present { value: Resolved { node: item.type_annotation.value } } } else { val_typed.inferred } TypedItemResult { item: Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: [], params: [], + occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: [], params: [], inferred: inferred_ret, return_cardinality: item.return_cardinality, uses: [], body: Present { value: val_typed }, connective: NoConnective, transport: typed_transport, properties: typed_properties, type_annotation: typed_anno, @@ -8892,7 +8896,7 @@ fn infer_item(item: Node, scope: InferScope) -> TypedItemResult { else if item.params |> count > 0 && item.body == none { TypedItemResult { item: Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: item.children |> map(c => infer_item(item: c, scope: scope).item), params: item.params, + occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: item.children |> map(c => infer_item(item: c, scope: scope).item), params: item.params, inferred: if item.inferred != none { item.inferred } else { Present { value: Resolved { node: unit_type } } }, return_cardinality: item.return_cardinality, uses: item.uses, body: none, connective: NoConnective, transport: typed_transport, properties: typed_properties, type_annotation: typed_anno, @@ -8904,7 +8908,7 @@ fn infer_item(item: Node, scope: InferScope) -> TypedItemResult { else { TypedItemResult { item: Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: item.children |> map(c => infer_item(item: c, scope: scope).item), params: item.params, + occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: item.children |> map(c => infer_item(item: c, scope: scope).item), params: item.params, inferred: if item.inferred != none { item.inferred } else { Present { value: Resolved { node: unit_type } } }, return_cardinality: item.return_cardinality, uses: item.uses, body: none, connective: item.connective, transport: typed_transport, properties: typed_properties, type_annotation: typed_anno, @@ -9104,7 +9108,7 @@ fn substitute_generics_apply(n: Node, subst: Map, source_indices: n } else { Node { - name: n.name, span: n.span, ident_span: n.ident_span, + occurrence_identity: OccurrenceSynthetic, name: n.name, span: n.span, ident_span: n.ident_span, children: new_children, connective: n.connective, params: new_params, @@ -9421,7 +9425,7 @@ fn local_binding_for_item(item: Node, source_indices: Map) let has_structure = item.connective != NoConnective if has_structure { let type_node = Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: item.children, + occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: item.children, connective: item.connective, params: item.params, inferred: none, return_cardinality: item.return_cardinality, uses: [], body: none, transport: none, properties: item.properties, @@ -9430,7 +9434,7 @@ fn local_binding_for_item(item: Node, source_indices: Map) Present { value: TypeBinding { name: authored_name_at(source_indices: source_indices, node: item), resolved: type_node, provenance: SubValueUnknown } } } else if item.body != none && item.transport == none { let fn_node = Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: [], + occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: [], connective: NoConnective, params: item.params, inferred: item.inferred, return_cardinality: item.return_cardinality, uses: [], body: none, transport: none, properties: item.properties, @@ -9439,7 +9443,7 @@ fn local_binding_for_item(item: Node, source_indices: Map) Present { value: TypeBinding { name: authored_name_at(source_indices: source_indices, node: item), resolved: fn_node, provenance: SubValueUnknown } } } else if item.inferred != none && item.params |> count == 0 && item.body == none { let alias_node = Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: [], + occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: [], connective: NoConnective, params: [], inferred: item.inferred, return_cardinality: item.return_cardinality, uses: [], body: none, transport: none, properties: [], @@ -9451,7 +9455,7 @@ fn local_binding_for_item(item: Node, source_indices: Map) Present { value: TypeBinding { name: authored_name_at(source_indices: source_indices, node: item), resolved: ref_node, provenance: SubValueUnknown } } } else if item.params |> count > 0 && item.connective == NoConnective && item.body == none && item.transport == none { let bare_node = Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: [], + occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: [], connective: NoConnective, params: item.params, inferred: item.inferred, return_cardinality: item.return_cardinality, uses: [], body: none, transport: none, properties: [], @@ -10270,20 +10274,20 @@ fn build_type_env(module: ResolvedModule, parent_index: Map init: empty_map(), f: (acc, name) => map_insert(acc, intern(table: intern_table, s: name).id, TypeBinding { name: name, - resolved: Node { name: name, span: kernel_span(name: name), ident_span: Present { value: kernel_span(name: name) }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: OccurrenceSynthetic, name: name, span: kernel_span(name: name), ident_span: Present { value: kernel_span(name: name) }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, provenance: SubValueUnknown }) ) let unit_span = kernel_span(name: "Unit") let kernel_bindings = map_insert(kernel_bindings_base, intern(table: intern_table, s: "Unit").id, TypeBinding { name: "Unit", - resolved: Node { name: "Unit", span: unit_span, ident_span: Present { value: unit_span }, children: [], connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: OccurrenceSynthetic, name: "Unit", span: unit_span, ident_span: Present { value: unit_span }, children: [], connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, provenance: SubValueUnknown }) - let present_value_field = Node { name: "value", span: kernel_span(name: "value"), ident_span: Present { value: kernel_span(name: "value") }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: "present_value" } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let present_variant = Node { name: "Present", span: kernel_span(name: "Present"), ident_span: Present { value: kernel_span(name: "Present") }, children: [present_value_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let absent_variant = Node { name: "Absent", span: kernel_span(name: "Absent"), ident_span: Present { value: kernel_span(name: "Absent") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let kernel_optional = Node { name: "Optional", span: kernel_span(name: "Optional"), ident_span: Present { value: kernel_span(name: "Optional") }, children: [present_variant, absent_variant], connective: Disj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let present_value_field = Node { occurrence_identity: OccurrenceSynthetic, name: "value", span: kernel_span(name: "value"), ident_span: Present { value: kernel_span(name: "value") }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: "present_value" } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let present_variant = Node { occurrence_identity: OccurrenceSynthetic, name: "Present", span: kernel_span(name: "Present"), ident_span: Present { value: kernel_span(name: "Present") }, children: [present_value_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let absent_variant = Node { occurrence_identity: OccurrenceSynthetic, name: "Absent", span: kernel_span(name: "Absent"), ident_span: Present { value: kernel_span(name: "Absent") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let kernel_optional = Node { occurrence_identity: OccurrenceSynthetic, name: "Optional", span: kernel_span(name: "Optional"), ident_span: Present { value: kernel_span(name: "Optional") }, children: [present_variant, absent_variant], connective: Disj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let kernel_bindings = map_insert(kernel_bindings, intern(table: intern_table, s: "Optional").id, TypeBinding { name: "Optional", resolved: kernel_optional, provenance: SubValueUnknown }) let node_fields = inductive_fields_list_to_map(fields: compiler_inductive_fields) @@ -10451,12 +10455,12 @@ fn build_type_env_unresolved(module: ResolvedModule, parent_index: Map map_insert(acc, intern(table: intern_table, s: name).id, TypeBinding { name: name, resolved: Node { name: name, span: kernel_span(name: name), ident_span: Present { value: kernel_span(name: name) }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, provenance: SubValueUnknown }) + f: (acc, name) => map_insert(acc, intern(table: intern_table, s: name).id, TypeBinding { name: name, resolved: Node { occurrence_identity: OccurrenceSynthetic, name: name, span: kernel_span(name: name), ident_span: Present { value: kernel_span(name: name) }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, provenance: SubValueUnknown }) ) - let present_value_field = Node { name: "value", span: kernel_span(name: "value"), ident_span: Present { value: kernel_span(name: "value") }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: "present_value" } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let present_variant = Node { name: "Present", span: kernel_span(name: "Present"), ident_span: Present { value: kernel_span(name: "Present") }, children: [present_value_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let absent_variant = Node { name: "Absent", span: kernel_span(name: "Absent"), ident_span: Present { value: kernel_span(name: "Absent") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let kernel_optional = Node { name: "Optional", span: kernel_span(name: "Optional"), ident_span: Present { value: kernel_span(name: "Optional") }, children: [present_variant, absent_variant], connective: Disj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let present_value_field = Node { occurrence_identity: OccurrenceSynthetic, name: "value", span: kernel_span(name: "value"), ident_span: Present { value: kernel_span(name: "value") }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: "present_value" } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let present_variant = Node { occurrence_identity: OccurrenceSynthetic, name: "Present", span: kernel_span(name: "Present"), ident_span: Present { value: kernel_span(name: "Present") }, children: [present_value_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let absent_variant = Node { occurrence_identity: OccurrenceSynthetic, name: "Absent", span: kernel_span(name: "Absent"), ident_span: Present { value: kernel_span(name: "Absent") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let kernel_optional = Node { occurrence_identity: OccurrenceSynthetic, name: "Optional", span: kernel_span(name: "Optional"), ident_span: Present { value: kernel_span(name: "Optional") }, children: [present_variant, absent_variant], connective: Disj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let kernel_bindings = map_insert(kernel_bindings, intern(table: intern_table, s: "Optional").id, TypeBinding { name: "Optional", resolved: kernel_optional, provenance: SubValueUnknown }) let kernel = TypeEnv { module_path: "", bindings: kernel_bindings, str_bindings: str_bindings_from_bindings(bindings: kernel_bindings), ancestry_str_bindings: empty_map(), parents: [], recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: source_indices, intern_table: intern_table, source_visible_names: empty_map(), authored_import_names: empty_map(), symbol_index: empty_symbol_index() } @@ -10475,10 +10479,10 @@ fn build_type_env_unresolved(module: ResolvedModule, parent_index: Map count == 0 && item.body == none { - let alias_node = Node { name: item.name, span: item.span, ident_span: item.ident_span, children: [], connective: NoConnective, params: [], inferred: item.inferred, return_cardinality: item.return_cardinality, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let alias_node = Node { occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: [], connective: NoConnective, params: [], inferred: item.inferred, return_cardinality: item.return_cardinality, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } map_insert(acc, item_ident, TypeBinding { name: authored_name_at(source_indices: source_indices, node: item), resolved: alias_node, provenance: SubValueUnknown }) } else if item.transport == none && item.children |> count > 0 { let ref_node = nominal_ref_node(name: authored_name_at(source_indices: source_indices, node: item), span: item.span, ident_span: item.ident_span) @@ -11028,7 +11032,7 @@ fn typecheck_module(resolved: ResolvedModule, parent_index: Map if item.is_self_recursive && item.body != none { Node { - name: item.name, span: item.span, ident_span: item.ident_span, + occurrence_identity: item.occurrence_identity, name: item.name, span: item.span, ident_span: item.ident_span, children: item.children, params: item.params, inferred: item.inferred, return_cardinality: item.return_cardinality, uses: item.uses, @@ -11051,7 +11055,7 @@ fn typecheck_module(resolved: ResolvedModule, parent_index: Map, intern_ta init: empty_map(), f: (acc, name) => map_insert(acc, intern(table: intern_table, s: name).id, TypeBinding { name: name, - resolved: Node { name: name, span: kernel_span(name: name), ident_span: Present { value: kernel_span(name: name) }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: OccurrenceSynthetic, name: name, span: kernel_span(name: name), ident_span: Present { value: kernel_span(name: name) }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, provenance: SubValueUnknown }) ) let unit_span = kernel_span(name: "Unit") let kernel_bindings = map_insert(kernel_bindings_base, intern(table: intern_table, s: "Unit").id, TypeBinding { name: "Unit", - resolved: Node { name: "Unit", span: unit_span, ident_span: Present { value: unit_span }, children: [], connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: OccurrenceSynthetic, name: "Unit", span: unit_span, ident_span: Present { value: unit_span }, children: [], connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, provenance: SubValueUnknown }) - let present_value_field = Node { name: "value", span: kernel_span(name: "value"), ident_span: Present { value: kernel_span(name: "value") }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: "present_value" } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let present_variant = Node { name: "Present", span: kernel_span(name: "Present"), ident_span: Present { value: kernel_span(name: "Present") }, children: [present_value_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let absent_variant = Node { name: "Absent", span: kernel_span(name: "Absent"), ident_span: Present { value: kernel_span(name: "Absent") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let kernel_optional = Node { name: "Optional", span: kernel_span(name: "Optional"), ident_span: Present { value: kernel_span(name: "Optional") }, children: [present_variant, absent_variant], connective: Disj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let present_value_field = Node { occurrence_identity: OccurrenceSynthetic, name: "value", span: kernel_span(name: "value"), ident_span: Present { value: kernel_span(name: "value") }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: "present_value" } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let present_variant = Node { occurrence_identity: OccurrenceSynthetic, name: "Present", span: kernel_span(name: "Present"), ident_span: Present { value: kernel_span(name: "Present") }, children: [present_value_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let absent_variant = Node { occurrence_identity: OccurrenceSynthetic, name: "Absent", span: kernel_span(name: "Absent"), ident_span: Present { value: kernel_span(name: "Absent") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let kernel_optional = Node { occurrence_identity: OccurrenceSynthetic, name: "Optional", span: kernel_span(name: "Optional"), ident_span: Present { value: kernel_span(name: "Optional") }, children: [present_variant, absent_variant], connective: Disj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let kernel_bindings = map_insert(kernel_bindings, intern(table: intern_table, s: "Optional").id, TypeBinding { name: "Optional", resolved: kernel_optional, provenance: SubValueUnknown }) let node_fields = inductive_fields_list_to_map(fields: compiler_inductive_fields) let kernel_recursive_types = map_keys(compiler_recursive_types) |> map(name => intern(table: intern_table, s: name).id) diff --git a/src/v1/04_items.dag b/src/v1/04_items.dag index ccb345a3144..d853589bca5 100644 --- a/src/v1/04_items.dag +++ b/src/v1/04_items.dag @@ -27,7 +27,7 @@ import v1.std.core { node_name_span, no_span, NewlineIndex, authored_name_at, } -import std.occurrence_identity { OccurrenceTransport } +import std.occurrence_identity { OccurrenceTransport, OccurrenceSynthetic } import v1.compiler.infer_types { child_type_node @@ -193,18 +193,18 @@ fn inferred_to_outputs(inferred: InferredNode?, span: SourceSpan, source_indices if rt.ident_span == none { map(rt.children, child => let child_type = child_type_node(ch: child) - make_field_node(name: authored_name_at(source_indices: source_indices, node: child), type_expr: child_type, cardinality: Required, default_value: none, from_key: none, span: span, name_span: node_name_span(n: child)) + make_field_node(occurrence_identity: OccurrenceSynthetic, name: authored_name_at(source_indices: source_indices, node: child), type_expr: child_type, cardinality: Required, default_value: none, from_key_properties: [], span: span, name_span: node_name_span(n: child)) ) } else { - [make_field_node(name: "value", type_expr: rt, cardinality: Required, default_value: none, from_key: none, span: span, name_span: no_span())] + [make_field_node(occurrence_identity: OccurrenceSynthetic, name: "value", type_expr: rt, cardinality: Required, default_value: none, from_key_properties: [], span: span, name_span: no_span())] } } else { - [make_field_node(name: "value", type_expr: rt, cardinality: Required, default_value: none, from_key: none, span: span, name_span: no_span())] + [make_field_node(occurrence_identity: OccurrenceSynthetic, name: "value", type_expr: rt, cardinality: Required, default_value: none, from_key_properties: [], span: span, name_span: no_span())] } } else if rt.connective == Conj && rt.children |> count == 0 { [] } else { - [make_field_node(name: "value", type_expr: rt, cardinality: Required, default_value: none, from_key: none, span: span, name_span: no_span())] + [make_field_node(occurrence_identity: OccurrenceSynthetic, name: "value", type_expr: rt, cardinality: Required, default_value: none, from_key_properties: [], span: span, name_span: no_span())] } } } diff --git a/src/v1/04_method.dag b/src/v1/04_method.dag index d0e1983c406..83db07febf2 100644 --- a/src/v1/04_method.dag +++ b/src/v1/04_method.dag @@ -1,5 +1,7 @@ module v1.compiler.infer_method +import std.occurrence_identity { OccurrenceSynthetic } + import std.types { SourceSpan } import v1.std.core { Node, TypeVariable, Resolved, @@ -25,7 +27,7 @@ fn filesystem_read_result_type() -> Node { } fn type_variable_node(id: String) -> Node { - Node { name: "", span: no_span(), ident_span: none, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: id } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: OccurrenceSynthetic, name: "", span: no_span(), ident_span: none, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: id } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn map_of_type_variables() -> Node { diff --git a/src/v1/04_patterns.dag b/src/v1/04_patterns.dag index 66ec9e88f05..b6c89d38434 100644 --- a/src/v1/04_patterns.dag +++ b/src/v1/04_patterns.dag @@ -1,5 +1,7 @@ module v1.compiler.infer_patterns +import std.occurrence_identity { OccurrenceSynthetic } + import std.types { SourceSpan } import std.syntax { LiteralValue } @@ -177,8 +179,8 @@ fn is_type_variable(inferred: InferredNode) -> Bool { fn synthesize_optional_present_variant(scrut: Node) -> Node { let inner = extract_optional_inner_node(n: scrut) - let value_field = Node { name: "value", span: scrut.span, ident_span: Present { value: kernel_span(name: "value") }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: inner } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let present_node = Node { name: "Present", span: scrut.span, ident_span: Present { value: kernel_span(name: "Present") }, children: [value_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let value_field = Node { occurrence_identity: OccurrenceSynthetic, name: "value", span: scrut.span, ident_span: Present { value: kernel_span(name: "value") }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: inner } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let present_node = Node { occurrence_identity: OccurrenceSynthetic, name: "Present", span: scrut.span, ident_span: Present { value: kernel_span(name: "Present") }, children: [value_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } present_node } @@ -187,14 +189,14 @@ fn synthesize_witness_holds_variant(scrut: Node) -> Node { Present { value: child } => child_type_node(ch: child) Absent => error_type } - let value_field = Node { name: "value", span: scrut.span, ident_span: Present { value: kernel_span(name: "value") }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: inner } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - Node { name: "Holds", span: scrut.span, ident_span: Present { value: kernel_span(name: "Holds") }, children: [value_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let value_field = Node { occurrence_identity: OccurrenceSynthetic, name: "value", span: scrut.span, ident_span: Present { value: kernel_span(name: "value") }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: inner } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: OccurrenceSynthetic, name: "Holds", span: scrut.span, ident_span: Present { value: kernel_span(name: "Holds") }, children: [value_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn synthesize_witness_violates_variant(scrut: Node) -> Node { - let diagnostic_type = Node { name: "Diagnostic", span: scrut.span, ident_span: Present { value: kernel_span(name: "Diagnostic") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let diagnostic_field = Node { name: "diagnostic", span: scrut.span, ident_span: Present { value: kernel_span(name: "diagnostic") }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: diagnostic_type } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - Node { name: "Violates", span: scrut.span, ident_span: Present { value: kernel_span(name: "Violates") }, children: [diagnostic_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let diagnostic_type = Node { occurrence_identity: OccurrenceSynthetic, name: "Diagnostic", span: scrut.span, ident_span: Present { value: kernel_span(name: "Diagnostic") }, children: [], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let diagnostic_field = Node { occurrence_identity: OccurrenceSynthetic, name: "diagnostic", span: scrut.span, ident_span: Present { value: kernel_span(name: "diagnostic") }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: diagnostic_type } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: OccurrenceSynthetic, name: "Violates", span: scrut.span, ident_span: Present { value: kernel_span(name: "Violates") }, children: [diagnostic_field], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn pattern_subject_preserving_outer_optional(outer: Node, inner: PatternSubject) -> PatternSubject { diff --git a/src/v1/04_resolve.dag b/src/v1/04_resolve.dag index 8b94b4c68ed..aa7f9910ea4 100644 --- a/src/v1/04_resolve.dag +++ b/src/v1/04_resolve.dag @@ -1,5 +1,7 @@ module v1.compiler.infer_resolve +import std.occurrence_identity { OccurrenceSynthetic } + import std.types { SourceSpan, container_param_name } import std.syntax { LiteralValue } @@ -116,7 +118,7 @@ fn is_type_variable(inferred: InferredNode) -> Bool { fn with_authored_identity(identity: Node, structural: Node) -> Node { Node { - name: structural.name, ident: structural.ident, span: structural.span, ident_span: identity.ident_span, + occurrence_identity: OccurrenceSynthetic, name: structural.name, ident: structural.ident, span: structural.span, ident_span: identity.ident_span, children: structural.children, connective: structural.connective, params: structural.params, inferred: structural.inferred, return_cardinality: join_optional_cardinality(left: identity.return_cardinality, right: structural.return_cardinality), uses: structural.uses, body: structural.body, transport: structural.transport, @@ -315,7 +317,7 @@ fn substitute_type_slots_scoped(n: Node, slot_bindings: Map, decl_ substitute_type_slots_scoped(n: arg, slot_bindings: slot_bindings, decl_name: decl_name, source_indices: source_indices, bind_type_variables: bind_type_variables) ) Node { - name: child.name, span: child.span, ident_span: child.ident_span, children: substituted_args, + occurrence_identity: child.occurrence_identity, name: child.name, span: child.span, ident_span: child.ident_span, children: substituted_args, connective: child.connective, params: child.params, inferred: child.inferred, return_cardinality: child.return_cardinality, uses: child.uses, body: child.body, transport: child.transport, @@ -333,7 +335,7 @@ fn substitute_type_slots_scoped(n: Node, slot_bindings: Map, decl_ _ => n.inferred } Node { - name: n.name, span: n.span, ident_span: n.ident_span, children: new_children, + occurrence_identity: n.occurrence_identity, name: n.name, span: n.span, ident_span: n.ident_span, children: new_children, connective: n.connective, params: n.params, inferred: new_inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, @@ -378,7 +380,7 @@ fn resolve_nominal_alias_rhs(n: Node, env: TypeEnv, module_name: String) -> Node let validation = resolve_node(n: n, env: env, module_name: module_name) NodeResolveResult { resolved: Node { - name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, children: resolved_args, + occurrence_identity: n.occurrence_identity, name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, children: resolved_args, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, @@ -413,7 +415,7 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int, let base_resolved = base_result.resolved let base_diags = base_result.diagnostics NodeResolveResult { - resolved: Node { name: n.name, span: n.span, ident_span: n.ident_span, children: [base_resolved], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: n.occurrence_identity, name: n.name, span: n.span, ident_span: n.ident_span, children: [base_resolved], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: base_diags } Absent => NodeResolveResult { resolved: n, diagnostics: [] } @@ -428,7 +430,7 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int, let rt_resolved = rt_result.resolved let rt_diags = rt_result.diagnostics NodeResolveResult { - resolved: Node { name: child.name, span: child.span, ident_span: child.ident_span, children: child.children, connective: child.connective, params: child.params, inferred: Present { value: Resolved { node: rt_resolved } }, return_cardinality: child.return_cardinality, uses: child.uses, body: child.body, transport: child.transport, properties: concat(child.properties, rt_resolved.properties), type_annotation: child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: child.occurrence_identity, name: child.name, span: child.span, ident_span: child.ident_span, children: child.children, connective: child.connective, params: child.params, inferred: Present { value: Resolved { node: rt_resolved } }, return_cardinality: child.return_cardinality, uses: child.uses, body: child.body, transport: child.transport, properties: concat(child.properties, rt_resolved.properties), type_annotation: child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: rt_diags } } @@ -436,7 +438,7 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int, let resolved_children = map(child_results, cr => cr.resolved) let all_diags = flat_map(child_results, cr => cr.diagnostics) NodeResolveResult { - resolved: Node { name: n.name, span: n.span, ident_span: n.ident_span, children: resolved_children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: n.occurrence_identity, name: n.name, span: n.span, ident_span: n.ident_span, children: resolved_children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: all_diags } } @@ -467,7 +469,7 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int, let rt_resolved = rt_result.resolved let rt_diags = rt_result.diagnostics NodeResolveResult { - resolved: Node { name: field_child.name, span: field_child.span, ident_span: field_child.ident_span, children: field_child.children, connective: field_child.connective, params: field_child.params, inferred: Present { value: Resolved { node: rt_resolved } }, return_cardinality: field_child.return_cardinality, uses: field_child.uses, body: field_child.body, transport: field_child.transport, properties: concat(field_child.properties, rt_resolved.properties), type_annotation: field_child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: field_child.occurrence_identity, name: field_child.name, span: field_child.span, ident_span: field_child.ident_span, children: field_child.children, connective: field_child.connective, params: field_child.params, inferred: Present { value: Resolved { node: rt_resolved } }, return_cardinality: field_child.return_cardinality, uses: field_child.uses, body: field_child.body, transport: field_child.transport, properties: concat(field_child.properties, rt_resolved.properties), type_annotation: field_child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: rt_diags } } @@ -475,14 +477,14 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int, let resolved_fields = map(field_results, fr => fr.resolved) let field_diags = flat_map(field_results, fr => fr.diagnostics) NodeResolveResult { - resolved: Node { name: variant_child.name, span: variant_child.span, ident_span: variant_child.ident_span, children: resolved_fields, connective: variant_child.connective, params: variant_child.params, inferred: variant_child.inferred, return_cardinality: variant_child.return_cardinality, uses: variant_child.uses, body: variant_child.body, transport: variant_child.transport, properties: variant_child.properties, type_annotation: variant_child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: variant_child.occurrence_identity, name: variant_child.name, span: variant_child.span, ident_span: variant_child.ident_span, children: resolved_fields, connective: variant_child.connective, params: variant_child.params, inferred: variant_child.inferred, return_cardinality: variant_child.return_cardinality, uses: variant_child.uses, body: variant_child.body, transport: variant_child.transport, properties: variant_child.properties, type_annotation: variant_child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: field_diags } ) let resolved_variants = map(variant_results, vr => vr.resolved) let all_diags = flat_map(variant_results, vr => vr.diagnostics) NodeResolveResult { - resolved: Node { name: n.name, span: n.span, ident_span: n.ident_span, children: resolved_variants, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: n.occurrence_identity, name: n.name, span: n.span, ident_span: n.ident_span, children: resolved_variants, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: all_diags } } @@ -514,17 +516,17 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int, } let target_result = resolve_node_bounded(n: alias_target, env: env, module_name: module_name, depth: depth + 1, masked: false) let is_recursive = is_recursive_type_by_name(env: env, name: type_name) - let expanded_node = Node { name: type_name, span: n.span, ident_span: n.ident_span, children: target_result.resolved.children, connective: target_result.resolved.connective, params: [], inferred: target_result.resolved.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: target_result.resolved.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } - let resolved_node = Node { name: type_name, span: n.span, ident_span: n.ident_span, children: resolved_args, connective: NoConnective, params: [], inferred: Present { value: Resolved { node: expanded_node } }, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: target_result.resolved.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } + let expanded_node = Node { occurrence_identity: OccurrenceSynthetic, name: type_name, span: n.span, ident_span: n.ident_span, children: target_result.resolved.children, connective: target_result.resolved.connective, params: [], inferred: target_result.resolved.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: target_result.resolved.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } + let resolved_node = Node { occurrence_identity: n.occurrence_identity, name: type_name, span: n.span, ident_span: n.ident_span, children: resolved_args, connective: NoConnective, params: [], inferred: Present { value: Resolved { node: expanded_node } }, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: target_result.resolved.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } NodeResolveResult { resolved: resolved_node, diagnostics: concat(arity_diags, arg_diags, target_result.diagnostics) } } else { let substituted_children = decl.children |> map(child => substitute_type_slots(n: child, slot_bindings: slot_bindings, decl_name: type_name, source_indices: env.source_indices) ) let is_recursive = is_recursive_type_by_name(env: env, name: type_name) - let expanded_node = Node { name: type_name, span: n.span, ident_span: n.ident_span, children: substituted_children, connective: decl.connective, params: [], inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: decl.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } + let expanded_node = Node { occurrence_identity: OccurrenceSynthetic, name: type_name, span: n.span, ident_span: n.ident_span, children: substituted_children, connective: decl.connective, params: [], inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: decl.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } let result = NodeResolveResult { - resolved: Node { name: type_name, span: n.span, ident_span: n.ident_span, children: resolved_args, connective: NoConnective, params: [], inferred: Present { value: Resolved { node: expanded_node } }, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: decl.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data }, + resolved: Node { occurrence_identity: n.occurrence_identity, name: type_name, span: n.span, ident_span: n.ident_span, children: resolved_args, connective: NoConnective, params: [], inferred: Present { value: Resolved { node: expanded_node } }, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: decl.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data }, diagnostics: concat(arity_diags, arg_diags) } result @@ -545,10 +547,10 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int, let val_diags = val_result.diagnostics let key_param_name = if key_child_node.inferred != none { authored_name(env: env, node: key_child_node) } else { match container_param_name(kind_name: type_name, index: 0) { Present { value: pn } => pn Absent => authored_name(env: env, node: key_child_node) } } let val_param_name = if val_child_node.inferred != none { authored_name(env: env, node: val_child_node) } else { match container_param_name(kind_name: type_name, index: 1) { Present { value: pn } => pn Absent => authored_name(env: env, node: val_child_node) } } - let resolved_key_child = Node { name: key_param_name, span: key_child_node.span, ident_span: key_child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: key_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let resolved_val_child = Node { name: val_param_name, span: val_child_node.span, ident_span: val_child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: val_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let resolved_key_child = Node { occurrence_identity: key_child_node.occurrence_identity, name: key_param_name, span: key_child_node.span, ident_span: key_child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: key_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let resolved_val_child = Node { occurrence_identity: val_child_node.occurrence_identity, name: val_param_name, span: val_child_node.span, ident_span: val_child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: val_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } NodeResolveResult { - resolved: Node { name: type_name, span: n.span, ident_span: n.ident_span, children: [resolved_key_child, resolved_val_child], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: n.occurrence_identity, name: type_name, span: n.span, ident_span: n.ident_span, children: [resolved_key_child, resolved_val_child], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: concat(key_diags, val_diags) } } else if n.children |> count == 1 { @@ -560,9 +562,9 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int, let el_resolved = el_result.resolved let el_diags = el_result.diagnostics let el_param_name = if child_node.inferred != none { authored_name(env: env, node: child_node) } else { match container_param_name(kind_name: type_name, index: 0) { Present { value: pn } => pn Absent => authored_name(env: env, node: child_node) } } - let resolved_child = Node { name: el_param_name, span: child_node.span, ident_span: child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: el_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let resolved_child = Node { occurrence_identity: child_node.occurrence_identity, name: el_param_name, span: child_node.span, ident_span: child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: el_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } NodeResolveResult { - resolved: Node { name: type_name, span: n.span, ident_span: n.ident_span, children: [resolved_child], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { occurrence_identity: n.occurrence_identity, name: type_name, span: n.span, ident_span: n.ident_span, children: [resolved_child], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: el_diags } Absent => NodeResolveResult { resolved: n, diagnostics: [] } @@ -651,11 +653,11 @@ fn resolve_optional_node(n: InferredNode?, env: TypeEnv, module_name: String) -> Resolved { node: inner } => resolve_node(n: inner, env: env, module_name: module_name) CompilerError { message: msg, span: sp } => NodeResolveResult { - resolved: make_expr_error_node(kind: SemanticExprError, message: msg, span: sp), + resolved: make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: SemanticExprError, message: msg, span: sp), diagnostics: [make_error_node(diagnostic: InternalError { message: msg, span: sp }, module_name: module_name)] } TypeVariable { id: tv } => - NodeResolveResult { resolved: Node { name: tv, span: kernel_span(name: tv), ident_span: Present { value: kernel_span(name: tv) }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: tv } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: [] } + NodeResolveResult { resolved: Node { occurrence_identity: OccurrenceSynthetic, name: tv, span: kernel_span(name: tv), ident_span: Present { value: kernel_span(name: tv) }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: tv } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: [] } } } } @@ -674,7 +676,8 @@ fn resolve_field(field: Node, env: TypeEnv, module_name: String) -> FieldResolve Absent => [] } FieldResolveResult { - field: make_field_node( + field: make_field_node(occurrence_identity: field.occurrence_identity, + occurrence_identity: field.occurrence_identity, name: field_node_name_at(n: field, source_indices: env.source_indices), type_expr: type_resolved, cardinality: field_node_cardinality(n: field), @@ -682,7 +685,7 @@ fn resolve_field(field: Node, env: TypeEnv, module_name: String) -> FieldResolve Present { value: result } => Present { value: result.expr } Absent => none }, - from_key: field_node_from_key(n: field, source_indices: env.source_indices), + from_key_properties: field.properties |> filter(p => field_init_node_name_at(n: p, source_indices: env.source_indices) == "from_key"), span: field.span, name_span: node_name_span(n: field) ), diagnostics: concat(type_diags, default_diags) @@ -694,7 +697,7 @@ fn resolve_param(param: Node, env: TypeEnv, module_name: String) -> ParamResolve let type_result = resolve_node(n: authored_type, env: env, module_name: module_name) let type_resolved = type_result.resolved let rendered_type = if authored_type.children |> count > 0 { - Node { name: authored_type.name, span: authored_type.span, ident_span: authored_type.ident_span, children: type_resolved.children, connective: authored_type.connective, params: authored_type.params, inferred: Present { value: Resolved { node: type_resolved } }, return_cardinality: authored_type.return_cardinality, uses: authored_type.uses, body: authored_type.body, transport: authored_type.transport, properties: type_resolved.properties, type_annotation: authored_type.type_annotation, is_self_recursive: authored_type.is_self_recursive, has_non_tail_self_call: authored_type.has_non_tail_self_call, match_pattern: authored_type.match_pattern, expr_data: authored_type.expr_data } + Node { occurrence_identity: authored_type.occurrence_identity, name: authored_type.name, span: authored_type.span, ident_span: authored_type.ident_span, children: type_resolved.children, connective: authored_type.connective, params: authored_type.params, inferred: Present { value: Resolved { node: type_resolved } }, return_cardinality: authored_type.return_cardinality, uses: authored_type.uses, body: authored_type.body, transport: authored_type.transport, properties: type_resolved.properties, type_annotation: authored_type.type_annotation, is_self_recursive: authored_type.is_self_recursive, has_non_tail_self_call: authored_type.has_non_tail_self_call, match_pattern: authored_type.match_pattern, expr_data: authored_type.expr_data } } else { type_resolved } @@ -712,7 +715,7 @@ fn resolve_param(param: Node, env: TypeEnv, module_name: String) -> ParamResolve Absent => none } ParamResolveResult { - param: make_resolved_param_node( + param: make_resolved_param_node(occurrence_identity: param.occurrence_identity, name: param_node_name_at(n: param, source_indices: env.source_indices), type_expr: rendered_type, default_value: default_expr, @@ -729,7 +732,7 @@ fn resolve_resource_use(ru: Node, env: TypeEnv, module_name: String) -> Resource let type_resolved = type_result.resolved let type_diags = type_result.diagnostics ResourceUseResult { - resource_use: make_resource_use_node(name: resource_use_name_at(n: ru, source_indices: env.source_indices), resource: type_resolved, span: ru.span, name_span: node_name_span(n: ru)), + resource_use: make_resource_use_node(occurrence_identity: ru.occurrence_identity, name: resource_use_name_at(n: ru, source_indices: env.source_indices), resource: type_resolved, span: ru.span, name_span: node_name_span(n: ru)), diagnostics: type_diags } } @@ -739,7 +742,7 @@ fn resolve_named_arg(arg: Node, env: TypeEnv, module_name: String) -> NamedArgRe let value_expr = value_result.expr let value_diags = value_result.diagnostics NamedArgResolveResult { - arg: make_arg_node(name: arg_name_at(n: arg, source_indices: env.source_indices), value: value_expr, span: arg.span, name_span: node_name_span(n: arg)), + arg: make_arg_node(occurrence_identity: arg.occurrence_identity, name: arg_name_at(n: arg, source_indices: env.source_indices), value: value_expr, span: arg.span, name_span: node_name_span(n: arg)), diagnostics: value_diags } } @@ -749,7 +752,7 @@ fn resolve_field_init(field_init: Node, env: TypeEnv, module_name: String) -> Fi let value_expr = value_result.expr let value_diags = value_result.diagnostics FieldInitResolveResult { - field_init: make_field_init_node(name: field_init_node_name_at(n: field_init, source_indices: env.source_indices), value: value_expr, span: field_init.span, name_span: node_name_span(n: field_init)), + field_init: make_field_init_node(occurrence_identity: field_init.occurrence_identity, name: field_init_node_name_at(n: field_init, source_indices: env.source_indices), value: value_expr, span: field_init.span, name_span: node_name_span(n: field_init)), diagnostics: value_diags } } @@ -768,7 +771,7 @@ fn resolve_match_arm(arm: Node, env: TypeEnv, module_name: String) -> MatchArmRe let body_expr = body_result.expr let body_diags = body_result.diagnostics MatchArmResolveResult { - arm: make_arm_node( + arm: make_arm_node(occurrence_identity: arm.occurrence_identity, pattern: arm_pattern(n: arm), guard: match guard_result { Present { value: result } => Present { value: result.expr } @@ -805,7 +808,7 @@ fn resolve_transport_binding(transport: Node, env: TypeEnv, module_name: String) } else { let prop_results = map(transport.properties, p => let val_result = resolve_expr_types(texpr: field_init_node_value(n: p), env: env, module_name: module_name) - FieldInitResolveResult { field_init: make_field_init_node(name: field_init_node_name_at(n: p, source_indices: env.source_indices), value: val_result.expr, span: p.span, name_span: node_name_span(n: p)), diagnostics: val_result.diagnostics } + FieldInitResolveResult { field_init: make_field_init_node(occurrence_identity: p.occurrence_identity, name: field_init_node_name_at(n: p, source_indices: env.source_indices), value: val_result.expr, span: p.span, name_span: node_name_span(n: p)), diagnostics: val_result.diagnostics } ) let resolved_props = map(prop_results, pr => pr.field_init) let prop_diags = flat_map(prop_results, pr => pr.diagnostics) @@ -820,7 +823,7 @@ fn resolve_transport_binding(transport: Node, env: TypeEnv, module_name: String) Absent => [] } TransportResolveResult { - transport: make_transport_node(properties: resolved_props, children: resolved_children, body: transport.body, span: transport.span), + transport: make_transport_node(occurrence_identity: transport.occurrence_identity, properties: resolved_props, children: resolved_children, body: transport.body, span: transport.span), diagnostics: concat(prop_diags, child_diags, body_diags) } } @@ -831,7 +834,7 @@ fn resolve_expr_types(texpr: Node, env: TypeEnv, module_name: String) -> ExprRes ExprLiteral { value: _ } => ExprResolveResult { expr: texpr, diagnostics: [] } ExprError { kind: kind, message: message } => ExprResolveResult { - expr: make_expr_error_node(kind: kind, message: message, span: texpr.span), + expr: make_expr_error_node(occurrence_identity: OccurrenceSynthetic, kind: kind, message: message, span: texpr.span), diagnostics: [make_error_node(diagnostic: InternalError { message: message, span: texpr.span }, module_name: module_name)] } ExprVar { binding_kind: _ } => ExprResolveResult { expr: texpr, diagnostics: [] } @@ -846,11 +849,11 @@ fn resolve_expr_types(texpr: Node, env: TypeEnv, module_name: String) -> ExprRes let arg_results = texpr.children |> map(arg_node => let val = match arg_node.children |> first { Present { value: v } => v Absent => arg_node } let vr = resolve_expr_types(texpr: val, env: env, module_name: module_name) - ExprResolveResult { expr: make_arg_node(name: if arg_node.ident_span == none { none } else { Present { value: authored_name(env: env, node: arg_node) } }, value: vr.expr, span: arg_node.span, name_span: node_name_span(n: arg_node)), diagnostics: vr.diagnostics } + ExprResolveResult { expr: make_arg_node(occurrence_identity: arg_node.occurrence_identity, name: if arg_node.ident_span == none { none } else { Present { value: authored_name(env: env, node: arg_node) } }, value: vr.expr, span: arg_node.span, name_span: node_name_span(n: arg_node)), diagnostics: vr.diagnostics } ) let resolved_children = arg_results |> map(r => r.expr) let all_diags = flat_map(arg_results, r => r.diagnostics) - ExprResolveResult { expr: make_named_expr_node(name: expr_call_func_at(texpr: texpr, source_indices: env.source_indices), expr_data: ExprCall { call_semantics: cs, descent_evidence: de }, children: resolved_children, inferred: texpr.inferred, span: texpr.span, name_span: node_name_span(n: texpr)), diagnostics: all_diags } + ExprResolveResult { expr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: expr_call_func_at(texpr: texpr, source_indices: env.source_indices), expr_data: ExprCall { call_semantics: cs, descent_evidence: de }, children: resolved_children, inferred: texpr.inferred, span: texpr.span, name_span: node_name_span(n: texpr)), diagnostics: all_diags } ExprMethodCall { method_semantics: ms } => let mc_results = texpr.children |> enumerate |> map(pair => @@ -862,12 +865,12 @@ fn resolve_expr_types(texpr: Node, env: TypeEnv, module_name: String) -> ExprRes } else { let val = match child.children |> first { Present { value: v } => v Absent => child } let vr = resolve_expr_types(texpr: val, env: env, module_name: module_name) - ExprResolveResult { expr: make_arg_node(name: if child.ident_span == none { none } else { Present { value: authored_name_at(source_indices: env.source_indices, node: child) } }, value: vr.expr, span: child.span, name_span: node_name_span(n: child)), diagnostics: vr.diagnostics } + ExprResolveResult { expr: make_arg_node(occurrence_identity: child.occurrence_identity, name: if child.ident_span == none { none } else { Present { value: authored_name_at(source_indices: env.source_indices, node: child) } }, value: vr.expr, span: child.span, name_span: node_name_span(n: child)), diagnostics: vr.diagnostics } } ) let resolved_children = mc_results |> map(r => r.expr) let all_diags = flat_map(mc_results, r => r.diagnostics) - ExprResolveResult { expr: make_named_expr_node(name: expr_method_name_at(texpr: texpr, source_indices: env.source_indices), expr_data: ExprMethodCall { method_semantics: ms }, children: resolved_children, inferred: texpr.inferred, span: texpr.span, name_span: node_name_span(n: texpr)), diagnostics: all_diags } + ExprResolveResult { expr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: expr_method_name_at(texpr: texpr, source_indices: env.source_indices), expr_data: ExprMethodCall { method_semantics: ms }, children: resolved_children, inferred: texpr.inferred, span: texpr.span, name_span: node_name_span(n: texpr)), diagnostics: all_diags } ExprMatch => let match_results = texpr.children |> enumerate |> map(pair => @@ -882,23 +885,23 @@ fn resolve_expr_types(texpr: Node, env: TypeEnv, module_name: String) -> ExprRes if has_guard { let guard_r = match arm_ch |> first { Present { value: g } => resolve_expr_types(texpr: g, env: env, module_name: module_name) Absent => ExprResolveResult { expr: child, diagnostics: [] } } let body_r = match arm_ch |> skip(1) |> first { Present { value: b } => resolve_expr_types(texpr: b, env: env, module_name: module_name) Absent => ExprResolveResult { expr: child, diagnostics: [] } } - ExprResolveResult { expr: make_arm_node(pattern: match child.match_pattern { Present { value: p } => p Absent => Wildcard }, guard: Present { value: guard_r.expr }, body: body_r.expr, span: child.span), diagnostics: concat(guard_r.diagnostics, body_r.diagnostics) } + ExprResolveResult { expr: make_arm_node(occurrence_identity: child.occurrence_identity, pattern: match child.match_pattern { Present { value: p } => p Absent => Wildcard }, guard: Present { value: guard_r.expr }, body: body_r.expr, span: child.span), diagnostics: concat(guard_r.diagnostics, body_r.diagnostics) } } else { let body_r = match arm_ch |> first { Present { value: b } => resolve_expr_types(texpr: b, env: env, module_name: module_name) Absent => ExprResolveResult { expr: child, diagnostics: [] } } - ExprResolveResult { expr: make_arm_node(pattern: match child.match_pattern { Present { value: p } => p Absent => Wildcard }, guard: none, body: body_r.expr, span: child.span), diagnostics: body_r.diagnostics } + ExprResolveResult { expr: make_arm_node(occurrence_identity: child.occurrence_identity, pattern: match child.match_pattern { Present { value: p } => p Absent => Wildcard }, guard: none, body: body_r.expr, span: child.span), diagnostics: body_r.diagnostics } } } ) let resolved_children = match_results |> map(r => r.expr) let all_diags = flat_map(match_results, r => r.diagnostics) - ExprResolveResult { expr: make_expr_node(expr_data: ExprMatch, children: resolved_children, inferred: texpr.inferred, span: texpr.span), diagnostics: all_diags } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprMatch, children: resolved_children, inferred: texpr.inferred, span: texpr.span), diagnostics: all_diags } ExprIf => let ch = texpr.children let cr = match ch |> first { Present { value: c } => resolve_expr_types(texpr: c, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } let tr = match ch |> skip(1) |> first { Present { value: t } => resolve_expr_types(texpr: t, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } let er = match ch |> skip(2) |> first { Present { value: e } => Present { value: resolve_expr_types(texpr: e, env: env, module_name: module_name) } Absent => none } let resolved_children = match er { Present { value: r } => [cr.expr, tr.expr, r.expr] Absent => [cr.expr, tr.expr] } - ExprResolveResult { expr: make_expr_node(expr_data: ExprIf, children: resolved_children, inferred: texpr.inferred, span: texpr.span), diagnostics: concat(cr.diagnostics, tr.diagnostics, match er { Present { value: r } => r.diagnostics Absent => [] }) } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprIf, children: resolved_children, inferred: texpr.inferred, span: texpr.span), diagnostics: concat(cr.diagnostics, tr.diagnostics, match er { Present { value: r } => r.diagnostics Absent => [] }) } ExprLet => let ch = texpr.children let vr = match ch |> first { Present { value: v } => resolve_expr_types(texpr: v, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } @@ -913,7 +916,7 @@ fn resolve_expr_types(texpr: Node, env: TypeEnv, module_name: String) -> ExprRes } let resolved_anno = if texpr.type_annotation == none { none } else if is_type_expr_annotation(n: texpr.type_annotation.value) { Present { value: anno_resolved.resolved } } else { texpr.type_annotation } let let_node = Node { - name: let_binding_name_at(texpr: texpr, source_indices: env.source_indices), + occurrence_identity: OccurrenceSynthetic, name: let_binding_name_at(texpr: texpr, source_indices: env.source_indices), span: texpr.span, ident_span: default_ident_span(name: let_binding_name_at(texpr: texpr, source_indices: env.source_indices), span: node_name_span(n: texpr)), children: resolved_children, @@ -937,28 +940,28 @@ fn resolve_expr_types(texpr: Node, env: TypeEnv, module_name: String) -> ExprRes let fi_results = texpr.children |> map(fi_node => let val = match fi_node.children |> first { Present { value: v } => v Absent => fi_node } let vr = resolve_expr_types(texpr: val, env: env, module_name: module_name) - ExprResolveResult { expr: make_field_init_node(name: authored_name(env: env, node: fi_node), value: vr.expr, span: fi_node.span, name_span: node_name_span(n: fi_node)), diagnostics: vr.diagnostics } + ExprResolveResult { expr: make_field_init_node(occurrence_identity: fi_node.occurrence_identity, name: authored_name(env: env, node: fi_node), value: vr.expr, span: fi_node.span, name_span: node_name_span(n: fi_node)), diagnostics: vr.diagnostics } ) let resolved_children = fi_results |> map(r => r.expr) let all_diags = flat_map(fi_results, r => r.diagnostics) - ExprResolveResult { expr: make_named_expr_node(name: authored_name_at(source_indices: env.source_indices, node: texpr), expr_data: ExprRecordLit { parent_enum: pe }, children: resolved_children, inferred: texpr.inferred, span: texpr.span, name_span: node_name_span(n: texpr)), diagnostics: all_diags } + ExprResolveResult { expr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: authored_name_at(source_indices: env.source_indices, node: texpr), expr_data: ExprRecordLit { parent_enum: pe }, children: resolved_children, inferred: texpr.inferred, span: texpr.span, name_span: node_name_span(n: texpr)), diagnostics: all_diags } ExprListLit => let el_results = texpr.children |> map(el => resolve_expr_types(texpr: el, env: env, module_name: module_name)) let resolved_children = el_results |> map(r => r.expr) let all_diags = flat_map(el_results, r => r.diagnostics) - ExprResolveResult { expr: make_expr_node(expr_data: ExprListLit, children: resolved_children, inferred: texpr.inferred, span: texpr.span), diagnostics: all_diags } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprListLit, children: resolved_children, inferred: texpr.inferred, span: texpr.span), diagnostics: all_diags } ExprBinOp { op: op, algebra_field: af } => let ch = texpr.children let lr = match ch |> first { Present { value: l } => resolve_expr_types(texpr: l, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } let rr = match ch |> skip(1) |> first { Present { value: r } => resolve_expr_types(texpr: r, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } - ExprResolveResult { expr: make_expr_node(expr_data: ExprBinOp { op: op, algebra_field: af }, children: [lr.expr, rr.expr], inferred: texpr.inferred, span: texpr.span), diagnostics: concat(lr.diagnostics, rr.diagnostics) } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprBinOp { op: op, algebra_field: af }, children: [lr.expr, rr.expr], inferred: texpr.inferred, span: texpr.span), diagnostics: concat(lr.diagnostics, rr.diagnostics) } ExprUnaryOp { op: op } => let r = match texpr.children |> first { Present { value: o } => resolve_expr_types(texpr: o, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } - ExprResolveResult { expr: make_expr_node(expr_data: ExprUnaryOp { op: op }, children: [r.expr], inferred: texpr.inferred, span: texpr.span), diagnostics: r.diagnostics } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprUnaryOp { op: op }, children: [r.expr], inferred: texpr.inferred, span: texpr.span), diagnostics: r.diagnostics } ExprLambda => let lam_param_nodes = texpr.children |> skip(1) let r = match texpr.children |> first { Present { value: b } => resolve_expr_types(texpr: b, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } - ExprResolveResult { expr: make_expr_node(expr_data: ExprLambda, children: concat([r.expr], lam_param_nodes), inferred: texpr.inferred, span: texpr.span), diagnostics: r.diagnostics } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprLambda, children: concat([r.expr], lam_param_nodes), inferred: texpr.inferred, span: texpr.span), diagnostics: r.diagnostics } ExprStringInterp => let part_results = texpr.children |> map(part_node => @@ -968,43 +971,43 @@ fn resolve_expr_types(texpr: Node, env: TypeEnv, module_name: String) -> ExprRes match part_node.children |> first { Present { value: inner } => let r = resolve_expr_types(texpr: inner, env: env, module_name: module_name) - ExprResolveResult { expr: make_interp_part_node(expr: r.expr, span: part_node.span), diagnostics: r.diagnostics } + ExprResolveResult { expr: make_interp_part_node(occurrence_identity: part_node.occurrence_identity, expr: r.expr, span: part_node.span), diagnostics: r.diagnostics } Absent => ExprResolveResult { expr: part_node, diagnostics: [] } } } ) let resolved_children = part_results |> map(r => r.expr) let all_diags = flat_map(part_results, r => r.diagnostics) - ExprResolveResult { expr: make_expr_node(expr_data: ExprStringInterp, children: resolved_children, inferred: texpr.inferred, span: texpr.span), diagnostics: all_diags } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprStringInterp, children: resolved_children, inferred: texpr.inferred, span: texpr.span), diagnostics: all_diags } ExprBlock => let stmt_results = texpr.children |> map(s => resolve_expr_types(texpr: s, env: env, module_name: module_name)) let resolved_children = stmt_results |> map(r => r.expr) let all_diags = flat_map(stmt_results, r => r.diagnostics) - ExprResolveResult { expr: make_expr_node(expr_data: ExprBlock, children: resolved_children, inferred: texpr.inferred, span: texpr.span), diagnostics: all_diags } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprBlock, children: resolved_children, inferred: texpr.inferred, span: texpr.span), diagnostics: all_diags } ExprCast => let ch = texpr.children let r = match ch |> first { Present { value: inner } => resolve_expr_types(texpr: inner, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } let tr = match ch |> skip(1) |> first { Present { value: target } => resolve_node(n: target, env: env, module_name: module_name) Absent => NodeResolveResult { resolved: unit_type, diagnostics: [] } } - ExprResolveResult { expr: make_expr_node(expr_data: ExprCast, children: [r.expr, tr.resolved], inferred: texpr.inferred, span: texpr.span), diagnostics: concat(r.diagnostics, tr.diagnostics) } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprCast, children: [r.expr, tr.resolved], inferred: texpr.inferred, span: texpr.span), diagnostics: concat(r.diagnostics, tr.diagnostics) } ExprForEach => let ch = texpr.children let cr = match ch |> first { Present { value: c } => resolve_expr_types(texpr: c, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } let br = match ch |> skip(1) |> first { Present { value: b } => resolve_expr_types(texpr: b, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } - ExprResolveResult { expr: make_named_expr_node(name: foreach_variable_at(texpr: texpr, source_indices: env.source_indices), expr_data: ExprForEach, children: [cr.expr, br.expr], inferred: texpr.inferred, span: texpr.span, name_span: node_name_span(n: texpr)), diagnostics: concat(cr.diagnostics, br.diagnostics) } + ExprResolveResult { expr: make_named_expr_node(occurrence_identity: texpr.occurrence_identity, name: foreach_variable_at(texpr: texpr, source_indices: env.source_indices), expr_data: ExprForEach, children: [cr.expr, br.expr], inferred: texpr.inferred, span: texpr.span, name_span: node_name_span(n: texpr)), diagnostics: concat(cr.diagnostics, br.diagnostics) } ExprIndex => let ch = texpr.children let br = match ch |> first { Present { value: base } => resolve_expr_types(texpr: base, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } let ir = match ch |> skip(1) |> first { Present { value: index } => resolve_expr_types(texpr: index, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } - ExprResolveResult { expr: make_expr_node(expr_data: ExprIndex, children: [br.expr, ir.expr], inferred: texpr.inferred, span: texpr.span), diagnostics: concat(br.diagnostics, ir.diagnostics) } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprIndex, children: [br.expr, ir.expr], inferred: texpr.inferred, span: texpr.span), diagnostics: concat(br.diagnostics, ir.diagnostics) } ExprSlice => let ch = texpr.children let br = match ch |> first { Present { value: base } => resolve_expr_types(texpr: base, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } let sr = match ch |> skip(1) |> first { Present { value: start } => resolve_expr_types(texpr: start, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } let er = match ch |> skip(2) |> first { Present { value: end_e } => resolve_expr_types(texpr: end_e, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } - ExprResolveResult { expr: make_expr_node(expr_data: ExprSlice, children: [br.expr, sr.expr, er.expr], inferred: texpr.inferred, span: texpr.span), diagnostics: concat(br.diagnostics, sr.diagnostics, er.diagnostics) } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprSlice, children: [br.expr, sr.expr, er.expr], inferred: texpr.inferred, span: texpr.span), diagnostics: concat(br.diagnostics, sr.diagnostics, er.diagnostics) } ExprReturn => let r = match texpr.children |> first { Present { value: inner } => resolve_expr_types(texpr: inner, env: env, module_name: module_name) Absent => ExprResolveResult { expr: texpr, diagnostics: [] } } - ExprResolveResult { expr: make_expr_node(expr_data: ExprReturn, children: [r.expr], inferred: texpr.inferred, span: texpr.span), diagnostics: r.diagnostics } + ExprResolveResult { expr: make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprReturn, children: [r.expr], inferred: texpr.inferred, span: texpr.span), diagnostics: r.diagnostics } NoExprData => ExprResolveResult { expr: texpr, diagnostics: [] } } } @@ -1070,7 +1073,7 @@ fn resolve_item_types(item: Node, env: TypeEnv, module_name: String) -> ItemReso let anno_diags = anno_resolved.diagnostics let transport_resolved = if item.transport == none { - TransportResolveResult { transport: local_transport_node(span: no_span()), diagnostics: [] } + TransportResolveResult { transport: local_transport_node(occurrence_identity: OccurrenceSynthetic, span: no_span()), diagnostics: [] } } else { resolve_transport_binding(transport: item.transport.value, env: env, module_name: module_name) } @@ -1087,7 +1090,7 @@ fn resolve_item_types(item: Node, env: TypeEnv, module_name: String) -> ItemReso let tr = resolve_node(n: authored_type, env: env, module_name: module_name) let type_diags = concat(tr.diagnostics, missing_generic_args_diagnostics(n: authored_type, env: env, module_name: module_name)) ItemResolveResult { - item: Node { name: child.name, span: child.span, ident_span: child.ident_span, children: child.children, connective: child.connective, params: child.params, inferred: child.inferred, return_cardinality: child.return_cardinality, uses: child.uses, body: child.body, transport: child.transport, properties: concat(child.properties, tr.resolved.properties), type_annotation: child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + item: Node { occurrence_identity: child.occurrence_identity, name: child.name, span: child.span, ident_span: child.ident_span, children: child.children, connective: child.connective, params: child.params, inferred: child.inferred, return_cardinality: child.return_cardinality, uses: child.uses, body: child.body, transport: child.transport, properties: concat(child.properties, tr.resolved.properties), type_annotation: child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: type_diags } ) @@ -1098,14 +1101,14 @@ fn resolve_item_types(item: Node, env: TypeEnv, module_name: String) -> ItemReso let tr = resolve_node(n: authored_type, env: env, module_name: module_name) let type_diags = concat(tr.diagnostics, missing_generic_args_diagnostics(n: authored_type, env: env, module_name: module_name)) ItemResolveResult { - item: Node { name: field.name, span: field.span, ident_span: field.ident_span, children: field.children, connective: field.connective, params: field.params, inferred: field.inferred, return_cardinality: field.return_cardinality, uses: field.uses, body: field.body, transport: field.transport, properties: concat(field.properties, tr.resolved.properties), type_annotation: field.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + item: Node { occurrence_identity: field.occurrence_identity, name: field.name, span: field.span, ident_span: field.ident_span, children: field.children, connective: field.connective, params: field.params, inferred: field.inferred, return_cardinality: field.return_cardinality, uses: field.uses, body: field.body, transport: field.transport, properties: concat(field.properties, tr.resolved.properties), type_annotation: field.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: type_diags } ) let resolved_fields = map(field_results, fr => fr.item) let field_diags = flat_map(field_results, fr => fr.diagnostics) ItemResolveResult { - item: Node { name: variant.name, span: variant.span, ident_span: variant.ident_span, children: resolved_fields, connective: variant.connective, params: variant.params, inferred: variant.inferred, return_cardinality: variant.return_cardinality, uses: variant.uses, body: variant.body, transport: variant.transport, properties: variant.properties, type_annotation: variant.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + item: Node { occurrence_identity: variant.occurrence_identity, name: variant.name, span: variant.span, ident_span: variant.ident_span, children: resolved_fields, connective: variant.connective, params: variant.params, inferred: variant.inferred, return_cardinality: variant.return_cardinality, uses: variant.uses, body: variant.body, transport: variant.transport, properties: variant.properties, type_annotation: variant.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: field_diags } ) @@ -1117,7 +1120,7 @@ fn resolve_item_types(item: Node, env: TypeEnv, module_name: String) -> ItemReso ItemResolveResult { item: Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: resolved_children, + occurrence_identity: OccurrenceSynthetic, name: item.name, span: item.span, ident_span: item.ident_span, children: resolved_children, params: resolved_params, inferred: resolved_ret, return_cardinality: item.return_cardinality, uses: resolved_uses, body: resolved_body, diff --git a/src/v1/04_service.dag b/src/v1/04_service.dag index c29e47907fd..d9b31679485 100644 --- a/src/v1/04_service.dag +++ b/src/v1/04_service.dag @@ -1,5 +1,7 @@ module v1.compiler.infer_service +import std.occurrence_identity { OccurrenceSynthetic } + import std.types { SourceSpan } import v1.std.core { @@ -240,8 +242,8 @@ fn check_service_method_call_node(receiver_type: Node, method: String, service_r } else { Present { value: ServiceMethodResult { result_type: Node { - name: "", span: no_span(), ident_span: none, - children: map(op.outputs, f => Node { name: f.name, span: f.span, ident_span: f.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: param_node_type_expr(n: f) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }), + occurrence_identity: OccurrenceSynthetic, name: "", span: no_span(), ident_span: none, + children: map(op.outputs, f => Node { occurrence_identity: OccurrenceSynthetic, name: f.name, span: f.span, ident_span: f.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: param_node_type_expr(n: f) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }), connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diff --git a/src/v1/04_types.dag b/src/v1/04_types.dag index 7179eb5a0fe..db9e7d9cb3b 100644 --- a/src/v1/04_types.dag +++ b/src/v1/04_types.dag @@ -1,5 +1,7 @@ module v1.compiler.infer_types +import std.occurrence_identity { OccurrenceSynthetic } + import v1.compiler.infer_env { TypeBinding } import std.types { SourceSpan, is_container_type, container_expected_arity, container_param_name, container_template_algebra, container_template_alias_algebra, container_template_alias_rows } @@ -51,7 +53,7 @@ fn is_type_variable(inferred: InferredNode) -> Bool { } fn type_variable_node(id: String) -> Node { - Node { name: "", span: no_span(), ident_span: none, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: id } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: OccurrenceSynthetic, name: "", span: no_span(), ident_span: none, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: id } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn resolved_type(n: Node) -> Node { @@ -153,7 +155,7 @@ fn kernel_profile_lookup(name: String) -> AlgebraProfile? { fn reground_alias_carrier_identity(n: Node, source_indices: Map) -> Node { if n.name != "" && n.name != authored_name_at(source_indices: source_indices, node: n) && is_declared_container_alias_spelling(name: n.name) { Node { - name: n.name, span: n.span, ident_span: Present { value: kernel_span(name: n.name) }, + occurrence_identity: OccurrenceSynthetic, name: n.name, span: n.span, ident_span: Present { value: kernel_span(name: n.name) }, children: n.children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, @@ -168,7 +170,7 @@ fn reground_alias_carrier_identity(n: Node, source_indices: Map) -> String { if n.name != "" { canonical_template_name(n: Node { - name: n.name, span: n.span, ident_span: Present { value: kernel_span(name: n.name) }, + occurrence_identity: OccurrenceSynthetic, name: n.name, span: n.span, ident_span: Present { value: kernel_span(name: n.name) }, children: n.children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, @@ -262,9 +264,9 @@ fn bare_map_node() -> Node? { match container_param_name(kind_name: "Map", index: 1) { Present { value: val_id } => Present { - value: Node { name: "Map", span: no_span(), ident_span: Present { value: no_span() }, children: [ - Node { name: key_id, span: no_span(), ident_span: Present { value: no_span() }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: type_variable_node(id: key_id) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, - Node { name: val_id, span: no_span(), ident_span: Present { value: no_span() }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: type_variable_node(id: val_id) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + value: Node { occurrence_identity: OccurrenceSynthetic, name: "Map", span: no_span(), ident_span: Present { value: no_span() }, children: [ + Node { occurrence_identity: OccurrenceSynthetic, name: key_id, span: no_span(), ident_span: Present { value: no_span() }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: type_variable_node(id: key_id) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + Node { occurrence_identity: OccurrenceSynthetic, name: val_id, span: no_span(), ident_span: Present { value: no_span() }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: type_variable_node(id: val_id) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } ], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } Absent => none @@ -277,8 +279,8 @@ fn bare_set_node() -> Node? { match container_param_name(kind_name: "Set", index: 0) { Present { value: elem_id } => Present { - value: Node { name: "Set", span: no_span(), ident_span: Present { value: no_span() }, children: [ - Node { name: elem_id, span: no_span(), ident_span: Present { value: no_span() }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: type_variable_node(id: elem_id) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + value: Node { occurrence_identity: OccurrenceSynthetic, name: "Set", span: no_span(), ident_span: Present { value: no_span() }, children: [ + Node { occurrence_identity: OccurrenceSynthetic, name: elem_id, span: no_span(), ident_span: Present { value: no_span() }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: type_variable_node(id: elem_id) } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } ], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } Absent => none @@ -296,7 +298,7 @@ fn kernel_container_profile_miss_diagnostic(kind_name: String) -> ErrorNode { fn missing_kernel_container_profile_type(kind_name: String) -> Node { let msg = concat("missing kernel container profile: ", kind_name) Node { - name: "", + occurrence_identity: OccurrenceSynthetic, name: "", span: no_span(), ident_span: none, children: [], @@ -320,7 +322,7 @@ data kernel_record_type_note: String = "A builtin whose return type is registere fn make_kernel_record_field(field_name: String, field_type: Node) -> Node { Node { - name: field_name, span: kernel_span(name: field_name), + occurrence_identity: OccurrenceSynthetic, name: field_name, span: kernel_span(name: field_name), ident_span: Present { value: kernel_span(name: field_name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: field_type } }, @@ -332,7 +334,7 @@ fn make_kernel_record_field(field_name: String, field_type: Node) -> Node { fn make_kernel_record_type(type_name: String, fields: List) -> Node { Node { - name: type_name, span: kernel_span(name: type_name), + occurrence_identity: OccurrenceSynthetic, name: type_name, span: kernel_span(name: type_name), ident_span: Present { value: kernel_span(name: type_name) }, children: fields, connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, @@ -345,8 +347,8 @@ fn make_container_type(kind_name: String, element: Node) -> KernelTypeBuild { match container_param_name(kind_name: kind_name, index: 0) { Present { value: param_name } => KernelTypeBuild { - ty: Node { name: kind_name, span: kernel_span(name: kind_name), ident_span: Present { value: kernel_span(name: kind_name) }, children: [ - Node { name: param_name, span: kernel_span(name: param_name), ident_span: Present { value: kernel_span(name: param_name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: element } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + ty: Node { occurrence_identity: OccurrenceSynthetic, name: kind_name, span: kernel_span(name: kind_name), ident_span: Present { value: kernel_span(name: kind_name) }, children: [ + Node { occurrence_identity: OccurrenceSynthetic, name: param_name, span: kernel_span(name: param_name), ident_span: Present { value: kernel_span(name: param_name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: element } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } ], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: [] } @@ -364,9 +366,9 @@ fn make_map_type(key: Node, value: Node) -> KernelTypeBuild { match container_param_name(kind_name: "Map", index: 1) { Present { value: val_name } => KernelTypeBuild { - ty: Node { name: "Map", span: kernel_span(name: "Map"), ident_span: Present { value: kernel_span(name: "Map") }, children: [ - Node { name: key_name, span: kernel_span(name: key_name), ident_span: Present { value: kernel_span(name: key_name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: key } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, - Node { name: val_name, span: kernel_span(name: val_name), ident_span: Present { value: kernel_span(name: val_name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: value } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + ty: Node { occurrence_identity: OccurrenceSynthetic, name: "Map", span: kernel_span(name: "Map"), ident_span: Present { value: kernel_span(name: "Map") }, children: [ + Node { occurrence_identity: OccurrenceSynthetic, name: key_name, span: kernel_span(name: key_name), ident_span: Present { value: kernel_span(name: key_name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: key } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + Node { occurrence_identity: OccurrenceSynthetic, name: val_name, span: kernel_span(name: val_name), ident_span: Present { value: kernel_span(name: val_name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: value } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } ], connective: NoConnective, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: [] } @@ -385,28 +387,28 @@ fn make_map_type(key: Node, value: Node) -> KernelTypeBuild { } fn make_callable_type(func_params: List, ret: Node) -> Node { - Node { name: "Callable", span: kernel_span(name: "Callable"), ident_span: Present { value: kernel_span(name: "Callable") }, children: [], connective: Arrow, params: func_params, inferred: Present { value: Resolved { node: ret } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: OccurrenceSynthetic, name: "Callable", span: kernel_span(name: "Callable"), ident_span: Present { value: kernel_span(name: "Callable") }, children: [], connective: Arrow, params: func_params, inferred: Present { value: Resolved { node: ret } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn make_tuple_type(first: Node, second: Node) -> Node { - Node { name: "", span: no_span(), ident_span: none, children: [ - Node { name: "first", span: kernel_span(name: "first"), ident_span: Present { value: kernel_span(name: "first") }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: first } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, - Node { name: "second", span: kernel_span(name: "second"), ident_span: Present { value: kernel_span(name: "second") }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: second } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: OccurrenceSynthetic, name: "", span: no_span(), ident_span: none, children: [ + Node { occurrence_identity: OccurrenceSynthetic, name: "first", span: kernel_span(name: "first"), ident_span: Present { value: kernel_span(name: "first") }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: first } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + Node { occurrence_identity: OccurrenceSynthetic, name: "second", span: kernel_span(name: "second"), ident_span: Present { value: kernel_span(name: "second") }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: second } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } ], connective: Conj, params: [], inferred: none, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn algebra_value_field(name: String, type_node: Node) -> Node { - Node { name: name, span: kernel_span(name: name), ident_span: Present { value: kernel_span(name: name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: type_node } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: OccurrenceSynthetic, name: name, span: kernel_span(name: name), ident_span: Present { value: kernel_span(name: name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: type_node } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn algebra_method_field(name: String, param_types: List, return_type: Node) -> Node { - let params = param_types |> map(t => make_param_node(name: "_", type_expr: t, default_value: none, span: no_span(), name_span: no_span())) + let params = param_types |> map(t => make_param_node(occurrence_identity: OccurrenceSynthetic, name: "_", type_expr: t, default_value: none, span: no_span(), name_span: no_span())) let callable = make_callable_type(func_params: params, ret: return_type) - Node { name: name, span: kernel_span(name: name), ident_span: Present { value: kernel_span(name: name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: callable } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: OccurrenceSynthetic, name: name, span: kernel_span(name: name), ident_span: Present { value: kernel_span(name: name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: callable } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn enrich_base_with_fields(name: String, base: Node, fields: List) -> Node { - Node { name: name, span: base.span, ident_span: base.ident_span, children: fields, connective: Conj, params: base.params, inferred: base.inferred, return_cardinality: base.return_cardinality, uses: base.uses, body: base.body, transport: base.transport, properties: base.properties, type_annotation: base.type_annotation, is_self_recursive: base.is_self_recursive, has_non_tail_self_call: base.has_non_tail_self_call, match_pattern: base.match_pattern, expr_data: base.expr_data } + Node { occurrence_identity: base.occurrence_identity, name: name, span: base.span, ident_span: base.ident_span, children: fields, connective: Conj, params: base.params, inferred: base.inferred, return_cardinality: base.return_cardinality, uses: base.uses, body: base.body, transport: base.transport, properties: base.properties, type_annotation: base.type_annotation, is_self_recursive: base.is_self_recursive, has_non_tail_self_call: base.has_non_tail_self_call, match_pattern: base.match_pattern, expr_data: base.expr_data } } fn placeholder_type_node(name: String) -> Node { @@ -414,7 +416,7 @@ fn placeholder_type_node(name: String) -> Node { } fn nominal_type_ref(name: String) -> Node { - leaf_node_with_span(name: name, span: kernel_span(name: name)) + leaf_node_with_span(occurrence_identity: OccurrenceSynthetic, name: name, span: kernel_span(name: name)) } fn algebra_child_or_placeholder(base: Node, child_index: Int, placeholder: String) -> Node { @@ -457,7 +459,7 @@ fn instantiate_algebra_type(template: AlgebraTypeTemplate, base: Node, source_in let param_nodes = param_bs |> map(b => b.ty) let rb = instantiate_algebra_type(template: r, base: base, source_indices: source_indices) KernelTypeBuild { - ty: make_callable_type(func_params: param_nodes |> map(pn => make_param_node(name: "_", type_expr: pn, default_value: none, span: no_span(), name_span: no_span())), ret: rb.ty), + ty: make_callable_type(func_params: param_nodes |> map(pn => make_param_node(occurrence_identity: OccurrenceSynthetic, name: "_", type_expr: pn, default_value: none, span: no_span(), name_span: no_span())), ret: rb.ty), diagnostics: concat(param_diags, rb.diagnostics) } } @@ -676,7 +678,7 @@ fn apply_type_substitution(template: AlgebraTypeTemplate, subst: Map flat_map(b => b.diagnostics) let rb = apply_type_substitution(template: r, subst: subst, receiver: receiver, source_indices: source_indices) KernelTypeBuild { - ty: make_callable_type(func_params: param_nodes |> map(pn => make_param_node(name: "_", type_expr: pn, default_value: none, span: no_span(), name_span: no_span())), ret: rb.ty), + ty: make_callable_type(func_params: param_nodes |> map(pn => make_param_node(occurrence_identity: OccurrenceSynthetic, name: "_", type_expr: pn, default_value: none, span: no_span(), name_span: no_span())), ret: rb.ty), diagnostics: concat(param_diags, rb.diagnostics) } } diff --git a/src/v1/05_emit.dag b/src/v1/05_emit.dag index 74743d64093..a12ff19557c 100644 --- a/src/v1/05_emit.dag +++ b/src/v1/05_emit.dag @@ -1,5 +1,7 @@ module v1.compiler.emit +import std.occurrence_identity { OccurrenceSynthetic } + import std.syntax { LiteralValue, BinOp, AlgebraFieldKind } import v1.std.core { Node, ErrorNode, make_error_node, TransportEmissionNotModeled, InferredNode, Resolved, CompilerError, TypeVariable, is_compiler_error, @@ -856,7 +858,7 @@ fn has_service_items(typed: ResolvedGraph) -> Bool { } fn service_fallback_transport(item: Node) -> Node { - if item.transport == none { local_transport_node(span: item.span) } else { item.transport.value } + if item.transport == none { local_transport_node(occurrence_identity: OccurrenceSynthetic, span: item.span) } else { item.transport.value } } fn effective_operation_transport(op_node: Node, fallback: Node) -> Node { diff --git a/src/v1/05_emit_rust.dag b/src/v1/05_emit_rust.dag index 516ff25397f..6d3b136b292 100644 --- a/src/v1/05_emit_rust.dag +++ b/src/v1/05_emit_rust.dag @@ -1,5 +1,7 @@ module v1.compiler.emit_rust +import std.occurrence_identity { OccurrenceSynthetic } + import extdeps.languages.rust.capabilities { phantom_opaque_carrier_derive_traits } import std.algebra { trim } @@ -1417,7 +1419,7 @@ fn render_rust_alias_rhs_type(n: Node, generic_param_names: List, shared } fn type_variable_node(id: String) -> Node { - Node { name: "", span: no_span(), ident_span: none, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: id } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + Node { occurrence_identity: OccurrenceSynthetic, name: "", span: no_span(), ident_span: none, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: id } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } } fn is_type_variable(inferred: InferredNode) -> Bool { @@ -8816,7 +8818,7 @@ fn fill_default_args(ordered: List, callee: ItemInfo?, registry: Map map(p => - make_arg_node(name: Present { value: param_node_name_at(n: p, source_indices: scope.type_env.source_indices) }, value: param_node_default_value(n: p).value, span: p.span, name_span: p.span) + make_arg_node(occurrence_identity: OccurrenceSynthetic, name: Present { value: param_node_name_at(n: p, source_indices: scope.type_env.source_indices) }, value: param_node_default_value(n: p).value, span: p.span, name_span: p.span) ) concat(ordered, default_args) Absent => ordered @@ -8838,7 +8840,7 @@ fn fill_op_default_args(ordered: List, op_params: List, registry: Ma Present { value: arg } => [arg] Absent => if param_node_default_value(n: p) != none { - [make_arg_node(name: Present { value: pname }, value: param_node_default_value(n: p).value, span: p.span, name_span: p.span)] + [make_arg_node(occurrence_identity: OccurrenceSynthetic, name: Present { value: pname }, value: param_node_default_value(n: p).value, span: p.span, name_span: p.span)] } else { [] } } ) diff --git a/src/v1/compile.dag b/src/v1/compile.dag index c38dc83e3af..8d88b49fcae 100644 --- a/src/v1/compile.dag +++ b/src/v1/compile.dag @@ -35,6 +35,7 @@ import v1.compiler.parse { ParseResult, } import std.occurrence_identity { + OccurrenceSynthetic, OccurrenceIdAllocator, OccurrenceIndex, OccurrenceTransport, @@ -427,7 +428,7 @@ fn serialize_span(span: SourceSpan) -> String { concat("{\"start\": ", to_string(value: span.start), ", \"end\": ", to_string(value: span.end), "}") } -fn serialize_import_node(imp: Node, source_indices: Map) -> String { +fn serialize_import_node(occurrence_identity: OccurrenceSynthetic, imp: Node, source_indices: Map) -> String { let names_json = if import_is_all(n: imp) { "{\"kind\": \"ImportAll\"}" } else { @@ -819,7 +820,7 @@ fn serialize_module_imports_json(node: Node, source_indices: Map count == 0 { "[]" } else if imports |> all(imp => imp.params |> count == 0) { - json_list(items: imports |> map(imp => serialize_import_node(imp: imp, source_indices: source_indices))) + json_list(items: imports |> map(imp => serialize_import_node(occurrence_identity: OccurrenceSynthetic, imp: imp, source_indices: source_indices))) } else { "[]" } diff --git a/src/v1/tests/claim/transport_roster_closure_witness_test.dag b/src/v1/tests/claim/transport_roster_closure_witness_test.dag index a095efe5303..15bb913322c 100644 --- a/src/v1/tests/claim/transport_roster_closure_witness_test.dag +++ b/src/v1/tests/claim/transport_roster_closure_witness_test.dag @@ -1,5 +1,7 @@ module v1.tests.claim.transport_roster_closure_witness_test +import std.occurrence_identity { OccurrenceSynthetic } + import std.syntax { LitStr } import v1.std.core { Node, SourceSpan, NewlineIndex, ExprLiteral, no_span, make_expr_node, make_field_init_node, @@ -11,7 +13,7 @@ import v1.std.core { data transport_roster_closure_witness_note: String = "EXECUTING-ON-DEMAND evidence that the transport roster is closed, that its precedence has ONE authority, and that a transport matching no member is refused rather than absorbed.\n\nWHERE THIS RUNS, STATED FIRST AND WITHOUT FLATTERY, BECAUSE THE FILE BESIDE THIS ONE GETS IT WRONG. THIS WITNESS IS NOT DISCOVERED BY CI. gunbc.ci_layer_roots witness_discovery_scan_dirs is [dag/test/claim, src/v2/test/claim/manual, src/v2/test/claim/emit] -- src/v1/tests/claim is not in it -- and the required run invokes claim_executor with --source-root dag --source-root src/v2, which could not resolve this file's `import v1.std.core` even if it were discovered. Zero witnesses under dag/test/claim import v1.* today, so there is currently NO executing home for evidence over v1 compiler internals. The rows below were run directly during authoring and PASS; direct execution is evidence the assertions HOLD, never evidence that CI runs them, and conflating those two is the error this file refuses to repeat. NEXT-RUNG TRIGGER: a discovery scope that admits src/v1 witnesses under a source-root envelope that includes src/v1, at which point this row deletes and the enrollment is stated instead.\n\nAND THE NEIGHBOUR IS NOW FALSE, WHICH IS WHY THE PARAGRAPH ABOVE IS WORDED THAT WAY. src/v1/tests/claim/checkpoint_identity_keying_witness_test.dag states at length that it executes via `gunbc.ci_layer_roots v1_claim_scoped_witness_entries`, consumed by `v1_claim_scoped_witness_batch`. That roster does not exist: v1_claim_scoped_witness_entries appears nowhere in dag/gunbc/ci_layer_roots.dag, and the batch died with the 2026-08-15 floor cut. So a file whose entire purpose was to repair a rung-inflation defect -- assertions that were authored, plausible, type-correct and never executed -- now carries the same defect in its own execution claim. Not repaired here because it is not this change's to repair; recorded so the next reader of that file does not inherit the claim.\n\nWHAT CHANGED AND WHY IT NEEDED EVIDENCE. is_local_transport was DEFINED as `not rest and not shell and not file`, so `local` absorbed every transport the other three predicates declined. The consequence was not local's: it made emit_unified_transport_dispatch's final arm, `unrecognized transport kind`, unreachable BY CONSTRUCTION -- no input of any shape could arrive there, because local claimed them all first. A check whose red is unreachable is a decoration, permanently green and cited as coverage (DESIGN, the reachability-read-as-occupancy class), and it is worse than absent because a reader counts it. classify_transport replaces four hand-copies of the precedence with one authority and makes local a POSITIVE test over the node local_transport_node actually builds.\n\nWHAT THIS PROVES AND WHAT IT DOES NOT. It proves the arm is REACHABLE: unrecognized_transport_matches_no_roster_member constructs a transport node carrying a property under no recognized key and shows classify_transport answers Absent for it. It does NOT prove the arm FIRES on any source spelling, and no row here claims that. A REACHABLE WALL AND A WALL THAT FIRES ARE DIFFERENT PROPERTIES. Both parse_file_fields and parse_rest_fields substitute an empty string literal when their key is omitted rather than producing a keyless transport node, so every transport the PARSER builds still lands in a roster member and the arm's occupancy is zero. That is a parser fact and the open next step; it is named here so the reachability claim is not read as the stronger one. It is also why no source-level witness could carry these rows: the state under test is unauthorable from .dag source, which is the same fact as the arm being unoccupied.\n\nTHE DISCRIMINATING ROW IS unrecognized_transport_is_not_local. Under the old negative definition it answered TRUE -- the keyless node WAS local, by exclusion -- and the emitted realization for it was a direct function call fabricated by omission. It answers false only because the predicate is positive. Restoring the negative definition turns this row red and nothing else in the corpus would notice.\n\nrest_wins_over_a_file_key_on_the_same_transport is the precedence row. A transport carrying both base_url and base_path is claimed by the FIRST arm, and that ordering used to be restated in four places that agreed by coincidence. It is asserted here so the single authority is pinned to an answer rather than merely being singular." fn str_expr(s: String) -> Node { - make_expr_node(expr_data: ExprLiteral { value: LitStr { value: s } }, children: [], inferred: none, span: no_span()) + make_expr_node(occurrence_identity: OccurrenceSynthetic, expr_data: ExprLiteral { value: LitStr { value: s } }, children: [], inferred: none, span: no_span()) } // Compared as a name rather than by structural equality on the coproduct, so the rows assert the @@ -31,22 +33,22 @@ fn kind_name(t: Node) -> String { // --------------------------------------------------------------------------- test fn rest_transport_classifies_as_rest() -> Bool { - kind_name(t: rest_transport_node(base_url: str_expr(s: "https://example.invalid"), auth_props: [], headers: [], method: none, path: none, query: none, request_body: none, response_format: none, span: no_span())) + kind_name(t: rest_transport_node(occurrence_identity: OccurrenceSynthetic, base_url: str_expr(s: "https://example.invalid"), auth_props: [], headers: [], method: none, path: none, query: none, request_body: none, response_format: none, span: no_span())) == "rest" } test fn shell_transport_classifies_as_shell() -> Bool { - kind_name(t: shell_transport_node(argv: [str_expr(s: "ls")], env: [], stdin: none, span: no_span())) + kind_name(t: shell_transport_node(occurrence_identity: OccurrenceSynthetic, argv: [str_expr(s: "ls")], env: [], stdin: none, span: no_span())) == "shell" } test fn file_transport_classifies_as_file() -> Bool { - kind_name(t: file_transport_node(base_path: str_expr(s: "/tmp/x"), verb: none, span: no_span())) + kind_name(t: file_transport_node(occurrence_identity: OccurrenceSynthetic, base_path: str_expr(s: "/tmp/x"), verb: none, span: no_span())) == "file" } test fn bare_transport_classifies_as_local() -> Bool { - kind_name(t: local_transport_node(span: no_span())) == "local" + kind_name(t: local_transport_node(occurrence_identity: OccurrenceSynthetic, span: no_span())) == "local" } // --------------------------------------------------------------------------- @@ -54,8 +56,8 @@ test fn bare_transport_classifies_as_local() -> Bool { // --------------------------------------------------------------------------- fn keyless_transport() -> Node { - make_transport_node( - properties: [make_field_init_node(name: "unrecognized_key", value: str_expr(s: "v"), span: no_span(), name_span: no_span())], + make_transport_node(occurrence_identity: OccurrenceSynthetic, + properties: [make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: "unrecognized_key", value: str_expr(s: "v"), span: no_span(), name_span: no_span())], children: [], body: none, span: no_span()) } @@ -71,7 +73,7 @@ test fn unrecognized_transport_is_not_local() -> Bool { // Positive control. Without it every refusal row above is satisfiable by a // classify_transport that answers none unconditionally. test fn the_bare_node_is_still_local_positive_control() -> Bool { - is_local_transport(t: local_transport_node(span: no_span()), source_indices: empty_map()) == true + is_local_transport(t: local_transport_node(occurrence_identity: OccurrenceSynthetic, span: no_span()), source_indices: empty_map()) == true } // --------------------------------------------------------------------------- @@ -79,10 +81,10 @@ test fn the_bare_node_is_still_local_positive_control() -> Bool { // --------------------------------------------------------------------------- test fn rest_wins_over_a_file_key_on_the_same_transport() -> Bool { - kind_name(t: make_transport_node( + kind_name(t: make_transport_node(occurrence_identity: OccurrenceSynthetic, properties: [ - make_field_init_node(name: "base_url", value: str_expr(s: "https://example.invalid"), span: no_span(), name_span: no_span()), - make_field_init_node(name: "base_path", value: str_expr(s: "/tmp/x"), span: no_span(), name_span: no_span()) + make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: "base_url", value: str_expr(s: "https://example.invalid"), span: no_span(), name_span: no_span()), + make_field_init_node(occurrence_identity: OccurrenceSynthetic, name: "base_path", value: str_expr(s: "/tmp/x"), span: no_span(), name_span: no_span()) ], children: [], body: none, span: no_span())) == "rest" } From 6b9c3192073af57c4d43ccbb053aa72ec1aa148b Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 02:39:17 +0000 Subject: [PATCH 10/30] Regenerate identity-bearing v1 seed --- src/v1/02_parse.dag | 26 +- src/v1/04_infer.dag | 10 +- src/v1/04_resolve.dag | 1 - src/v1/compile.dag | 4 +- .../bin/dag_collect_fingerprint_witness.rs | 3 + .../stage0/src/bin/infer_semantics_witness.rs | 55 +- src/v1/stage0/src/cli_run.rs | 35 +- src/v1/stage0/src/compiler_tests.rs | 3 + src/v1/stage0/src/coproduct_reflection.rs | 2 + src/v1/stage0/src/v1_compiler_compile.rs | 3 +- src/v1/stage0/src/v1_compiler_emit.rs | 7 +- src/v1/stage0/src/v1_compiler_emit_rust.rs | 5 + src/v1/stage0/src/v1_compiler_infer.rs | 400 ++- src/v1/stage0/src/v1_compiler_infer_env.rs | 8 + src/v1/stage0/src/v1_compiler_infer_items.rs | 17 +- src/v1/stage0/src/v1_compiler_infer_method.rs | 3 + .../stage0/src/v1_compiler_infer_patterns.rs | 9 + .../stage0/src/v1_compiler_infer_resolve.rs | 95 +- .../stage0/src/v1_compiler_infer_service.rs | 8 + src/v1/stage0/src/v1_compiler_infer_types.rs | 38 +- src/v1/stage0/src/v1_compiler_parse.rs | 2816 ++++++++++------- .../src/v1_compiler_trait_derive_emit.rs | 1 + src/v1/stage0/src/v1_interpreter.rs | 53 +- src/v1/stage0/src/v1_std_core.rs | 162 +- ...m_transport_roster_closure_witness_test.rs | 21 +- .../tests/namespace_occurrence_serde.rs | 148 +- 26 files changed, 2588 insertions(+), 1345 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index 73863713eef..2a1ed4ccf15 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -484,7 +484,7 @@ type FromKeyResult { properties: List, tokens: TokenStream, ctx: ParseCont type PostfixResult { expr: Node, changed: Bool, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type PipeCalleeResult { spine: Node?, method: String, method_span: SourceSpan, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } -type ParserParam { name: String, span: SourceSpan } +type ParserParam { occurrence_identity: NodeOccurrenceIdentity, name: String, span: SourceSpan } type LambdaCheckResult { is_lambda: Bool, params: List, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type IdentCollectResult { success: Bool, params: List, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type RangeArgsResult { min_val: Int?, max_val: Int?, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } @@ -2712,8 +2712,8 @@ fn parse_optional_from_key(tokens: TokenStream, ctx: ParseContext) -> FromKeyRes let key = tok2.value.text let value_mint = mint_parsed_node_identity(ctx: ctx) let property_mint = mint_parsed_node_identity(ctx: value_mint.ctx) - let value = make_named_expr_node(occurrence_identity: value_mint.identity, name: key, expr_data: NoExprData, children: [], inferred: none, span: token_span(tok: tok2.value), name_span: token_span(tok: tok2.value)) - let property = make_field_init_node(occurrence_identity: property_mint.identity, name: "from_key", value: value, span: token_span(tok: tok.value), name_span: token_span(tok: tok.value)) + let value = make_named_expr_node(occurrence_identity: value_mint.identity, name: key, expr_data: NoExprData, children: [], inferred: none, span: token_span(tok: tok2), name_span: token_span(tok: tok2)) + let property = make_field_init_node(occurrence_identity: property_mint.identity, name: "from_key", value: value, span: token_span(tok: tok), name_span: token_span(tok: tok)) FromKeyResult { properties: [property], tokens: token_stream_advance(stream: tokens, n: 2), ctx: property_mint.ctx, err: none } } _ => @@ -4719,7 +4719,8 @@ fn parse_ident_expr(tokens: TokenStream, ctx: ParseContext, name: String) -> Exp if tok_is_fat_arrow(tok: token_stream_first(stream: tokens)) { let r = parse_lambda_body(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx) if has_err(err: r.err) { return r } - parsed_expr_result(tokens: r.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLambda, children: concat([r.expr], [parsed_name_leaf(name: name, span: span)]), inferred: none, span: span)) + let param_mint = mint_parsed_node_identity(ctx: r.ctx) + parsed_expr_result(tokens: r.tokens, ctx: param_mint.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLambda, children: concat([r.expr], [parsed_name_leaf(occurrence_identity: param_mint.identity, name: name, span: span)]), inferred: none, span: span)) } else { if is_uppercase_start(name: name) && tok_is_lbrace(tok: token_stream_first(stream: tokens)) { parse_record_literal(tokens: tokens, ctx: ctx, name: name, span: span) @@ -5658,7 +5659,7 @@ fn parse_paren_expr(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if lambda_r.is_lambda { let r = parse_lambda_body(tokens: lambda_r.tokens, ctx: lambda_r.ctx) if has_err(err: r.err) { return ExprResult { expr: r.expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } - parsed_expr_result(tokens: r.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLambda, children: concat([r.expr], lambda_r.params |> map(p => parsed_name_leaf(name: p.name, span: p.span))), inferred: none, span: span)) + parsed_expr_result(tokens: r.tokens, ctx: r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLambda, children: concat([r.expr], lambda_r.params |> map(p => parsed_name_leaf(occurrence_identity: p.occurrence_identity, name: p.name, span: p.span))), inferred: none, span: span)) } else { let r = parse_expr(tokens: lambda_r.tokens, ctx: lambda_r.ctx) if has_err(err: r.err) { return ExprResult { expr: r.expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } @@ -5683,7 +5684,7 @@ fn parse_fn_lambda(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let tokens = skip_newlines(tokens: r3.tokens) let body_r = parse_brace_expr(tokens: tokens, ctx: params_r.ctx) if has_err(err: body_r.err) { return body_r } - parsed_expr_result(tokens: body_r.tokens, ctx: body_r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLambda, children: concat([body_r.expr], params_r.params |> map(p => parsed_name_leaf(name: p.name, span: p.span))), inferred: none, span: span)) + parsed_expr_result(tokens: body_r.tokens, ctx: body_r.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprLambda, children: concat([body_r.expr], params_r.params |> map(p => parsed_name_leaf(occurrence_identity: p.occurrence_identity, name: p.name, span: p.span))), inferred: none, span: span)) } fn collect_fn_lambda_params(tokens: TokenStream, ctx: ParseContext, acc: List) -> IdentCollectResult { @@ -5697,9 +5698,11 @@ fn collect_fn_lambda_params(tokens: TokenStream, ctx: ParseContext, acc: List LambdaCheckResul fn collect_lambda_idents(tokens: TokenStream, ctx: ParseContext, acc: List) -> IdentCollectResult { if tok_is_ident(tok: token_stream_first(stream: tokens)) { let tok = token_stream_first(stream: tokens) - let param = ParserParam { name: tok.value.text, span: tok.value.span } + let minted = mint_parsed_node_identity(ctx: ctx) + let param = ParserParam { occurrence_identity: minted.identity, name: tok.value.text, span: tok.value.span } let new_acc = list_push(acc, param) match eat(tokens: token_stream_advance(stream: tokens, n: 1), expected: ExpectComma) { EatConsumed { token: _, tokens: __ec } => - collect_lambda_idents(tokens: __ec, ctx: ctx, acc: new_acc) + collect_lambda_idents(tokens: __ec, ctx: minted.ctx, acc: new_acc) EatUnchanged { tokens: __eu } => - IdentCollectResult { success: true, params: new_acc, tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx, err: none } + IdentCollectResult { success: true, params: new_acc, tokens: token_stream_advance(stream: tokens, n: 1), ctx: minted.ctx, err: none } } } else { IdentCollectResult { success: false, params: acc, tokens: tokens, ctx: ctx, err: none } diff --git a/src/v1/04_infer.dag b/src/v1/04_infer.dag index 56d8c004850..26cdced0244 100644 --- a/src/v1/04_infer.dag +++ b/src/v1/04_infer.dag @@ -4177,7 +4177,7 @@ fn empty_override_map() -> Map { fn infer_arg_with_element_type(arg: Node, element_type: Node, scope: InferScope) -> ArgInferResult { let ar = infer_expr(texpr: arg_value(n: arg), scope: scope, expected: Present { value: element_type }) - ArgInferResult { typed_arg: make_arg_node(occurrence_identity: a.occurrence_identity, name: arg_name_at(n: arg, source_indices: scope.type_env.source_indices), value: ar.typed, span: arg.span, name_span: arg.span), diagnostics: ar.diagnostics } + ArgInferResult { typed_arg: make_arg_node(occurrence_identity: arg.occurrence_identity, name: arg_name_at(n: arg, source_indices: scope.type_env.source_indices), value: ar.typed, span: arg.span, name_span: arg.span), diagnostics: ar.diagnostics } } fn binding_is_namespace_root_nominal(binding: TypeBinding) -> Bool { @@ -4877,7 +4877,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu diagnostics: arg_diags } } else { - match infer_variant_constructor_call(func_name: func_name, call_args: call_args, span: span, name_span: node_name_span(n: texpr), scope: scope) { + match infer_variant_constructor_call(occurrence_identity: texpr.occurrence_identity, func_name: func_name, call_args: call_args, span: span, name_span: node_name_span(n: texpr), scope: scope) { Present { value: ctor_result } => ctor_result Absent => let type_match = lookup_type_by_name(env: scope.type_env, name: func_name) @@ -5687,7 +5687,7 @@ fn infer_expr_body(texpr: Node, scope: InferScope, expected: Node?) -> InferResu } } -fn infer_variant_constructor_call(func_name: String, call_args: List, span: SourceSpan, name_span: SourceSpan, scope: InferScope) -> InferResult? { +fn infer_variant_constructor_call(occurrence_identity: NodeOccurrenceIdentity, func_name: String, call_args: List, span: SourceSpan, name_span: SourceSpan, scope: InferScope) -> InferResult? { match lookup_variant_parent_enum(scope: scope, name: func_name) { Absent => none Present { value: parent_enum } => @@ -5719,7 +5719,7 @@ fn infer_variant_constructor_call(func_name: String, call_args: List, span name_span: kernel_span(name: "0") ) Present { value: infer_record_lit( - occurrence_identity: texpr.occurrence_identity, + occurrence_identity: occurrence_identity, type_name: Present { value: func_name }, field_inits: [payload_init], span: span, @@ -6344,7 +6344,7 @@ fn infer_record_lit_structural(occurrence_identity: NodeOccurrenceIdentity, type body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } let typed_field_nodes = typed_fields - let texpr = make_expr_node(occurrence_identity: texpr.occurrence_identity, expr_data: ExprRecordLit { parent_enum: none }, children: typed_field_nodes, inferred: Present { value: Resolved { node: anon_node } }, span: span) + let texpr = make_expr_node(occurrence_identity: occurrence_identity, expr_data: ExprRecordLit { parent_enum: none }, children: typed_field_nodes, inferred: Present { value: Resolved { node: anon_node } }, span: span) InferResult { typed: texpr, diagnostics: concat(fi_diags, alias_struct_diags) diff --git a/src/v1/04_resolve.dag b/src/v1/04_resolve.dag index aa7f9910ea4..90802240726 100644 --- a/src/v1/04_resolve.dag +++ b/src/v1/04_resolve.dag @@ -677,7 +677,6 @@ fn resolve_field(field: Node, env: TypeEnv, module_name: String) -> FieldResolve } FieldResolveResult { field: make_field_node(occurrence_identity: field.occurrence_identity, - occurrence_identity: field.occurrence_identity, name: field_node_name_at(n: field, source_indices: env.source_indices), type_expr: type_resolved, cardinality: field_node_cardinality(n: field), diff --git a/src/v1/compile.dag b/src/v1/compile.dag index 8d88b49fcae..ada4b38cf4e 100644 --- a/src/v1/compile.dag +++ b/src/v1/compile.dag @@ -428,7 +428,7 @@ fn serialize_span(span: SourceSpan) -> String { concat("{\"start\": ", to_string(value: span.start), ", \"end\": ", to_string(value: span.end), "}") } -fn serialize_import_node(occurrence_identity: OccurrenceSynthetic, imp: Node, source_indices: Map) -> String { +fn serialize_import_node(imp: Node, source_indices: Map) -> String { let names_json = if import_is_all(n: imp) { "{\"kind\": \"ImportAll\"}" } else { @@ -820,7 +820,7 @@ fn serialize_module_imports_json(node: Node, source_indices: Map count == 0 { "[]" } else if imports |> all(imp => imp.params |> count == 0) { - json_list(items: imports |> map(imp => serialize_import_node(occurrence_identity: OccurrenceSynthetic, imp: imp, source_indices: source_indices))) + json_list(items: imports |> map(imp => serialize_import_node(imp: imp, source_indices: source_indices))) } else { "[]" } diff --git a/src/v1/stage0/src/bin/dag_collect_fingerprint_witness.rs b/src/v1/stage0/src/bin/dag_collect_fingerprint_witness.rs index 81eec21a578..c9fda6735e6 100644 --- a/src/v1/stage0/src/bin/dag_collect_fingerprint_witness.rs +++ b/src/v1/stage0/src/bin/dag_collect_fingerprint_witness.rs @@ -48,6 +48,9 @@ fn shell_node( params: Vec>, ) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: name.to_string(), ident: None, span: synth_span(), diff --git a/src/v1/stage0/src/bin/infer_semantics_witness.rs b/src/v1/stage0/src/bin/infer_semantics_witness.rs index 9da4fc43ccf..16e4c9af65c 100644 --- a/src/v1/stage0/src/bin/infer_semantics_witness.rs +++ b/src/v1/stage0/src/bin/infer_semantics_witness.rs @@ -182,7 +182,11 @@ fn empty_source_indices() -> Rc>> { } fn leaf_node(name: String) -> Rc { - leaf_node_with_span(name, no_span()) + leaf_node_with_span( + Rc::new(v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), + name, + no_span(), + ) } fn container_node(kind_name: String, element: Rc) -> Rc { @@ -192,11 +196,17 @@ fn container_node(kind_name: String, element: Rc) -> Rc { }; let sp = no_span(); Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: kind_name.clone(), ident: None, span: sp.clone(), ident_span: default_ident_span(kind_name, sp.clone()), children: Rc::new(vec![Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: param_name.clone(), ident: None, span: sp.clone(), @@ -239,12 +249,14 @@ fn map_node(key: Rc, value: Rc) -> Rc { .expect("kernel Map should resolve V from PartialFunction profile"); let sp = no_span(); Rc::new(Node { + occurrence_identity: Rc::new(v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Map".to_string(), ident: None, span: sp.clone(), ident_span: Some(sp.clone()), children: Rc::new(vec![ Rc::new(Node { + occurrence_identity: Rc::new(v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), name: key_name, ident: None, span: sp.clone(), @@ -265,6 +277,7 @@ fn map_node(key: Rc, value: Rc) -> Rc { expr_data: Rc::new(ExprData::NoExprData), }), Rc::new(Node { + occurrence_identity: Rc::new(v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), name: val_name, ident: None, span: sp.clone(), @@ -353,6 +366,9 @@ fn empty_infer_scope() -> Rc { fn sum_node(name: &str, variants: Vec>, cardinality: Cardinality) -> Rc { let sp = no_span(); Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: name.to_string(), ident: None, span: sp.clone(), @@ -376,6 +392,7 @@ fn sum_node(name: &str, variants: Vec>, cardinality: Cardinality) -> Rc fn variant_arm(name: &str) -> Rc { make_arm_node( + Rc::new(v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), Rc::new(MatchPattern::VariantPattern { name: name.to_string(), parent_enum: None, @@ -784,11 +801,17 @@ fn optional_pattern_lookup_resolves_present_variant() { fn optional_pattern_lookup_prefers_optional_present_over_inner_present_variant() { let sp = no_span(); let inner_present = Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "Present".to_string(), ident: None, span: sp.clone(), ident_span: default_ident_span("Present".to_string(), sp.clone()), children: Rc::new(vec![Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "inner".to_string(), ident: None, span: sp.clone(), @@ -825,6 +848,9 @@ fn optional_pattern_lookup_prefers_optional_present_over_inner_present_variant() expr_data: Rc::new(ExprData::NoExprData), }); let optional_inner_sum = Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "Inner".to_string(), ident: None, span: sp.clone(), @@ -904,6 +930,9 @@ fn optional_present_absent_patterns_keep_canonical_names() { fn applied_generic_type_node(type_name: &str, type_arg: Rc) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: type_name.to_string(), ident: None, span: no_span(), @@ -1195,6 +1224,9 @@ fn coproduct_runtime_arm_names_match_on_last_segment_not_type_name_compatible() fn resolve_node_uses_node_name_for_lookup() { let node_ref = Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "User".to_string(), ident: None, span: zero_span(), @@ -1612,7 +1644,11 @@ fn authored_leaf_node(name: &str, text: &str) -> Rc { start, end: start + name.chars().count() as i64, }); - leaf_node_with_span(name.to_string(), span) + leaf_node_with_span( + Rc::new(v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), + name.to_string(), + span, + ) } fn container_spelling_verdict_declared_for_kernel_container() { @@ -1814,6 +1850,9 @@ fn node_inferred_to_outputs_returns_empty_when_child_has_error() { end: 0, })); let typed_child = Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "x".to_string(), ident_span: syn_span.clone(), inferred: Some(Rc::new(InferredNode::Resolved { @@ -1823,6 +1862,9 @@ fn node_inferred_to_outputs_returns_empty_when_child_has_error() { ..(*leaf_node("".to_string())).clone() }); let error_child = Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "y".to_string(), ident_span: syn_span.clone(), inferred: Some(Rc::new(InferredNode::CompilerError { @@ -1833,6 +1875,9 @@ fn node_inferred_to_outputs_returns_empty_when_child_has_error() { ..(*leaf_node("".to_string())).clone() }); let conj_node = Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "Result".to_string(), ident_span: syn_span.clone(), connective: Connective::Conj, @@ -1884,6 +1929,9 @@ fn resolve_applied_generic_struct_expands_to_conj_for_field_lookup() { let t_param = leaf_node("T".to_string()); let value_field = Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "value".to_string(), ident: None, span: no_span(), @@ -1906,6 +1954,9 @@ fn resolve_applied_generic_struct_expands_to_conj_for_field_lookup() { expr_data: Rc::new(ExprData::NoExprData), }); let box_decl = Rc::new(Node { + occurrence_identity: Rc::new( + v1_compiler::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "Box".to_string(), ident: None, span: no_span(), diff --git a/src/v1/stage0/src/cli_run.rs b/src/v1/stage0/src/cli_run.rs index befa3ad4cb5..944f3935a52 100644 --- a/src/v1/stage0/src/cli_run.rs +++ b/src/v1/stage0/src/cli_run.rs @@ -12562,6 +12562,7 @@ const CENSUS_HEADS_FN_STAND_IN_NAME: &str = "^census_heads_fn_stand_in"; thread_local! { static STRIPPED_FN_BODY_MARKER: Rc = Rc::new(Node { + occurrence_identity: Rc::new(crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), name: CENSUS_HEADS_FN_STAND_IN_NAME.to_string(), span: no_span(), ident_span: None, @@ -12634,6 +12635,7 @@ fn census_heads_module_item(item: Rc) -> Rc { census_heads_children(&item.children) }; Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -12657,6 +12659,7 @@ fn census_heads_module_item(item: Rc) -> Rc { fn census_heads_module_node(module: Rc) -> Rc { Rc::new(Node { + occurrence_identity: module.occurrence_identity.clone(), name: module.name.clone(), span: module.span.clone(), ident_span: module.ident_span.clone(), @@ -40986,7 +40989,12 @@ pub fn shell_transport_operation_declaration( let fallback_transport = if let Some(t) = item.transport.as_ref() { t.clone() } else { - crate::v1_std_core::local_transport_node(item.span.clone()) + crate::v1_std_core::local_transport_node( + Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), + item.span.clone(), + ) }; for op in item.children.iter() { if op.name != operation { @@ -41377,7 +41385,12 @@ pub fn extdeps_shape_transport_policy_module_facts( let fallback_transport = if let Some(t) = item.transport.as_ref() { t.clone() } else { - crate::v1_std_core::local_transport_node(item.span.clone()) + crate::v1_std_core::local_transport_node( + Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), + item.span.clone(), + ) }; for op in item.children.iter() { if op.name.is_empty() { @@ -42756,11 +42769,19 @@ mod peel_alias_fixpoint_termination { std::thread::spawn(move || { let span = crate::v1_std_core::kernel_span("PeelFixpointProbe".to_string()); let elem = crate::v1_std_core::leaf_node_with_span( + std::rc::Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), "PeelFixpointElem".to_string(), crate::v1_std_core::kernel_span("PeelFixpointElem".to_string()), ); - let base = - crate::v1_std_core::leaf_node_with_span("PeelFixpointProbe".to_string(), span); + let base = crate::v1_std_core::leaf_node_with_span( + std::rc::Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), + "PeelFixpointProbe".to_string(), + span, + ); let n = std::rc::Rc::new(crate::v1_std_core::Node { children: std::rc::Rc::new(im::vector![elem]), ..(*base).clone() @@ -42850,6 +42871,9 @@ mod peel_alias_fixpoint_termination { // report. Keeping this at zero prevents the typed carrier change // from turning ordinary speculative misses into false reds. let plain_int = crate::v1_std_core::leaf_node_with_span( + std::rc::Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), "Int".to_string(), crate::v1_std_core::kernel_span("Int".to_string()), ); @@ -42973,6 +42997,9 @@ mod sigs_env_flat_parents { name: fn_name.to_string(), params: Rc::new(im::vector![]), inferred: crate::v1_std_core::leaf_node_with_span( + std::rc::Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), marker.to_string(), crate::v1_std_core::kernel_span(marker.to_string()), ), diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index 1cc1406d348..81cc8196800 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -2163,6 +2163,9 @@ mod compiler_tests { ) -> std::rc::Rc { let span = crate::v1_std_core::no_span(); std::rc::Rc::new(crate::v1_std_core::Node { + occurrence_identity: std::rc::Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: name.to_string(), ident: None, span: span.clone(), diff --git a/src/v1/stage0/src/coproduct_reflection.rs b/src/v1/stage0/src/coproduct_reflection.rs index 9d49ca1fe9d..0abde7645ed 100644 --- a/src/v1/stage0/src/coproduct_reflection.rs +++ b/src/v1/stage0/src/coproduct_reflection.rs @@ -1859,6 +1859,7 @@ mod parse_only_uppercase_variant_regression_tests { fn uppercase_var_without_binding() -> Rc { make_named_expr_node( + Rc::new(crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), "SharedArm".to_string(), Rc::new(ExprData::ExprVar { binding_kind: None }), empty_node_list(), @@ -1870,6 +1871,7 @@ mod parse_only_uppercase_variant_regression_tests { fn uppercase_var_with_variant_binding() -> Rc { make_named_expr_node( + Rc::new(crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), "SharedArm".to_string(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::VariantValueBinding { diff --git a/src/v1/stage0/src/v1_compiler_compile.rs b/src/v1/stage0/src/v1_compiler_compile.rs index 2dcbb6ac237..261dcc3d83d 100644 --- a/src/v1/stage0/src/v1_compiler_compile.rs +++ b/src/v1/stage0/src/v1_compiler_compile.rs @@ -12,12 +12,13 @@ use crate::std_induction::SubValueRelation::{ StrictAxisErased, StrictSubValue, SubValueUnknown, }; pub use crate::std_induction::{InductiveField, RecursionShape, SubValueRelation}; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic; pub use crate::std_occurrence_identity::OccurrenceId; pub use crate::std_occurrence_identity::{ occurrence_id_allocator_initial, occurrence_transport_refusal, }; pub use crate::std_occurrence_identity::{ - OccurrenceIdAllocator, OccurrenceIndex, OccurrenceTransport, + NodeOccurrenceIdentity, OccurrenceIdAllocator, OccurrenceIndex, OccurrenceTransport, }; pub use crate::std_source_annotation::{ source_annotation_graph_concat, source_annotation_graph_empty, diff --git a/src/v1/stage0/src/v1_compiler_emit.rs b/src/v1/stage0/src/v1_compiler_emit.rs index bff8c8b48ff..95bc1f0e7f6 100644 --- a/src/v1/stage0/src/v1_compiler_emit.rs +++ b/src/v1/stage0/src/v1_compiler_emit.rs @@ -16,6 +16,8 @@ pub use crate::extdeps_languages_python_emit::python_method_templates_flat; pub use crate::extdeps_languages_rust_emit::rust_method_templates; use crate::std_induction::SubValueRelation::SubValueUnknown; pub use crate::std_induction::{InductiveField, SubValueRelation}; +pub use crate::std_occurrence_identity::NodeOccurrenceIdentity; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic; use crate::std_syntax::AlgebraFieldKind::*; use crate::std_syntax::BinOp::NullCoalesce; use crate::std_syntax::BinOp::*; @@ -1984,7 +1986,10 @@ pub fn has_service_items(typed: Rc) -> bool { pub fn service_fallback_transport(item: Rc) -> Rc { if (item.transport.clone() == None) { - local_transport_node(item.span.clone()) + local_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + item.span.clone(), + ) } else { item.transport.clone().clone().unwrap() } diff --git a/src/v1/stage0/src/v1_compiler_emit_rust.rs b/src/v1/stage0/src/v1_compiler_emit_rust.rs index 0c66a28c308..260be14f802 100644 --- a/src/v1/stage0/src/v1_compiler_emit_rust.rs +++ b/src/v1/stage0/src/v1_compiler_emit_rust.rs @@ -42,6 +42,8 @@ pub use crate::std_magnitude::Magnitude; pub use crate::std_measure::millisecond_count; pub use crate::std_measure::Millisecond; pub use crate::std_nat::Nat; +pub use crate::std_occurrence_identity::NodeOccurrenceIdentity; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic; use crate::std_serialization::VariantEncoding::*; use crate::std_serialization::VariantNaming::*; pub use crate::std_serialization::{CoproductWireContract, VariantEncoding, VariantNaming}; @@ -2811,6 +2813,7 @@ pub fn render_rust_alias_rhs_type( pub fn type_variable_node(id: String) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: no_span(), ident_span: None, @@ -21960,6 +21963,7 @@ pub fn fill_default_args( let mut __result = Vec::new(); for p in missing_with_defaults.iter().cloned() { __result.push(make_arg_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), Some(param_node_name_at( p.clone(), scope.type_env.clone().source_indices.clone(), @@ -22018,6 +22022,7 @@ pub fn fill_op_default_args( None => { if (param_node_default_value(p.clone()) != None) { Rc::new(vec![make_arg_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), Some(pname.clone()), param_node_default_value(p.clone()).clone().unwrap(), p.span.clone(), diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index 166c3e06a62..9d204c79903 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -42,6 +42,8 @@ use crate::std_interface_summary::ExportKind::{ExportData, ExportFn, ExportServi pub use crate::std_interface_summary::{interface_summary_rollup, signature_contract}; pub use crate::std_interface_summary::{ExportEntry, ExportKind, InterfaceSummary}; pub use crate::std_node::{compiler_inductive_fields, compiler_recursive_types}; +pub use crate::std_occurrence_identity::NodeOccurrenceIdentity; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic; pub use crate::std_occurrence_identity::OccurrenceId; use crate::std_syntax::BinOp::Add; use crate::std_syntax::BinOp::{And, Div, Eq, Ge, Gt, Le, Lt, Mod, Mul, Ne, NullCoalesce, Or, Sub}; @@ -804,6 +806,7 @@ pub fn nominal_ref_node( ident_span: Option>, ) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: span.clone(), ident_span: ident_span.clone(), @@ -905,6 +908,7 @@ pub fn ok_infer(texpr: Rc) -> Rc { pub fn semantic_expr_error_node(message: String, span: Rc) -> Rc { make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::SemanticExprError, message.clone(), span.clone(), @@ -913,6 +917,7 @@ pub fn semantic_expr_error_node(message: String, span: Rc) -> Rc) -> Rc { make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, message.clone(), span.clone(), @@ -1866,93 +1871,78 @@ pub fn record_lit_instantiated_fields( scope: Rc, ) -> Option>>> { match type_name.clone() { - Some(tn) => match expected.clone() { - Some(exp) => { - if (type_name_compatible( - authored_name_at(scope.type_env.clone().source_indices.clone(), exp.clone()), - tn.clone(), - ) == false) - { - None - } else { - if ((exp.children.clone().len() as i64) == 0) { + Some(tn) => { + match expected.clone() { + Some(exp) => { + if (type_name_compatible( + authored_name_at( + scope.type_env.clone().source_indices.clone(), + exp.clone(), + ), + tn.clone(), + ) == false) + { None } else { - match lookup_type_for(scope.type_env.clone(), exp.clone()) { - Some(decl) => { - if ((decl.params.clone().len() as i64) - != (exp.children.clone().len() as i64)) - { - None - } else { + if ((exp.children.clone().len() as i64) == 0) { + None + } else { + match lookup_type_for(scope.type_env.clone(), exp.clone()) { + Some(decl) => { + if ((decl.params.clone().len() as i64) + != (exp.children.clone().len() as i64)) { - let subst = Rc::new(decl.params.clone().iter().cloned().enumerate().map(|(i, v)| (i as i64, v)).collect::>()).iter().cloned().fold(v1_rt::rc_empty_map::>(), |acc: Rc>>, pair: (i64, Rc)| { + None + } else { + { + let subst = Rc::new(decl.params.clone().iter().cloned().enumerate().map(|(i, v)| (i as i64, v)).collect::>()).iter().cloned().fold(v1_rt::rc_empty_map::>(), |acc: Rc>>, pair: (i64, Rc)| { let slot = authored_name_at(scope.type_env.clone().source_indices.clone(), pair.1.clone()); match exp.children.clone().iter().cloned().skip(pair.0.clone() as usize).next() { Some(arg) => v1_rt::rc_map_insert(acc.clone(), slot.clone(), resolved_type(arg.clone())), None => acc.clone(), } }); - let template_fields = decl.children.clone(); - Some(Rc::new({ - let mut __result = Vec::new(); - for sf in template_fields.iter().cloned() { - __result.push(Rc::new(Node { - name: sf.name.clone(), - span: sf.span.clone(), - ident_span: sf.ident_span.clone(), - children: sf.children.clone(), - connective: sf.connective.clone(), - params: sf.params.clone(), - inferred: Some(Rc::new( - InferredNode::Resolved { - node: substitute_generics( - field_substitution_carrier( - sf.clone(), - scope - .type_env - .clone() - .source_indices - .clone(), - ), - subst.clone(), - scope - .type_env - .clone() - .source_indices - .clone(), - ), - }, - )), - return_cardinality: sf - .return_cardinality - .clone(), - uses: sf.uses.clone(), - body: sf.body.clone(), - transport: sf.transport.clone(), - properties: sf.properties.clone(), - type_annotation: sf.type_annotation.clone(), - is_self_recursive: sf.is_self_recursive.clone(), - has_non_tail_self_call: sf - .has_non_tail_self_call - .clone(), - match_pattern: sf.match_pattern.clone(), - expr_data: sf.expr_data.clone(), - ident: None, - })); - } - __result - })) + let template_fields = decl.children.clone(); + Some(Rc::new({ + let mut __result = Vec::new(); + for sf in template_fields.iter().cloned() { + __result.push(Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + name: sf.name.clone(), + span: sf.span.clone(), + ident_span: sf.ident_span.clone(), + children: sf.children.clone(), + connective: sf.connective.clone(), + params: sf.params.clone(), + inferred: Some(Rc::new(InferredNode::Resolved { + node: substitute_generics(field_substitution_carrier(sf.clone(), scope.type_env.clone().source_indices.clone()), subst.clone(), scope.type_env.clone().source_indices.clone()), +})), + return_cardinality: sf.return_cardinality.clone(), + uses: sf.uses.clone(), + body: sf.body.clone(), + transport: sf.transport.clone(), + properties: sf.properties.clone(), + type_annotation: sf.type_annotation.clone(), + is_self_recursive: sf.is_self_recursive.clone(), + has_non_tail_self_call: sf.has_non_tail_self_call.clone(), + match_pattern: sf.match_pattern.clone(), + expr_data: sf.expr_data.clone(), + ident: None, +})); + } + __result + })) + } } } + None => None, } - None => None, } } } + None => None, } - None => None, - }, + } None => None, } } @@ -6022,6 +6012,7 @@ pub fn optional_cast_diags( pub fn type_variable_node(id: String) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: no_span(), ident_span: None, @@ -6169,6 +6160,7 @@ pub fn annotate_pattern_parent_enums( ); let field_subject = lookup_result_subject(field_lookup.clone()); make_field_binding_node( + binding.occurrence_identity.clone(), field_binding_name_at( binding.clone(), scope.type_env.clone().source_indices.clone(), @@ -6592,6 +6584,7 @@ pub fn extract_fold_init_info( infer_expr(arg_value(ia.clone()), scope.clone(), expected.clone()); Some(Rc::new(ArgInferResult { typed_arg: make_arg_node( + ia.occurrence_identity.clone(), arg_name_at( ia.clone(), scope.type_env.clone().source_indices.clone(), @@ -6702,8 +6695,9 @@ if ((is_fold.clone() && (fold_info.clone() != None)) && is_init_arg.clone()) { } else { if (is_fold.clone() && (fold_info.clone() != None)) { { - let fold_params = Rc::new(vec![make_param_node("acc".to_string(), fold_acc_type.clone(), None, no_span(), no_span()), make_param_node("elem".to_string(), element_type.clone(), None, no_span(), no_span())]); + let fold_params = Rc::new(vec![make_param_node(Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "acc".to_string(), fold_acc_type.clone(), None, no_span(), no_span()), make_param_node(Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "elem".to_string(), element_type.clone(), None, no_span(), no_span())]); let fold_callable = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: no_span(), ident_span: None, @@ -6742,7 +6736,7 @@ let fold_scope = Rc::new(InferScope { }); let ar = infer_expr(lam_value.clone(), fold_scope.clone(), Some(fold_callable.clone())); Rc::new(ArgInferResult { - typed_arg: make_arg_node(arg_name_at(a.clone(), scope.type_env.clone().source_indices.clone()), ar.typed.clone(), a.span.clone(), a.span.clone()), + typed_arg: make_arg_node(a.occurrence_identity.clone(), arg_name_at(a.clone(), scope.type_env.clone().source_indices.clone()), ar.typed.clone(), a.span.clone(), a.span.clone()), diagnostics: ar.diagnostics.clone(), }) } @@ -6775,7 +6769,7 @@ match (*arg_contract.clone()).clone() { let ar = infer_expr(nf_lam_value.clone(), nf_scope.clone(), None); let contract_diag = categorized_error("no declared argument contract is available for this method call; refusing rather than substituting the receiver element type".to_string(), a.span.clone(), nf_scope.module_name.clone(), "method-arg-contract-unavailable".to_string()); Rc::new(ArgInferResult { - typed_arg: make_arg_node(arg_name_at(a.clone(), nf_scope.type_env.clone().source_indices.clone()), ar.typed.clone(), a.span.clone(), a.span.clone()), + typed_arg: make_arg_node(a.occurrence_identity.clone(), arg_name_at(a.clone(), nf_scope.type_env.clone().source_indices.clone()), ar.typed.clone(), a.span.clone(), a.span.clone()), diagnostics: v1_rt::concat(ar.diagnostics.clone(), Rc::new(vec![contract_diag.clone()])), }) }, @@ -6785,7 +6779,7 @@ Rc::new(ArgInferResult { let ar = infer_expr(nf_lam_value.clone(), nf_scope.clone(), None); let contract_diag = categorized_error("no declared argument contract is available at this parameter position; refusing rather than substituting the receiver element type".to_string(), a.span.clone(), nf_scope.module_name.clone(), "method-arg-contract-unavailable".to_string()); Rc::new(ArgInferResult { - typed_arg: make_arg_node(arg_name_at(a.clone(), nf_scope.type_env.clone().source_indices.clone()), ar.typed.clone(), a.span.clone(), a.span.clone()), + typed_arg: make_arg_node(a.occurrence_identity.clone(), arg_name_at(a.clone(), nf_scope.type_env.clone().source_indices.clone()), ar.typed.clone(), a.span.clone(), a.span.clone()), diagnostics: v1_rt::concat(ar.diagnostics.clone(), Rc::new(vec![contract_diag.clone()])), }) }, @@ -6838,6 +6832,7 @@ pub fn infer_arg_with_element_type( ); Rc::new(ArgInferResult { typed_arg: make_arg_node( + arg.occurrence_identity.clone(), arg_name_at(arg.clone(), scope.type_env.clone().source_indices.clone()), ar.typed.clone(), arg.span.clone(), @@ -6890,6 +6885,7 @@ pub fn qualified_value_projection( v1_rt::rc_empty_map::(), ); Some(ok_infer(make_named_expr_node( + texpr.occurrence_identity.clone(), spine.dotted.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new(VarBindingKind::FunctionValueBinding)), @@ -6916,6 +6912,7 @@ pub fn infer_expr_body( ExprData::ExprLiteral { value: lit, .. } => { let span = texpr.span.clone(); ok_infer(make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprLiteral { value: lit.clone() }), Rc::new(vec![]), Some(Rc::new(InferredNode::Resolved { @@ -6935,7 +6932,12 @@ pub fn infer_expr_body( _ => Rc::new(vec![]), }; Rc::new(InferResult { - typed: make_expr_error_node(kind.clone(), message.clone(), span.clone()), + typed: make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + kind.clone(), + message.clone(), + span.clone(), + ), diagnostics: diagnostics.clone(), }) } @@ -6956,6 +6958,7 @@ pub fn infer_expr_body( let scope_parent = lookup_variant_parent_enum(scope.clone(), name.clone()); match scope_parent.clone() { Some(scope_enum) => ok_infer(make_named_expr_node( + texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new( @@ -6981,6 +6984,7 @@ pub fn infer_expr_body( let binding_kind = infer_var_binding_kind(scope.clone(), name.clone()); ok_infer(make_named_expr_node( + texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(binding_kind.clone()), @@ -7005,6 +7009,7 @@ pub fn infer_expr_body( FuncSigLookup::FuncSigResolved { sig: fsig, .. } => { match ((fsig.params.clone().len() as i64) == 0) { true => ok_infer(make_named_expr_node( + texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), @@ -7018,6 +7023,7 @@ pub fn infer_expr_body( span.clone(), )), false => ok_infer(make_named_expr_node( + texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new( @@ -7052,6 +7058,7 @@ pub fn infer_expr_body( lookup_variant_parent_enum(scope.clone(), name.clone()); match scope_parent.clone() { Some(scope_enum) => ok_infer(make_named_expr_node( + texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new( @@ -7077,6 +7084,7 @@ pub fn infer_expr_body( let binding_kind = infer_var_binding_kind(scope.clone(), name.clone()); ok_infer(make_named_expr_node( + texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(binding_kind.clone()), @@ -7100,6 +7108,7 @@ pub fn infer_expr_body( ); match expected_variant_enum.clone() { Some(exp_enum) => ok_infer(make_named_expr_node( + texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: Some(Rc::new( @@ -7138,6 +7147,7 @@ pub fn infer_expr_body( } else { { let err_texpr = make_named_expr_node( + texpr.occurrence_identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: None, @@ -7212,6 +7222,7 @@ pub fn infer_expr_body( if resolved_base_is_error.clone() { Rc::new(InferResult { typed: make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::SemanticExprError, "error type cascade".to_string(), span.clone(), @@ -7248,6 +7259,7 @@ pub fn infer_expr_body( ), }; let fa_texpr = make_named_expr_node( + texpr.occurrence_identity.clone(), field_name.clone(), Rc::new(ExprData::ExprFieldAccess { summary: field_summary.clone(), @@ -7275,6 +7287,7 @@ pub fn infer_expr_body( if base_is_type_var.clone() { { let fa_texpr = make_named_expr_node( + texpr.occurrence_identity.clone(), field_name.clone(), Rc::new(ExprData::ExprFieldAccess { summary: Some(Rc::new(FieldSummary { @@ -7306,6 +7319,7 @@ pub fn infer_expr_body( ) { Some(svc_type) => { let fa_texpr = make_named_expr_node( + texpr.occurrence_identity.clone(), field_name.clone(), Rc::new(ExprData::ExprFieldAccess { summary: Some(Rc::new(FieldSummary { @@ -7352,6 +7366,9 @@ pub fn infer_expr_body( "'".to_string(), ); let fa_texpr = make_expr_error_node( + Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), ExprErrorKind::SemanticExprError, error_message.clone(), span.clone(), @@ -7487,6 +7504,7 @@ pub fn infer_expr_body( v1_rt::concat( Rc::new(vec![Rc::new(ArgInferResult { typed_arg: make_arg_node( + first_arg.occurrence_identity.clone(), arg_name_at( first_arg.clone(), scope @@ -7543,7 +7561,7 @@ let next_subst = if (is_lambda_expr(arg_value(a.clone())) || !has_formal.clone() }; Rc::new(ArgGenericFoldState { results: v1_rt::concat(st.results.clone(), Rc::new(vec![Rc::new(ArgInferResult { - typed_arg: make_arg_node(arg_name_at(a.clone(), scope.type_env.clone().source_indices.clone()), ar.typed.clone(), a.span.clone(), a.span.clone()), + typed_arg: make_arg_node(a.occurrence_identity.clone(), arg_name_at(a.clone(), scope.type_env.clone().source_indices.clone()), ar.typed.clone(), a.span.clone(), a.span.clone()), diagnostics: ar.diagnostics.clone(), })])), subst: next_subst.clone(), @@ -7629,6 +7647,7 @@ Rc::new(ArgGenericFoldState { ); Rc::new(InferResult { typed: make_named_expr_node( + texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some( @@ -7855,55 +7874,56 @@ Rc::new(ArgGenericFoldState { _ => false, } }; - let final_receiver = if ((returns_receiver_self - .clone() - && is_fully_resolved( - bridge_result_type.clone(), - scope.type_env.clone().source_indices.clone(), - )) - && !is_fully_resolved( - first_arg_type.clone(), - scope.type_env.clone().source_indices.clone(), - )) { - Rc::new(Node { - name: receiver.name.clone(), - span: receiver.span.clone(), - ident_span: receiver.ident_span.clone(), - children: bridge_result_type.children.clone(), - connective: receiver.connective.clone(), - params: receiver.params.clone(), - inferred: Some(Rc::new( - InferredNode::Resolved { - node: bridge_result_type.clone(), - }, - )), - return_cardinality: receiver - .return_cardinality - .clone(), - uses: receiver.uses.clone(), - body: receiver.body.clone(), - transport: receiver.transport.clone(), - properties: receiver.properties.clone(), - type_annotation: receiver - .type_annotation - .clone(), - is_self_recursive: receiver - .is_self_recursive - .clone(), - has_non_tail_self_call: receiver - .has_non_tail_self_call - .clone(), - match_pattern: receiver.match_pattern.clone(), - expr_data: receiver.expr_data.clone(), - ident: None, - }) - } else { - receiver.clone() - }; + let final_receiver = + if ((returns_receiver_self.clone() + && is_fully_resolved( + bridge_result_type.clone(), + scope + .type_env + .clone() + .source_indices + .clone(), + )) + && !is_fully_resolved( + first_arg_type.clone(), + scope + .type_env + .clone() + .source_indices + .clone(), + )) + { + Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + name: receiver.name.clone(), + span: receiver.span.clone(), + ident_span: receiver.ident_span.clone(), + children: bridge_result_type.children.clone(), + connective: receiver.connective.clone(), + params: receiver.params.clone(), + inferred: Some(Rc::new(InferredNode::Resolved { + node: bridge_result_type.clone(), +})), + return_cardinality: receiver.return_cardinality.clone(), + uses: receiver.uses.clone(), + body: receiver.body.clone(), + transport: receiver.transport.clone(), + properties: receiver.properties.clone(), + type_annotation: receiver.type_annotation.clone(), + is_self_recursive: receiver.is_self_recursive.clone(), + has_non_tail_self_call: receiver.has_non_tail_self_call.clone(), + match_pattern: receiver.match_pattern.clone(), + expr_data: receiver.expr_data.clone(), + ident: None, +}) + } else { + receiver.clone() + }; let remaining_arg_nodes = Rc::new({ let mut __result = Vec::new(); for ta in remaining.iter().cloned() { __result.push(make_arg_node( + ta.occurrence_identity.clone(), arg_name_at( ta.clone(), scope @@ -7921,6 +7941,7 @@ Rc::new(ArgGenericFoldState { }); Rc::new(InferResult { typed: make_named_expr_node( + texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprMethodCall { method_semantics: method_resolution @@ -7955,7 +7976,7 @@ Rc::new(ArgGenericFoldState { match expected.clone() { Some(exp) => if node_is_keyed_collection(exp.clone(), scope.type_env.clone().source_indices.clone()) { Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, }), typed_arg_nodes.clone(), Some(Rc::new(InferredNode::Resolved { @@ -7968,7 +7989,7 @@ Rc::new(ArgGenericFoldState { let empty_map_diags = v1_rt::concat(arg_diags.clone(), Rc::new(vec![inference_error("empty_map(): expected type is not a keyed collection".to_string(), span.clone(), scope.module_name.clone())])); match bare_m.clone() { Some(map_t) => Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, }), typed_arg_nodes.clone(), Some(Rc::new(InferredNode::Resolved { @@ -7977,7 +7998,7 @@ match bare_m.clone() { diagnostics: empty_map_diags.clone(), }), None => Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, }), typed_arg_nodes.clone(), Some(Rc::new(InferredNode::CompilerError { @@ -7991,7 +8012,7 @@ match bare_m.clone() { }, None => match bare_m.clone() { Some(map_t) => Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, }), typed_arg_nodes.clone(), Some(Rc::new(InferredNode::Resolved { @@ -8000,7 +8021,7 @@ match bare_m.clone() { diagnostics: arg_diags.clone(), }), None => Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, }), typed_arg_nodes.clone(), Some(Rc::new(InferredNode::CompilerError { @@ -8021,7 +8042,7 @@ match bare_m.clone() { match expected.clone() { Some(exp) => if node_is_set_collection(exp.clone(), scope.type_env.clone().source_indices.clone()) { Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, }), typed_arg_nodes.clone(), Some(Rc::new(InferredNode::Resolved { @@ -8034,7 +8055,7 @@ match bare_m.clone() { let empty_set_diags = v1_rt::concat(arg_diags.clone(), Rc::new(vec![inference_error("empty_set(): expected type is not Set<...>".to_string(), span.clone(), scope.module_name.clone())])); match bare_s.clone() { Some(set_t) => Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, }), typed_arg_nodes.clone(), Some(Rc::new(InferredNode::Resolved { @@ -8043,7 +8064,7 @@ match bare_s.clone() { diagnostics: empty_set_diags.clone(), }), None => Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, }), typed_arg_nodes.clone(), Some(Rc::new(InferredNode::CompilerError { @@ -8057,7 +8078,7 @@ match bare_s.clone() { }, None => match bare_s.clone() { Some(set_t) => Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, }), typed_arg_nodes.clone(), Some(Rc::new(InferredNode::Resolved { @@ -8066,7 +8087,7 @@ match bare_s.clone() { diagnostics: arg_diags.clone(), }), None => Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, }), typed_arg_nodes.clone(), Some(Rc::new(InferredNode::CompilerError { @@ -8101,6 +8122,7 @@ match bare_s.clone() { }; Rc::new(InferResult { typed: make_named_expr_node( + texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: call_semantics @@ -8157,7 +8179,7 @@ match bare_s.clone() { _ => error_type(), }; Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(if callee_is_body_binding.clone() { CallSemantics::FunctionValueCallSemantics } else { @@ -8172,6 +8194,7 @@ match bare_s.clone() { } } else { match infer_variant_constructor_call( + texpr.occurrence_identity.clone(), func_name.clone(), call_args.clone(), span.clone(), @@ -8221,7 +8244,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { }, }; Rc::new(InferResult { - typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { + typed: make_named_expr_node(texpr.occurrence_identity.clone(), func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, }), typed_arg_nodes.clone(), Some(Rc::new(InferredNode::Resolved { @@ -8273,6 +8296,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { None => None, Some(_) => Some(infer_expr( make_named_expr_node( + texpr.occurrence_identity.clone(), dotted.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), @@ -8479,6 +8503,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { }; let typed_mc_arg_nodes = typed_mc_args.clone(); let mc_texpr = make_named_expr_node( + texpr.occurrence_identity.clone(), method_name.clone(), Rc::new(ExprData::ExprMethodCall { method_semantics: method_semantics.clone(), @@ -8562,6 +8587,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { }; Rc::new(ArmInferResult { typed_arm: make_arm_node( + arm_node.occurrence_identity.clone(), typed_pattern.clone(), if (guard_result.clone() != None) { Some(guard_unwrapped.typed.clone()) @@ -8717,6 +8743,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { }; Rc::new(ArmInferResult { typed_arm: make_arm_node( + arm_node.occurrence_identity.clone(), typed_pattern.clone(), if (guard_result.clone() != None) { Some(guard_unwrapped.typed.clone()) @@ -8783,6 +8810,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { PatternSubject::PatternLookupBlocked => Rc::new(vec![]), }; let match_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprMatch), v1_rt::concat(Rc::new(vec![scrut_typed.clone()]), typed_arms.clone()), Some(Rc::new(InferredNode::Resolved { @@ -8880,6 +8908,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { )]) }; let if_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprIf), Rc::new(vec![ cond_typed.clone(), @@ -8904,6 +8933,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { } None => { let if_texpr2 = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprIf), Rc::new(vec![cond_typed.clone(), then_typed.clone()]), Some(Rc::new(InferredNode::Resolved { node: unit_type() })), @@ -8967,6 +8997,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { if (body_expr.clone() == None) { { let let_texpr = make_named_expr_node( + texpr.occurrence_identity.clone(), let_name.clone(), Rc::new(ExprData::ExprLet), Rc::new(vec![val_typed.clone()]), @@ -8997,6 +9028,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { let body_typed = body_result.typed.clone(); let body_diags = body_result.diagnostics.clone(); let let_texpr2 = make_named_expr_node( + texpr.occurrence_identity.clone(), let_name.clone(), Rc::new(ExprData::ExprLet), Rc::new(vec![val_typed.clone(), body_typed.clone()]), @@ -9015,6 +9047,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { let span = texpr.span.clone(); let field_inits = texpr.children.clone(); infer_record_lit( + texpr.occurrence_identity.clone(), record_lit_type_name_at( texpr.clone(), scope.type_env.clone().source_indices.clone(), @@ -9149,6 +9182,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { }; let list_k = list_kernel_ty_from_element(elem_type_node.clone()); let ll_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprListLit), typed_elements.clone(), Some(Rc::new(InferredNode::Resolved { @@ -9180,6 +9214,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { scope.type_env.clone().source_indices.clone(), ); let bo_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprBinOp { op: op.clone(), algebra_field: binop_info.algebra_field.clone(), @@ -9206,6 +9241,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { UnaryOpKind::Neg => resolved_type(operand_typed.clone()), }; let uo_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprUnaryOp { op: op.clone() }), Rc::new(vec![operand_typed.clone()]), Some(Rc::new(InferredNode::Resolved { @@ -9435,6 +9471,9 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { None => None, }; Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: pn.name.clone(), ident: pn.ident.clone(), span: pn.span.clone(), @@ -9459,6 +9498,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { __result }); let lam_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprLambda), v1_rt::concat(Rc::new(vec![body_typed.clone()]), typed_param_nodes.clone()), body_typed.inferred.clone(), @@ -9479,7 +9519,11 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { _ => match part_node.children.clone().first().cloned() { Some(inner) => { let r = infer_expr(inner.clone(), scope.clone(), None); - make_interp_part_node(r.typed.clone(), part_node.span.clone()) + make_interp_part_node( + part_node.occurrence_identity.clone(), + r.typed.clone(), + part_node.span.clone(), + ) } None => part_node.clone(), }, @@ -9508,6 +9552,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { __result }); let si_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprStringInterp), typed_part_nodes.clone(), Some(Rc::new(InferredNode::Resolved { @@ -9535,6 +9580,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { expected.clone(), ); let blk_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprBlock), state.typed_stmts.clone(), Some(Rc::new(InferredNode::Resolved { @@ -9555,6 +9601,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { } } else { ok_infer(make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprBlock), Rc::new(vec![]), Some(Rc::new(InferredNode::Resolved { node: unit_type() })), @@ -9602,6 +9649,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { scope.type_env.clone(), ); let cast_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprCast), Rc::new(vec![inner_typed.clone(), target_type.clone()]), Some(Rc::new(InferredNode::Resolved { @@ -9651,6 +9699,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { let body_typed = body_result.typed.clone(); let body_diags = body_result.diagnostics.clone(); let fe_texpr = make_named_expr_node( + texpr.occurrence_identity.clone(), variable.clone(), Rc::new(ExprData::ExprForEach), Rc::new(vec![coll_typed.clone(), body_typed.clone()]), @@ -9707,6 +9756,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { None => Rc::new(vec![]), }; let idx_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprIndex), Rc::new(vec![base_typed.clone(), index_typed.clone()]), idx_inferred.clone(), @@ -9779,6 +9829,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { None => Rc::new(vec![]), }; let slc_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprSlice), Rc::new(vec![ base_typed.clone(), @@ -9804,6 +9855,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { let inner_expr = return_value(texpr.clone()); let inner_result = infer_expr(inner_expr.clone(), scope.clone(), expected.clone()); let ret_texpr = make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprReturn), Rc::new(vec![inner_result.typed.clone()]), inner_result.typed.clone().inferred.clone(), @@ -9818,6 +9870,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { let span = texpr.span.clone(); Rc::new(InferResult { typed: make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "unhandled expression variant in infer_expr".to_string(), span.clone(), @@ -9833,6 +9886,7 @@ if ((call_ambiguity_cands.clone().len() as i64) > 0) { } pub fn infer_variant_constructor_call( + occurrence_identity: Rc, func_name: String, call_args: Rc>>, span: Rc, @@ -9871,12 +9925,14 @@ pub fn infer_variant_constructor_call( None => { let payload_expr = arg_value(arg.clone()); let payload_init = make_field_init_node( + arg.occurrence_identity.clone(), "0".to_string(), payload_expr.clone(), payload_expr.span.clone(), kernel_span("0".to_string()), ); Some(infer_record_lit( + occurrence_identity.clone(), Some(func_name.clone()), Rc::new(vec![payload_init.clone()]), span.clone(), @@ -10607,6 +10663,7 @@ pub fn map_literal_expected_keyed_node( } pub fn infer_map_literal( + occurrence_identity: Rc, map_node: Rc, field_inits: Rc>>, span: Rc, @@ -10635,6 +10692,7 @@ pub fn infer_map_literal( ); Rc::new(FieldInferResult { typed_field: make_field_init_node( + fi.occurrence_identity.clone(), field_init_node_name_at( fi.clone(), scope.type_env.clone().source_indices.clone(), @@ -10652,6 +10710,7 @@ pub fn infer_map_literal( }); Rc::new(InferResult { typed: make_expr_node( + occurrence_identity.clone(), Rc::new(ExprData::ExprRecordLit { parent_enum: None }), Rc::new({ let mut __result = Vec::new(); @@ -10677,6 +10736,7 @@ pub fn infer_map_literal( } pub fn infer_record_lit( + occurrence_identity: Rc, type_name: Option, field_inits: Rc>>, span: Rc, @@ -10686,12 +10746,14 @@ pub fn infer_record_lit( ) -> Rc { match map_literal_expected_keyed_node(type_name.clone(), expected.clone(), scope.clone()) { Some(map_node) => infer_map_literal( + occurrence_identity.clone(), map_node.clone(), field_inits.clone(), span.clone(), scope.clone(), ), None => infer_record_lit_structural( + occurrence_identity.clone(), type_name.clone(), field_inits.clone(), span.clone(), @@ -10703,6 +10765,7 @@ pub fn infer_record_lit( } pub fn infer_record_lit_structural( + occurrence_identity: Rc, type_name: Option, field_inits: Rc>>, span: Rc, @@ -11142,6 +11205,7 @@ pub fn infer_record_lit_structural( }; Rc::new(FieldInferResult { typed_field: make_field_init_node( + fi.occurrence_identity.clone(), fi_name.clone(), ar_typed.clone(), fi.span.clone(), @@ -11186,6 +11250,9 @@ pub fn infer_record_lit_structural( let mut __result = Vec::new(); for fir in fi_infer_results.iter().cloned() { __result.push(Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: field_init_node_name_at( fir.typed_field.clone(), scope.type_env.clone().source_indices.clone(), @@ -11212,6 +11279,7 @@ pub fn infer_record_lit_structural( __result }); let anon_node = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: no_span(), ident_span: None, @@ -11233,6 +11301,7 @@ pub fn infer_record_lit_structural( }); let typed_field_nodes = typed_fields.clone(); let texpr = make_expr_node( + occurrence_identity.clone(), Rc::new(ExprData::ExprRecordLit { parent_enum: None }), typed_field_nodes.clone(), Some(Rc::new(InferredNode::Resolved { @@ -11370,6 +11439,7 @@ pub fn infer_record_lit_structural( None => "".to_string(), }; let texpr = make_named_expr_node( + occurrence_identity.clone(), rl_name.clone(), Rc::new(ExprData::ExprRecordLit { parent_enum: local_variant_parent.clone(), @@ -13530,6 +13600,7 @@ pub fn annotate_descent(body: Rc, ctx: Rc) -> Rc { body_locals: ctx.body_locals.clone(), }); make_arg_node( + child.occurrence_identity.clone(), arg_name_at( child.clone(), ctx.type_env.clone().source_indices.clone(), @@ -13544,6 +13615,7 @@ pub fn annotate_descent(body: Rc, ctx: Rc) -> Rc { } } else { make_arg_node( + child.occurrence_identity.clone(), arg_name_at( child.clone(), ctx.type_env.clone().source_indices.clone(), @@ -13555,6 +13627,7 @@ pub fn annotate_descent(body: Rc, ctx: Rc) -> Rc { } } _ => make_arg_node( + child.occurrence_identity.clone(), arg_name_at( child.clone(), ctx.type_env.clone().source_indices.clone(), @@ -13569,6 +13642,7 @@ pub fn annotate_descent(body: Rc, ctx: Rc) -> Rc { __result }); Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: body.name.clone(), span: body.span.clone(), ident_span: body.ident_span.clone(), @@ -13863,12 +13937,13 @@ match matching.clone() { }, }; let annotated_body = annotate_descent(arm_body(arm_node.clone()), descent_ctx_shadowing_names(arm_ctx.clone(), descent_pattern_bound_names(arm_pattern(arm_node.clone())))); -make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annotated_body.clone(), arm_node.span.clone()) +make_arm_node(arm_node.occurrence_identity.clone(), arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annotated_body.clone(), arm_node.span.clone()) }); } __result }); Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: body.name.clone(), span: body.span.clone(), ident_span: body.ident_span.clone(), @@ -13990,6 +14065,7 @@ make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annota None => Rc::new(vec![annotated_value.clone()]), }; Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: body.name.clone(), span: body.span.clone(), ident_span: body.ident_span.clone(), @@ -14123,6 +14199,7 @@ make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annota }, ); Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: body.name.clone(), span: body.span.clone(), ident_span: body.ident_span.clone(), @@ -14359,6 +14436,7 @@ make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annota }; if is_lambda.clone() { make_arg_node( + arg_node.occurrence_identity.clone(), match arg_name_at( arg_node.clone(), ctx.type_env.clone().source_indices.clone(), @@ -14372,6 +14450,7 @@ make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annota ) } else { make_arg_node( + arg_node.occurrence_identity.clone(), match arg_name_at( arg_node.clone(), ctx.type_env.clone().source_indices.clone(), @@ -14389,6 +14468,9 @@ make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annota __result }); Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: body.name.clone(), span: body.span.clone(), ident_span: body.ident_span.clone(), @@ -14483,6 +14565,7 @@ make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annota let annotated_coll = annotate_descent(coll.clone(), ctx.clone()); let annotated_body = annotate_descent(fe_body.clone(), inner_ctx.clone()); Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: body.name.clone(), span: body.span.clone(), ident_span: body.ident_span.clone(), @@ -16292,6 +16375,9 @@ pub fn infer_property_values( let val_result = infer_expr(val.clone(), scope.clone(), None); Rc::new(PropertyInferenceResult { prop: Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: p.name.clone(), span: p.span.clone(), ident_span: p.ident_span.clone(), @@ -16401,6 +16487,7 @@ match (*service_config_field_judgment(field.clone())).clone() { let val_result = infer_expr(val.clone(), scope.clone(), None); Rc::new(PropertyInferenceResult { prop: Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: p.name.clone(), span: p.span.clone(), ident_span: p.ident_span.clone(), @@ -16473,6 +16560,7 @@ pub fn infer_transport_node( let prop_result = infer_property_values(t.properties.clone(), scope.clone()); Rc::new(InferTransportResult { transport: Some(Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: t.name.clone(), span: t.span.clone(), ident_span: t.ident_span.clone(), @@ -16518,6 +16606,7 @@ pub fn infer_item(item: Rc, scope: Rc) -> Rc { Rc::new(TypedItemResult { item: Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -16638,6 +16727,7 @@ pub fn infer_item(item: Rc, scope: Rc) -> Rc }; Rc::new(TypedItemResult { item: Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -16723,6 +16813,7 @@ pub fn infer_item(item: Rc, scope: Rc) -> Rc ); Rc::new(TypedItemResult { item: Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -16784,6 +16875,7 @@ pub fn infer_item(item: Rc, scope: Rc) -> Rc }; Rc::new(TypedItemResult { item: Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -16814,6 +16906,7 @@ pub fn infer_item(item: Rc, scope: Rc) -> Rc { Rc::new(TypedItemResult { item: Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -16853,6 +16946,7 @@ pub fn infer_item(item: Rc, scope: Rc) -> Rc } else { Rc::new(TypedItemResult { item: Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -17332,6 +17426,9 @@ pub fn substitute_generics_apply( n.clone() } else { Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: n.name.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), @@ -17882,6 +17979,7 @@ pub fn local_binding_for_item( if has_structure.clone() { { let type_node = Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -17911,6 +18009,7 @@ pub fn local_binding_for_item( if ((item.body.clone() != None) && (item.transport.clone() == None)) { { let fn_node = Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -17943,6 +18042,7 @@ pub fn local_binding_for_item( { { let alias_node = Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -17992,6 +18092,7 @@ pub fn local_binding_for_item( { { let bare_node = Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -19635,6 +19736,9 @@ pub fn build_type_env( Rc::new(TypeBinding { name: name.clone(), resolved: Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: name.clone(), span: kernel_span(name.clone()), ident_span: Some(kernel_span(name.clone())), @@ -19666,6 +19770,7 @@ pub fn build_type_env( Rc::new(TypeBinding { name: "Unit".to_string(), resolved: Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Unit".to_string(), span: unit_span.clone(), ident_span: Some(unit_span.clone()), @@ -19689,6 +19794,7 @@ pub fn build_type_env( }), ); let present_value_field = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "value".to_string(), span: kernel_span("value".to_string()), ident_span: Some(kernel_span("value".to_string())), @@ -19711,6 +19817,7 @@ pub fn build_type_env( ident: None, }); let present_variant = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Present".to_string(), span: kernel_span("Present".to_string()), ident_span: Some(kernel_span("Present".to_string())), @@ -19731,6 +19838,7 @@ pub fn build_type_env( ident: None, }); let absent_variant = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Absent".to_string(), span: kernel_span("Absent".to_string()), ident_span: Some(kernel_span("Absent".to_string())), @@ -19751,6 +19859,7 @@ pub fn build_type_env( ident: None, }); let kernel_optional = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Optional".to_string(), span: kernel_span("Optional".to_string()), ident_span: Some(kernel_span("Optional".to_string())), @@ -20290,6 +20399,9 @@ pub fn build_type_env_unresolved( Rc::new(TypeBinding { name: name.clone(), resolved: Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: name.clone(), span: kernel_span(name.clone()), ident_span: Some(kernel_span(name.clone())), @@ -20315,6 +20427,7 @@ pub fn build_type_env_unresolved( }, ); let present_value_field = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "value".to_string(), span: kernel_span("value".to_string()), ident_span: Some(kernel_span("value".to_string())), @@ -20337,6 +20450,7 @@ pub fn build_type_env_unresolved( ident: None, }); let present_variant = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Present".to_string(), span: kernel_span("Present".to_string()), ident_span: Some(kernel_span("Present".to_string())), @@ -20357,6 +20471,7 @@ pub fn build_type_env_unresolved( ident: None, }); let absent_variant = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Absent".to_string(), span: kernel_span("Absent".to_string()), ident_span: Some(kernel_span("Absent".to_string())), @@ -20377,6 +20492,7 @@ pub fn build_type_env_unresolved( ident: None, }); let kernel_optional = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Optional".to_string(), span: kernel_span("Optional".to_string()), ident_span: Some(kernel_span("Optional".to_string())), @@ -20458,6 +20574,7 @@ pub fn build_type_env_unresolved( if has_structure.clone() { { let type_node = Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -20497,6 +20614,7 @@ pub fn build_type_env_unresolved( { { let alias_node = Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -21682,6 +21800,7 @@ pub fn typecheck_module( __result.push( if (item.is_self_recursive.clone() && (item.body.clone() != None)) { Rc::new(Node { + occurrence_identity: item.occurrence_identity.clone(), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), @@ -21722,6 +21841,7 @@ pub fn typecheck_module( variant_locals: ctx.variant_locals.clone(), }); let typed_base = module_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), resolved_module_name.clone(), module_imports(resolved.module.clone()), ctx.resolved_items.clone(), @@ -22856,6 +22976,9 @@ pub fn compiler_kernel_type_env( Rc::new(TypeBinding { name: name.clone(), resolved: Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: name.clone(), span: kernel_span(name.clone()), ident_span: Some(kernel_span(name.clone())), @@ -22887,6 +23010,7 @@ pub fn compiler_kernel_type_env( Rc::new(TypeBinding { name: "Unit".to_string(), resolved: Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Unit".to_string(), span: unit_span.clone(), ident_span: Some(unit_span.clone()), @@ -22910,6 +23034,7 @@ pub fn compiler_kernel_type_env( }), ); let present_value_field = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "value".to_string(), span: kernel_span("value".to_string()), ident_span: Some(kernel_span("value".to_string())), @@ -22932,6 +23057,7 @@ pub fn compiler_kernel_type_env( ident: None, }); let present_variant = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Present".to_string(), span: kernel_span("Present".to_string()), ident_span: Some(kernel_span("Present".to_string())), @@ -22952,6 +23078,7 @@ pub fn compiler_kernel_type_env( ident: None, }); let absent_variant = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Absent".to_string(), span: kernel_span("Absent".to_string()), ident_span: Some(kernel_span("Absent".to_string())), @@ -22972,6 +23099,7 @@ pub fn compiler_kernel_type_env( ident: None, }); let kernel_optional = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Optional".to_string(), span: kernel_span("Optional".to_string()), ident_span: Some(kernel_span("Optional".to_string())), diff --git a/src/v1/stage0/src/v1_compiler_infer_env.rs b/src/v1/stage0/src/v1_compiler_infer_env.rs index 3971226ac13..c361c5ddbaa 100644 --- a/src/v1/stage0/src/v1_compiler_infer_env.rs +++ b/src/v1/stage0/src/v1_compiler_infer_env.rs @@ -8,6 +8,8 @@ use crate::std_induction::RecursionShape::{ }; use crate::std_induction::SubValueRelation::{PreservedValue, SubValueUnknown}; pub use crate::std_induction::{InductiveField, RecursionShape, SubValueRelation}; +pub use crate::std_occurrence_identity::NodeOccurrenceIdentity; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic; pub use crate::std_syntax::BinOp; use crate::std_syntax::BinOp::*; pub use crate::std_types::is_kernel_type; @@ -1312,6 +1314,9 @@ pub fn qualify_borrowed_type_names( let qname = v1_rt::concat(v1_rt::concat(mp.clone(), ".".to_string()), name.clone()); Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: qname.clone(), span: n.span.clone(), ident_span: Some(kernel_span(qname.clone())), @@ -1341,6 +1346,7 @@ pub fn qualify_borrowed_type_names( pub fn node_with_children(n: Rc, children: Rc>>) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: n.name.clone(), ident: n.ident.clone(), span: n.span.clone(), @@ -1364,6 +1370,7 @@ pub fn node_with_children(n: Rc, children: Rc>>) -> Rc pub fn node_with_inferred(n: Rc, inferred: Option>) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: n.name.clone(), ident: n.ident.clone(), span: n.span.clone(), @@ -1940,6 +1947,7 @@ pub fn env_with_type_variable_bindings(env: Rc, tp_names: Rc Rc { pub fn type_variable_node(id: String) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: no_span(), ident_span: None, diff --git a/src/v1/stage0/src/v1_compiler_infer_patterns.rs b/src/v1/stage0/src/v1_compiler_infer_patterns.rs index 4c46ac8baf0..dde25c1b25c 100644 --- a/src/v1/stage0/src/v1_compiler_infer_patterns.rs +++ b/src/v1/stage0/src/v1_compiler_infer_patterns.rs @@ -3,6 +3,8 @@ use self::NodeLookupStatus::*; use self::PatternSubject::*; +pub use crate::std_occurrence_identity::NodeOccurrenceIdentity; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic; pub use crate::std_syntax::BinOp; use crate::std_syntax::BinOp::*; pub use crate::std_syntax::LiteralValue; @@ -287,6 +289,7 @@ pub fn synthesize_optional_present_variant(scrut: Rc) -> Rc { { let inner = extract_optional_inner_node(scrut.clone()); let value_field = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "value".to_string(), span: scrut.span.clone(), ident_span: Some(kernel_span("value".to_string())), @@ -309,6 +312,7 @@ pub fn synthesize_optional_present_variant(scrut: Rc) -> Rc { ident: None, }); let present_node = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Present".to_string(), span: scrut.span.clone(), ident_span: Some(kernel_span("Present".to_string())), @@ -339,6 +343,7 @@ pub fn synthesize_witness_holds_variant(scrut: Rc) -> Rc { None => error_type(), }; let value_field = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "value".to_string(), span: scrut.span.clone(), ident_span: Some(kernel_span("value".to_string())), @@ -361,6 +366,7 @@ pub fn synthesize_witness_holds_variant(scrut: Rc) -> Rc { ident: None, }); Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Holds".to_string(), span: scrut.span.clone(), ident_span: Some(kernel_span("Holds".to_string())), @@ -386,6 +392,7 @@ pub fn synthesize_witness_holds_variant(scrut: Rc) -> Rc { pub fn synthesize_witness_violates_variant(scrut: Rc) -> Rc { { let diagnostic_type = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Diagnostic".to_string(), span: scrut.span.clone(), ident_span: Some(kernel_span("Diagnostic".to_string())), @@ -406,6 +413,7 @@ pub fn synthesize_witness_violates_variant(scrut: Rc) -> Rc { ident: None, }); let diagnostic_field = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "diagnostic".to_string(), span: scrut.span.clone(), ident_span: Some(kernel_span("diagnostic".to_string())), @@ -428,6 +436,7 @@ pub fn synthesize_witness_violates_variant(scrut: Rc) -> Rc { ident: None, }); Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Violates".to_string(), span: scrut.span.clone(), ident_span: Some(kernel_span("Violates".to_string())), diff --git a/src/v1/stage0/src/v1_compiler_infer_resolve.rs b/src/v1/stage0/src/v1_compiler_infer_resolve.rs index f5e222d7ff5..d634e86e5c0 100644 --- a/src/v1/stage0/src/v1_compiler_infer_resolve.rs +++ b/src/v1/stage0/src/v1_compiler_infer_resolve.rs @@ -4,6 +4,8 @@ use self::AliasKind::*; pub use crate::std_induction::SubValueRelation; use crate::std_induction::SubValueRelation::SubValueUnknown; +pub use crate::std_occurrence_identity::NodeOccurrenceIdentity; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic; pub use crate::std_syntax::BinOp; use crate::std_syntax::BinOp::*; pub use crate::std_syntax::LiteralValue; @@ -174,6 +176,7 @@ pub fn is_type_variable(inferred: Rc) -> bool { pub fn with_authored_identity(identity: Rc, structural: Rc) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: structural.name.clone(), ident: structural.ident.clone(), span: structural.span.clone(), @@ -554,6 +557,7 @@ pub fn substitute_type_slots_scoped( __result }); Rc::new(Node { + occurrence_identity: child.occurrence_identity.clone(), name: child.name.clone(), span: child.span.clone(), ident_span: child.ident_span.clone(), @@ -604,6 +608,7 @@ pub fn substitute_type_slots_scoped( _ => n.inferred.clone(), }; Rc::new(Node { + occurrence_identity: n.occurrence_identity.clone(), name: n.name.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), @@ -728,6 +733,7 @@ pub fn resolve_nominal_alias_rhs( let validation = resolve_node(n.clone(), env.clone(), module_name.clone()); Rc::new(NodeResolveResult { resolved: Rc::new(Node { + occurrence_identity: n.occurrence_identity.clone(), name: n.name.clone(), ident: n.ident.clone(), span: n.span.clone(), @@ -819,6 +825,7 @@ pub fn resolve_node_bounded( let base_diags = base_result.diagnostics.clone(); Rc::new(NodeResolveResult { resolved: Rc::new(Node { + occurrence_identity: n.occurrence_identity.clone(), name: n.name.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), @@ -870,6 +877,9 @@ pub fn resolve_node_bounded( let rt_diags = rt_result.diagnostics.clone(); Rc::new(NodeResolveResult { resolved: Rc::new(Node { + occurrence_identity: child + .occurrence_identity + .clone(), name: child.name.clone(), span: child.span.clone(), ident_span: child.ident_span.clone(), @@ -921,6 +931,7 @@ pub fn resolve_node_bounded( }); Rc::new(NodeResolveResult { resolved: Rc::new(Node { + occurrence_identity: n.occurrence_identity.clone(), name: n.name.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), @@ -1024,6 +1035,7 @@ pub fn resolve_node_bounded( rt_result.diagnostics.clone(); Rc::new(NodeResolveResult { resolved: Rc::new(Node { + occurrence_identity: field_child.occurrence_identity.clone(), name: field_child.name.clone(), span: field_child.span.clone(), ident_span: field_child.ident_span.clone(), @@ -1071,6 +1083,9 @@ pub fn resolve_node_bounded( }); Rc::new(NodeResolveResult { resolved: Rc::new(Node { + occurrence_identity: variant_child + .occurrence_identity + .clone(), name: variant_child.name.clone(), span: variant_child.span.clone(), ident_span: variant_child.ident_span.clone(), @@ -1116,6 +1131,7 @@ pub fn resolve_node_bounded( }); Rc::new(NodeResolveResult { resolved: Rc::new(Node { + occurrence_identity: n.occurrence_identity.clone(), name: n.name.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), @@ -1275,6 +1291,9 @@ pub fn resolve_node_bounded( let is_recursive = is_recursive_type_by_name(env.clone(), type_name.clone()); let expanded_node = Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: type_name.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), @@ -1295,6 +1314,7 @@ pub fn resolve_node_bounded( ident: None, }); let resolved_node = Rc::new(Node { + occurrence_identity: n.occurrence_identity.clone(), name: type_name.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), @@ -1341,6 +1361,9 @@ pub fn resolve_node_bounded( let is_recursive = is_recursive_type_by_name(env.clone(), type_name.clone()); let expanded_node = Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: type_name.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), @@ -1362,6 +1385,7 @@ pub fn resolve_node_bounded( }); let result = Rc::new(NodeResolveResult { resolved: Rc::new(Node { + occurrence_identity: n.occurrence_identity.clone(), name: type_name.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), @@ -1441,6 +1465,7 @@ pub fn resolve_node_bounded( } }; let resolved_key_child = Rc::new(Node { + occurrence_identity: key_child_node.occurrence_identity.clone(), name: key_param_name.clone(), span: key_child_node.span.clone(), ident_span: key_child_node.ident_span.clone(), @@ -1463,6 +1488,7 @@ pub fn resolve_node_bounded( ident: None, }); let resolved_val_child = Rc::new(Node { + occurrence_identity: val_child_node.occurrence_identity.clone(), name: val_param_name.clone(), span: val_child_node.span.clone(), ident_span: val_child_node.ident_span.clone(), @@ -1486,6 +1512,7 @@ pub fn resolve_node_bounded( }); Rc::new(NodeResolveResult { resolved: Rc::new(Node { + occurrence_identity: n.occurrence_identity.clone(), name: type_name.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), @@ -1539,6 +1566,9 @@ pub fn resolve_node_bounded( } }; let resolved_child = Rc::new(Node { + occurrence_identity: child_node + .occurrence_identity + .clone(), name: el_param_name.clone(), span: child_node.span.clone(), ident_span: child_node.ident_span.clone(), @@ -1562,6 +1592,7 @@ pub fn resolve_node_bounded( }); Rc::new(NodeResolveResult { resolved: Rc::new(Node { + occurrence_identity: n.occurrence_identity.clone(), name: type_name.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), @@ -1874,6 +1905,7 @@ pub fn resolve_optional_node( .. } => Rc::new(NodeResolveResult { resolved: make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::SemanticExprError, msg.clone(), sp.clone(), @@ -1888,6 +1920,7 @@ pub fn resolve_optional_node( }), InferredNode::TypeVariable { id: tv, .. } => Rc::new(NodeResolveResult { resolved: Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: tv.clone(), span: kernel_span(tv.clone()), ident_span: Some(kernel_span(tv.clone())), @@ -1944,6 +1977,7 @@ pub fn resolve_field( }; Rc::new(FieldResolveResult { field: make_field_node( + field.occurrence_identity.clone(), field_node_name_at(field.clone(), env.source_indices.clone()), type_resolved.clone(), field_node_cardinality(field.clone()), @@ -1951,7 +1985,17 @@ pub fn resolve_field( Some(result) => Some(result.expr.clone()), None => None, }, - field_node_from_key(field.clone(), env.source_indices.clone()), + Rc::new({ + let mut __result = Vec::new(); + for p in field.properties.clone().iter().cloned() { + if (field_init_node_name_at(p.clone(), env.source_indices.clone()) + == "from_key".to_string()) + { + __result.push(p); + } + } + __result + }), field.span.clone(), node_name_span(field.clone()), ), @@ -1971,6 +2015,7 @@ pub fn resolve_param( let type_resolved = type_result.resolved.clone(); let rendered_type = if ((authored_type.children.clone().len() as i64) > 0) { Rc::new(Node { + occurrence_identity: authored_type.occurrence_identity.clone(), name: authored_type.name.clone(), span: authored_type.span.clone(), ident_span: authored_type.ident_span.clone(), @@ -2021,6 +2066,7 @@ pub fn resolve_param( }; Rc::new(ParamResolveResult { param: make_resolved_param_node( + param.occurrence_identity.clone(), param_node_name_at(param.clone(), env.source_indices.clone()), rendered_type.clone(), default_expr.clone(), @@ -2048,6 +2094,7 @@ pub fn resolve_resource_use( let type_diags = type_result.diagnostics.clone(); Rc::new(ResourceUseResult { resource_use: make_resource_use_node( + ru.occurrence_identity.clone(), resource_use_name_at(ru.clone(), env.source_indices.clone()), type_resolved.clone(), ru.span.clone(), @@ -2070,6 +2117,7 @@ pub fn resolve_named_arg( let value_diags = value_result.diagnostics.clone(); Rc::new(NamedArgResolveResult { arg: make_arg_node( + arg.occurrence_identity.clone(), arg_name_at(arg.clone(), env.source_indices.clone()), value_expr.clone(), arg.span.clone(), @@ -2095,6 +2143,7 @@ pub fn resolve_field_init( let value_diags = value_result.diagnostics.clone(); Rc::new(FieldInitResolveResult { field_init: make_field_init_node( + field_init.occurrence_identity.clone(), field_init_node_name_at(field_init.clone(), env.source_indices.clone()), value_expr.clone(), field_init.span.clone(), @@ -2130,6 +2179,7 @@ pub fn resolve_match_arm( let body_diags = body_result.diagnostics.clone(); Rc::new(MatchArmResolveResult { arm: make_arm_node( + arm.occurrence_identity.clone(), arm_pattern(arm.clone()), match guard_result.clone() { Some(result) => Some(result.expr.clone()), @@ -2192,6 +2242,7 @@ pub fn resolve_transport_binding( ); Rc::new(FieldInitResolveResult { field_init: make_field_init_node( + p.occurrence_identity.clone(), field_init_node_name_at(p.clone(), env.source_indices.clone()), val_result.expr.clone(), p.span.clone(), @@ -2257,6 +2308,7 @@ pub fn resolve_transport_binding( }; Rc::new(TransportResolveResult { transport: make_transport_node( + transport.occurrence_identity.clone(), resolved_props.clone(), resolved_children.clone(), transport.body.clone(), @@ -2283,7 +2335,12 @@ pub fn resolve_expr_types( diagnostics: Rc::new(vec![]), }), ExprData::ExprError { kind, message, .. } => Rc::new(ExprResolveResult { - expr: make_expr_error_node(kind.clone(), message.clone(), texpr.span.clone()), + expr: make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + kind.clone(), + message.clone(), + texpr.span.clone(), + ), diagnostics: Rc::new(vec![make_error_node( Rc::new(CompilerDiagnostic::InternalError { message: message.clone(), @@ -2330,6 +2387,7 @@ pub fn resolve_expr_types( resolve_expr_types(val.clone(), env.clone(), module_name.clone()); Rc::new(ExprResolveResult { expr: make_arg_node( + arg_node.occurrence_identity.clone(), if (arg_node.ident_span.clone() == None) { None } else { @@ -2361,6 +2419,7 @@ pub fn resolve_expr_types( }); Rc::new(ExprResolveResult { expr: make_named_expr_node( + texpr.occurrence_identity.clone(), expr_call_func_at(texpr.clone(), env.source_indices.clone()), Rc::new(ExprData::ExprCall { call_semantics: cs.clone(), @@ -2421,6 +2480,7 @@ pub fn resolve_expr_types( ); Rc::new(ExprResolveResult { expr: make_arg_node( + child.occurrence_identity.clone(), if (child.ident_span.clone() == None) { None } else { @@ -2457,6 +2517,7 @@ pub fn resolve_expr_types( }); Rc::new(ExprResolveResult { expr: make_named_expr_node( + texpr.occurrence_identity.clone(), expr_method_name_at(texpr.clone(), env.source_indices.clone()), Rc::new(ExprData::ExprMethodCall { method_semantics: ms.clone(), @@ -2536,6 +2597,7 @@ pub fn resolve_expr_types( }; Rc::new(ExprResolveResult { expr: make_arm_node( + child.occurrence_identity.clone(), match child.match_pattern.clone() { Some(p) => p.clone(), None => Rc::new(MatchPattern::Wildcard), @@ -2565,6 +2627,7 @@ pub fn resolve_expr_types( }; Rc::new(ExprResolveResult { expr: make_arm_node( + child.occurrence_identity.clone(), match child.match_pattern.clone() { Some(p) => p.clone(), None => Rc::new(MatchPattern::Wildcard), @@ -2599,6 +2662,7 @@ pub fn resolve_expr_types( }); Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprMatch), resolved_children.clone(), texpr.inferred.clone(), @@ -2637,6 +2701,7 @@ pub fn resolve_expr_types( }; Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprIf), resolved_children.clone(), texpr.inferred.clone(), @@ -2701,6 +2766,7 @@ pub fn resolve_expr_types( } }; let let_node = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: let_binding_name_at(texpr.clone(), env.source_indices.clone()), span: texpr.span.clone(), ident_span: default_ident_span( @@ -2752,6 +2818,7 @@ pub fn resolve_expr_types( resolve_expr_types(val.clone(), env.clone(), module_name.clone()); Rc::new(ExprResolveResult { expr: make_field_init_node( + fi_node.occurrence_identity.clone(), authored_name(env.clone(), fi_node.clone()), vr.expr.clone(), fi_node.span.clone(), @@ -2779,6 +2846,7 @@ pub fn resolve_expr_types( }); Rc::new(ExprResolveResult { expr: make_named_expr_node( + texpr.occurrence_identity.clone(), authored_name_at(env.source_indices.clone(), texpr.clone()), Rc::new(ExprData::ExprRecordLit { parent_enum: pe.clone(), @@ -2819,6 +2887,7 @@ pub fn resolve_expr_types( }); Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprListLit), resolved_children.clone(), texpr.inferred.clone(), @@ -2849,6 +2918,7 @@ pub fn resolve_expr_types( }; Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprBinOp { op: op.clone(), algebra_field: af.clone(), @@ -2870,6 +2940,7 @@ pub fn resolve_expr_types( }; Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprUnaryOp { op: op.clone() }), Rc::new(vec![r.expr.clone()]), texpr.inferred.clone(), @@ -2897,6 +2968,7 @@ pub fn resolve_expr_types( }; Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprLambda), v1_rt::concat(Rc::new(vec![r.expr.clone()]), lam_param_nodes.clone()), texpr.inferred.clone(), @@ -2923,6 +2995,7 @@ pub fn resolve_expr_types( ); Rc::new(ExprResolveResult { expr: make_interp_part_node( + part_node.occurrence_identity.clone(), r.expr.clone(), part_node.span.clone(), ), @@ -2954,6 +3027,7 @@ pub fn resolve_expr_types( }); Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprStringInterp), resolved_children.clone(), texpr.inferred.clone(), @@ -2990,6 +3064,7 @@ pub fn resolve_expr_types( }); Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprBlock), resolved_children.clone(), texpr.inferred.clone(), @@ -3018,6 +3093,7 @@ pub fn resolve_expr_types( }; Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprCast), Rc::new(vec![r.expr.clone(), tr.resolved.clone()]), texpr.inferred.clone(), @@ -3044,6 +3120,7 @@ pub fn resolve_expr_types( }; Rc::new(ExprResolveResult { expr: make_named_expr_node( + texpr.occurrence_identity.clone(), foreach_variable_at(texpr.clone(), env.source_indices.clone()), Rc::new(ExprData::ExprForEach), Rc::new(vec![cr.expr.clone(), br.expr.clone()]), @@ -3076,6 +3153,7 @@ pub fn resolve_expr_types( }; Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprIndex), Rc::new(vec![br.expr.clone(), ir.expr.clone()]), texpr.inferred.clone(), @@ -3115,6 +3193,7 @@ pub fn resolve_expr_types( }; Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprSlice), Rc::new(vec![br.expr.clone(), sr.expr.clone(), er.expr.clone()]), texpr.inferred.clone(), @@ -3138,6 +3217,7 @@ pub fn resolve_expr_types( }; Rc::new(ExprResolveResult { expr: make_expr_node( + texpr.occurrence_identity.clone(), Rc::new(ExprData::ExprReturn), Rc::new(vec![r.expr.clone()]), texpr.inferred.clone(), @@ -3366,7 +3446,10 @@ pub fn resolve_item_types( let anno_diags = anno_resolved.diagnostics.clone(); let transport_resolved = if (item.transport.clone() == None) { Rc::new(TransportResolveResult { - transport: local_transport_node(no_span()), + transport: local_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + no_span(), + ), diagnostics: Rc::new(vec![]), }) } else { @@ -3427,6 +3510,7 @@ pub fn resolve_item_types( ); Rc::new(ItemResolveResult { item: Rc::new(Node { + occurrence_identity: child.occurrence_identity.clone(), name: child.name.clone(), span: child.span.clone(), ident_span: child.ident_span.clone(), @@ -3481,6 +3565,9 @@ pub fn resolve_item_types( ); Rc::new(ItemResolveResult { item: Rc::new(Node { + occurrence_identity: field + .occurrence_identity + .clone(), name: field.name.clone(), span: field.span.clone(), ident_span: field.ident_span.clone(), @@ -3527,6 +3614,7 @@ pub fn resolve_item_types( }); Rc::new(ItemResolveResult { item: Rc::new(Node { + occurrence_identity: variant.occurrence_identity.clone(), name: variant.name.clone(), span: variant.span.clone(), ident_span: variant.ident_span.clone(), @@ -3582,6 +3670,7 @@ pub fn resolve_item_types( }); Rc::new(ItemResolveResult { item: Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: item.name.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), diff --git a/src/v1/stage0/src/v1_compiler_infer_service.rs b/src/v1/stage0/src/v1_compiler_infer_service.rs index 2c18a2c86d4..d92172a23d5 100644 --- a/src/v1/stage0/src/v1_compiler_infer_service.rs +++ b/src/v1/stage0/src/v1_compiler_infer_service.rs @@ -1,6 +1,8 @@ // Generated by v1 compiler -- do not edit. // Source module: v1.compiler.infer_service +pub use crate::std_occurrence_identity::NodeOccurrenceIdentity; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic; pub use crate::std_syntax::BinOp; use crate::std_syntax::BinOp::*; pub use crate::std_types::SourceSpan; @@ -415,6 +417,9 @@ pub fn check_service_method_call_node( } else { Some(Rc::new(ServiceMethodResult { result_type: Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "".to_string(), span: no_span(), ident_span: None, @@ -422,6 +427,9 @@ pub fn check_service_method_call_node( let mut __result = Vec::new(); for f in op.outputs.clone().iter().cloned() { __result.push(Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: f.name.clone(), span: f.span.clone(), ident_span: f.ident_span.clone(), diff --git a/src/v1/stage0/src/v1_compiler_infer_types.rs b/src/v1/stage0/src/v1_compiler_infer_types.rs index 4906512027c..3f53c66f222 100644 --- a/src/v1/stage0/src/v1_compiler_infer_types.rs +++ b/src/v1/stage0/src/v1_compiler_infer_types.rs @@ -16,6 +16,8 @@ pub use crate::std_algebra::{algebra_templates_for_profile, kernel_algebra_profi pub use crate::std_algebra::{ AlgebraFieldTemplate, AlgebraProfile, AlgebraTypeTemplate, ContainerSource, }; +pub use crate::std_occurrence_identity::NodeOccurrenceIdentity; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic; use crate::std_syntax::AlgebraFieldKind::AlgAdd; use crate::std_syntax::AlgebraFieldKind::{ AlgCompare, AlgJoin, AlgMeet, AlgMul, AlgQuotient, AlgReciprocal, AlgRemainder, @@ -71,6 +73,7 @@ pub fn is_type_variable(inferred: Rc) -> bool { pub fn type_variable_node(id: String) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: no_span(), ident_span: None, @@ -236,6 +239,7 @@ pub fn reground_alias_carrier_identity( && is_declared_container_alias_spelling(n.name.clone())) { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: n.name.clone(), span: n.span.clone(), ident_span: Some(kernel_span(n.name.clone())), @@ -267,6 +271,7 @@ pub fn structural_carrier_template_name( if (n.name.clone() != "".to_string()) { canonical_template_name( Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: n.name.clone(), span: n.span.clone(), ident_span: Some(kernel_span(n.name.clone())), @@ -415,11 +420,13 @@ pub fn bare_map_node() -> Option> { match container_param_name("Map".to_string(), 0) { Some(key_id) => match container_param_name("Map".to_string(), 1) { Some(val_id) => Some(Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Map".to_string(), span: no_span(), ident_span: Some(no_span()), children: Rc::new(vec![ Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: key_id.clone(), span: no_span(), ident_span: Some(no_span()), @@ -442,6 +449,7 @@ pub fn bare_map_node() -> Option> { ident: None, }), Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: val_id.clone(), span: no_span(), ident_span: Some(no_span()), @@ -488,10 +496,12 @@ pub fn bare_map_node() -> Option> { pub fn bare_set_node() -> Option> { match container_param_name("Set".to_string(), 0) { Some(elem_id) => Some(Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Set".to_string(), span: no_span(), ident_span: Some(no_span()), children: Rc::new(vec![Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: elem_id.clone(), span: no_span(), ident_span: Some(no_span()), @@ -555,6 +565,7 @@ pub fn missing_kernel_container_profile_type(kind_name: String) -> Rc { kind_name.clone(), ); Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: no_span(), ident_span: None, @@ -600,6 +611,7 @@ pub fn kernel_record_type_note() -> String { pub fn make_kernel_record_field(field_name: String, field_type: Rc) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: field_name.clone(), span: kernel_span(field_name.clone()), ident_span: Some(kernel_span(field_name.clone())), @@ -625,6 +637,7 @@ pub fn make_kernel_record_field(field_name: String, field_type: Rc) -> Rc< pub fn make_kernel_record_type(type_name: String, fields: Rc>>) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: type_name.clone(), span: kernel_span(type_name.clone()), ident_span: Some(kernel_span(type_name.clone())), @@ -650,10 +663,12 @@ pub fn make_container_type(kind_name: String, element: Rc) -> Rc Rc::new(KernelTypeBuild { ty: Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: kind_name.clone(), span: kernel_span(kind_name.clone()), ident_span: Some(kernel_span(kind_name.clone())), children: Rc::new(vec![Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: param_name.clone(), span: kernel_span(param_name.clone()), ident_span: Some(kernel_span(param_name.clone())), @@ -706,11 +721,15 @@ pub fn make_map_type(key: Rc, value: Rc) -> Rc { Some(key_name) => match container_param_name("Map".to_string(), 1) { Some(val_name) => Rc::new(KernelTypeBuild { ty: Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Map".to_string(), span: kernel_span("Map".to_string()), ident_span: Some(kernel_span("Map".to_string())), children: Rc::new(vec![ Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: key_name.clone(), span: kernel_span(key_name.clone()), ident_span: Some(kernel_span(key_name.clone())), @@ -731,6 +750,9 @@ pub fn make_map_type(key: Rc, value: Rc) -> Rc { ident: None, }), Rc::new(Node { + occurrence_identity: Rc::new( + NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: val_name.clone(), span: kernel_span(val_name.clone()), ident_span: Some(kernel_span(val_name.clone())), @@ -788,6 +810,7 @@ pub fn make_map_type(key: Rc, value: Rc) -> Rc { pub fn make_callable_type(func_params: Rc>>, ret: Rc) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Callable".to_string(), span: kernel_span("Callable".to_string()), ident_span: Some(kernel_span("Callable".to_string())), @@ -811,11 +834,13 @@ pub fn make_callable_type(func_params: Rc>>, ret: Rc) -> Rc, second: Rc) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: no_span(), ident_span: None, children: Rc::new(vec![ Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "first".to_string(), span: kernel_span("first".to_string()), ident_span: Some(kernel_span("first".to_string())), @@ -838,6 +863,7 @@ pub fn make_tuple_type(first: Rc, second: Rc) -> Rc { ident: None, }), Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "second".to_string(), span: kernel_span("second".to_string()), ident_span: Some(kernel_span("second".to_string())), @@ -879,6 +905,7 @@ pub fn make_tuple_type(first: Rc, second: Rc) -> Rc { pub fn algebra_value_field(name: String, type_node: Rc) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: kernel_span(name.clone()), ident_span: Some(kernel_span(name.clone())), @@ -912,6 +939,7 @@ pub fn algebra_method_field( let mut __result = Vec::new(); for t in param_types.iter().cloned() { __result.push(make_param_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "_".to_string(), t.clone(), None, @@ -923,6 +951,7 @@ pub fn algebra_method_field( }); let callable = make_callable_type(params.clone(), return_type.clone()); Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: kernel_span(name.clone()), ident_span: Some(kernel_span(name.clone())), @@ -953,6 +982,7 @@ pub fn enrich_base_with_fields( fields: Rc>>, ) -> Rc { Rc::new(Node { + occurrence_identity: base.occurrence_identity.clone(), name: name.clone(), span: base.span.clone(), ident_span: base.ident_span.clone(), @@ -979,7 +1009,11 @@ pub fn placeholder_type_node(name: String) -> Rc { } pub fn nominal_type_ref(name: String) -> Rc { - leaf_node_with_span(name.clone(), kernel_span(name.clone())) + leaf_node_with_span( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + name.clone(), + kernel_span(name.clone()), + ) } pub fn algebra_child_or_placeholder( @@ -1147,6 +1181,7 @@ pub fn instantiate_algebra_type( let mut __result = Vec::new(); for pn in param_nodes.iter().cloned() { __result.push(make_param_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "_".to_string(), pn.clone(), None, @@ -1842,6 +1877,7 @@ pub fn apply_type_substitution( let mut __result = Vec::new(); for pn in param_nodes.iter().cloned() { __result.push(make_param_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "_".to_string(), pn.clone(), None, diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index 626e7089761..3003bc673a6 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -10,6 +10,9 @@ use self::ParserHelperIdentity::*; use self::ParserResultWitness::*; pub use crate::extdeps_languages_dag_syntax::{dag_non_name_keywords, dag_syntax_spec}; pub use crate::std_algebra::FreeMonoid; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::{ + OccurrenceMinted, OccurrenceProjected, OccurrenceSynthetic, +}; use crate::std_occurrence_identity::OccurrenceCategory::{ CallableOccurrence, FieldOccurrence, LexicalValueOccurrence, MethodOccurrence, NamespaceSegmentOccurrence, TypeOccurrence, @@ -18,10 +21,11 @@ pub use crate::std_occurrence_identity::OccurrenceRole; use crate::std_occurrence_identity::OccurrenceRole::*; pub use crate::std_occurrence_identity::{ alloc_occurrence_id, authored_token_ordinal_space_from_allocator, - occurrence_id_allocator_advance_to, occurrence_id_allocator_initial, + node_occurrence_identity_minted, occurrence_id_allocator_advance_to, + occurrence_id_allocator_initial, }; pub use crate::std_occurrence_identity::{ - AuthoredTokenOrdinalSpace, DeclarationOccurrence, OccurrenceCategory, + AuthoredTokenOrdinalSpace, DeclarationOccurrence, NodeOccurrenceIdentity, OccurrenceCategory, OccurrenceContainmentPath, OccurrenceId, OccurrenceIdAllocResult, OccurrenceIdAllocator, OccurrenceIndex, OccurrenceIndexEntry, OccurrenceProjection, OccurrenceTransport, ReferenceOccurrence, @@ -165,24 +169,28 @@ pub struct ParseWithTableResult { pub struct ParsedNodeStampResult { pub node: Rc, pub ctx: Rc, + pub err: Option>, } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct ParsedNodeListStampResult { pub nodes: Rc>>, pub ctx: Rc, + pub err: Option>, } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct ParsedOptionalNodeStampResult { pub node: Option>, pub ctx: Rc, + pub err: Option>, } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct ParsedPatternStampResult { pub pattern: Option>, pub ctx: Rc, + pub err: Option>, } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] @@ -208,6 +216,28 @@ impl ParsedOccurrenceRole { } } +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct ParsedNodeIdentityMint { + pub identity: Rc, + pub ctx: Rc, +} + +pub fn mint_parsed_node_identity(ctx: Rc) -> Rc { + { + let allocated = alloc_occurrence_id(parse_context_occurrence_allocator(ctx.clone())); + Rc::new(ParsedNodeIdentityMint { + identity: node_occurrence_identity_minted(allocated.id.clone()), + ctx: parse_context_with_occurrence_state( + ctx.clone(), + Some(allocated.alloc.clone()), + ctx.occurrence_index.clone(), + ctx.declaration_occurrences.clone(), + ctx.reference_occurrences.clone(), + ), + }) + } +} + pub fn parse_context_occurrence_allocator(ctx: Rc) -> OccurrenceIdAllocator { match ctx.occurrence_allocator.clone() { Some(allocator) => allocator.clone(), @@ -277,6 +307,7 @@ pub fn parse_context_with_intern_table( pub fn parsed_node_with_ident(node: Rc, ident: i64) -> Rc { Rc::new(Node { + occurrence_identity: node.occurrence_identity.clone(), name: node.name.clone(), ident: Some(ident.clone()), span: node.span.clone(), @@ -501,6 +532,197 @@ pub struct ResUseResult { pub err: Option>, } +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct ParsedPropertiesResult { + pub properties: Rc>>, + pub ctx: Rc, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct ParsedPropertyResult { + pub property: Rc, + pub ctx: Rc, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct ParsedNodesResult { + pub nodes: Rc>>, + pub ctx: Rc, +} + +pub fn parsed_expr_result( + tokens: Rc, + ctx: Rc, + build: impl Fn(Rc) -> Rc + Clone, +) -> Rc { + { + let minted = mint_parsed_node_identity(ctx.clone()); + Rc::new(ExprResult { + expr: build(minted.identity.clone()), + tokens: tokens.clone(), + ctx: minted.ctx.clone(), + err: None, + }) + } +} + +pub fn parsed_sole_constructor_properties( + ctx: Rc, + enabled: bool, + span: Rc, +) -> Rc { + if enabled.clone() { + { + let value_mint = mint_parsed_node_identity(ctx.clone()); + let property_mint = mint_parsed_node_identity(value_mint.ctx.clone()); + Rc::new(ParsedPropertiesResult { + properties: Rc::new(vec![make_field_init_node( + property_mint.identity.clone(), + "sole_constructor".to_string(), + make_expr_node( + value_mint.identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitBool { value: true }), + }), + Rc::new(vec![]), + None, + span.clone(), + ), + span.clone(), + no_span(), + )]), + ctx: property_mint.ctx.clone(), + }) + } + } else { + Rc::new(ParsedPropertiesResult { + properties: Rc::new(vec![]), + ctx: ctx.clone(), + }) + } +} + +pub fn mint_parsed_bool_property( + ctx: Rc, + name: String, + span: Rc, +) -> Rc { + { + let value_mint = mint_parsed_node_identity(ctx.clone()); + let property_mint = mint_parsed_node_identity(value_mint.ctx.clone()); + Rc::new(ParsedPropertyResult { + property: make_field_init_node( + property_mint.identity.clone(), + name.clone(), + make_expr_node( + value_mint.identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitBool { value: true }), + }), + Rc::new(vec![]), + None, + span.clone(), + ), + span.clone(), + span.clone(), + ), + ctx: property_mint.ctx.clone(), + }) + } +} + +pub fn mint_parsed_optional_int_property( + ctx: Rc, + name: String, + value: Option, + span: Rc, +) -> Rc { + match value.clone() { + Some(n) => { + let value_mint = mint_parsed_node_identity(ctx.clone()); + let property_mint = mint_parsed_node_identity(value_mint.ctx.clone()); + Rc::new(ParsedPropertiesResult { + properties: Rc::new(vec![make_field_init_node( + property_mint.identity.clone(), + name.clone(), + make_expr_node( + value_mint.identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitInt { value: n.clone() }), + }), + Rc::new(vec![]), + None, + span.clone(), + ), + span.clone(), + span.clone(), + )]), + ctx: property_mint.ctx.clone(), + }) + } + None => Rc::new(ParsedPropertiesResult { + properties: Rc::new(vec![]), + ctx: ctx.clone(), + }), + } +} + +pub fn mint_parsed_string_part_nodes( + mut parts: Rc>>, + mut ctx: Rc, + mut span: Rc, + mut acc: Rc>>, +) -> Rc { + loop { + match parts.clone().first().cloned() { + Some(part) => { + let minted = mint_parsed_node_identity(ctx.clone()); + let node = match (*part.clone()).clone() { + StringPart::Text { value: text, .. } => { + make_text_part_node(minted.identity.clone(), text.clone(), span.clone()) + } + StringPart::Interpolation { expr: expr, .. } => { + make_interp_part_node(minted.identity.clone(), expr.clone(), span.clone()) + } + }; + { + let __tco_0 = + Rc::new(parts.iter().cloned().skip(1 as usize).collect::>()); + let __tco_1 = minted.ctx.clone(); + let __tco_2 = v1_rt::rc_list_push(acc, node.clone()); + parts = __tco_0; + ctx = __tco_1; + acc = __tco_2; + continue; + } + } + None => { + break Rc::new(ParsedNodesResult { + nodes: acc.clone(), + ctx: ctx.clone(), + }); + } + } + } +} + +pub fn parsed_predicate_result( + tokens: Rc, + ctx: Rc, + build: impl Fn(Rc, Rc) -> Rc + Clone, +) -> Rc { + { + let value_mint = mint_parsed_node_identity(ctx.clone()); + let predicate_mint = mint_parsed_node_identity(value_mint.ctx.clone()); + Rc::new(PredResult { + predicate: build(value_mint.identity.clone(), predicate_mint.identity.clone()), + tokens: tokens.clone(), + ctx: predicate_mint.ctx.clone(), + err: None, + }) + } +} + #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct ItemPrefixResult { pub name: String, @@ -688,7 +910,7 @@ pub struct ArmsResult { #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct ModsResult { - pub modifiers: Rc>, + pub properties: Rc>>, pub tokens: Rc, pub ctx: Rc, pub err: Option>, @@ -704,6 +926,7 @@ pub struct BindingsResult { pub fn parse_recovery_expr(span: Rc, message: String) -> Rc { make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::ParseRecoveryError, message.clone(), span.clone(), @@ -732,7 +955,7 @@ pub struct GuardResult { #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct FromKeyResult { - pub from_key: Option, + pub properties: Rc>>, pub tokens: Rc, pub ctx: Rc, pub err: Option>, @@ -753,11 +976,13 @@ pub struct PipeCalleeResult { pub method: String, pub method_span: Rc, pub tokens: Rc, + pub ctx: Rc, pub err: Option>, } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct ParserParam { + pub occurrence_identity: Rc, pub name: String, pub span: Rc, } @@ -2140,8 +2365,13 @@ pub fn parser_result_witness( } } -pub fn leaf_type_node(name: String, span: Rc) -> Rc { +pub fn leaf_type_node( + occurrence_identity: Rc, + name: String, + span: Rc, +) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: if (name.clone() == "".to_string()) { @@ -2167,8 +2397,13 @@ pub fn leaf_type_node(name: String, span: Rc) -> Rc { }) } -pub fn literal_width_nat_type_node(value: i64, span: Rc) -> Rc { +pub fn literal_width_nat_type_node( + occurrence_identity: Rc, + value: i64, + span: Rc, +) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: "".to_string(), span: span.clone(), ident_span: None, @@ -2208,18 +2443,29 @@ pub fn parse_type_angle_arg(tokens: Rc, ctx: Rc) -> R let r = parse_int_literal_value(tokens.clone()); if has_err(r.err.clone()) { Rc::new(TypeResult { - type_expr: leaf_type_node("".to_string(), span.clone()), + type_expr: leaf_type_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + "".to_string(), + span.clone(), + ), tokens: r.tokens.clone(), ctx: ctx.clone(), err: r.err.clone(), }) } else { - Rc::new(TypeResult { - type_expr: literal_width_nat_type_node(r.value.clone(), span.clone()), - tokens: r.tokens.clone(), - ctx: ctx.clone(), - err: None, - }) + { + let minted = mint_parsed_node_identity(ctx.clone()); + Rc::new(TypeResult { + type_expr: literal_width_nat_type_node( + minted.identity.clone(), + r.value.clone(), + span.clone(), + ), + tokens: r.tokens.clone(), + ctx: minted.ctx.clone(), + err: None, + }) + } } } _ => parse_type_expr(tokens.clone(), ctx.clone()), @@ -2262,11 +2508,12 @@ pub fn node_inferred_to_outputs( let mut __result = Vec::new(); for ch in rt.children.clone().iter().cloned() { __result.push(make_field_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), authored_name_at(source_indices.clone(), ch.clone()), child_inferred_or_empty(ch.clone()), Cardinality::Required, ch.body.clone(), - None, + Rc::new(vec![]), ch.span.clone(), node_name_span(ch.clone()), )); @@ -2279,11 +2526,12 @@ pub fn node_inferred_to_outputs( } } else { Rc::new(vec![make_field_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "value".to_string(), rt.clone(), Cardinality::Required, None, - None, + Rc::new(vec![]), rt.span.clone(), no_span(), )]) @@ -2364,16 +2612,25 @@ pub fn stamp_parsed_node_list( Rc::new(ParsedNodeListStampResult { nodes: Rc::new(vec![]), ctx: ctx.clone(), + err: None, }), |acc: Rc, node: Rc| { - let acc = v1_rt::take_owned(acc); - { - let stamped = - stamp_parsed_node(node.clone(), ancestors.clone(), acc.ctx, role.clone()); - Rc::new(ParsedNodeListStampResult { - nodes: v1_rt::rc_list_push(acc.nodes, stamped.node.clone()), - ctx: stamped.ctx.clone(), - }) + if has_err(acc.err.clone()) { + acc.clone() + } else { + { + let stamped = stamp_parsed_node( + node.clone(), + ancestors.clone(), + acc.ctx.clone(), + role.clone(), + ); + Rc::new(ParsedNodeListStampResult { + nodes: v1_rt::rc_list_push(acc.nodes.clone(), stamped.node.clone()), + ctx: stamped.ctx.clone(), + err: stamped.err.clone(), + }) + } } }, ) @@ -2392,11 +2649,13 @@ pub fn stamp_parsed_optional_node( Rc::new(ParsedOptionalNodeStampResult { node: Some(stamped.node.clone()), ctx: stamped.ctx.clone(), + err: stamped.err.clone(), }) } None => Rc::new(ParsedOptionalNodeStampResult { node: None, ctx: ctx.clone(), + err: None, }), } } @@ -2424,6 +2683,7 @@ pub fn stamp_parsed_pattern( declaration: stamped.node.clone(), })), ctx: stamped.ctx.clone(), + err: stamped.err.clone(), }) } Some(MatchPattern::VariantPattern { @@ -2447,6 +2707,7 @@ pub fn stamp_parsed_pattern( field_bindings: stamped.nodes.clone(), })), ctx: stamped.ctx.clone(), + err: stamped.err.clone(), }) } Some(MatchPattern::LitPattern { value: value, .. }) => Rc::new(ParsedPatternStampResult { @@ -2454,14 +2715,17 @@ pub fn stamp_parsed_pattern( value: value.clone(), })), ctx: ctx.clone(), + err: None, }), Some(MatchPattern::Wildcard) => Rc::new(ParsedPatternStampResult { pattern: Some(Rc::new(MatchPattern::Wildcard)), ctx: ctx.clone(), + err: None, }), None => Rc::new(ParsedPatternStampResult { pattern: None, ctx: ctx.clone(), + err: None, }), } } @@ -2484,11 +2748,13 @@ pub fn stamp_parsed_inferred( Rc::new(ParsedOptionalNodeStampResult { node: Some(stamped.node.clone()), ctx: stamped.ctx.clone(), + err: stamped.err.clone(), }) } _ => Rc::new(ParsedOptionalNodeStampResult { node: None, ctx: ctx.clone(), + err: None, }), } } @@ -2599,30 +2865,42 @@ pub fn stamp_parsed_node_list_with_head_role( ctx.clone(), head_role.clone(), ); - let stamped_tail = stamp_parsed_node_list( - Rc::new( - nodes - .clone() - .iter() - .cloned() - .skip(1 as usize) - .collect::>(), - ), - ancestors.clone(), - stamped_head.ctx.clone(), - tail_role.clone(), - ); - Rc::new(ParsedNodeListStampResult { - nodes: v1_rt::concat( - Rc::new(vec![stamped_head.node.clone()]), - stamped_tail.nodes.clone(), - ), - ctx: stamped_tail.ctx.clone(), - }) + if has_err(stamped_head.err.clone()) { + Rc::new(ParsedNodeListStampResult { + nodes: Rc::new(vec![stamped_head.node.clone()]), + ctx: stamped_head.ctx.clone(), + err: stamped_head.err.clone(), + }) + } else { + { + let stamped_tail = stamp_parsed_node_list( + Rc::new( + nodes + .clone() + .iter() + .cloned() + .skip(1 as usize) + .collect::>(), + ), + ancestors.clone(), + stamped_head.ctx.clone(), + tail_role.clone(), + ); + Rc::new(ParsedNodeListStampResult { + nodes: v1_rt::concat( + Rc::new(vec![stamped_head.node.clone()]), + stamped_tail.nodes.clone(), + ), + ctx: stamped_tail.ctx.clone(), + err: stamped_tail.err.clone(), + }) + } + } } None => Rc::new(ParsedNodeListStampResult { nodes: Rc::new(vec![]), ctx: ctx.clone(), + err: None, }), } } @@ -2688,41 +2966,61 @@ pub fn stamp_parsed_node( role: Rc, ) -> Rc { { - let allocated = alloc_occurrence_id(parse_context_occurrence_allocator(ctx.clone())); - let occurrence = allocated.id.clone(); - let containment = Rc::new(OccurrenceContainmentPath { - ancestors: ancestors.clone(), - terminal: occurrence.clone(), - }); - let projection = Rc::new(OccurrenceProjection { - occurrence: occurrence.clone(), - authored_name: node.name.clone(), - diagnostic_span: node.span.clone(), - }); + let occurrence = match (*node.occurrence_identity.clone()).clone() { + NodeOccurrenceIdentity::OccurrenceMinted { id: id, .. } => Some(id.clone()), + NodeOccurrenceIdentity::OccurrenceSynthetic => None, + NodeOccurrenceIdentity::OccurrenceProjected { .. } => { + return Rc::new(ParsedNodeStampResult { + node: node.clone(), + ctx: ctx.clone(), + err: Some(parse_error( + "projected occurrence identity is invalid at the authored parser boundary" + .to_string(), + node.span.clone(), + )), + }) + } + }; let effective_role = parsed_occurrence_role_for_node(node.clone(), role.clone()); - let indexed_ctx = parse_context_with_occurrence_state( - ctx.clone(), - Some(allocated.alloc.clone()), - Some(Rc::new(OccurrenceIndex { - entries: v1_rt::rc_list_push( - parse_context_occurrence_index(ctx.clone()).entries.clone(), - Rc::new(OccurrenceIndexEntry { - projection: projection.clone(), - containment: containment.clone(), - }), - ), - })), - ctx.declaration_occurrences.clone(), - ctx.reference_occurrences.clone(), - ); - let indexed_ctx = parse_context_record_occurrence( - indexed_ctx.clone(), - effective_role.clone(), - occurrence.clone(), - containment.clone(), - node.span.clone(), - ); - let child_ancestors = occurrence_ancestors_push(ancestors.clone(), occurrence.clone()); + let indexed_ctx = match occurrence.clone() { + Some(id) => { + let containment = Rc::new(OccurrenceContainmentPath { + ancestors: ancestors.clone(), + terminal: id.clone(), + }); + let with_index = parse_context_with_occurrence_state( + ctx.clone(), + ctx.occurrence_allocator.clone(), + Some(Rc::new(OccurrenceIndex { + entries: v1_rt::rc_list_push( + parse_context_occurrence_index(ctx.clone()).entries.clone(), + Rc::new(OccurrenceIndexEntry { + projection: Rc::new(OccurrenceProjection { + occurrence: id.clone(), + authored_name: node.name.clone(), + diagnostic_span: node.span.clone(), + }), + containment: containment.clone(), + }), + ), + })), + ctx.declaration_occurrences.clone(), + ctx.reference_occurrences.clone(), + ); + parse_context_record_occurrence( + with_index.clone(), + effective_role.clone(), + id.clone(), + containment.clone(), + node.span.clone(), + ) + } + None => ctx.clone(), + }; + let child_ancestors = match occurrence.clone() { + Some(id) => occurrence_ancestors_push(ancestors.clone(), id.clone()), + None => ancestors.clone(), + }; let children = stamp_parsed_node_children( node.clone(), child_ancestors.clone(), @@ -2782,6 +3080,39 @@ pub fn stamp_parsed_node( Rc::new(ParsedNodeStampResult { node: node.clone(), ctx: pattern.ctx.clone(), + err: if has_err(children.err.clone()) { + children.err.clone() + } else { + if has_err(params.err.clone()) { + params.err.clone() + } else { + if has_err(uses.err.clone()) { + uses.err.clone() + } else { + if has_err(properties.err.clone()) { + properties.err.clone() + } else { + if has_err(body.err.clone()) { + body.err.clone() + } else { + if has_err(transport.err.clone()) { + transport.err.clone() + } else { + if has_err(annotation.err.clone()) { + annotation.err.clone() + } else { + if has_err(inferred.err.clone()) { + inferred.err.clone() + } else { + pattern.err.clone() + } + } + } + } + } + } + } + }, }) } } @@ -2851,8 +3182,12 @@ pub fn parse_with_table_at( let occurrence_allocator = parse_context_occurrence_allocator(stamped.ctx.clone()); Rc::new(ParseWithTableResult { result: Rc::new(ParseResult { - module: Some(stamped.node.clone()), - error: None, + module: if has_err(stamped.err.clone()) { + None + } else { + Some(stamped.node.clone()) + }, + error: stamped.err.clone(), }), intern_table: intern_table_with_authored_token_ordinals( stamped.ctx.clone().intern_table.clone(), @@ -2950,6 +3285,7 @@ pub fn parse_module(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc { let tokens = skip_newlines(tokens.clone()); + let minted = mint_parsed_node_identity(ctx.clone()); let base_imp = import_node( + minted.identity.clone(), mod_path.clone(), true, Rc::new(vec![]), @@ -3222,7 +3568,7 @@ pub fn parse_import(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc< parse_import_names_acc(tokens.clone(), ctx.clone(), Rc::new(vec![])) } -pub fn parsed_name_leaf(name: String, span: Rc) -> Rc { - leaf_node_with_span(name.clone(), span.clone()) +pub fn parsed_name_leaf( + occurrence_identity: Rc, + name: String, + span: Rc, +) -> Rc { + leaf_node_with_span(occurrence_identity.clone(), name.clone(), span.clone()) } pub fn parse_import_names_acc( @@ -3267,7 +3617,9 @@ pub fn parse_import_names_acc( err: r.err.clone(), }); } - let name_node = parsed_name_leaf(r.name.clone(), r.span.clone()); + let minted = mint_parsed_node_identity(ctx.clone()); + let name_node = + parsed_name_leaf(minted.identity.clone(), r.name.clone(), r.span.clone()); tokens = skip_newlines(r.tokens.clone()); let e = eat(tokens.clone(), Rc::new(ExpectedToken::ExpectComma)); tokens = skip_newlines(match (*e.clone()).clone() { @@ -3275,8 +3627,10 @@ pub fn parse_import_names_acc( EatResult::EatUnchanged { tokens: _, .. } => tokens.clone(), }); { - let __tco_0 = v1_rt::rc_list_push(acc, name_node.clone()); - acc = __tco_0; + let __tco_0 = minted.ctx.clone(); + let __tco_1 = v1_rt::rc_list_push(acc, name_node.clone()); + ctx = __tco_0; + acc = __tco_1; continue; } } @@ -3313,6 +3667,7 @@ pub fn parse_item(tokens: Rc, ctx: Rc) -> Rc parse_item_by_form(tokens.clone(), ctx.clone(), f.clone()), None => Rc::new(ItemResult { item: Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: span.clone(), ident_span: Some(span.clone()), @@ -3496,6 +3851,7 @@ pub fn parse_item_by_form( { let start_span = token_span(token_stream_first(tokens.clone())); let dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: start_span.clone(), ident_span: None, @@ -3601,23 +3957,8 @@ pub fn field_to_child_node( ) -> Rc { { let ret_type = field_node_type_expr(field.clone()); - let props = match field_node_from_key(field.clone(), source_indices.clone()) { - Some(key) => Rc::new(vec![make_field_init_node( - "from_key".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitStr { value: key.clone() }), - }), - Rc::new(vec![]), - None, - field.span.clone(), - ), - field.span.clone(), - no_span(), - )]), - None => Rc::new(vec![]), - }; Rc::new(Node { + occurrence_identity: field.occurrence_identity.clone(), name: field_node_name_at(field.clone(), source_indices.clone()), span: field.span.clone(), ident_span: field.ident_span.clone(), @@ -3631,7 +3972,7 @@ pub fn field_to_child_node( uses: Rc::new(vec![]), body: field_node_default_value(field.clone()), transport: None, - properties: props.clone(), + properties: field.properties.clone(), type_annotation: None, is_self_recursive: false, has_non_tail_self_call: false, @@ -3656,6 +3997,7 @@ pub fn variant_to_child_node( __result }); Rc::new(Node { + occurrence_identity: variant.occurrence_identity.clone(), name: variant_node_name_at(variant.clone(), source_indices.clone()), span: variant.span.clone(), ident_span: variant.ident_span.clone(), @@ -3690,6 +4032,7 @@ pub fn outputs_to_inferred( if ((outputs.clone().len() as i64) > 0) { Some(Rc::new(InferredNode::Resolved { node: Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: span.clone(), ident_span: None, @@ -3722,6 +4065,7 @@ pub fn outputs_to_inferred( } pub fn make_operation_node( + occurrence_identity: Rc, name: String, ident_span: Option>, inputs: Rc>>, @@ -3743,6 +4087,7 @@ pub fn make_operation_node( mock_props.clone(), ); Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: ident_span.clone(), @@ -3751,6 +4096,7 @@ pub fn make_operation_node( let mut __result = Vec::new(); for f in inputs.iter().cloned() { __result.push(make_param_node( + f.occurrence_identity.clone(), field_node_name_at(f.clone(), source_indices.clone()), field_node_type_expr(f.clone()), field_node_default_value(f.clone()), @@ -3778,6 +4124,7 @@ pub fn make_operation_node( } pub fn make_capability_node( + occurrence_identity: Rc, name: String, ident_span: Option>, inputs: Rc>>, @@ -3786,6 +4133,7 @@ pub fn make_capability_node( source_indices: Rc>>, ) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: ident_span.clone(), @@ -3794,6 +4142,7 @@ pub fn make_capability_node( let mut __result = Vec::new(); for f in inputs.iter().cloned() { __result.push(make_param_node( + f.occurrence_identity.clone(), field_node_name_at(f.clone(), source_indices.clone()), field_node_type_expr(f.clone()), field_node_default_value(f.clone()), @@ -3823,6 +4172,7 @@ pub fn parse_type_def(tokens: Rc, ctx: Rc) -> Rc Rc { { let dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: start_span.clone(), ident_span: None, @@ -3911,6 +4262,7 @@ pub fn parse_type_after_kw( EatResult::EatConsumed { tokens: __ec, .. } => { let r = parse_field_list(skip_newlines(__ec.clone()), ctx.clone()); let named_dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -3956,24 +4308,14 @@ pub fn parse_type_after_kw( } __result }); - let sole_ctor_prop = if is_sole_constructor.clone() { - Rc::new(vec![make_field_init_node( - "sole_constructor".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitBool { value: true }), - }), - Rc::new(vec![]), - None, - start_span.clone(), - ), - start_span.clone(), - no_span(), - )]) - } else { - Rc::new(vec![]) - }; + let sole = parsed_sole_constructor_properties( + ctx.clone(), + is_sole_constructor.clone(), + start_span.clone(), + ); + let minted = mint_parsed_node_identity(sole.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -3985,7 +4327,7 @@ pub fn parse_type_after_kw( uses: Rc::new(vec![]), body: None, transport: None, - properties: sole_ctor_prop.clone(), + properties: sole.properties.clone(), type_annotation: None, is_self_recursive: false, has_non_tail_self_call: false, @@ -3996,7 +4338,7 @@ pub fn parse_type_after_kw( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(r2.tokens.clone()), - ctx: ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -4015,7 +4357,10 @@ pub fn parse_type_after_kw( ) } EatResult::EatUnchanged { tokens: __eu, .. } => { + let type_mint = mint_parsed_node_identity(ctx.clone()); + let item_mint = mint_parsed_node_identity(type_mint.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: item_mint.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -4023,7 +4368,11 @@ pub fn parse_type_after_kw( connective: Connective::NoConnective, params: type_params.clone(), inferred: Some(Rc::new(InferredNode::Resolved { - node: leaf_type_node(name.clone(), name_span.clone()), + node: leaf_type_node( + type_mint.identity.clone(), + name.clone(), + name_span.clone(), + ), })), return_cardinality: Cardinality::Required, uses: Rc::new(vec![]), @@ -4040,7 +4389,7 @@ pub fn parse_type_after_kw( Rc::new(ItemResult { item: item.clone(), tokens: __eu.clone(), - ctx: ctx.clone(), + ctx: item_mint.ctx.clone(), err: None, }) } @@ -4060,6 +4409,7 @@ pub fn parse_type_body_from_prefix( let type_params = prefix.type_params.clone(); let ctx = prefix.ctx.clone(); let named_dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -4114,24 +4464,14 @@ pub fn parse_type_body_from_prefix( } __result }); - let sole_ctor_prop = if is_sole_constructor.clone() { - Rc::new(vec![make_field_init_node( - "sole_constructor".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitBool { value: true }), - }), - Rc::new(vec![]), - None, - start_span.clone(), - ), - start_span.clone(), - no_span(), - )]) - } else { - Rc::new(vec![]) - }; + let sole = parsed_sole_constructor_properties( + ctx.clone(), + is_sole_constructor.clone(), + start_span.clone(), + ); + let minted = mint_parsed_node_identity(sole.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -4143,7 +4483,7 @@ pub fn parse_type_body_from_prefix( uses: Rc::new(vec![]), body: None, transport: None, - properties: sole_ctor_prop.clone(), + properties: sole.properties.clone(), type_annotation: None, is_self_recursive: false, has_non_tail_self_call: false, @@ -4154,7 +4494,7 @@ pub fn parse_type_body_from_prefix( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(r2.tokens.clone()), - ctx: ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -4173,7 +4513,10 @@ pub fn parse_type_body_from_prefix( ) } EatResult::EatUnchanged { tokens: __eu, .. } => { + let type_mint = mint_parsed_node_identity(ctx.clone()); + let item_mint = mint_parsed_node_identity(type_mint.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: item_mint.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -4181,7 +4524,11 @@ pub fn parse_type_body_from_prefix( connective: Connective::NoConnective, params: type_params.clone(), inferred: Some(Rc::new(InferredNode::Resolved { - node: leaf_type_node(name.clone(), name_span.clone()), + node: leaf_type_node( + type_mint.identity.clone(), + name.clone(), + name_span.clone(), + ), })), return_cardinality: Cardinality::Required, uses: Rc::new(vec![]), @@ -4198,7 +4545,7 @@ pub fn parse_type_body_from_prefix( Rc::new(ItemResult { item: item.clone(), tokens: __eu.clone(), - ctx: ctx.clone(), + ctx: item_mint.ctx.clone(), err: None, }) } @@ -4214,55 +4561,39 @@ pub fn alias_rhs_is_anonymous_record(te: Rc) -> bool { } pub fn type_item_from_alias_rhs( + occurrence_identity: Rc, name: String, name_span: Rc, start_span: Rc, type_params: Rc>>, te: Rc, - is_sole_constructor: bool, + sole_constructor_properties: Rc>>, ) -> Rc { if alias_rhs_is_anonymous_record(te.clone()) { - { - let sole_ctor_prop = if is_sole_constructor.clone() { - Rc::new(vec![make_field_init_node( - "sole_constructor".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitBool { value: true }), - }), - Rc::new(vec![]), - None, - start_span.clone(), - ), - start_span.clone(), - no_span(), - )]) - } else { - Rc::new(vec![]) - }; - Rc::new(Node { - name: name.clone(), - span: start_span.clone(), - ident_span: Some(name_span.clone()), - children: te.children.clone(), - connective: Connective::Conj, - params: type_params.clone(), - inferred: None, - return_cardinality: Cardinality::Required, - uses: Rc::new(vec![]), - body: None, - transport: None, - properties: sole_ctor_prop.clone(), - type_annotation: None, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }) - } + Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), + name: name.clone(), + span: start_span.clone(), + ident_span: Some(name_span.clone()), + children: te.children.clone(), + connective: Connective::Conj, + params: type_params.clone(), + inferred: None, + return_cardinality: Cardinality::Required, + uses: Rc::new(vec![]), + body: None, + transport: None, + properties: sole_constructor_properties.clone(), + type_annotation: None, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + }) } else { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -4274,7 +4605,7 @@ pub fn type_item_from_alias_rhs( uses: Rc::new(vec![]), body: None, transport: None, - properties: Rc::new(vec![]), + properties: sole_constructor_properties.clone(), type_annotation: None, is_self_recursive: false, has_non_tail_self_call: false, @@ -4296,6 +4627,7 @@ pub fn parse_type_body_after_eq( ) -> Rc { { let dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -4364,7 +4696,9 @@ pub fn parse_type_body_after_eq( } __result }); + let minted = mint_parsed_node_identity(rest.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -4387,7 +4721,7 @@ pub fn parse_type_body_after_eq( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(rest.tokens.clone()), - ctx: rest.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -4450,7 +4784,9 @@ pub fn parse_type_body_after_eq( } __result }); + let minted = mint_parsed_node_identity(rest.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -4473,7 +4809,7 @@ pub fn parse_type_body_after_eq( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(rest.tokens.clone()), - ctx: rest.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -4507,18 +4843,25 @@ pub fn parse_type_body_after_eq( err: wr.err.clone(), }); } + let sole = parsed_sole_constructor_properties( + wr.ctx.clone(), + is_sole_constructor.clone(), + start_span.clone(), + ); + let minted = mint_parsed_node_identity(sole.ctx.clone()); let item = type_item_from_alias_rhs( + minted.identity.clone(), name.clone(), name_span.clone(), start_span.clone(), type_params.clone(), wr.type_expr.clone(), - is_sole_constructor.clone(), + sole.properties.clone(), ); Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(wr.tokens.clone()), - ctx: wr.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -4549,18 +4892,25 @@ pub fn parse_type_body_after_eq( err: wr.err.clone(), }); } + let sole = parsed_sole_constructor_properties( + wr.ctx.clone(), + is_sole_constructor.clone(), + start_span.clone(), + ); + let minted = mint_parsed_node_identity(sole.ctx.clone()); let item = type_item_from_alias_rhs( + minted.identity.clone(), name.clone(), name_span.clone(), start_span.clone(), type_params.clone(), wr.type_expr.clone(), - is_sole_constructor.clone(), + sole.properties.clone(), ); Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(wr.tokens.clone()), - ctx: wr.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -4588,7 +4938,10 @@ pub fn try_where_clause( err: r.err.clone(), }); } + let predicate_mint = mint_parsed_node_identity(r.ctx.clone()); + let refined_mint = mint_parsed_node_identity(predicate_mint.ctx.clone()); let predicate_node = Rc::new(Node { + occurrence_identity: predicate_mint.identity.clone(), name: "".to_string(), span: start_span.clone(), ident_span: None, @@ -4609,6 +4962,7 @@ pub fn try_where_clause( ident: None, }); let refined = Rc::new(Node { + occurrence_identity: refined_mint.identity.clone(), name: "".to_string(), span: start_span.clone(), ident_span: None, @@ -4631,7 +4985,7 @@ pub fn try_where_clause( Rc::new(TypeResult { type_expr: refined.clone(), tokens: r.tokens.clone(), - ctx: r.ctx.clone(), + ctx: refined_mint.ctx.clone(), err: None, }) } @@ -4696,8 +5050,10 @@ pub fn parse_single_predicate(tokens: Rc, ctx: Rc) -> { let zero_span = no_span(); let dummy_pred = make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "".to_string(), make_expr_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), Rc::new(ExprData::ExprLiteral { value: Rc::new(LiteralValue::LitBool { value: false }), }), @@ -4742,26 +5098,29 @@ pub fn parse_single_predicate(tokens: Rc, ctx: Rc) -> err: r3.err.clone(), }); } - Rc::new(PredResult { - predicate: make_field_init_node( - "Pattern".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitStr { - value: r2.value.clone(), + parsed_predicate_result( + r3.tokens.clone(), + ctx.clone(), + |value_identity, predicate_identity| { + make_field_init_node( + predicate_identity.clone(), + "Pattern".to_string(), + make_expr_node( + value_identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitStr { + value: r2.value.clone(), + }), }), - }), - Rc::new(vec![]), - None, + Rc::new(vec![]), + None, + zero_span.clone(), + ), zero_span.clone(), - ), - zero_span.clone(), - zero_span.clone(), - ), - tokens: r3.tokens.clone(), - ctx: ctx.clone(), - err: None, - }) + zero_span.clone(), + ) + }, + ) } "format" => { let r2 = expect_ident(tokens.clone()); @@ -4782,26 +5141,29 @@ pub fn parse_single_predicate(tokens: Rc, ctx: Rc) -> err: r3.err.clone(), }); } - Rc::new(PredResult { - predicate: make_field_init_node( - "Format".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitStr { - value: r2.name.clone(), + parsed_predicate_result( + r3.tokens.clone(), + ctx.clone(), + |value_identity, predicate_identity| { + make_field_init_node( + predicate_identity.clone(), + "Format".to_string(), + make_expr_node( + value_identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitStr { + value: r2.name.clone(), + }), }), - }), - Rc::new(vec![]), - None, + Rc::new(vec![]), + None, + zero_span.clone(), + ), zero_span.clone(), - ), - zero_span.clone(), - zero_span.clone(), - ), - tokens: r3.tokens.clone(), - ctx: ctx.clone(), - err: None, - }) + zero_span.clone(), + ) + }, + ) } "brand" => { let r2 = parse_string_literal_value(tokens.clone()); @@ -4822,26 +5184,29 @@ pub fn parse_single_predicate(tokens: Rc, ctx: Rc) -> err: r3.err.clone(), }); } - Rc::new(PredResult { - predicate: make_field_init_node( - "Brand".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitStr { - value: r2.value.clone(), + parsed_predicate_result( + r3.tokens.clone(), + ctx.clone(), + |value_identity, predicate_identity| { + make_field_init_node( + predicate_identity.clone(), + "Brand".to_string(), + make_expr_node( + value_identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitStr { + value: r2.value.clone(), + }), }), - }), - Rc::new(vec![]), - None, + Rc::new(vec![]), + None, + zero_span.clone(), + ), zero_span.clone(), - ), - zero_span.clone(), - zero_span.clone(), - ), - tokens: r3.tokens.clone(), - ctx: ctx.clone(), - err: None, - }) + zero_span.clone(), + ) + }, + ) } "content" => { let r2 = expect_ident(tokens.clone()); @@ -4862,26 +5227,29 @@ pub fn parse_single_predicate(tokens: Rc, ctx: Rc) -> err: r3.err.clone(), }); } - Rc::new(PredResult { - predicate: make_field_init_node( - "ContentEncoding".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitStr { - value: r2.name.clone(), + parsed_predicate_result( + r3.tokens.clone(), + ctx.clone(), + |value_identity, predicate_identity| { + make_field_init_node( + predicate_identity.clone(), + "ContentEncoding".to_string(), + make_expr_node( + value_identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitStr { + value: r2.name.clone(), + }), }), - }), - Rc::new(vec![]), - None, + Rc::new(vec![]), + None, + zero_span.clone(), + ), zero_span.clone(), - ), - zero_span.clone(), - zero_span.clone(), - ), - tokens: r3.tokens.clone(), - ctx: ctx.clone(), - err: None, - }) + zero_span.clone(), + ) + }, + ) } "domain" => { let r2 = expect_ident(tokens.clone()); @@ -4902,26 +5270,29 @@ pub fn parse_single_predicate(tokens: Rc, ctx: Rc) -> err: r3.err.clone(), }); } - Rc::new(PredResult { - predicate: make_field_init_node( - "Domain".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitStr { - value: r2.name.clone(), + parsed_predicate_result( + r3.tokens.clone(), + ctx.clone(), + |value_identity, predicate_identity| { + make_field_init_node( + predicate_identity.clone(), + "Domain".to_string(), + make_expr_node( + value_identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitStr { + value: r2.name.clone(), + }), }), - }), - Rc::new(vec![]), - None, + Rc::new(vec![]), + None, + zero_span.clone(), + ), zero_span.clone(), - ), - zero_span.clone(), - zero_span.clone(), - ), - tokens: r3.tokens.clone(), - ctx: ctx.clone(), - err: None, - }) + zero_span.clone(), + ) + }, + ) } "range" => { let r2 = parse_named_int_args(tokens.clone(), ctx.clone()); @@ -4942,60 +5313,40 @@ pub fn parse_single_predicate(tokens: Rc, ctx: Rc) -> err: r3.err.clone(), }); } - let min_fields = if (r2.min_val.clone() != None) { - Rc::new(vec![make_field_init_node( - "min".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitInt { - value: r2.min_val.clone().clone().unwrap(), - }), - }), - Rc::new(vec![]), - None, - zero_span.clone(), - ), - zero_span.clone(), - zero_span.clone(), - )]) - } else { - Rc::new(vec![]) - }; - let max_fields = if (r2.max_val.clone() != None) { - Rc::new(vec![make_field_init_node( - "max".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitInt { - value: r2.max_val.clone().clone().unwrap(), - }), - }), - Rc::new(vec![]), - None, + let min = mint_parsed_optional_int_property( + r2.ctx.clone(), + "min".to_string(), + r2.min_val.clone(), + zero_span.clone(), + ); + let max = mint_parsed_optional_int_property( + min.ctx.clone(), + "max".to_string(), + r2.max_val.clone(), + zero_span.clone(), + ); + parsed_predicate_result( + r3.tokens.clone(), + max.ctx.clone(), + |value_identity, predicate_identity| { + make_field_init_node( + predicate_identity.clone(), + "range".to_string(), + make_expr_node( + value_identity.clone(), + Rc::new(ExprData::ExprRecordLit { parent_enum: None }), + v1_rt::concat( + min.properties.clone(), + max.properties.clone(), + ), + None, + zero_span.clone(), + ), zero_span.clone(), - ), - zero_span.clone(), - zero_span.clone(), - )]) - } else { - Rc::new(vec![]) - }; - Rc::new(PredResult { - predicate: make_field_init_node( - "range".to_string(), - make_expr_node( - Rc::new(ExprData::ExprRecordLit { parent_enum: None }), - v1_rt::concat(min_fields.clone(), max_fields.clone()), - None, zero_span.clone(), - ), - zero_span.clone(), - zero_span.clone(), - ), - tokens: r3.tokens.clone(), - ctx: r2.ctx.clone(), - err: None, - }) + ) + }, + ) } _ => Rc::new(PredResult { predicate: dummy_pred.clone(), @@ -5015,42 +5366,48 @@ pub fn parse_single_predicate(tokens: Rc, ctx: Rc) -> } } EatResult::EatUnchanged { tokens: __eu, .. } => match pred_name.clone().as_str() { - "non_empty" => Rc::new(PredResult { - predicate: make_field_init_node( - "non_empty".to_string(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitBool { value: true }), - }), - Rc::new(vec![]), - None, + "non_empty" => parsed_predicate_result( + tokens.clone(), + ctx.clone(), + |value_identity, predicate_identity| { + make_field_init_node( + predicate_identity.clone(), + "non_empty".to_string(), + make_expr_node( + value_identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitBool { value: true }), + }), + Rc::new(vec![]), + None, + zero_span.clone(), + ), zero_span.clone(), - ), - zero_span.clone(), - zero_span.clone(), - ), - tokens: tokens.clone(), - ctx: ctx.clone(), - err: None, - }), - _ => Rc::new(PredResult { - predicate: make_field_init_node( - pred_name.clone(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitBool { value: true }), - }), - Rc::new(vec![]), - None, zero_span.clone(), - ), - zero_span.clone(), - zero_span.clone(), - ), - tokens: tokens.clone(), - ctx: ctx.clone(), - err: None, - }), + ) + }, + ), + _ => parsed_predicate_result( + tokens.clone(), + ctx.clone(), + |value_identity, predicate_identity| { + make_field_init_node( + predicate_identity.clone(), + pred_name.clone(), + make_expr_node( + value_identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitBool { value: true }), + }), + Rc::new(vec![]), + None, + zero_span.clone(), + ), + zero_span.clone(), + zero_span.clone(), + ) + }, + ), }, } } @@ -5190,15 +5547,6 @@ pub fn parse_positional_variant_type_fields( err: r.err.clone(), }); } - let field = make_field_node( - "0".to_string(), - r.type_expr.clone(), - Cardinality::Required, - None, - None, - r.type_expr.clone().span.clone(), - kernel_span("0".to_string()), - ); match (*eat(r.tokens.clone(), Rc::new(ExpectedToken::ExpectComma))).clone() { EatResult::EatConsumed { token: comma_tok, tokens: __ec, .. } => Rc::new(FieldsResult { fields: Rc::new(vec![]), @@ -5206,12 +5554,16 @@ pub fn parse_positional_variant_type_fields( ctx: r.ctx.clone(), err: Some(parse_error("positional variant payload accepts a single type only (comma-separated fields not supported yet)".to_string(), token_span(Some(comma_tok.clone())))), }), - EatResult::EatUnchanged { tokens: __eu, .. } => Rc::new(FieldsResult { + EatResult::EatUnchanged { tokens: __eu, .. } => { + let minted = mint_parsed_node_identity(r.ctx.clone()); +let field = make_field_node(minted.identity.clone(), "0".to_string(), r.type_expr.clone(), Cardinality::Required, None, Rc::new(vec![]), r.type_expr.clone().span.clone(), kernel_span("0".to_string())); +Rc::new(FieldsResult { fields: Rc::new(vec![field.clone()]), tokens: r.tokens.clone(), - ctx: r.ctx.clone(), + ctx: minted.ctx.clone(), err: None, -}), +}) +}, } } } @@ -5230,6 +5582,7 @@ pub fn parse_variant_fields( if has_err(r.err.clone()) { return Rc::new(VariantResult { variant: make_variant_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), vname.clone(), Rc::new(vec![]), start_span.clone(), @@ -5245,6 +5598,7 @@ pub fn parse_variant_fields( if has_err(r2.err.clone()) { return Rc::new(VariantResult { variant: make_variant_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), vname.clone(), Rc::new(vec![]), start_span.clone(), @@ -5255,7 +5609,9 @@ pub fn parse_variant_fields( err: r2.err.clone(), }); } + let minted = mint_parsed_node_identity(r.ctx.clone()); let v = make_variant_node( + minted.identity.clone(), vname.clone(), r.fields.clone(), start_span.clone(), @@ -5264,7 +5620,7 @@ pub fn parse_variant_fields( Rc::new(VariantResult { variant: v.clone(), tokens: r2.tokens.clone(), - ctx: r.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -5275,6 +5631,7 @@ pub fn parse_variant_fields( if has_err(r.err.clone()) { return Rc::new(VariantResult { variant: make_variant_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), vname.clone(), Rc::new(vec![]), start_span.clone(), @@ -5289,6 +5646,7 @@ pub fn parse_variant_fields( if has_err(r2.err.clone()) { return Rc::new(VariantResult { variant: make_variant_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), vname.clone(), Rc::new(vec![]), start_span.clone(), @@ -5299,7 +5657,9 @@ pub fn parse_variant_fields( err: r2.err.clone(), }); } + let minted = mint_parsed_node_identity(r.ctx.clone()); let v = make_variant_node( + minted.identity.clone(), vname.clone(), r.fields.clone(), start_span.clone(), @@ -5308,12 +5668,14 @@ pub fn parse_variant_fields( Rc::new(VariantResult { variant: v.clone(), tokens: r2.tokens.clone(), - ctx: r.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } EatResult::EatUnchanged { tokens: __eu2, .. } => { + let minted = mint_parsed_node_identity(ctx.clone()); let v = make_variant_node( + minted.identity.clone(), vname.clone(), Rc::new(vec![]), vname_span.clone(), @@ -5322,7 +5684,7 @@ pub fn parse_variant_fields( Rc::new(VariantResult { variant: v.clone(), tokens: tokens.clone(), - ctx: ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -5408,7 +5770,11 @@ pub fn parse_type_expr(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc Rc::new(TypeResult { - type_expr: leaf_type_node("".to_string(), span.clone()), + type_expr: leaf_type_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + "".to_string(), + span.clone(), + ), tokens: tokens.clone(), ctx: ctx.clone(), err: Some(parse_error( @@ -5513,7 +5897,11 @@ pub fn parse_callable_type_expr( start_span: Rc, ) -> Rc { { - let dummy_te = leaf_type_node("".to_string(), start_span.clone()); + let dummy_te = leaf_type_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + "".to_string(), + start_span.clone(), + ); let r = expect(tokens.clone(), Rc::new(ExpectedToken::ExpectLParen)); if has_err(r.err.clone()) { return Rc::new(TypeResult { @@ -5570,7 +5958,9 @@ pub fn parse_callable_type_expr( err: ret.err.clone(), }); } + let minted = mint_parsed_node_identity(ret.ctx.clone()); let te = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: "Callable".to_string(), span: start_span.clone(), ident_span: Some(start_span.clone()), @@ -5594,7 +5984,7 @@ pub fn parse_callable_type_expr( }); maybe_optional( ret.tokens.clone(), - ret.ctx.clone(), + minted.ctx.clone(), te.clone(), start_span.clone(), ) @@ -5616,7 +6006,9 @@ pub fn parse_callable_param_types( err: r.err.clone(), }); } + let minted = mint_parsed_node_identity(r.ctx.clone()); let param = make_param_node( + minted.identity.clone(), "".to_string(), r.type_expr.clone(), None, @@ -5631,12 +6023,12 @@ pub fn parse_callable_param_types( break Rc::new(ParamsResult { params: acc.clone(), tokens: tokens.clone(), - ctx: r.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }); } else { { - let __tco_0 = r.ctx.clone(); + let __tco_0 = minted.ctx.clone(); ctx = __tco_0; continue; } @@ -5646,7 +6038,7 @@ pub fn parse_callable_param_types( break Rc::new(ParamsResult { params: acc.clone(), tokens: r.tokens.clone(), - ctx: r.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }); } @@ -5661,7 +6053,11 @@ pub fn finish_type_expr_from_name( start_span: Rc, ) -> Rc { { - let dummy_te = leaf_type_node(type_name.clone(), start_span.clone()); + let dummy_te = leaf_type_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + type_name.clone(), + start_span.clone(), + ); match (*eat(tokens.clone(), Rc::new(ExpectedToken::ExpectLt))).clone() { EatResult::EatConsumed { tokens: __ec, .. } => { let r = parse_type_angle_arg(__ec.clone(), ctx.clone()); @@ -5691,7 +6087,9 @@ pub fn finish_type_expr_from_name( err: r3.err.clone(), }); } + let minted = mint_parsed_node_identity(type_args.ctx.clone()); let te = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: type_name.clone(), span: start_span.clone(), ident_span: Some(start_span.clone()), @@ -5713,14 +6111,24 @@ pub fn finish_type_expr_from_name( }); maybe_optional( r3.tokens.clone(), - type_args.ctx.clone(), + minted.ctx.clone(), te.clone(), start_span.clone(), ) } EatResult::EatUnchanged { tokens: __eu, .. } => { - let te = leaf_type_node(type_name.clone(), start_span.clone()); - maybe_optional(tokens.clone(), ctx.clone(), te.clone(), start_span.clone()) + let minted = mint_parsed_node_identity(ctx.clone()); + let te = leaf_type_node( + minted.identity.clone(), + type_name.clone(), + start_span.clone(), + ); + maybe_optional( + tokens.clone(), + minted.ctx.clone(), + te.clone(), + start_span.clone(), + ) } } } @@ -5768,9 +6176,14 @@ pub fn collect_type_param_names( if tok_is_ident(token_stream_first(tokens.clone())) { let r = expect_ident(tokens.clone()); let span = r.span.clone(); + let type_mint = mint_parsed_node_identity(ctx.clone()); + let type_expr = + leaf_type_node(type_mint.identity.clone(), r.name.clone(), span.clone()); + let param_mint = mint_parsed_node_identity(type_mint.ctx.clone()); let param = make_param_node( + param_mint.identity.clone(), r.name.clone(), - leaf_type_node(r.name.clone(), span.clone()), + type_expr.clone(), None, span.clone(), span.clone(), @@ -5779,16 +6192,18 @@ pub fn collect_type_param_names( match (*eat(r.tokens.clone(), Rc::new(ExpectedToken::ExpectComma))).clone() { EatResult::EatConsumed { tokens: __ec, .. } => { let __tco_0 = __ec.clone(); - let __tco_1 = next_params.clone(); + let __tco_1 = param_mint.ctx.clone(); + let __tco_2 = next_params.clone(); tokens = __tco_0; - params = __tco_1; + ctx = __tco_1; + params = __tco_2; continue; } EatResult::EatUnchanged { tokens: __eu, .. } => { break Rc::new(TypeParamsResult { params: next_params.clone(), tokens: r.tokens.clone(), - ctx: ctx.clone(), + ctx: param_mint.ctx.clone(), }); } } @@ -5858,6 +6273,7 @@ pub fn maybe_optional( match (*eat(tokens.clone(), Rc::new(ExpectedToken::ExpectQuestion))).clone() { EatResult::EatConsumed { tokens: __ec, .. } => { let ote = Rc::new(Node { + occurrence_identity: te.occurrence_identity.clone(), name: te.name.clone(), span: te.span.clone(), ident_span: te.ident_span.clone(), @@ -5952,11 +6368,16 @@ pub fn parse_field(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc { + let minted = mint_parsed_node_identity(ctx.clone()); let f = make_field_node( + minted.identity.clone(), name.clone(), te.clone(), te.return_cardinality.clone(), None, - from_key.clone(), + from_key_properties.clone(), start_span.clone(), name_span.clone(), ); Rc::new(FieldResult { field: f.clone(), tokens: tokens.clone(), - ctx: ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -6081,15 +6506,34 @@ pub fn parse_optional_from_key( match sh2.clone() { Some(TokenShape::ShLitStr) => { let key = tok2.clone().unwrap().text.clone(); + let value_mint = mint_parsed_node_identity(ctx.clone()); + let property_mint = + mint_parsed_node_identity(value_mint.ctx.clone()); + let value = make_named_expr_node( + value_mint.identity.clone(), + key.clone(), + Rc::new(ExprData::NoExprData), + Rc::new(vec![]), + None, + token_span(tok2.clone()), + token_span(tok2.clone()), + ); + let property = make_field_init_node( + property_mint.identity.clone(), + "from_key".to_string(), + value.clone(), + token_span(tok.clone()), + token_span(tok.clone()), + ); Rc::new(FromKeyResult { - from_key: Some(key.clone()), + properties: Rc::new(vec![property.clone()]), tokens: token_stream_advance(tokens.clone(), 2), - ctx: ctx.clone(), + ctx: property_mint.ctx.clone(), err: None, }) } _ => Rc::new(FromKeyResult { - from_key: None, + properties: Rc::new(vec![]), tokens: tokens.clone(), ctx: ctx.clone(), err: None, @@ -6098,7 +6542,7 @@ pub fn parse_optional_from_key( } } else { Rc::new(FromKeyResult { - from_key: None, + properties: Rc::new(vec![]), tokens: tokens.clone(), ctx: ctx.clone(), err: None, @@ -6106,7 +6550,7 @@ pub fn parse_optional_from_key( } } _ => Rc::new(FromKeyResult { - from_key: None, + properties: Rc::new(vec![]), tokens: tokens.clone(), ctx: ctx.clone(), err: None, @@ -6119,6 +6563,7 @@ pub fn parse_fn_def(tokens: Rc, ctx: Rc) -> Rc Rc { { let dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: start_span.clone(), ident_span: None, @@ -6195,6 +6641,7 @@ pub fn parse_fn_after_kw( let name_span = r.span.clone(); let tokens = r.tokens.clone(); let named_dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -6248,7 +6695,9 @@ pub fn parse_fn_after_kw( }); } let body = r.expr.clone(); + let minted = mint_parsed_node_identity(r.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -6271,7 +6720,7 @@ pub fn parse_fn_after_kw( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(r.tokens.clone()), - ctx: r.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -6350,6 +6799,7 @@ pub fn parse_fn_body_from_prefix( let ctx = prefix.ctx.clone(); let all_params = v1_rt::concat(type_params.clone(), params.clone()); let named_dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -6422,7 +6872,9 @@ pub fn parse_fn_body_from_prefix( }); } let body = body_result.expr.clone(); + let minted = mint_parsed_node_identity(body_result.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -6445,7 +6897,7 @@ pub fn parse_fn_body_from_prefix( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(body_result.tokens.clone()), - ctx: body_result.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -6455,6 +6907,7 @@ pub fn parse_func_def(tokens: Rc, ctx: Rc) -> Rc Rc { { let dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: start_span.clone(), ident_span: None, @@ -6580,6 +7034,7 @@ pub fn parse_block_item_after_kw( let name_span = r.span.clone(); let tokens = r.tokens.clone(); let named_dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -6654,7 +7109,9 @@ pub fn parse_block_item_after_kw( }); } let body = r.expr.clone(); + let minted = mint_parsed_node_identity(r.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -6677,7 +7134,7 @@ pub fn parse_block_item_after_kw( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(r.tokens.clone()), - ctx: r.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -6695,6 +7152,7 @@ pub fn parse_block_body_from_prefix( let uses = prefix.uses.clone(); let ctx = prefix.ctx.clone(); let named_dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -6724,7 +7182,9 @@ pub fn parse_block_body_from_prefix( }); } let body = r.expr.clone(); + let minted = mint_parsed_node_identity(r.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -6747,7 +7207,7 @@ pub fn parse_block_body_from_prefix( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(r.tokens.clone()), - ctx: r.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -6758,7 +7218,9 @@ pub fn parse_no_body_from_prefix( start_span: Rc, ) -> Rc { { + let minted = mint_parsed_node_identity(prefix.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: prefix.name.clone(), span: start_span.clone(), ident_span: Some(prefix.name_span.clone()), @@ -6781,7 +7243,7 @@ pub fn parse_no_body_from_prefix( Rc::new(ItemResult { item: item.clone(), tokens: prefix.tokens.clone(), - ctx: prefix.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -6863,8 +7325,13 @@ pub fn parse_uses_entry(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc { + let minted = mint_parsed_node_identity(r3.ctx.clone()); let ru = make_resource_use_node( + minted.identity.clone(), name.clone(), r3.type_expr.clone(), start_span.clone(), @@ -6960,7 +7432,7 @@ pub fn parse_uses_entry(tokens: Rc, ctx: Rc) -> Rc { let __tco_0 = skip_newlines(__ec.clone()); - let __tco_1 = r3.ctx.clone(); + let __tco_1 = minted.ctx.clone(); tokens = __tco_0; ctx = __tco_1; continue; @@ -7045,7 +7519,7 @@ pub fn parse_resource_config_acc( break Rc::new(ResConfigResult { fields: acc.clone(), tokens: r3.tokens.clone(), - ctx: r3.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }); } @@ -7087,6 +7561,7 @@ pub fn parse_service_def(tokens: Rc, ctx: Rc) -> Rc Rc { { let dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: start_span.clone(), ident_span: None, @@ -7168,6 +7644,7 @@ pub fn parse_service_after_kw( let name = r.name.clone(); let svc_name_span = r.span.clone(); let named_dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: start_span.clone(), ident_span: Some(svc_name_span.clone()), @@ -7216,9 +7693,14 @@ pub fn parse_service_after_kw( err: r2.err.clone(), }); } + let ns_value_mint = mint_parsed_node_identity(r.ctx.clone()); + let ns_property_mint = mint_parsed_node_identity(ns_value_mint.ctx.clone()); + let item_mint = mint_parsed_node_identity(ns_property_mint.ctx.clone()); let ns_prop = make_field_init_node( + ns_property_mint.identity.clone(), "namespace_root".to_string(), make_expr_node( + ns_value_mint.identity.clone(), Rc::new(ExprData::ExprLiteral { value: Rc::new(LiteralValue::LitStr { value: namespace_root.clone(), @@ -7242,6 +7724,7 @@ pub fn parse_service_after_kw( None => Rc::new(vec![]), }; let item = Rc::new(Node { + occurrence_identity: item_mint.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(svc_name_span.clone()), @@ -7264,7 +7747,7 @@ pub fn parse_service_after_kw( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(r2.tokens.clone()), - ctx: r.ctx.clone(), + ctx: item_mint.ctx.clone(), err: None, }) } @@ -7275,7 +7758,10 @@ pub fn parse_service_body(tokens: Rc, ctx: Rc) -> Rc< tokens.clone(), ctx.clone(), None, - local_transport_node(token_span(token_stream_first(tokens.clone()))), + local_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + token_span(token_stream_first(tokens.clone())), + ), Rc::new(vec![]), ) } @@ -7480,6 +7966,7 @@ pub fn parse_config_fields( endpoint: match endpoint.clone() { Some(e) => e.clone(), None => make_expr_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), Rc::new(ExprData::ExprLiteral { value: Rc::new(LiteralValue::LitStr { value: "".to_string(), @@ -7504,6 +7991,7 @@ pub fn parse_config_fields( } else { let dummy_cfg = Rc::new(ServiceConfig { endpoint: make_expr_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), Rc::new(ExprData::ExprLiteral { value: Rc::new(LiteralValue::LitStr { value: "".to_string(), @@ -7598,7 +8086,10 @@ pub fn parse_transport_binding( ) -> Rc { { let span = token_span(token_stream_first(tokens.clone())); - let dummy = local_transport_node(span.clone()); + let dummy = local_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + span.clone(), + ); let tok = token_stream_first(tokens.clone()); let tok_text = match tok.clone() { Some(t) => t.text.clone(), @@ -7797,13 +8288,17 @@ pub fn parse_rest_fields( loop { tokens = skip_newlines(tokens.clone()); let span = token_span(token_stream_first(tokens.clone())); - let dummy = local_transport_node(span.clone()); + let dummy = local_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + span.clone(), + ); if (tok_is_rbrace(token_stream_first(tokens.clone())) || tok_is_eof(token_stream_first(tokens.clone()))) { let bu = match base_url.clone() { Some(e) => e.clone(), None => make_expr_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), Rc::new(ExprData::ExprLiteral { value: Rc::new(LiteralValue::LitStr { value: "".to_string(), @@ -7814,8 +8309,10 @@ pub fn parse_rest_fields( no_span(), ), }; + let minted = mint_parsed_node_identity(ctx.clone()); break Rc::new(TransportResult { transport: rest_transport_node( + minted.identity.clone(), bu.clone(), Rc::new(vec![]), headers.clone(), @@ -7827,7 +8324,7 @@ pub fn parse_rest_fields( span.clone(), ), tokens: tokens.clone(), - ctx: ctx.clone(), + ctx: minted.ctx.clone(), err: None, }); } else { @@ -7929,18 +8426,22 @@ pub fn parse_rest_fields( if ((fname.clone() == transport_auth_basic_key()) || (fname.clone() == transport_tls_key())) { + let minted = mint_parsed_node_identity(ctx.clone()); let field = make_field_init_node( + minted.identity.clone(), fname.clone(), r3.expr.clone(), no_span(), no_span(), ); { - let __tco_0 = v1_rt::concat( + let __tco_0 = minted.ctx.clone(); + let __tco_1 = v1_rt::concat( headers, Rc::new(vec![field.clone()]), ); - headers = __tco_0; + ctx = __tco_0; + headers = __tco_1; continue; } } else { @@ -7978,19 +8479,24 @@ pub fn parse_shell_fields( loop { tokens = skip_newlines(tokens.clone()); let span = token_span(token_stream_first(tokens.clone())); - let dummy = local_transport_node(span.clone()); + let dummy = local_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + span.clone(), + ); if (tok_is_rbrace(token_stream_first(tokens.clone())) || tok_is_eof(token_stream_first(tokens.clone()))) { + let minted = mint_parsed_node_identity(ctx.clone()); break Rc::new(TransportResult { transport: shell_transport_node( + minted.identity.clone(), argv.clone(), Rc::new(vec![]), stdin.clone(), span.clone(), ), tokens: tokens.clone(), - ctx: ctx.clone(), + ctx: minted.ctx.clone(), err: None, }); } else { @@ -8118,16 +8624,25 @@ pub fn parse_file_fields( loop { tokens = skip_newlines(tokens.clone()); let span = token_span(token_stream_first(tokens.clone())); - let dummy = local_transport_node(span.clone()); + let dummy = local_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + span.clone(), + ); if (tok_is_rbrace(token_stream_first(tokens.clone())) || tok_is_eof(token_stream_first(tokens.clone()))) { match base_path.clone() { Some(bp) => { + let minted = mint_parsed_node_identity(ctx.clone()); break Rc::new(TransportResult { - transport: file_transport_node(bp.clone(), verb.clone(), span.clone()), + transport: file_transport_node( + minted.identity.clone(), + bp.clone(), + verb.clone(), + span.clone(), + ), tokens: tokens.clone(), - ctx: ctx.clone(), + ctx: minted.ctx.clone(), err: None, }); } @@ -8217,6 +8732,7 @@ pub fn parse_operation_def(tokens: Rc, ctx: Rc) -> Rc { let start_span = token_span(token_stream_first(tokens.clone())); let dummy_op = make_operation_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "".to_string(), None, Rc::new(vec![]), @@ -8284,6 +8800,7 @@ pub fn parse_operation_v2_inline( ) -> Rc { { let dummy_op = make_operation_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "".to_string(), None, Rc::new(vec![]), @@ -8297,8 +8814,7 @@ pub fn parse_operation_v2_inline( ctx.source_indices.clone(), ); let mods_r = parse_operation_modifiers(tokens.clone(), ctx.clone()); - let modifiers = mods_r.modifiers.clone(); - let mod_props = modifiers_to_props(modifiers.clone(), start_span.clone()); + let mod_props = mods_r.properties.clone(); let tokens = mods_r.tokens.clone(); let ctx = mods_r.ctx.clone(); let r = expect(tokens.clone(), Rc::new(ExpectedToken::ExpectLParen)); @@ -8320,6 +8836,7 @@ pub fn parse_operation_v2_inline( }); } let inputs = r.fields.clone(); + let ctx = r.ctx.clone(); let r = expect( skip_newlines(r.tokens.clone()), Rc::new(ExpectedToken::ExpectRParen), @@ -8373,7 +8890,9 @@ pub fn parse_operation_v2_inline( } let tokens = skip_newlines(mock_r.tokens.clone()); let ctx = mock_r.ctx.clone(); + let minted = mint_parsed_node_identity(ctx.clone()); let op = make_operation_node( + minted.identity.clone(), name.clone(), Some(name_span.clone()), inputs.clone(), @@ -8389,7 +8908,7 @@ pub fn parse_operation_v2_inline( Rc::new(OpResult { operation: op.clone(), tokens: tokens.clone(), - ctx: ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -8404,6 +8923,7 @@ pub fn parse_operation_v1_body( ) -> Rc { { let dummy_op = make_operation_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "".to_string(), None, Rc::new(vec![]), @@ -8457,7 +8977,9 @@ pub fn parse_operation_v1_body( err: r3.err.clone(), }); } + let minted = mint_parsed_node_identity(r2.ctx.clone()); let op = make_operation_node( + minted.identity.clone(), name.clone(), Some(name_span.clone()), r2.inputs.clone(), @@ -8473,7 +8995,7 @@ pub fn parse_operation_v1_body( Rc::new(OpResult { operation: op.clone(), tokens: skip_newlines(r3.tokens.clone()), - ctx: r2.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -8641,36 +9163,59 @@ pub fn parse_op_body_entries( } } else { if (kw_text.clone() == "idempotent".to_string()) { - let prop = modifier_to_prop("idempotent".to_string(), span.clone()); + let minted = mint_parsed_bool_property( + ctx.clone(), + "idempotent".to_string(), + span.clone(), + ); { let __tco_0 = token_stream_advance(tokens, 1); - let __tco_1 = v1_rt::rc_list_push(modifier_props, prop.clone()); + let __tco_1 = minted.ctx.clone(); + let __tco_2 = v1_rt::rc_list_push( + modifier_props, + minted.property.clone(), + ); tokens = __tco_0; - modifier_props = __tco_1; + ctx = __tco_1; + modifier_props = __tco_2; continue; } } else { if (kw_text.clone() == "readonly".to_string()) { - let prop = - modifier_to_prop("readonly".to_string(), span.clone()); + let minted = mint_parsed_bool_property( + ctx.clone(), + "readonly".to_string(), + span.clone(), + ); { let __tco_0 = token_stream_advance(tokens, 1); - let __tco_1 = - v1_rt::rc_list_push(modifier_props, prop.clone()); + let __tco_1 = minted.ctx.clone(); + let __tco_2 = v1_rt::rc_list_push( + modifier_props, + minted.property.clone(), + ); tokens = __tco_0; - modifier_props = __tco_1; + ctx = __tco_1; + modifier_props = __tco_2; continue; } } else { if (kw_text.clone() == "hermetic".to_string()) { - let prop = - modifier_to_prop("hermetic".to_string(), span.clone()); + let minted = mint_parsed_bool_property( + ctx.clone(), + "hermetic".to_string(), + span.clone(), + ); { let __tco_0 = token_stream_advance(tokens, 1); - let __tco_1 = - v1_rt::rc_list_push(modifier_props, prop.clone()); + let __tco_1 = minted.ctx.clone(); + let __tco_2 = v1_rt::rc_list_push( + modifier_props, + minted.property.clone(), + ); tokens = __tco_0; - modifier_props = __tco_1; + ctx = __tco_1; + modifier_props = __tco_2; continue; } } else { @@ -8933,45 +9478,6 @@ pub fn parse_op_body_entries( } } -pub fn modifier_to_prop(name: String, span: Rc) -> Rc { - make_field_init_node( - name.clone(), - make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitBool { value: true }), - }), - Rc::new(vec![]), - None, - span.clone(), - ), - span.clone(), - span.clone(), - ) -} - -pub fn modifiers_to_props( - modifiers: Rc>, - span: Rc, -) -> Rc>> { - Rc::new({ - let mut __result = Vec::new(); - for m in modifiers.iter().cloned() { - __result.push(match m.clone() { - OperationModifier::Idempotent => { - modifier_to_prop("idempotent".to_string(), span.clone()) - } - OperationModifier::Readonly => { - modifier_to_prop("readonly".to_string(), span.clone()) - } - OperationModifier::Hermetic => { - modifier_to_prop("hermetic".to_string(), span.clone()) - } - }); - } - __result - }) -} - pub fn status_expr_to_str( expr: Rc, source_indices: Rc>>, @@ -9203,9 +9709,12 @@ pub fn parse_exit_entries_acc( let code_str = status_expr_to_str(code.clone(), ctx.source_indices.clone()); let type_name = node_to_name_str(r3.type_expr.clone(), ctx.source_indices.clone()); let prop_name = v1_rt::concat("exit_".to_string(), code_str.clone()); + let minted = mint_parsed_node_identity(r3.ctx.clone()); let entry = make_field_init_node( + minted.identity.clone(), prop_name.clone(), make_named_expr_node( + r3.type_expr.clone().occurrence_identity.clone(), type_name.clone(), Rc::new(ExprData::ExprVar { binding_kind: None }), Rc::new(vec![]), @@ -9222,7 +9731,7 @@ pub fn parse_exit_entries_acc( EatResult::EatUnchanged { tokens: _, .. } => desc_tokens.clone(), }); { - let __tco_0 = r3.ctx.clone(); + let __tco_0 = minted.ctx.clone(); let __tco_1 = v1_rt::rc_list_push(acc, entry.clone()); ctx = __tco_0; acc = __tco_1; @@ -9239,39 +9748,60 @@ pub fn parse_operation_modifiers(tokens: Rc, ctx: Rc) pub fn parse_operation_modifiers_acc( mut tokens: Rc, mut ctx: Rc, - mut acc: Rc>, + mut acc: Rc>>, ) -> Rc { loop { let kw = tok_keyword_text(token_stream_first(tokens.clone())); if (kw.clone() == "idempotent".to_string()) { + let minted = mint_parsed_bool_property( + ctx.clone(), + "idempotent".to_string(), + token_span(token_stream_first(tokens.clone())), + ); { let __tco_0 = token_stream_advance(tokens, 1); - let __tco_1 = v1_rt::rc_list_push(acc, OperationModifier::Idempotent); + let __tco_1 = minted.ctx.clone(); + let __tco_2 = v1_rt::rc_list_push(acc, minted.property.clone()); tokens = __tco_0; - acc = __tco_1; + ctx = __tco_1; + acc = __tco_2; continue; } } else { if (kw.clone() == "readonly".to_string()) { + let minted = mint_parsed_bool_property( + ctx.clone(), + "readonly".to_string(), + token_span(token_stream_first(tokens.clone())), + ); { let __tco_0 = token_stream_advance(tokens, 1); - let __tco_1 = v1_rt::rc_list_push(acc, OperationModifier::Readonly); + let __tco_1 = minted.ctx.clone(); + let __tco_2 = v1_rt::rc_list_push(acc, minted.property.clone()); tokens = __tco_0; - acc = __tco_1; + ctx = __tco_1; + acc = __tco_2; continue; } } else { if (kw.clone() == "hermetic".to_string()) { + let minted = mint_parsed_bool_property( + ctx.clone(), + "hermetic".to_string(), + token_span(token_stream_first(tokens.clone())), + ); { let __tco_0 = token_stream_advance(tokens, 1); - let __tco_1 = v1_rt::rc_list_push(acc, OperationModifier::Hermetic); + let __tco_1 = minted.ctx.clone(); + let __tco_2 = v1_rt::rc_list_push(acc, minted.property.clone()); tokens = __tco_0; - acc = __tco_1; + ctx = __tco_1; + acc = __tco_2; continue; } } else { break Rc::new(ModsResult { - modifiers: acc.clone(), + properties: acc.clone(), tokens: tokens.clone(), ctx: ctx.clone(), err: None, @@ -9298,6 +9828,7 @@ pub fn parse_status_pattern(tokens: Rc, ctx: Rc) -> R None => { return Rc::new(ExprResult { expr: make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, v1_rt::concat( v1_rt::concat( @@ -9320,83 +9851,95 @@ pub fn parse_status_pattern(tokens: Rc, ctx: Rc) -> R Some(t) => { if (is_ident_shape(t.shape.clone()) && (t.text.clone() == "xx".to_string())) { - Rc::new(ExprResult { - expr: make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitStr { - value: format!("{}xx", n.clone()), + parsed_expr_result( + token_stream_advance(tokens.clone(), 2), + ctx.clone(), + |identity| { + make_expr_node( + identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitStr { + value: format!("{}xx", n.clone()), + }), }), - }), - Rc::new(vec![]), - None, - span.clone(), - ), - tokens: token_stream_advance(tokens.clone(), 2), - ctx: ctx.clone(), - err: None, - }) + Rc::new(vec![]), + None, + span.clone(), + ) + }, + ) } else { - Rc::new(ExprResult { - expr: make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitInt { value: n.clone() }), - }), - Rc::new(vec![]), - None, - span.clone(), - ), - tokens: token_stream_advance(tokens.clone(), 1), - ctx: ctx.clone(), - err: None, - }) + parsed_expr_result( + token_stream_advance(tokens.clone(), 1), + ctx.clone(), + |identity| { + make_expr_node( + identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitInt { + value: n.clone(), + }), + }), + Rc::new(vec![]), + None, + span.clone(), + ) + }, + ) } } - None => Rc::new(ExprResult { - expr: make_expr_node( + None => parsed_expr_result( + token_stream_advance(tokens.clone(), 1), + ctx.clone(), + |identity| { + make_expr_node( + identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitInt { value: n.clone() }), + }), + Rc::new(vec![]), + None, + span.clone(), + ) + }, + ), + } + } + Some(TokenShape::ShIdent) => { + let id = tok.clone().unwrap().text.clone(); + parsed_expr_result( + token_stream_advance(tokens.clone(), 1), + ctx.clone(), + |identity| { + make_expr_node( + identity.clone(), Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitInt { value: n.clone() }), + value: Rc::new(LiteralValue::LitStr { value: id.clone() }), }), Rc::new(vec![]), None, span.clone(), - ), - tokens: token_stream_advance(tokens.clone(), 1), - ctx: ctx.clone(), - err: None, - }), - } + ) + }, + ) } - Some(TokenShape::ShIdent) => { - let id = tok.clone().unwrap().text.clone(); - Rc::new(ExprResult { - expr: make_expr_node( + _ => parsed_expr_result( + token_stream_advance(tokens.clone(), 1), + ctx.clone(), + |identity| { + make_expr_node( + identity.clone(), Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitStr { value: id.clone() }), + value: Rc::new(LiteralValue::LitStr { + value: "_".to_string(), + }), }), Rc::new(vec![]), None, span.clone(), - ), - tokens: token_stream_advance(tokens.clone(), 1), - ctx: ctx.clone(), - err: None, - }) - } - _ => Rc::new(ExprResult { - expr: make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitStr { - value: "_".to_string(), - }), - }), - Rc::new(vec![]), - None, - span.clone(), - ), - tokens: token_stream_advance(tokens.clone(), 1), - ctx: ctx.clone(), - err: None, - }), + ) + }, + ), } } } @@ -9521,9 +10064,12 @@ pub fn parse_response_entries_acc( let status_str = status_expr_to_str(status.clone(), ctx.source_indices.clone()); let type_name = node_to_name_str(r3.type_expr.clone(), ctx.source_indices.clone()); let prop_name = v1_rt::concat("response_".to_string(), status_str.clone()); + let minted = mint_parsed_node_identity(r3.ctx.clone()); let entry = make_field_init_node( + minted.identity.clone(), prop_name.clone(), make_named_expr_node( + r3.type_expr.clone().occurrence_identity.clone(), type_name.clone(), Rc::new(ExprData::ExprVar { binding_kind: None }), Rc::new(vec![]), @@ -9540,7 +10086,7 @@ pub fn parse_response_entries_acc( EatResult::EatUnchanged { tokens: _, .. } => r3.tokens.clone(), }); { - let __tco_0 = r3.ctx.clone(); + let __tco_0 = minted.ctx.clone(); let __tco_1 = v1_rt::rc_list_push(acc, entry.clone()); ctx = __tco_0; acc = __tco_1; @@ -9679,14 +10225,21 @@ pub fn parse_mock_response_entries_acc( }; let status_str = status_expr_to_str(status.clone(), ctx.source_indices.clone()); let prop_name = v1_rt::concat("mock_".to_string(), status_str.clone()); - let entry = make_field_init_node(prop_name.clone(), body.clone(), no_span(), no_span()); + let minted = mint_parsed_node_identity(r3.ctx.clone()); + let entry = make_field_init_node( + minted.identity.clone(), + prop_name.clone(), + body.clone(), + no_span(), + no_span(), + ); let e = eat(desc_tokens.clone(), Rc::new(ExpectedToken::ExpectComma)); tokens = skip_newlines(match (*e.clone()).clone() { EatResult::EatConsumed { tokens: __ec, .. } => __ec.clone(), EatResult::EatUnchanged { tokens: _, .. } => desc_tokens.clone(), }); { - let __tco_0 = r3.ctx.clone(); + let __tco_0 = minted.ctx.clone(); let __tco_1 = v1_rt::rc_list_push(acc, entry.clone()); ctx = __tco_0; acc = __tco_1; @@ -9700,6 +10253,7 @@ pub fn parse_resource_def(tokens: Rc, ctx: Rc) -> Rc< { let start_span = token_span(token_stream_first(tokens.clone())); let dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: start_span.clone(), ident_span: None, @@ -9744,6 +10298,7 @@ pub fn parse_resource_after_kw( ) -> Rc { { let dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: start_span.clone(), ident_span: None, @@ -9775,6 +10330,7 @@ pub fn parse_resource_after_kw( let name = r.name.clone(); let name_span = r.span.clone(); let named_dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -9829,7 +10385,9 @@ pub fn parse_resource_after_kw( err: r2.err.clone(), }); } + let minted = mint_parsed_node_identity(r.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -9852,7 +10410,7 @@ pub fn parse_resource_after_kw( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(r2.tokens.clone()), - ctx: r.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -10016,7 +10574,9 @@ pub fn parse_resource_entries( err: r3.err.clone(), }); } + let minted = mint_parsed_node_identity(r3.ctx.clone()); let fi = make_field_init_node( + minted.identity.clone(), fname.clone(), r3.expr.clone(), no_span(), @@ -10024,7 +10584,7 @@ pub fn parse_resource_entries( ); { let __tco_0 = skip_newlines(r3.tokens.clone()); - let __tco_1 = r3.ctx.clone(); + let __tco_1 = minted.ctx.clone(); let __tco_2 = v1_rt::rc_list_push(properties, fi.clone()); tokens = __tco_0; ctx = __tco_1; @@ -10100,6 +10660,7 @@ pub fn parse_capability(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc Rc::new(vec![]), }; + let minted = mint_parsed_node_identity(ret.ctx.clone()); let cap = make_capability_node( + minted.identity.clone(), name.clone(), Some(name_span.clone()), inputs.clone(), @@ -10241,13 +10806,15 @@ pub fn parse_capability(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc Rc { { let dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: start_span.clone(), ident_span: None, @@ -10482,6 +11051,7 @@ pub fn parse_alias_after_kw( let name = r.name.clone(); let name_span = r.span.clone(); let named_dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -10520,9 +11090,14 @@ pub fn parse_alias_after_kw( }); } let target_path = r.name.clone(); + let value_mint = mint_parsed_node_identity(ctx.clone()); + let property_mint = mint_parsed_node_identity(value_mint.ctx.clone()); + let item_mint = mint_parsed_node_identity(property_mint.ctx.clone()); let target_prop = make_field_init_node( + property_mint.identity.clone(), "namespace_alias_target".to_string(), make_expr_node( + value_mint.identity.clone(), Rc::new(ExprData::ExprLiteral { value: Rc::new(LiteralValue::LitStr { value: target_path.clone(), @@ -10536,6 +11111,7 @@ pub fn parse_alias_after_kw( no_span(), ); let item = Rc::new(Node { + occurrence_identity: item_mint.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -10558,7 +11134,7 @@ pub fn parse_alias_after_kw( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(r.tokens.clone()), - ctx: ctx.clone(), + ctx: item_mint.ctx.clone(), err: None, }) } @@ -10571,6 +11147,7 @@ pub fn parse_data_after_kw( ) -> Rc { { let dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: start_span.clone(), ident_span: None, @@ -10602,6 +11179,7 @@ pub fn parse_data_after_kw( let name = r.name.clone(); let name_span = r.span.clone(); let named_dummy = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -10640,6 +11218,7 @@ pub fn parse_data_after_kw( }); } let te = r.type_expr.clone(); + let ctx = r.ctx.clone(); let r = expect(r.tokens.clone(), Rc::new(ExpectedToken::ExpectEq)); if has_err(r.err.clone()) { return Rc::new(ItemResult { @@ -10658,7 +11237,9 @@ pub fn parse_data_after_kw( err: r.err.clone(), }); } + let minted = mint_parsed_node_identity(r.ctx.clone()); let item = Rc::new(Node { + occurrence_identity: minted.identity.clone(), name: name.clone(), span: start_span.clone(), ident_span: Some(name_span.clone()), @@ -10681,7 +11262,7 @@ pub fn parse_data_after_kw( Rc::new(ItemResult { item: item.clone(), tokens: skip_newlines(r.tokens.clone()), - ctx: r.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }) } @@ -10787,8 +11368,13 @@ pub fn parse_param(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc { + let minted = mint_parsed_node_identity(ctx.clone()); let p = make_param_node( + minted.identity.clone(), name.clone(), type_expr.clone(), None, @@ -10875,7 +11465,7 @@ pub fn parse_param(tokens: Rc, ctx: Rc) -> Rc String { pub fn census_heads_body_stand_in() -> Rc { make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::CensusHeadsBodyStripped, census_heads_body_stand_in_message(), no_span(), @@ -11049,16 +11640,14 @@ pub fn parse_block(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc Some(r3.expr.clone()), EatResult::EatUnchanged { tokens: _, .. } => None, }; - let node = Rc::new(Node { - name: name.clone(), - span: span.clone(), - ident_span: Some(name_span.clone()), - children: Rc::new(vec![r3.expr.clone()]), - connective: Connective::NoConnective, - params: Rc::new(vec![]), - inferred: ret.inferred.clone(), - return_cardinality: Cardinality::Required, - uses: Rc::new(vec![]), - body: None, - transport: None, - properties: cr.constraints.clone(), - type_annotation: type_ann.clone(), - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::ExprLet), - ident: None, - }); - Rc::new(ExprResult { - expr: node.clone(), - tokens: ret.tokens.clone(), - ctx: ret.ctx.clone(), - err: None, + parsed_expr_result(ret.tokens.clone(), ret.ctx.clone(), |identity| { + Rc::new(Node { + occurrence_identity: identity.clone(), + name: name.clone(), + span: span.clone(), + ident_span: Some(name_span.clone()), + children: Rc::new(vec![r3.expr.clone()]), + connective: Connective::NoConnective, + params: Rc::new(vec![]), + inferred: ret.inferred.clone(), + return_cardinality: Cardinality::Required, + uses: Rc::new(vec![]), + body: None, + transport: None, + properties: cr.constraints.clone(), + type_annotation: type_ann.clone(), + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::ExprLet), + ident: None, + }) }) } } @@ -11386,7 +11961,7 @@ pub fn parse_bare_assignment(tokens: Rc, ctx: Rc) -> } let r3 = parse_expr(r2.tokens.clone(), ctx.clone()); if has_err(r3.err.clone()) { - return r3; + return r3.clone(); } let cr = try_constraint_annotations(r3.tokens.clone(), r3.ctx.clone()); if has_err(cr.err.clone()) { @@ -11397,51 +11972,29 @@ pub fn parse_bare_assignment(tokens: Rc, ctx: Rc) -> err: cr.err.clone(), }); } - let node = make_named_expr_node( - name.clone(), - Rc::new(ExprData::ExprLet), - Rc::new(vec![r3.expr.clone()]), - None, - span.clone(), - name_span.clone(), - ); - if ((cr.constraints.clone().len() as i64) > 0) { - { - let node = Rc::new(Node { - name: node.name.clone(), - span: node.span.clone(), - ident_span: node.ident_span.clone(), - children: node.children.clone(), - params: node.params.clone(), - inferred: node.inferred.clone(), - return_cardinality: node.return_cardinality.clone(), - uses: node.uses.clone(), - body: node.body.clone(), - connective: node.connective.clone(), - transport: node.transport.clone(), - properties: cr.constraints.clone(), - type_annotation: node.type_annotation.clone(), - is_self_recursive: node.is_self_recursive.clone(), - has_non_tail_self_call: node.has_non_tail_self_call.clone(), - match_pattern: node.match_pattern.clone(), - expr_data: node.expr_data.clone(), - ident: None, - }); - Rc::new(ExprResult { - expr: node.clone(), - tokens: cr.tokens.clone(), - ctx: cr.ctx.clone(), - err: None, - }) - } - } else { - Rc::new(ExprResult { - expr: node.clone(), - tokens: cr.tokens.clone(), - ctx: cr.ctx.clone(), - err: None, + parsed_expr_result(cr.tokens.clone(), cr.ctx.clone(), |identity| { + Rc::new(Node { + occurrence_identity: identity.clone(), + name: name.clone(), + span: span.clone(), + ident_span: Some(name_span.clone()), + children: Rc::new(vec![r3.expr.clone()]), + params: Rc::new(vec![]), + inferred: None, + return_cardinality: Cardinality::Required, + uses: Rc::new(vec![]), + body: None, + connective: Connective::NoConnective, + transport: None, + properties: cr.constraints.clone(), + type_annotation: None, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::ExprLet), + ident: None, }) - } + }) } } @@ -11529,7 +12082,9 @@ pub fn parse_expr_loop( err: r.err.clone(), }); } + let minted = mint_parsed_node_identity(ctx.clone()); let new_lhs = make_named_expr_node( + minted.identity.clone(), r.name.clone(), Rc::new(ExprData::ExprFieldAccess { summary: None, @@ -11541,9 +12096,11 @@ pub fn parse_expr_loop( ); { let __tco_0 = r.tokens.clone(); - let __tco_1 = new_lhs.clone(); + let __tco_1 = minted.ctx.clone(); + let __tco_2 = new_lhs.clone(); tokens = __tco_0; - lhs = __tco_1; + ctx = __tco_1; + lhs = __tco_2; continue; } } else { @@ -11592,7 +12149,11 @@ pub fn parse_expr_loop( ); match binop_opt.clone() { Some(binop) => { + let minted = mint_parsed_node_identity( + r.ctx.clone(), + ); let new_lhs = make_expr_node( + minted.identity.clone(), Rc::new(ExprData::ExprBinOp { op: binop.clone(), algebra_field: None, @@ -11606,7 +12167,7 @@ pub fn parse_expr_loop( ); { let __tco_0 = r.tokens.clone(); - let __tco_1 = r.ctx.clone(); + let __tco_1 = minted.ctx.clone(); let __tco_2 = new_lhs.clone(); tokens = __tco_0; ctx = __tco_1; @@ -11675,6 +12236,7 @@ pub fn pipe_callee_path_is_applied(candidate: Rc) -> bool { pub fn parse_pipe_callee_rest( mut tokens: Rc, + mut ctx: Rc, mut spine: Option>, mut name: String, mut name_span: Rc, @@ -11688,11 +12250,14 @@ pub fn parse_pipe_callee_rest( method: name.clone(), method_span: name_span.clone(), tokens: r.tokens.clone(), + ctx: ctx.clone(), err: r.err.clone(), }); } + let minted = mint_parsed_node_identity(ctx.clone()); let next_spine = match spine.clone() { None => make_named_expr_node( + minted.identity.clone(), name.clone(), Rc::new(ExprData::ExprVar { binding_kind: None }), Rc::new(vec![]), @@ -11701,6 +12266,7 @@ pub fn parse_pipe_callee_rest( name_span.clone(), ), Some(base) => make_named_expr_node( + minted.identity.clone(), name.clone(), Rc::new(ExprData::ExprFieldAccess { summary: None }), Rc::new(vec![base.clone()]), @@ -11711,13 +12277,15 @@ pub fn parse_pipe_callee_rest( }; { let __tco_0 = r.tokens.clone(); - let __tco_1 = Some(next_spine.clone()); - let __tco_2 = r.name.clone(); - let __tco_3 = r.span.clone(); + let __tco_1 = minted.ctx.clone(); + let __tco_2 = Some(next_spine.clone()); + let __tco_3 = r.name.clone(); + let __tco_4 = r.span.clone(); tokens = __tco_0; - spine = __tco_1; - name = __tco_2; - name_span = __tco_3; + ctx = __tco_1; + spine = __tco_2; + name = __tco_3; + name_span = __tco_4; continue; } } else { @@ -11726,6 +12294,7 @@ pub fn parse_pipe_callee_rest( method: name.clone(), method_span: name_span.clone(), tokens: tokens.clone(), + ctx: ctx.clone(), err: None, }); } @@ -11749,7 +12318,13 @@ pub fn parse_pipe_rhs( err: r.err.clone(), }); } - let dotted = parse_pipe_callee_rest(r.tokens.clone(), None, r.name.clone(), r.span.clone()); + let dotted = parse_pipe_callee_rest( + r.tokens.clone(), + ctx.clone(), + None, + r.name.clone(), + r.span.clone(), + ); if has_err(dotted.err.clone()) { return Rc::new(ExprResult { expr: dummy_expr.clone(), @@ -11766,26 +12341,37 @@ pub fn parse_pipe_rhs( method: r.name.clone(), method_span: r.span.clone(), tokens: r.tokens.clone(), + ctx: ctx.clone(), err: None, }) }; let method = callee.method.clone(); - let leading = match callee.spine.clone() { - None => Rc::new(vec![receiver.clone()]), - Some(qualifier) => Rc::new(vec![ - qualifier.clone(), - make_arg_node( - None, - receiver.clone(), - receiver.span.clone(), - receiver.span.clone(), - ), - ]), + let leading_result = match callee.spine.clone() { + None => Rc::new(ParsedNodesResult { + nodes: Rc::new(vec![receiver.clone()]), + ctx: callee.ctx.clone(), + }), + Some(qualifier) => { + let wrapper_mint = mint_parsed_node_identity(callee.ctx.clone()); + Rc::new(ParsedNodesResult { + nodes: Rc::new(vec![ + qualifier.clone(), + make_arg_node( + wrapper_mint.identity.clone(), + None, + receiver.clone(), + receiver.span.clone(), + receiver.span.clone(), + ), + ]), + ctx: wrapper_mint.ctx.clone(), + }) + } }; let tokens = skip_newlines(callee.tokens.clone()); if tok_is_lparen(token_stream_first(tokens.clone())) { { - let r2 = parse_call_args(tokens.clone(), ctx.clone()); + let r2 = parse_call_args(tokens.clone(), leading_result.ctx.clone()); if has_err(r2.err.clone()) { return Rc::new(ExprResult { expr: dummy_expr.clone(), @@ -11794,18 +12380,20 @@ pub fn parse_pipe_rhs( err: r2.err.clone(), }); } - Rc::new(ExprResult { - expr: make_named_expr_node( + parsed_expr_result(r2.tokens.clone(), r2.ctx.clone(), |identity| { + make_named_expr_node( + identity.clone(), method.clone(), Rc::new(ExprData::ExprMethodCall { method_semantics: None, }), v1_rt::concat( - leading.clone(), + leading_result.nodes.clone(), Rc::new({ let mut __result = Vec::new(); for na in r2.args.clone().iter().cloned() { __result.push(make_arg_node( + na.occurrence_identity.clone(), arg_name_at(na.clone(), ctx.source_indices.clone()), arg_value(na.clone()), na.span.clone(), @@ -11818,27 +12406,22 @@ pub fn parse_pipe_rhs( None, span.clone(), callee.method_span.clone(), - ), - tokens: r2.tokens.clone(), - ctx: r2.ctx.clone(), - err: None, + ) }) } } else { - Rc::new(ExprResult { - expr: make_named_expr_node( + parsed_expr_result(tokens.clone(), leading_result.ctx.clone(), |identity| { + make_named_expr_node( + identity.clone(), method.clone(), Rc::new(ExprData::ExprMethodCall { method_semantics: None, }), - leading.clone(), + leading_result.nodes.clone(), None, span.clone(), callee.method_span.clone(), - ), - tokens: tokens.clone(), - ctx: ctx.clone(), - err: None, + ) }) } } @@ -11863,18 +12446,16 @@ pub fn parse_prefix(tokens: Rc, ctx: Rc) -> Rc { @@ -11887,18 +12468,16 @@ pub fn parse_prefix(tokens: Rc, ctx: Rc) -> Rc parse_primary(tokens.clone(), ctx.clone()), @@ -11922,21 +12501,23 @@ pub fn parse_caret_expr(tokens: Rc, ctx: Rc) -> Rc { let r = parse_expr(token_stream_advance(after_caret.clone(), 1), ctx.clone()); @@ -11963,7 +12544,9 @@ pub fn parse_caret_expr(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc Rc::new(ExprResult { - expr: make_expr_node( - Rc::new(ExprData::ExprLiteral { value: lv.clone() }), - Rc::new(vec![]), - None, - span.clone(), - ), - tokens: token_stream_advance(tokens.clone(), 1), - ctx: ctx.clone(), - err: None, - }), + Some(lv) => parsed_expr_result( + token_stream_advance(tokens.clone(), 1), + ctx.clone(), + |identity| { + make_expr_node( + identity.clone(), + Rc::new(ExprData::ExprLiteral { value: lv.clone() }), + Rc::new(vec![]), + None, + span.clone(), + ) + }, + ), None => { if (kw_text.clone() == "match".to_string()) { parse_match(tokens.clone(), ctx.clone()) @@ -12084,6 +12671,7 @@ pub fn parse_primary(tokens: Rc, ctx: Rc) -> Rc { return Rc::new(ExprResult { expr: make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, v1_rt::concat( v1_rt::concat( @@ -12101,51 +12689,57 @@ pub fn parse_primary(tokens: Rc, ctx: Rc) -> Rc { let f = tok.clone().unwrap().text.clone(); - Rc::new(ExprResult { - expr: make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitFloat { value: f.clone() }), - }), - Rc::new(vec![]), - None, - span.clone(), - ), - tokens: token_stream_advance(tokens.clone(), 1), - ctx: ctx.clone(), - err: None, - }) + parsed_expr_result( + token_stream_advance(tokens.clone(), 1), + ctx.clone(), + |identity| { + make_expr_node( + identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitFloat { value: f.clone() }), + }), + Rc::new(vec![]), + None, + span.clone(), + ) + }, + ) } Some(TokenShape::ShLitStr) => { let s = tok.clone().unwrap().text.clone(); - Rc::new(ExprResult { - expr: make_expr_node( - Rc::new(ExprData::ExprLiteral { - value: Rc::new(LiteralValue::LitStr { value: s.clone() }), - }), - Rc::new(vec![]), - None, - span.clone(), - ), - tokens: token_stream_advance(tokens.clone(), 1), - ctx: ctx.clone(), - err: None, - }) + parsed_expr_result( + token_stream_advance(tokens.clone(), 1), + ctx.clone(), + |identity| { + make_expr_node( + identity.clone(), + Rc::new(ExprData::ExprLiteral { + value: Rc::new(LiteralValue::LitStr { value: s.clone() }), + }), + Rc::new(vec![]), + None, + span.clone(), + ) + }, + ) } Some(TokenShape::ShStrBegin) => parse_string_interp(tokens.clone(), ctx.clone()), Some(TokenShape::ShCaret) => parse_caret_expr(tokens.clone(), ctx.clone()), @@ -12204,16 +12798,14 @@ pub fn parse_lambda_body(tokens: Rc, ctx: Rc) -> Rc { let __tco_0 = __ec.clone(); - let __tco_1 = r.ctx.clone(); + let __tco_1 = minted.ctx.clone(); tokens = __tco_0; ctx = __tco_1; continue; @@ -12705,7 +13309,7 @@ pub fn parse_constraint_list( break Rc::new(ConstraintsResult { constraints: acc.clone(), tokens: r.tokens.clone(), - ctx: r.ctx.clone(), + ctx: minted.ctx.clone(), err: None, }); } @@ -12730,6 +13334,7 @@ pub fn try_constraint_annotations( } pub fn make_call_expr( + occurrence_identity: Rc, lhs: Rc, args: Rc>>, span: Rc, @@ -12739,6 +13344,7 @@ pub fn make_call_expr( ExprData::ExprVar { binding_kind: _, .. } => make_named_expr_node( + occurrence_identity.clone(), expr_var_name_at(lhs.clone(), source_indices.clone()), Rc::new(ExprData::ExprCall { call_semantics: None, @@ -12750,6 +13356,7 @@ pub fn make_call_expr( node_name_span(lhs.clone()), ), ExprData::ExprFieldAccess { summary: _, .. } => make_named_expr_node( + occurrence_identity.clone(), field_access_field_at(lhs.clone(), source_indices.clone()), Rc::new(ExprData::ExprMethodCall { method_semantics: None, @@ -12763,6 +13370,7 @@ pub fn make_call_expr( node_name_span(lhs.clone()), ), _ => make_named_expr_node( + occurrence_identity.clone(), "".to_string(), Rc::new(ExprData::ExprCall { call_semantics: None, @@ -12826,16 +13434,14 @@ pub fn parse_index_or_slice( err: r.err.clone(), }); } - Rc::new(ExprResult { - expr: make_expr_node( + parsed_expr_result(r.tokens.clone(), ctx.clone(), |identity| { + make_expr_node( + identity.clone(), Rc::new(ExprData::ExprSlice), Rc::new(vec![base.clone(), first_expr.clone(), end_expr.clone()]), None, span.clone(), - ), - tokens: r.tokens.clone(), - ctx: ctx.clone(), - err: None, + ) }) } } else { @@ -12848,17 +13454,15 @@ pub fn parse_index_or_slice( ctx: ctx.clone(), err: r.err.clone(), }); - } - Rc::new(ExprResult { - expr: make_expr_node( + } + parsed_expr_result(r.tokens.clone(), ctx.clone(), |identity| { + make_expr_node( + identity.clone(), Rc::new(ExprData::ExprIndex), Rc::new(vec![base.clone(), first_expr.clone()]), None, span.clone(), - ), - tokens: r.tokens.clone(), - ctx: ctx.clone(), - err: None, + ) }) } } @@ -12966,6 +13570,7 @@ pub fn parse_single_arg(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc { + let minted = mint_parsed_node_identity( + r.ctx.clone(), + ); let new_lhs = make_expr_node( + minted.identity.clone(), Rc::new(ExprData::ExprBinOp { op: binop.clone(), algebra_field: None, @@ -13373,7 +14010,7 @@ pub fn parse_expr_loop_no_brace( ); { let __tco_0 = r.tokens.clone(); - let __tco_1 = r.ctx.clone(); + let __tco_1 = minted.ctx.clone(); let __tco_2 = new_lhs.clone(); tokens = __tco_0; ctx = __tco_1; @@ -13476,6 +14113,7 @@ pub fn parse_match_arm(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> R err: None, }) } else { - Rc::new(ExprResult { - expr: make_expr_node( + parsed_expr_result(r.tokens.clone(), r.ctx.clone(), |identity| { + make_expr_node( + identity.clone(), Rc::new(ExprData::ExprBlock), r.stmts.clone(), None, span.clone(), - ), - tokens: r.tokens.clone(), - ctx: r.ctx.clone(), - err: None, + ) }) } } @@ -13857,17 +14500,21 @@ pub fn parse_pattern(tokens: Rc, ctx: Rc) -> Rc __ec.clone(), EatResult::EatUnchanged { tokens: _, .. } => r2.tokens.clone(), }); + let minted = mint_parsed_node_identity(r2.ctx.clone()); let fb = make_field_binding_node( + minted.identity.clone(), field_name.clone(), r2.pattern.clone(), bind_span.clone(), field_name_span.clone(), ); { - let __tco_0 = r2.ctx.clone(); + let __tco_0 = minted.ctx.clone(); let __tco_1 = v1_rt::rc_list_push(acc, fb.clone()); ctx = __tco_0; acc = __tco_1; @@ -14114,10 +14765,14 @@ pub fn parse_variant_bindings_brace_acc( EatResult::EatConsumed { tokens: __ec, .. } => __ec.clone(), EatResult::EatUnchanged { tokens: _, .. } => tokens.clone(), }); + let declaration_mint = mint_parsed_node_identity(ctx.clone()); + let field_mint = mint_parsed_node_identity(declaration_mint.ctx.clone()); let fb = make_field_binding_node( + field_mint.identity.clone(), field_name.clone(), Rc::new(MatchPattern::Bind { declaration: make_pattern_binder_declaration_node( + declaration_mint.identity.clone(), field_name.clone(), field_name_span.clone(), ), @@ -14126,8 +14781,10 @@ pub fn parse_variant_bindings_brace_acc( field_name_span.clone(), ); { - let __tco_0 = v1_rt::rc_list_push(acc, fb.clone()); - acc = __tco_0; + let __tco_0 = field_mint.ctx.clone(); + let __tco_1 = v1_rt::rc_list_push(acc, fb.clone()); + ctx = __tco_0; + acc = __tco_1; continue; } } @@ -14197,8 +14854,9 @@ pub fn parse_if(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc Rc::new(ExprResult { - expr: make_expr_node( - Rc::new(ExprData::ExprIf), - Rc::new(vec![condition.clone(), then_branch.clone()]), - None, - span.clone(), - ), - tokens: tokens.clone(), - ctx: ctx.clone(), - err: None, - }), + EatResult::EatUnchanged { tokens: __eu, .. } => { + parsed_expr_result(tokens.clone(), ctx.clone(), |identity| { + make_expr_node( + identity.clone(), + Rc::new(ExprData::ExprIf), + Rc::new(vec![condition.clone(), then_branch.clone()]), + None, + span.clone(), + ) + }) + } } }) } @@ -14334,7 +14987,9 @@ pub fn parse_let(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc< err: r2.err.clone(), }); } - Rc::new(ExprResult { - expr: make_expr_node( + parsed_expr_result(r2.tokens.clone(), r.ctx.clone(), |identity| { + make_expr_node( + identity.clone(), Rc::new(ExprData::ExprListLit), r.exprs.clone(), None, span.clone(), - ), - tokens: r2.tokens.clone(), - ctx: r.ctx.clone(), - err: None, + ) }) } } @@ -14902,17 +15563,19 @@ pub fn parse_paren_expr(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc { let __tco_0 = __ec.clone(); - let __tco_1 = new_acc.clone(); + let __tco_1 = minted.ctx.clone(); + let __tco_2 = new_acc.clone(); tokens = __tco_0; - acc = __tco_1; + ctx = __tco_1; + acc = __tco_2; continue; } EatResult::EatUnchanged { tokens: __eu, .. } => { @@ -15191,7 +15865,7 @@ pub fn collect_lambda_idents( success: true, params: new_acc.clone(), tokens: token_stream_advance(tokens.clone(), 1), - ctx: ctx.clone(), + ctx: minted.ctx.clone(), err: None, }); } @@ -15327,44 +16001,46 @@ pub fn parse_interp_parts( } else { new_parts.clone() }; - break Rc::new(ExprResult { - expr: make_expr_node( - Rc::new(ExprData::ExprStringInterp), - Rc::new({ - let mut __result = Vec::new(); - for p in final_parts.iter().cloned() { - __result.push(match (*p.clone()).clone() { - StringPart::Text { value: v, .. } => { - make_text_part_node(v.clone(), span.clone()) - } - StringPart::Interpolation { expr: e, .. } => { - make_interp_part_node(e.clone(), span.clone()) - } - }); - } - __result - }), - None, - span.clone(), - ), - tokens: token_stream_advance(tokens.clone(), 1), - ctx: ctx.clone(), - err: None, - }); + let children = mint_parsed_string_part_nodes( + final_parts.clone(), + ctx.clone(), + span.clone(), + Rc::new(vec![]), + ); + break parsed_expr_result( + token_stream_advance(tokens.clone(), 1), + children.ctx.clone(), + |identity| { + make_expr_node( + identity.clone(), + Rc::new(ExprData::ExprStringInterp), + children.nodes.clone(), + None, + span.clone(), + ) + }, + ); } _ => { break Rc::new(ExprResult { expr: make_expr_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), Rc::new(ExprData::ExprStringInterp), Rc::new({ let mut __result = Vec::new(); for p in new_parts.iter().cloned() { __result.push(match (*p.clone()).clone() { - StringPart::Text { value: v, .. } => { - make_text_part_node(v.clone(), span.clone()) - } + StringPart::Text { value: v, .. } => make_text_part_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + v.clone(), + span.clone(), + ), StringPart::Interpolation { expr: e, .. } => { - make_interp_part_node(e.clone(), span.clone()) + make_interp_part_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + e.clone(), + span.clone(), + ) } }); } @@ -15389,17 +16065,19 @@ pub fn parse_brace_expr(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc) -> Rc { Rc::new(Node { + occurrence_identity: Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: name.to_string(), span: span.clone(), ident_span: None, @@ -16249,23 +16259,34 @@ mod map_shell_outputs_optional_stream_tests { let span = no_span(); let str_type = bare_type_node("String", span.clone()); let mut field = make_field_node( + Rc::new(crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), from_key.to_string(), str_type, Cardinality::CardOptional, None, - Some(from_key.to_string()), + Rc::new(vec![]), span.clone(), span.clone(), ); // make_field_node's from_key stub is not a LitStr; extract_from_key needs one. let from_key_prop = make_field_init_node( + Rc::new(crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), "from_key".to_string(), - make_text_part_node(from_key.to_string(), span.clone()), + make_text_part_node( + Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), + from_key.to_string(), + span.clone(), + ), span.clone(), span.clone(), ); Rc::make_mut(&mut field).properties = Rc::new(im_vec![from_key_prop]); let return_type = Rc::new(Node { + occurrence_identity: Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "FixtureShellRecord".to_string(), span: span.clone(), ident_span: None, @@ -16286,6 +16307,9 @@ mod map_shell_outputs_optional_stream_tests { ident: None, }); let op_node = Rc::new(Node { + occurrence_identity: Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: "fixture_shell_op".to_string(), span: span.clone(), ident_span: None, @@ -16699,10 +16723,29 @@ mod argv_arg_limit_test { fn shell_check_style_transport(command: &str) -> Rc { let span = no_span(); shell_transport_node( + Rc::new(crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic), Rc::new(im_vec![ - make_text_part_node("sh".to_string(), span.clone()), - make_text_part_node("-c".to_string(), span.clone()), - make_text_part_node(command.to_string(), span.clone()), + make_text_part_node( + Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic + ), + "sh".to_string(), + span.clone() + ), + make_text_part_node( + Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic + ), + "-c".to_string(), + span.clone() + ), + make_text_part_node( + Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic + ), + command.to_string(), + span.clone() + ), ]), Rc::new(im_vec![]), None, diff --git a/src/v1/stage0/src/v1_std_core.rs b/src/v1/stage0/src/v1_std_core.rs index 17620c44282..ad2dc37b35c 100644 --- a/src/v1/stage0/src/v1_std_core.rs +++ b/src/v1/stage0/src/v1_std_core.rs @@ -28,6 +28,7 @@ use crate::std_algebra::CostShape::*; pub use crate::std_algebra::{AlgebraFieldTemplate, CollectionSizeEffect, CostShape}; pub use crate::std_induction::SubValueRelation; use crate::std_induction::SubValueRelation::*; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic; use crate::std_occurrence_identity::OccurrenceRole::*; use crate::std_occurrence_identity::OccurrenceTransportRefusal::{ DuplicateAuthoredOccurrenceIdentity, DuplicateSuppliedCandidateIdentity, @@ -39,7 +40,8 @@ pub use crate::std_occurrence_identity::{ occurrence_id_allocator_advance_to, }; pub use crate::std_occurrence_identity::{ - AuthoredTokenOrdinalSpace, OccurrenceIdAllocator, OccurrenceTransportRefusal, + AuthoredTokenOrdinalSpace, NodeOccurrenceIdentity, OccurrenceIdAllocator, + OccurrenceTransportRefusal, }; pub use crate::std_occurrence_identity::{OccurrenceId, OccurrenceRole}; pub use crate::std_source_annotation::AnnotationAttachmentRefusal; @@ -933,6 +935,7 @@ pub struct DeclaredFuncEnv { #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct Node { + pub occurrence_identity: Rc, pub name: String, pub ident: Option, pub span: Rc, @@ -973,12 +976,14 @@ pub fn empty_node_list() -> Rc>> { } pub fn make_expr_node( + occurrence_identity: Rc, expr_data: Rc, children: Rc>>, inferred: Option>, span: Rc, ) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: "".to_string(), span: span.clone(), ident_span: None, @@ -1001,6 +1006,7 @@ pub fn make_expr_node( } pub fn make_named_expr_node( + occurrence_identity: Rc, name: String, expr_data: Rc, children: Rc>>, @@ -1009,6 +1015,7 @@ pub fn make_named_expr_node( name_span: Rc, ) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: default_ident_span(name.clone(), name_span.clone()), @@ -1030,8 +1037,13 @@ pub fn make_named_expr_node( }) } -pub fn make_pattern_binder_declaration_node(name: String, span: Rc) -> Rc { +pub fn make_pattern_binder_declaration_node( + occurrence_identity: Rc, + name: String, + span: Rc, +) -> Rc { make_named_expr_node( + occurrence_identity.clone(), name.clone(), Rc::new(ExprData::NoExprData), Rc::new(vec![]), @@ -1042,11 +1054,13 @@ pub fn make_pattern_binder_declaration_node(name: String, span: Rc) } pub fn make_expr_error_node( + occurrence_identity: Rc, kind: ExprErrorKind, message: String, span: Rc, ) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: "".to_string(), span: span.clone(), ident_span: None, @@ -1075,6 +1089,7 @@ pub fn make_expr_error_node( } pub fn make_arg_node( + occurrence_identity: Rc, name: Option, value: Rc, span: Rc, @@ -1086,6 +1101,7 @@ pub fn make_arg_node( None => "".to_string(), }; Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: arg_name.clone(), span: span.clone(), ident_span: default_ident_span(arg_name.clone(), name_span.clone()), @@ -1109,6 +1125,7 @@ pub fn make_arg_node( } pub fn make_arm_node( + occurrence_identity: Rc, pattern: Rc, guard: Option>, body: Rc, @@ -1120,6 +1137,7 @@ pub fn make_arm_node( None => Rc::new(vec![body.clone()]), }; Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: "".to_string(), span: span.clone(), ident_span: None, @@ -1143,12 +1161,14 @@ pub fn make_arm_node( } pub fn make_resource_use_node( + occurrence_identity: Rc, name: String, resource: Rc, span: Rc, name_span: Rc, ) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: default_ident_span(name.clone(), name_span.clone()), @@ -1181,6 +1201,7 @@ pub fn resource_use_resource(n: Rc) -> Rc { match n.children.clone().first().cloned() { Some(v) => v.clone(), None => make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "malformed resource-use: missing resource".to_string(), n.span.clone(), @@ -1189,12 +1210,14 @@ pub fn resource_use_resource(n: Rc) -> Rc { } pub fn make_field_init_node( + occurrence_identity: Rc, name: String, value: Rc, span: Rc, name_span: Rc, ) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: default_ident_span(name.clone(), name_span.clone()), @@ -1217,12 +1240,14 @@ pub fn make_field_init_node( } pub fn make_field_binding_node( + occurrence_identity: Rc, field_name: String, binding: Rc, span: Rc, name_span: Rc, ) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: field_name.clone(), span: span.clone(), ident_span: default_ident_span(field_name.clone(), name_span.clone()), @@ -1258,8 +1283,13 @@ pub fn field_binding_pattern(n: Rc) -> Rc { } } -pub fn make_text_part_node(text: String, span: Rc) -> Rc { +pub fn make_text_part_node( + occurrence_identity: Rc, + text: String, + span: Rc, +) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: "".to_string(), span: span.clone(), ident_span: None, @@ -1285,8 +1315,13 @@ pub fn make_text_part_node(text: String, span: Rc) -> Rc { }) } -pub fn make_interp_part_node(expr: Rc, span: Rc) -> Rc { +pub fn make_interp_part_node( + occurrence_identity: Rc, + expr: Rc, + span: Rc, +) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: "".to_string(), span: span.clone(), ident_span: None, @@ -1309,6 +1344,7 @@ pub fn make_interp_part_node(expr: Rc, span: Rc) -> Rc { } pub fn make_param_node( + occurrence_identity: Rc, name: String, type_expr: Rc, default_value: Option>, @@ -1321,6 +1357,7 @@ pub fn make_param_node( None => Rc::new(vec![type_expr.clone()]), }; Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: default_ident_span(name.clone(), name_span.clone()), @@ -1344,6 +1381,7 @@ pub fn make_param_node( } pub fn make_resolved_param_node( + occurrence_identity: Rc, name: String, type_expr: Rc, default_value: Option>, @@ -1357,6 +1395,7 @@ pub fn make_resolved_param_node( None => Rc::new(vec![type_expr.clone()]), }; Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: default_ident_span(name.clone(), name_span.clone()), @@ -1470,6 +1509,7 @@ pub fn param_node_type_expr(n: Rc) -> Rc { match n.children.clone().first().cloned() { Some(v) => v.clone(), None => make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "malformed param: missing type_expr".to_string(), n.span.clone(), @@ -1490,11 +1530,12 @@ pub fn param_node_span(n: Rc) -> Rc { } pub fn make_field_node( + occurrence_identity: Rc, name: String, type_expr: Rc, cardinality: Cardinality, default_value: Option>, - from_key: Option, + from_key_properties: Rc>>, span: Rc, name_span: Rc, ) -> Rc { @@ -1503,35 +1544,8 @@ pub fn make_field_node( Some(dv) => Rc::new(vec![type_expr.clone(), dv.clone()]), None => Rc::new(vec![type_expr.clone()]), }; - let props = match from_key.clone() { - Some(fk) => Rc::new(vec![make_field_init_node( - "from_key".to_string(), - Rc::new(Node { - name: fk.clone(), - span: no_span(), - ident_span: default_ident_span(fk.clone(), no_span()), - children: Rc::new(vec![]), - connective: Connective::NoConnective, - params: Rc::new(vec![]), - inferred: None, - return_cardinality: Cardinality::Required, - uses: Rc::new(vec![]), - body: None, - transport: None, - properties: Rc::new(vec![]), - type_annotation: None, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }), - no_span(), - no_span(), - )]), - None => Rc::new(vec![]), - }; Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: default_ident_span(name.clone(), name_span.clone()), @@ -1543,7 +1557,7 @@ pub fn make_field_node( uses: Rc::new(vec![]), body: None, transport: None, - properties: v1_rt::concat(props.clone(), type_expr.properties.clone()), + properties: v1_rt::concat(from_key_properties.clone(), type_expr.properties.clone()), type_annotation: None, is_self_recursive: false, has_non_tail_self_call: false, @@ -1565,6 +1579,7 @@ pub fn field_node_type_expr(n: Rc) -> Rc { match n.children.clone().first().cloned() { Some(v) => v.clone(), None => make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "malformed field: missing type_expr".to_string(), n.span.clone(), @@ -1603,12 +1618,14 @@ pub fn field_node_span(n: Rc) -> Rc { } pub fn make_variant_node( + occurrence_identity: Rc, name: String, fields: Rc>>, span: Rc, name_span: Rc, ) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: default_ident_span(name.clone(), name_span.clone()), @@ -1843,6 +1860,7 @@ pub fn expr_child_at(texpr: Rc, index: i64, role: String) -> Rc { { Some(v) => v.clone(), None => make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, v1_rt::concat("malformed node: missing ".to_string(), role.clone()), texpr.span.clone(), @@ -1868,6 +1886,7 @@ pub fn arg_value(n: Rc) -> Rc { match n.children.clone().first().cloned() { Some(v) => v.clone(), None => make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "malformed arg: missing value".to_string(), n.span.clone(), @@ -1894,6 +1913,7 @@ pub fn arm_body(n: Rc) -> Rc { match n.children.clone().last().cloned() { Some(v) => v.clone(), None => make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "malformed arm: missing body".to_string(), n.span.clone(), @@ -1912,6 +1932,7 @@ pub fn field_init_node_value(n: Rc) -> Rc { match n.children.clone().first().cloned() { Some(v) => v.clone(), None => make_expr_error_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), ExprErrorKind::InternalExprError, "malformed field-init: missing value".to_string(), n.span.clone(), @@ -2491,12 +2512,14 @@ pub fn transport_tls_key() -> String { } pub fn make_transport_node( + occurrence_identity: Rc, properties: Rc>>, children: Rc>>, body: Option>, span: Rc, ) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: "".to_string(), span: span.clone(), ident_span: None, @@ -2518,11 +2541,21 @@ pub fn make_transport_node( }) } -pub fn local_transport_node(span: Rc) -> Rc { - make_transport_node(Rc::new(vec![]), Rc::new(vec![]), None, span.clone()) +pub fn local_transport_node( + occurrence_identity: Rc, + span: Rc, +) -> Rc { + make_transport_node( + occurrence_identity.clone(), + Rc::new(vec![]), + Rc::new(vec![]), + None, + span.clone(), + ) } pub fn rest_transport_node( + occurrence_identity: Rc, base_url: Rc, auth_props: Rc>>, headers: Rc>>, @@ -2536,6 +2569,7 @@ pub fn rest_transport_node( { let zero_span = no_span(); let url_field = make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), transport_url_key(), base_url.clone(), zero_span.clone(), @@ -2543,6 +2577,7 @@ pub fn rest_transport_node( ); let method_props = match method.clone() { Some(m) => Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), transport_method_key(), m.clone(), zero_span.clone(), @@ -2552,6 +2587,7 @@ pub fn rest_transport_node( }; let path_props = match path.clone() { Some(p) => Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), transport_path_template_key(), p.clone(), zero_span.clone(), @@ -2561,6 +2597,7 @@ pub fn rest_transport_node( }; let query_props = match query.clone() { Some(q) => Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), transport_query_key(), q.clone(), zero_span.clone(), @@ -2570,6 +2607,7 @@ pub fn rest_transport_node( }; let body_props = match request_body.clone() { Some(b) => Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), transport_body_key(), b.clone(), zero_span.clone(), @@ -2579,6 +2617,7 @@ pub fn rest_transport_node( }; let rf_props = match response_format.clone() { Some(rf) => Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), transport_response_format_key(), rf.clone(), zero_span.clone(), @@ -2608,11 +2647,18 @@ pub fn rest_transport_node( ), headers.clone(), ); - make_transport_node(props.clone(), Rc::new(vec![]), None, span.clone()) + make_transport_node( + occurrence_identity.clone(), + props.clone(), + Rc::new(vec![]), + None, + span.clone(), + ) } } pub fn shell_transport_node( + occurrence_identity: Rc, argv: Rc>>, env: Rc>>, stdin: Option>, @@ -2620,6 +2666,7 @@ pub fn shell_transport_node( ) -> Rc { { let shell_marker = Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: span.clone(), ident_span: None, @@ -2642,6 +2689,7 @@ pub fn shell_transport_node( let zero_span = no_span(); let stdin_props = match stdin.clone() { Some(s) => Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), transport_stdin_key(), s.clone(), zero_span.clone(), @@ -2651,6 +2699,7 @@ pub fn shell_transport_node( }; let all_props = v1_rt::concat(env.clone(), stdin_props.clone()); Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: "".to_string(), span: span.clone(), ident_span: None, @@ -2674,12 +2723,14 @@ pub fn shell_transport_node( } pub fn file_transport_node( + occurrence_identity: Rc, base_path: Rc, verb: Option>, span: Rc, ) -> Rc { { let path_field = make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), transport_path_key(), base_path.clone(), no_span(), @@ -2689,6 +2740,7 @@ pub fn file_transport_node( Some(verb_expr) => Rc::new(vec![ path_field.clone(), make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), transport_verb_key(), verb_expr.clone(), no_span(), @@ -2697,7 +2749,13 @@ pub fn file_transport_node( ]), None => Rc::new(vec![path_field.clone()]), }; - make_transport_node(props.clone(), Rc::new(vec![]), None, span.clone()) + make_transport_node( + occurrence_identity.clone(), + props.clone(), + Rc::new(vec![]), + None, + span.clone(), + ) } } @@ -3130,6 +3188,7 @@ pub fn transport_env( pub fn map_children(node: Rc, transform: impl Fn(Rc) -> Rc + Clone) -> Rc { Rc::new(Node { + occurrence_identity: node.occurrence_identity.clone(), name: node.name.clone(), ident: node.ident.clone(), span: node.span.clone(), @@ -3510,6 +3569,7 @@ pub fn service_config_properties( { let zero_span = no_span(); let ep_prop = Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), service_config_field_property_name(ServiceConfigField::SvcEndpoint), endpoint.clone(), zero_span.clone(), @@ -3517,6 +3577,7 @@ pub fn service_config_properties( )]); let auth_prop = match auth.clone() { Some(a) => Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), service_config_field_property_name(ServiceConfigField::SvcAuth), a.clone(), zero_span.clone(), @@ -3526,6 +3587,7 @@ pub fn service_config_properties( }; let auth_input_prop = match auth_input.clone() { Some(ai) => Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), service_config_field_property_name(ServiceConfigField::SvcAuthInput), ai.clone(), zero_span.clone(), @@ -3535,6 +3597,7 @@ pub fn service_config_properties( }; let auth_source_prop = match auth_source.clone() { Some(src) => Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), service_config_field_property_name(ServiceConfigField::SvcAuthSource), src.clone(), zero_span.clone(), @@ -3544,6 +3607,7 @@ pub fn service_config_properties( }; let rate_prop = match rate_limit.clone() { Some(r) => Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), service_config_field_property_name(ServiceConfigField::SvcRateLimit), r.clone(), zero_span.clone(), @@ -3638,12 +3702,14 @@ pub fn service_config_auth_source( } pub fn module_node( + occurrence_identity: Rc, name: String, imports: Rc>>, items: Rc>>, span: Rc, ) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: default_ident_span(name.clone(), span.clone()), @@ -3666,6 +3732,7 @@ pub fn module_node( } pub fn import_node( + occurrence_identity: Rc, module_path: String, is_all: bool, specific_names: Rc>>, @@ -3675,6 +3742,7 @@ pub fn import_node( { let wildcard_marker = if is_all.clone() { Some(Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: span.clone(), ident_span: None, @@ -3698,6 +3766,7 @@ pub fn import_node( None }; Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: module_path.clone(), span: span.clone(), ident_span: Some(name_span.clone()), @@ -3745,8 +3814,13 @@ pub fn module_items(n: Rc) -> Rc>> { n.children.clone() } -pub fn leaf_node_with_span(name: String, span: Rc) -> Rc { +pub fn leaf_node_with_span( + occurrence_identity: Rc, + name: String, + span: Rc, +) -> Rc { Rc::new(Node { + occurrence_identity: occurrence_identity.clone(), name: name.clone(), span: span.clone(), ident_span: default_ident_span(name.clone(), span.clone()), @@ -3783,6 +3857,7 @@ pub fn unit_type() -> Rc { thread_local! { static CACHED: Rc = { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Unit".to_string(), span: kernel_span("Unit".to_string()), ident_span: Some(kernel_span("Unit".to_string())), @@ -3811,6 +3886,7 @@ pub fn bool_type() -> Rc { thread_local! { static CACHED: Rc = { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Bool".to_string(), span: kernel_span("Bool".to_string()), ident_span: Some(kernel_span("Bool".to_string())), @@ -3839,6 +3915,7 @@ pub fn string_type() -> Rc { thread_local! { static CACHED: Rc = { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "String".to_string(), span: kernel_span("String".to_string()), ident_span: Some(kernel_span("String".to_string())), @@ -3867,6 +3944,7 @@ pub fn hash_type() -> Rc { thread_local! { static CACHED: Rc = { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Hash".to_string(), span: kernel_span("Hash".to_string()), ident_span: Some(kernel_span("Hash".to_string())), @@ -3895,6 +3973,7 @@ pub fn int_type() -> Rc { thread_local! { static CACHED: Rc = { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Int".to_string(), span: kernel_span("Int".to_string()), ident_span: Some(kernel_span("Int".to_string())), @@ -3923,6 +4002,7 @@ pub fn float_type() -> Rc { thread_local! { static CACHED: Rc = { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "Float".to_string(), span: kernel_span("Float".to_string()), ident_span: Some(kernel_span("Float".to_string())), @@ -3951,6 +4031,7 @@ pub fn none_type() -> Rc { thread_local! { static CACHED: Rc = { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "None".to_string(), span: kernel_span("None".to_string()), ident_span: Some(kernel_span("None".to_string())), @@ -3988,6 +4069,7 @@ pub fn error_type() -> Rc { thread_local! { static CACHED: Rc = { Rc::new(Node { + occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), name: "".to_string(), span: no_span(), ident_span: None, @@ -4288,6 +4370,7 @@ pub fn pre_intern_tokens(tokens: Rc>>, table: Rc) -> pub fn with_optional_cardinality(n: Rc) -> Rc { Rc::new(Node { + occurrence_identity: n.occurrence_identity.clone(), name: n.name.clone(), ident: n.ident.clone(), span: n.span.clone(), @@ -4311,6 +4394,7 @@ pub fn with_optional_cardinality(n: Rc) -> Rc { pub fn with_required_cardinality(n: Rc) -> Rc { Rc::new(Node { + occurrence_identity: n.occurrence_identity.clone(), name: n.name.clone(), ident: n.ident.clone(), span: n.span.clone(), diff --git a/src/v1/stage0/src/v1_tests_claim_transport_roster_closure_witness_test.rs b/src/v1/stage0/src/v1_tests_claim_transport_roster_closure_witness_test.rs index 2f1dc9fd378..e6b6ee447d2 100644 --- a/src/v1/stage0/src/v1_tests_claim_transport_roster_closure_witness_test.rs +++ b/src/v1/stage0/src/v1_tests_claim_transport_roster_closure_witness_test.rs @@ -1,6 +1,8 @@ // Generated by v1 compiler -- do not edit. // Source module: v1.tests.claim.transport_roster_closure_witness_test +pub use crate::std_occurrence_identity::NodeOccurrenceIdentity; +use crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic; pub use crate::std_syntax::LiteralValue; use crate::std_syntax::LiteralValue::LitStr; pub use crate::std_types::SourceSpan; @@ -32,6 +34,7 @@ pub fn transport_roster_closure_witness_note() -> String { pub fn str_expr(s: String) -> Rc { make_expr_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), Rc::new(ExprData::ExprLiteral { value: Rc::new(LiteralValue::LitStr { value: s.clone() }), }), @@ -53,6 +56,7 @@ pub fn kind_name(t: Rc) -> String { pub fn rest_transport_classifies_as_rest() -> bool { (kind_name(rest_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), str_expr("https://example.invalid".to_string()), Rc::new(vec![]), Rc::new(vec![]), @@ -67,6 +71,7 @@ pub fn rest_transport_classifies_as_rest() -> bool { pub fn shell_transport_classifies_as_shell() -> bool { (kind_name(shell_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), Rc::new(vec![str_expr("ls".to_string())]), Rc::new(vec![]), None, @@ -76,6 +81,7 @@ pub fn shell_transport_classifies_as_shell() -> bool { pub fn file_transport_classifies_as_file() -> bool { (kind_name(file_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), str_expr("/tmp/x".to_string()), None, no_span(), @@ -83,12 +89,17 @@ pub fn file_transport_classifies_as_file() -> bool { } pub fn bare_transport_classifies_as_local() -> bool { - (kind_name(local_transport_node(no_span())) == "local".to_string()) + (kind_name(local_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + no_span(), + )) == "local".to_string()) } pub fn keyless_transport() -> Rc { make_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), Rc::new(vec![make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "unrecognized_key".to_string(), str_expr("v".to_string()), no_span(), @@ -113,21 +124,27 @@ pub fn unrecognized_transport_is_not_local() -> bool { pub fn the_bare_node_is_still_local_positive_control() -> bool { (is_local_transport( - local_transport_node(no_span()), + local_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + no_span(), + ), v1_rt::rc_empty_map::>(), ) == true) } pub fn rest_wins_over_a_file_key_on_the_same_transport() -> bool { (kind_name(make_transport_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), Rc::new(vec![ make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "base_url".to_string(), str_expr("https://example.invalid".to_string()), no_span(), no_span(), ), make_field_init_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), "base_path".to_string(), str_expr("/tmp/x".to_string()), no_span(), diff --git a/src/v1/stage0/tests/namespace_occurrence_serde.rs b/src/v1/stage0/tests/namespace_occurrence_serde.rs index 313a99adcc1..dea6613fcca 100644 --- a/src/v1/stage0/tests/namespace_occurrence_serde.rs +++ b/src/v1/stage0/tests/namespace_occurrence_serde.rs @@ -6,12 +6,15 @@ use im::HashMap; use std::rc::Rc; use v1_compiler::std_occurrence_identity::{ - occurrence_id_allocator_initial, OccurrenceCategory, OccurrenceContainmentPath, - OccurrenceIdAllocator, OccurrenceTransport, + occurrence_id_allocator_initial, NodeOccurrenceIdentity, OccurrenceCategory, + OccurrenceContainmentPath, OccurrenceIdAllocator, OccurrenceTransport, }; use v1_compiler::v1_compiler_parse::{parse_with_table_in_occurrence_scope, ParseWithTableResult}; use v1_compiler::v1_compiler_tokenize::tokenize; -use v1_compiler::v1_std_core::{build_newline_index, empty_intern_table, NewlineIndex}; +use v1_compiler::v1_std_core::{ + build_newline_index, empty_intern_table, make_expr_node, no_span, with_required_cardinality, + ExprData, NewlineIndex, Node, +}; fn parse_source( source: &str, @@ -98,6 +101,38 @@ fn declaration_spans(transport: &OccurrenceTransport) -> Vec<(i64, i64)> { .collect() } +fn node_occurrence_ids(node: &Node, ids: &mut Vec, synthetic_count: &mut usize) { + match node.occurrence_identity.as_ref() { + NodeOccurrenceIdentity::OccurrenceMinted { id } => ids.push(id.value), + NodeOccurrenceIdentity::OccurrenceSynthetic => *synthetic_count += 1, + NodeOccurrenceIdentity::OccurrenceProjected { .. } => { + panic!("authored parser returned a projected occurrence") + } + } + for child in node.children.iter() { + node_occurrence_ids(child, ids, synthetic_count); + } + for param in node.params.iter() { + node_occurrence_ids(param, ids, synthetic_count); + } + for used in node.uses.iter() { + node_occurrence_ids(used, ids, synthetic_count); + } + for property in node.properties.iter() { + node_occurrence_ids(property, ids, synthetic_count); + } + for optional in [ + node.body.as_ref(), + node.transport.as_ref(), + node.type_annotation.as_ref(), + ] + .into_iter() + .flatten() + { + node_occurrence_ids(optional, ids, synthetic_count); + } +} + #[test] fn occurrence_transport_round_trips_with_node_identity_and_paths() { let source = "module occurrence.serde\n\nfn left(x: Int) -> Int { x }\nfn right(x: Int) -> Int { left(x) }\n"; @@ -110,68 +145,55 @@ fn occurrence_transport_round_trips_with_node_identity_and_paths() { assert!(!parsed.occurrence_transport.index.entries.is_empty()); assert!(!parsed.occurrence_transport.declarations.is_empty()); assert!(!parsed.occurrence_transport.references.is_empty()); + let module = parsed + .result + .module + .as_ref() + .expect("successful parse module"); + let mut node_ids = Vec::new(); + let mut synthetic_count = 0; + node_occurrence_ids(module, &mut node_ids, &mut synthetic_count); + let mut sidecar_ids: Vec = parsed + .occurrence_transport + .index + .entries + .iter() + .map(|entry| entry.projection.occurrence.value) + .collect(); + node_ids.sort_unstable(); + sidecar_ids.sort_unstable(); assert_eq!( - occurrence_identity_view(&parsed.occurrence_transport), - ( - vec![ - (0, (vec![], 0)), - (1, (vec![0], 1)), - (2, (vec![0, 1], 2)), - (3, (vec![0, 1, 2], 3)), - (4, (vec![0, 1], 4)), - (5, (vec![0, 1], 5)), - (6, (vec![0], 6)), - (7, (vec![0, 6], 7)), - (8, (vec![0, 6, 7], 8)), - (9, (vec![0, 6], 9)), - (10, (vec![0, 6, 9], 10)), - (11, (vec![0, 6, 9, 10], 11)), - (12, (vec![0, 6], 12)), - ], - vec![ - ( - 0, - OccurrenceCategory::NamespaceSegmentOccurrence, - (vec![], 0) - ), - (1, OccurrenceCategory::CallableOccurrence, (vec![0], 1)), - ( - 2, - OccurrenceCategory::LexicalValueOccurrence, - (vec![0, 1], 2) - ), - (6, OccurrenceCategory::CallableOccurrence, (vec![0], 6)), - ( - 7, - OccurrenceCategory::LexicalValueOccurrence, - (vec![0, 6], 7) - ), - ], - vec![ - (3, OccurrenceCategory::TypeOccurrence, (vec![0, 1, 2], 3)), - ( - 4, - OccurrenceCategory::LexicalValueOccurrence, - (vec![0, 1], 4) - ), - (5, OccurrenceCategory::TypeOccurrence, (vec![0, 1], 5)), - (8, OccurrenceCategory::TypeOccurrence, (vec![0, 6, 7], 8)), - (9, OccurrenceCategory::CallableOccurrence, (vec![0, 6], 9)), - ( - 10, - OccurrenceCategory::CallableOccurrence, - (vec![0, 6, 9], 10) - ), - ( - 11, - OccurrenceCategory::LexicalValueOccurrence, - (vec![0, 6, 9, 10], 11) - ), - (12, OccurrenceCategory::TypeOccurrence, (vec![0, 6], 12)), - ], - ), - "successful-tree stamp population, ids, roles, containment and traversal order changed" + node_ids, sidecar_ids, + "parser node identities must equal sidecar identities" + ); + node_ids.dedup(); + assert_eq!( + node_ids.len(), + sidecar_ids.len(), + "authored node identities must be distinct" + ); + assert_eq!( + synthetic_count, 0, + "successful authored parse must not default nodes to synthetic" + ); + + let rebuilt = with_required_cardinality(module.clone()); + assert_eq!( + rebuilt.occurrence_identity, module.occurrence_identity, + "rebuild must preserve identity exactly" + ); + + let synthesized = make_expr_node( + Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), + Rc::new(ExprData::NoExprData), + Rc::new(vec![].into()), + None, + no_span(), ); + assert!(matches!( + synthesized.occurrence_identity.as_ref(), + NodeOccurrenceIdentity::OccurrenceSynthetic + )); let encoded = serde_json::to_vec(&parsed).expect("serialize occurrence parse result"); let decoded: Rc = From 40d55d44b66b4212a438c11b65058da0dc28cf93 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 02:45:49 +0000 Subject: [PATCH 11/30] Traverse nested nodes in identity control --- .../stage0/tests/namespace_occurrence_serde.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/v1/stage0/tests/namespace_occurrence_serde.rs b/src/v1/stage0/tests/namespace_occurrence_serde.rs index dea6613fcca..bd614b888ee 100644 --- a/src/v1/stage0/tests/namespace_occurrence_serde.rs +++ b/src/v1/stage0/tests/namespace_occurrence_serde.rs @@ -13,7 +13,7 @@ use v1_compiler::v1_compiler_parse::{parse_with_table_in_occurrence_scope, Parse use v1_compiler::v1_compiler_tokenize::tokenize; use v1_compiler::v1_std_core::{ build_newline_index, empty_intern_table, make_expr_node, no_span, with_required_cardinality, - ExprData, NewlineIndex, Node, + ExprData, InferredNode, MatchPattern, NewlineIndex, Node, }; fn parse_source( @@ -131,6 +131,20 @@ fn node_occurrence_ids(node: &Node, ids: &mut Vec, synthetic_count: &mut us { node_occurrence_ids(optional, ids, synthetic_count); } + if let Some(InferredNode::Resolved { node: inferred }) = node.inferred.as_deref() { + node_occurrence_ids(inferred, ids, synthetic_count); + } + match node.match_pattern.as_deref() { + Some(MatchPattern::Bind { declaration }) => { + node_occurrence_ids(declaration, ids, synthetic_count); + } + Some(MatchPattern::VariantPattern { field_bindings, .. }) => { + for binding in field_bindings.iter() { + node_occurrence_ids(binding, ids, synthetic_count); + } + } + Some(MatchPattern::LitPattern { .. } | MatchPattern::Wildcard) | None => {} + } } #[test] From e6bdbcdf21de075c1982ed4294fd41a0d62e026c Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 02:51:35 +0000 Subject: [PATCH 12/30] Account for shared nodes in identity control --- .../tests/namespace_occurrence_serde.rs | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/v1/stage0/tests/namespace_occurrence_serde.rs b/src/v1/stage0/tests/namespace_occurrence_serde.rs index bd614b888ee..d1498ecd5ae 100644 --- a/src/v1/stage0/tests/namespace_occurrence_serde.rs +++ b/src/v1/stage0/tests/namespace_occurrence_serde.rs @@ -180,11 +180,30 @@ fn occurrence_transport_round_trips_with_node_identity_and_paths() { node_ids, sidecar_ids, "parser node identities must equal sidecar identities" ); - node_ids.dedup(); + let mut unique_node_ids = node_ids.clone(); + unique_node_ids.dedup(); + let mut unique_sidecar_ids = sidecar_ids.clone(); + unique_sidecar_ids.dedup(); assert_eq!( - node_ids.len(), - sidecar_ids.len(), - "authored node identities must be distinct" + unique_node_ids, unique_sidecar_ids, + "authored node and sidecar identity sets must agree despite shared node reachability" + ); + let mut equal_parameter_ids: Vec = module + .children + .iter() + .flat_map(|declaration| declaration.params.iter()) + .filter(|parameter| parameter.name == "x") + .map(|parameter| match parameter.occurrence_identity.as_ref() { + NodeOccurrenceIdentity::OccurrenceMinted { id } => id.value, + _ => panic!("authored parameter did not carry a minted identity"), + }) + .collect(); + equal_parameter_ids.sort_unstable(); + equal_parameter_ids.dedup(); + assert_eq!( + equal_parameter_ids.len(), + 2, + "structurally equal authored parameters must have distinct identities" ); assert_eq!( synthetic_count, 0, From 765465d68675438566769b18c94f49eb9ca14b5f Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 03:15:26 +0000 Subject: [PATCH 13/30] Index shared authored occurrences once --- src/v1/02_parse.dag | 50 ++++++++---- src/v1/stage0/src/compiler_tests.rs | 3 - src/v1/stage0/src/v1_compiler_parse.rs | 81 ++++++++++++------- .../tests/namespace_occurrence_serde.rs | 8 +- 4 files changed, 89 insertions(+), 53 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index 2a1ed4ccf15..96e2c1ecb8d 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -1162,6 +1162,18 @@ fn occurrence_ancestors_push( concat(ancestors, Cons { head: occurrence, tail: Empty }) } +fn occurrence_index_contains( + entries: List, + occurrence: OccurrenceId +) -> Bool { + fold( + entries, + init: false, + f: (found, entry) => + found || entry.projection.occurrence.value == occurrence.value + ) +} + fn stamp_parsed_node_list( nodes: List, ancestors: FreeMonoid, @@ -1484,23 +1496,27 @@ fn stamp_parsed_node( ) let indexed_ctx = match occurrence { Present { value: id } => { - let containment = OccurrenceContainmentPath { ancestors: ancestors, terminal: id } - let with_index = parse_context_with_occurrence_state( - ctx: ctx, - occurrence_allocator: ctx.occurrence_allocator, - occurrence_index: Present { value: OccurrenceIndex { - entries: list_push( - parse_context_occurrence_index(ctx: ctx).entries, - OccurrenceIndexEntry { - projection: OccurrenceProjection { occurrence: id, authored_name: node.name, diagnostic_span: node.span }, - containment: containment, - } - ), - } }, - declaration_occurrences: ctx.declaration_occurrences, - reference_occurrences: ctx.reference_occurrences - ) - parse_context_record_occurrence(ctx: with_index, role: effective_role, occurrence: id, containment: containment, diagnostic_span: node.span) + if occurrence_index_contains(entries: parse_context_occurrence_index(ctx: ctx).entries, occurrence: id) { + ctx + } else { + let containment = OccurrenceContainmentPath { ancestors: ancestors, terminal: id } + let with_index = parse_context_with_occurrence_state( + ctx: ctx, + occurrence_allocator: ctx.occurrence_allocator, + occurrence_index: Present { value: OccurrenceIndex { + entries: list_push( + parse_context_occurrence_index(ctx: ctx).entries, + OccurrenceIndexEntry { + projection: OccurrenceProjection { occurrence: id, authored_name: node.name, diagnostic_span: node.span }, + containment: containment, + } + ), + } }, + declaration_occurrences: ctx.declaration_occurrences, + reference_occurrences: ctx.reference_occurrences + ) + parse_context_record_occurrence(ctx: with_index, role: effective_role, occurrence: id, containment: containment, diagnostic_span: node.span) + } } Absent => ctx } diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index 81cc8196800..1cc1406d348 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -2163,9 +2163,6 @@ mod compiler_tests { ) -> std::rc::Rc { let span = crate::v1_std_core::no_span(); std::rc::Rc::new(crate::v1_std_core::Node { - occurrence_identity: std::rc::Rc::new( - crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, - ), name: name.to_string(), ident: None, span: span.clone(), diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index 3003bc673a6..b4edd8beef4 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -2602,6 +2602,20 @@ pub fn occurrence_ancestors_push( ) } +pub fn occurrence_index_contains( + entries: Rc>>, + occurrence: OccurrenceId, +) -> bool { + entries + .iter() + .cloned() + .fold(false, |found: bool, entry: Rc| { + (found + || (entry.projection.clone().occurrence.clone().value.clone() + == occurrence.value.clone())) + }) +} + pub fn stamp_parsed_node_list( nodes: Rc>>, ancestors: Rc>, @@ -2984,36 +2998,45 @@ pub fn stamp_parsed_node( let effective_role = parsed_occurrence_role_for_node(node.clone(), role.clone()); let indexed_ctx = match occurrence.clone() { Some(id) => { - let containment = Rc::new(OccurrenceContainmentPath { - ancestors: ancestors.clone(), - terminal: id.clone(), - }); - let with_index = parse_context_with_occurrence_state( - ctx.clone(), - ctx.occurrence_allocator.clone(), - Some(Rc::new(OccurrenceIndex { - entries: v1_rt::rc_list_push( - parse_context_occurrence_index(ctx.clone()).entries.clone(), - Rc::new(OccurrenceIndexEntry { - projection: Rc::new(OccurrenceProjection { - occurrence: id.clone(), - authored_name: node.name.clone(), - diagnostic_span: node.span.clone(), - }), - containment: containment.clone(), - }), - ), - })), - ctx.declaration_occurrences.clone(), - ctx.reference_occurrences.clone(), - ); - parse_context_record_occurrence( - with_index.clone(), - effective_role.clone(), + if occurrence_index_contains( + parse_context_occurrence_index(ctx.clone()).entries.clone(), id.clone(), - containment.clone(), - node.span.clone(), - ) + ) { + ctx.clone() + } else { + { + let containment = Rc::new(OccurrenceContainmentPath { + ancestors: ancestors.clone(), + terminal: id.clone(), + }); + let with_index = parse_context_with_occurrence_state( + ctx.clone(), + ctx.occurrence_allocator.clone(), + Some(Rc::new(OccurrenceIndex { + entries: v1_rt::rc_list_push( + parse_context_occurrence_index(ctx.clone()).entries.clone(), + Rc::new(OccurrenceIndexEntry { + projection: Rc::new(OccurrenceProjection { + occurrence: id.clone(), + authored_name: node.name.clone(), + diagnostic_span: node.span.clone(), + }), + containment: containment.clone(), + }), + ), + })), + ctx.declaration_occurrences.clone(), + ctx.reference_occurrences.clone(), + ); + parse_context_record_occurrence( + with_index.clone(), + effective_role.clone(), + id.clone(), + containment.clone(), + node.span.clone(), + ) + } + } } None => ctx.clone(), }; diff --git a/src/v1/stage0/tests/namespace_occurrence_serde.rs b/src/v1/stage0/tests/namespace_occurrence_serde.rs index d1498ecd5ae..c39879b56fe 100644 --- a/src/v1/stage0/tests/namespace_occurrence_serde.rs +++ b/src/v1/stage0/tests/namespace_occurrence_serde.rs @@ -176,14 +176,14 @@ fn occurrence_transport_round_trips_with_node_identity_and_paths() { .collect(); node_ids.sort_unstable(); sidecar_ids.sort_unstable(); - assert_eq!( - node_ids, sidecar_ids, - "parser node identities must equal sidecar identities" - ); let mut unique_node_ids = node_ids.clone(); unique_node_ids.dedup(); let mut unique_sidecar_ids = sidecar_ids.clone(); unique_sidecar_ids.dedup(); + assert_eq!( + sidecar_ids, unique_sidecar_ids, + "the parser sidecar must index each authored identity exactly once" + ); assert_eq!( unique_node_ids, unique_sidecar_ids, "authored node and sidecar identity sets must agree despite shared node reachability" From 43f5c0c40e47c7b1f0317cff30d59ced869d2b9f Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 03:49:47 +0000 Subject: [PATCH 14/30] Canonicalize occurrence transport projections --- src/v1/02_parse.dag | 75 ++++++++++++++++++++++- src/v1/stage0/src/v1_compiler_parse.rs | 84 +++++++++++++++++++++++++- 2 files changed, 153 insertions(+), 6 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index 96e2c1ecb8d..a598fd3b03c 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -1174,6 +1174,73 @@ fn occurrence_index_contains( ) } +fn occurrence_index_unique(entries: List) -> List { + fold( + entries, + init: [], + f: (unique, entry) => + if occurrence_index_contains(entries: unique, occurrence: entry.projection.occurrence) { + unique + } else { + list_push(unique, entry) + } + ) +} + +fn declaration_occurrences_contain( + declarations: List, + occurrence: OccurrenceId +) -> Bool { + fold( + declarations, + init: false, + f: (found, declaration) => + found || declaration.occurrence.value == occurrence.value + ) +} + +fn declaration_occurrences_unique( + declarations: List +) -> List { + fold( + declarations, + init: [], + f: (unique, declaration) => + if declaration_occurrences_contain(declarations: unique, occurrence: declaration.occurrence) { + unique + } else { + list_push(unique, declaration) + } + ) +} + +fn reference_occurrences_contain( + references: List, + occurrence: OccurrenceId +) -> Bool { + fold( + references, + init: false, + f: (found, reference) => + found || reference.occurrence.value == occurrence.value + ) +} + +fn reference_occurrences_unique( + references: List +) -> List { + fold( + references, + init: [], + f: (unique, reference) => + if reference_occurrences_contain(references: unique, occurrence: reference.occurrence) { + unique + } else { + list_push(unique, reference) + } + ) +} + fn stamp_parsed_node_list( nodes: List, ancestors: FreeMonoid, @@ -1593,9 +1660,11 @@ fn stamp_parsed_node( fn occurrence_transport_from_parse_context(ctx: ParseContext) -> OccurrenceTransport { OccurrenceTransport { - index: parse_context_occurrence_index(ctx: ctx), - declarations: parse_context_declaration_occurrences(ctx: ctx), - references: parse_context_reference_occurrences(ctx: ctx), + index: OccurrenceIndex { + entries: occurrence_index_unique(entries: parse_context_occurrence_index(ctx: ctx).entries), + }, + declarations: declaration_occurrences_unique(declarations: parse_context_declaration_occurrences(ctx: ctx)), + references: reference_occurrences_unique(references: parse_context_reference_occurrences(ctx: ctx)), } } diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index b4edd8beef4..9e337563993 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -2616,6 +2616,78 @@ pub fn occurrence_index_contains( }) } +pub fn occurrence_index_unique( + entries: Rc>>, +) -> Rc>> { + entries.iter().cloned().fold( + Rc::new(vec![]), + |unique: Rc>>, entry: Rc| { + if occurrence_index_contains( + unique.clone(), + entry.projection.clone().occurrence.clone(), + ) { + unique.clone() + } else { + v1_rt::rc_list_push(unique.clone(), entry.clone()) + } + }, + ) +} + +pub fn declaration_occurrences_contain( + declarations: Rc>>, + occurrence: OccurrenceId, +) -> bool { + declarations.iter().cloned().fold( + false, + |found: bool, declaration: Rc| { + (found || (declaration.occurrence.clone().value.clone() == occurrence.value.clone())) + }, + ) +} + +pub fn declaration_occurrences_unique( + declarations: Rc>>, +) -> Rc>> { + declarations.iter().cloned().fold( + Rc::new(vec![]), + |unique: Rc>>, declaration: Rc| { + if declaration_occurrences_contain(unique.clone(), declaration.occurrence.clone()) { + unique.clone() + } else { + v1_rt::rc_list_push(unique.clone(), declaration.clone()) + } + }, + ) +} + +pub fn reference_occurrences_contain( + references: Rc>>, + occurrence: OccurrenceId, +) -> bool { + references + .iter() + .cloned() + .fold(false, |found: bool, reference: Rc| { + (found || (reference.occurrence.clone().value.clone() == occurrence.value.clone())) + }) +} + +pub fn reference_occurrences_unique( + references: Rc>>, +) -> Rc>> { + references.iter().cloned().fold( + Rc::new(vec![]), + |unique: Rc>>, reference: Rc| { + if reference_occurrences_contain(unique.clone(), reference.occurrence.clone()) { + unique.clone() + } else { + v1_rt::rc_list_push(unique.clone(), reference.clone()) + } + }, + ) +} + pub fn stamp_parsed_node_list( nodes: Rc>>, ancestors: Rc>, @@ -3142,9 +3214,15 @@ pub fn stamp_parsed_node( pub fn occurrence_transport_from_parse_context(ctx: Rc) -> Rc { Rc::new(OccurrenceTransport { - index: parse_context_occurrence_index(ctx.clone()), - declarations: parse_context_declaration_occurrences(ctx.clone()), - references: parse_context_reference_occurrences(ctx.clone()), + index: Rc::new(OccurrenceIndex { + entries: occurrence_index_unique( + parse_context_occurrence_index(ctx.clone()).entries.clone(), + ), + }), + declarations: declaration_occurrences_unique(parse_context_declaration_occurrences( + ctx.clone(), + )), + references: reference_occurrences_unique(parse_context_reference_occurrences(ctx.clone())), }) } From 26962d0e9256f62c330c3a62e0bf6abe8f8a9de5 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 03:57:27 +0000 Subject: [PATCH 15/30] Revert "Canonicalize occurrence transport projections" This reverts commit 43f5c0c40e47c7b1f0317cff30d59ced869d2b9f. --- src/v1/02_parse.dag | 75 +---------------------- src/v1/stage0/src/v1_compiler_parse.rs | 84 +------------------------- 2 files changed, 6 insertions(+), 153 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index a598fd3b03c..96e2c1ecb8d 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -1174,73 +1174,6 @@ fn occurrence_index_contains( ) } -fn occurrence_index_unique(entries: List) -> List { - fold( - entries, - init: [], - f: (unique, entry) => - if occurrence_index_contains(entries: unique, occurrence: entry.projection.occurrence) { - unique - } else { - list_push(unique, entry) - } - ) -} - -fn declaration_occurrences_contain( - declarations: List, - occurrence: OccurrenceId -) -> Bool { - fold( - declarations, - init: false, - f: (found, declaration) => - found || declaration.occurrence.value == occurrence.value - ) -} - -fn declaration_occurrences_unique( - declarations: List -) -> List { - fold( - declarations, - init: [], - f: (unique, declaration) => - if declaration_occurrences_contain(declarations: unique, occurrence: declaration.occurrence) { - unique - } else { - list_push(unique, declaration) - } - ) -} - -fn reference_occurrences_contain( - references: List, - occurrence: OccurrenceId -) -> Bool { - fold( - references, - init: false, - f: (found, reference) => - found || reference.occurrence.value == occurrence.value - ) -} - -fn reference_occurrences_unique( - references: List -) -> List { - fold( - references, - init: [], - f: (unique, reference) => - if reference_occurrences_contain(references: unique, occurrence: reference.occurrence) { - unique - } else { - list_push(unique, reference) - } - ) -} - fn stamp_parsed_node_list( nodes: List, ancestors: FreeMonoid, @@ -1660,11 +1593,9 @@ fn stamp_parsed_node( fn occurrence_transport_from_parse_context(ctx: ParseContext) -> OccurrenceTransport { OccurrenceTransport { - index: OccurrenceIndex { - entries: occurrence_index_unique(entries: parse_context_occurrence_index(ctx: ctx).entries), - }, - declarations: declaration_occurrences_unique(declarations: parse_context_declaration_occurrences(ctx: ctx)), - references: reference_occurrences_unique(references: parse_context_reference_occurrences(ctx: ctx)), + index: parse_context_occurrence_index(ctx: ctx), + declarations: parse_context_declaration_occurrences(ctx: ctx), + references: parse_context_reference_occurrences(ctx: ctx), } } diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index 9e337563993..b4edd8beef4 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -2616,78 +2616,6 @@ pub fn occurrence_index_contains( }) } -pub fn occurrence_index_unique( - entries: Rc>>, -) -> Rc>> { - entries.iter().cloned().fold( - Rc::new(vec![]), - |unique: Rc>>, entry: Rc| { - if occurrence_index_contains( - unique.clone(), - entry.projection.clone().occurrence.clone(), - ) { - unique.clone() - } else { - v1_rt::rc_list_push(unique.clone(), entry.clone()) - } - }, - ) -} - -pub fn declaration_occurrences_contain( - declarations: Rc>>, - occurrence: OccurrenceId, -) -> bool { - declarations.iter().cloned().fold( - false, - |found: bool, declaration: Rc| { - (found || (declaration.occurrence.clone().value.clone() == occurrence.value.clone())) - }, - ) -} - -pub fn declaration_occurrences_unique( - declarations: Rc>>, -) -> Rc>> { - declarations.iter().cloned().fold( - Rc::new(vec![]), - |unique: Rc>>, declaration: Rc| { - if declaration_occurrences_contain(unique.clone(), declaration.occurrence.clone()) { - unique.clone() - } else { - v1_rt::rc_list_push(unique.clone(), declaration.clone()) - } - }, - ) -} - -pub fn reference_occurrences_contain( - references: Rc>>, - occurrence: OccurrenceId, -) -> bool { - references - .iter() - .cloned() - .fold(false, |found: bool, reference: Rc| { - (found || (reference.occurrence.clone().value.clone() == occurrence.value.clone())) - }) -} - -pub fn reference_occurrences_unique( - references: Rc>>, -) -> Rc>> { - references.iter().cloned().fold( - Rc::new(vec![]), - |unique: Rc>>, reference: Rc| { - if reference_occurrences_contain(unique.clone(), reference.occurrence.clone()) { - unique.clone() - } else { - v1_rt::rc_list_push(unique.clone(), reference.clone()) - } - }, - ) -} - pub fn stamp_parsed_node_list( nodes: Rc>>, ancestors: Rc>, @@ -3214,15 +3142,9 @@ pub fn stamp_parsed_node( pub fn occurrence_transport_from_parse_context(ctx: Rc) -> Rc { Rc::new(OccurrenceTransport { - index: Rc::new(OccurrenceIndex { - entries: occurrence_index_unique( - parse_context_occurrence_index(ctx.clone()).entries.clone(), - ), - }), - declarations: declaration_occurrences_unique(parse_context_declaration_occurrences( - ctx.clone(), - )), - references: reference_occurrences_unique(parse_context_reference_occurrences(ctx.clone())), + index: parse_context_occurrence_index(ctx.clone()), + declarations: parse_context_declaration_occurrences(ctx.clone()), + references: parse_context_reference_occurrences(ctx.clone()), }) } From 7de2a77525a6974972ada992fe23614cae88d094 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 04:04:01 +0000 Subject: [PATCH 16/30] Complete remaining identity test constructions --- src/v1/compiler_tests_rust.dag | 1 + src/v1/stage0/src/compiler_tests.rs | 3 +++ src/v1/stage0/src/v1_interpreter.rs | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/v1/compiler_tests_rust.dag b/src/v1/compiler_tests_rust.dag index c783051dc49..2925b95d4c4 100644 --- a/src/v1/compiler_tests_rust.dag +++ b/src/v1/compiler_tests_rust.dag @@ -722,6 +722,7 @@ fn ct_rust_btree_set_ord_eligibility_test() -> String { " fn shaped_type_node(name: &str, children: Vec>) -> std::rc::Rc {\n", " let span = crate::v1_std_core::no_span();\n", " std::rc::Rc::new(crate::v1_std_core::Node {\n", + " occurrence_identity: std::rc::Rc::new(crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic),\n", " name: name.to_string(),\n", " ident: None,\n", " span: span.clone(),\n", diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index 1cc1406d348..81cc8196800 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -2163,6 +2163,9 @@ mod compiler_tests { ) -> std::rc::Rc { let span = crate::v1_std_core::no_span(); std::rc::Rc::new(crate::v1_std_core::Node { + occurrence_identity: std::rc::Rc::new( + crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic, + ), name: name.to_string(), ident: None, span: span.clone(), diff --git a/src/v1/stage0/src/v1_interpreter.rs b/src/v1/stage0/src/v1_interpreter.rs index d0a02a7309c..be06f240333 100644 --- a/src/v1/stage0/src/v1_interpreter.rs +++ b/src/v1/stage0/src/v1_interpreter.rs @@ -16264,7 +16264,7 @@ mod map_shell_outputs_optional_stream_tests { str_type, Cardinality::CardOptional, None, - Rc::new(vec![]), + Rc::new(vec![].into()), span.clone(), span.clone(), ); From 594c932f0b99d6d5f222731cb49770cc8ee5ccad Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 04:11:06 +0000 Subject: [PATCH 17/30] Control OCI parser identity uniqueness --- .../tests/namespace_occurrence_serde.rs | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/v1/stage0/tests/namespace_occurrence_serde.rs b/src/v1/stage0/tests/namespace_occurrence_serde.rs index c39879b56fe..583a3b93df8 100644 --- a/src/v1/stage0/tests/namespace_occurrence_serde.rs +++ b/src/v1/stage0/tests/namespace_occurrence_serde.rs @@ -3,6 +3,7 @@ // (dag/test/claim/namespace_occurrence_transport_test.dag). v1-test class: this file // deletes with src/v1 once its behavior is carried per the v1-test-migration coverage bar. use im::HashMap; +use std::collections::HashSet; use std::rc::Rc; use v1_compiler::std_occurrence_identity::{ @@ -147,6 +148,80 @@ fn node_occurrence_ids(node: &Node, ids: &mut Vec, synthetic_count: &mut us } } +fn node_occurrence_descriptions(node: &Node, wanted: i64, found: &mut Vec) { + if matches!(node.occurrence_identity.as_ref(), NodeOccurrenceIdentity::OccurrenceMinted { id } if id.value == wanted) + { + found.push(format!( + "name={:?} span={}:{}-{}", + node.name, node.span.file, node.span.start, node.span.end + )); + } + for child in node + .children + .iter() + .chain(node.params.iter()) + .chain(node.uses.iter()) + .chain(node.properties.iter()) + { + node_occurrence_descriptions(child, wanted, found); + } + for optional in [ + node.body.as_ref(), + node.transport.as_ref(), + node.type_annotation.as_ref(), + ] + .into_iter() + .flatten() + { + node_occurrence_descriptions(optional, wanted, found); + } + if let Some(InferredNode::Resolved { node: inferred }) = node.inferred.as_deref() { + node_occurrence_descriptions(inferred, wanted, found); + } + match node.match_pattern.as_deref() { + Some(MatchPattern::Bind { declaration }) => { + node_occurrence_descriptions(declaration, wanted, found) + } + Some(MatchPattern::VariantPattern { field_bindings, .. }) => { + for binding in field_bindings.iter() { + node_occurrence_descriptions(binding, wanted, found); + } + } + _ => {} + } +} + +#[test] +fn oci_digest_parser_does_not_reuse_authored_identity() { + let parsed = parse_source( + include_str!("../../../../dag/extdeps/container/oci/digest.dag"), + "dag/extdeps/container/oci/digest.dag", + occurrence_id_allocator_initial(), + ); + assert!(parsed.result.error.is_none(), "{:?}", parsed.result.error); + let mut seen = HashSet::new(); + if let Some(duplicate) = parsed + .occurrence_transport + .index + .entries + .iter() + .map(|entry| entry.projection.occurrence.value) + .find(|id| !seen.insert(*id)) + { + let mut descriptions = Vec::new(); + node_occurrence_descriptions( + parsed + .result + .module + .as_ref() + .expect("successful parse module"), + duplicate, + &mut descriptions, + ); + panic!("duplicate authored identity {duplicate}: {descriptions:?}"); + } +} + #[test] fn occurrence_transport_round_trips_with_node_identity_and_paths() { let source = "module occurrence.serde\n\nfn left(x: Int) -> Int { x }\nfn right(x: Int) -> Int { left(x) }\n"; From 4a89871e513aebe8315ddde8ba4e59c5441251fe Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 04:28:02 +0000 Subject: [PATCH 18/30] Advance allocator beyond published occurrences --- src/v1/02_parse.dag | 26 ++++++++++++++-- .../src/v1_compiler_compiler_tests_rust.rs | 2 +- src/v1/stage0/src/v1_compiler_parse.rs | 30 +++++++++++++++++-- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index 96e2c1ecb8d..ab7aa83a3ba 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -1174,6 +1174,22 @@ fn occurrence_index_contains( ) } +fn occurrence_allocator_after_index( + alloc: OccurrenceIdAllocator, + entries: List +) -> OccurrenceIdAllocator { + fold( + entries, + init: alloc, + f: (current, entry) => + if current.next_id <= entry.projection.occurrence.value { + OccurrenceIdAllocator { next_id: entry.projection.occurrence.value + 1 } + } else { + current + } + ) +} + fn stamp_parsed_node_list( nodes: List, ancestors: FreeMonoid, @@ -1627,7 +1643,10 @@ fn parse_with_table_at( let r = parse_module(tokens: token_stream_new(all: tokens), ctx: ctx) if has_err(err: r.err) { let occurrence_transport = occurrence_transport_from_parse_context(ctx: r.ctx) - let occurrence_allocator = parse_context_occurrence_allocator(ctx: r.ctx) + let occurrence_allocator = occurrence_allocator_after_index( + alloc: parse_context_occurrence_allocator(ctx: r.ctx), + entries: occurrence_transport.index.entries + ) ParseWithTableResult { result: ParseResult { module: none, error: r.err }, intern_table: intern_table_with_authored_token_ordinals( @@ -1647,7 +1666,10 @@ fn parse_with_table_at( role: ParsedOccurrenceDeclaration { category: NamespaceSegmentOccurrence } ) let occurrence_transport = occurrence_transport_from_parse_context(ctx: stamped.ctx) - let occurrence_allocator = parse_context_occurrence_allocator(ctx: stamped.ctx) + let occurrence_allocator = occurrence_allocator_after_index( + alloc: parse_context_occurrence_allocator(ctx: stamped.ctx), + entries: occurrence_transport.index.entries + ) ParseWithTableResult { result: ParseResult { module: if has_err(err: stamped.err) { none } else { Present { value: stamped.node } }, diff --git a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs index 9532f0ecda6..9d64204f5a5 100644 --- a/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs +++ b/src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs @@ -99,7 +99,7 @@ pub fn ct_diagnostics_carrier_grounding_test() -> String { } pub fn ct_rust_btree_set_ord_eligibility_test() -> String { - v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" fn shaped_type_node(name: &str, children: Vec>) -> std::rc::Rc {\n".to_string(), " let span = crate::v1_std_core::no_span();\n".to_string()), " std::rc::Rc::new(crate::v1_std_core::Node {\n".to_string()), " name: name.to_string(),\n".to_string()), " ident: None,\n".to_string()), " span: span.clone(),\n".to_string()), " ident_span: Some(span),\n".to_string()), " children: std::rc::Rc::new(children.into()),\n".to_string()), " connective: crate::v1_std_core::Connective::NoConnective,\n".to_string()), " params: std::rc::Rc::new(im::Vector::new()),\n".to_string()), " inferred: None,\n".to_string()), " return_cardinality: crate::v1_std_core::Cardinality::Required,\n".to_string()), " uses: std::rc::Rc::new(im::Vector::new()),\n".to_string()), " body: None,\n".to_string()), " transport: None,\n".to_string()), " properties: std::rc::Rc::new(im::Vector::new()),\n".to_string()), " type_annotation: None,\n".to_string()), " is_self_recursive: false,\n".to_string()), " has_non_tail_self_call: false,\n".to_string()), " match_pattern: None,\n".to_string()), " expr_data: std::rc::Rc::new(crate::v1_std_core::ExprData::NoExprData),\n".to_string()), " })\n".to_string()), " }\n\n".to_string()), " fn named_type_node(name: &str) -> std::rc::Rc {\n".to_string()), " shaped_type_node(name, Vec::new())\n".to_string()), " }\n\n".to_string()), " #[test]\n".to_string()), " fn rust_btree_set_ord_eligibility_requires_nominal_carrier_shape() {\n".to_string()), " let source_indices = std::rc::Rc::new(HashMap::new());\n".to_string()), " let empty_emit = crate::v1_compiler_infer_emit_info::empty_emit_graph_info();\n".to_string()), " let symbol = named_type_node(\"Symbol\");\n".to_string()), " let diff_id = shaped_type_node(\"DiffId\", vec![symbol.clone()]);\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " symbol.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " diff_id.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " let formal_nonterminal = shaped_type_node(\"FormalNonterminal\", vec![symbol.clone()]);\n".to_string()), " let formal_terminal = shaped_type_node(\"FormalTerminal\", vec![symbol.clone()]);\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " formal_nonterminal.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " formal_terminal.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " shaped_type_node(\"Symbol\", vec![named_type_node(\"Float\")]),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " shaped_type_node(\"DiffId\", vec![named_type_node(\"Float\")]),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " named_type_node(\"TestClaimId\"),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " }\n\n".to_string()) + v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(" fn shaped_type_node(name: &str, children: Vec>) -> std::rc::Rc {\n".to_string(), " let span = crate::v1_std_core::no_span();\n".to_string()), " std::rc::Rc::new(crate::v1_std_core::Node {\n".to_string()), " occurrence_identity: std::rc::Rc::new(crate::std_occurrence_identity::NodeOccurrenceIdentity::OccurrenceSynthetic),\n".to_string()), " name: name.to_string(),\n".to_string()), " ident: None,\n".to_string()), " span: span.clone(),\n".to_string()), " ident_span: Some(span),\n".to_string()), " children: std::rc::Rc::new(children.into()),\n".to_string()), " connective: crate::v1_std_core::Connective::NoConnective,\n".to_string()), " params: std::rc::Rc::new(im::Vector::new()),\n".to_string()), " inferred: None,\n".to_string()), " return_cardinality: crate::v1_std_core::Cardinality::Required,\n".to_string()), " uses: std::rc::Rc::new(im::Vector::new()),\n".to_string()), " body: None,\n".to_string()), " transport: None,\n".to_string()), " properties: std::rc::Rc::new(im::Vector::new()),\n".to_string()), " type_annotation: None,\n".to_string()), " is_self_recursive: false,\n".to_string()), " has_non_tail_self_call: false,\n".to_string()), " match_pattern: None,\n".to_string()), " expr_data: std::rc::Rc::new(crate::v1_std_core::ExprData::NoExprData),\n".to_string()), " })\n".to_string()), " }\n\n".to_string()), " fn named_type_node(name: &str) -> std::rc::Rc {\n".to_string()), " shaped_type_node(name, Vec::new())\n".to_string()), " }\n\n".to_string()), " #[test]\n".to_string()), " fn rust_btree_set_ord_eligibility_requires_nominal_carrier_shape() {\n".to_string()), " let source_indices = std::rc::Rc::new(HashMap::new());\n".to_string()), " let empty_emit = crate::v1_compiler_infer_emit_info::empty_emit_graph_info();\n".to_string()), " let symbol = named_type_node(\"Symbol\");\n".to_string()), " let diff_id = shaped_type_node(\"DiffId\", vec![symbol.clone()]);\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " symbol.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " diff_id.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " let formal_nonterminal = shaped_type_node(\"FormalNonterminal\", vec![symbol.clone()]);\n".to_string()), " let formal_terminal = shaped_type_node(\"FormalTerminal\", vec![symbol.clone()]);\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " formal_nonterminal.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " formal_terminal.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " shaped_type_node(\"Symbol\", vec![named_type_node(\"Float\")]),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " shaped_type_node(\"DiffId\", vec![named_type_node(\"Float\")]),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v1_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " named_type_node(\"TestClaimId\"),\n".to_string()), " source_indices.clone(),\n".to_string()), " empty_emit.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " }\n\n".to_string()) } pub fn render_target_rust_enum(target: RenderTarget) -> String { diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index b4edd8beef4..daca2459934 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -2616,6 +2616,26 @@ pub fn occurrence_index_contains( }) } +pub fn occurrence_allocator_after_index( + alloc: OccurrenceIdAllocator, + entries: Rc>>, +) -> OccurrenceIdAllocator { + entries.iter().cloned().fold( + alloc.clone(), + |current: OccurrenceIdAllocator, entry: Rc| { + if (current.next_id.clone() + <= entry.projection.clone().occurrence.clone().value.clone()) + { + OccurrenceIdAllocator { + next_id: (entry.projection.clone().occurrence.clone().value.clone() + 1), + } + } else { + current.clone() + } + }, + ) +} + pub fn stamp_parsed_node_list( nodes: Rc>>, ancestors: Rc>, @@ -3176,7 +3196,10 @@ pub fn parse_with_table_at( if has_err(r.err.clone()) { { let occurrence_transport = occurrence_transport_from_parse_context(r.ctx.clone()); - let occurrence_allocator = parse_context_occurrence_allocator(r.ctx.clone()); + let occurrence_allocator = occurrence_allocator_after_index( + parse_context_occurrence_allocator(r.ctx.clone()), + occurrence_transport.index.clone().entries.clone(), + ); Rc::new(ParseWithTableResult { result: Rc::new(ParseResult { module: None, @@ -3202,7 +3225,10 @@ pub fn parse_with_table_at( ); let occurrence_transport = occurrence_transport_from_parse_context(stamped.ctx.clone()); - let occurrence_allocator = parse_context_occurrence_allocator(stamped.ctx.clone()); + let occurrence_allocator = occurrence_allocator_after_index( + parse_context_occurrence_allocator(stamped.ctx.clone()), + occurrence_transport.index.clone().entries.clone(), + ); Rc::new(ParseWithTableResult { result: Rc::new(ParseResult { module: if has_err(stamped.err.clone()) { From 4ea83bc1ed9f7f52047f6b667bc1be9c99d67574 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 04:35:45 +0000 Subject: [PATCH 19/30] Control annotation subject identity coverage --- .../tests/namespace_occurrence_serde.rs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/v1/stage0/tests/namespace_occurrence_serde.rs b/src/v1/stage0/tests/namespace_occurrence_serde.rs index 583a3b93df8..40b1c9ee4ee 100644 --- a/src/v1/stage0/tests/namespace_occurrence_serde.rs +++ b/src/v1/stage0/tests/namespace_occurrence_serde.rs @@ -222,6 +222,44 @@ fn oci_digest_parser_does_not_reuse_authored_identity() { } } +#[test] +fn expected_red_roster_items_remain_annotation_subjects() { + let parsed = parse_source( + include_str!("../../expected_red_roster_join.dag"), + "src/v1/expected_red_roster_join.dag", + occurrence_id_allocator_initial(), + ); + assert!(parsed.result.error.is_none(), "{:?}", parsed.result.error); + let module = parsed + .result + .module + .as_ref() + .expect("successful parse module"); + let synthetic_items: Vec = module + .children + .iter() + .filter(|item| { + matches!( + item.occurrence_identity.as_ref(), + NodeOccurrenceIdentity::OccurrenceSynthetic + ) + }) + .map(|item| item.name.clone()) + .collect(); + let depth_one = parsed + .occurrence_transport + .index + .entries + .iter() + .filter(|entry| entry.containment.ancestors.len() == 1) + .count(); + assert_eq!( + depth_one, + module.children.len() + module.params.len(), + "every module item/import must remain an annotation subject; synthetic items={synthetic_items:?}" + ); +} + #[test] fn occurrence_transport_round_trips_with_node_identity_and_paths() { let source = "module occurrence.serde\n\nfn left(x: Int) -> Int { x }\nfn right(x: Int) -> Int { left(x) }\n"; From 724ce2dd6b3af6c403688950f71f6c97f4f81c7c Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 04:53:21 +0000 Subject: [PATCH 20/30] Publish allocator state from accepted node trees --- src/v1/02_parse.dag | 148 +++++++++++++----- src/v1/stage0/src/v1_compiler_parse.rs | 203 ++++++++++++++++++------- 2 files changed, 262 insertions(+), 89 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index ab7aa83a3ba..e18fba1a8cc 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -1162,18 +1162,6 @@ fn occurrence_ancestors_push( concat(ancestors, Cons { head: occurrence, tail: Empty }) } -fn occurrence_index_contains( - entries: List, - occurrence: OccurrenceId -) -> Bool { - fold( - entries, - init: false, - f: (found, entry) => - found || entry.projection.occurrence.value == occurrence.value - ) -} - fn occurrence_allocator_after_index( alloc: OccurrenceIdAllocator, entries: List @@ -1190,6 +1178,100 @@ fn occurrence_allocator_after_index( ) } +fn occurrence_allocator_after_identity( + alloc: OccurrenceIdAllocator, + identity: NodeOccurrenceIdentity +) -> OccurrenceIdAllocator { + match identity { + OccurrenceMinted { id: id } => + if alloc.next_id <= id.value { + OccurrenceIdAllocator { next_id: id.value + 1 } + } else { + alloc + } + OccurrenceProjected { id: id, caused_by: _ } => + if alloc.next_id <= id.value { + OccurrenceIdAllocator { next_id: id.value + 1 } + } else { + alloc + } + OccurrenceSynthetic => alloc + } +} + +fn occurrence_allocator_after_node_list( + alloc: OccurrenceIdAllocator, + nodes: List +) -> OccurrenceIdAllocator { + fold(nodes, init: alloc, f: (current, node) => occurrence_allocator_after_node(alloc: current, node: node)) +} + +fn occurrence_allocator_after_optional_node( + alloc: OccurrenceIdAllocator, + node: Node? +) -> OccurrenceIdAllocator { + match node { + Present { value: value } => occurrence_allocator_after_node(alloc: alloc, node: value) + Absent => alloc + } +} + +fn occurrence_allocator_after_inferred_node( + alloc: OccurrenceIdAllocator, + inferred: InferredNode? +) -> OccurrenceIdAllocator { + match inferred { + Present { value: Resolved { node: node } } => occurrence_allocator_after_node(alloc: alloc, node: node) + Present { value: CompilerError { message: _, span: _ } } => alloc + Present { value: TypeVariable { id: _ } } => alloc + Absent => alloc + } +} + +fn occurrence_allocator_after_match_pattern( + alloc: OccurrenceIdAllocator, + pattern: MatchPattern? +) -> OccurrenceIdAllocator { + match pattern { + Present { value: Bind { declaration: declaration } } => occurrence_allocator_after_node(alloc: alloc, node: declaration) + Present { value: VariantPattern { name: _, parent_enum: _, field_bindings: bindings } } => occurrence_allocator_after_node_list(alloc: alloc, nodes: bindings) + Present { value: LitPattern { value: _ } } => alloc + Present { value: Wildcard } => alloc + Absent => alloc + } +} + +fn occurrence_allocator_after_node( + alloc: OccurrenceIdAllocator, + node: Node +) -> OccurrenceIdAllocator { + let current = occurrence_allocator_after_identity(alloc: alloc, identity: node.occurrence_identity) + let current = occurrence_allocator_after_node_list(alloc: current, nodes: node.children) + let current = occurrence_allocator_after_node_list(alloc: current, nodes: node.params) + let current = occurrence_allocator_after_node_list(alloc: current, nodes: node.uses) + let current = occurrence_allocator_after_node_list(alloc: current, nodes: node.properties) + let current = occurrence_allocator_after_optional_node(alloc: current, node: node.body) + let current = occurrence_allocator_after_optional_node(alloc: current, node: node.transport) + let current = occurrence_allocator_after_optional_node(alloc: current, node: node.type_annotation) + let current = occurrence_allocator_after_inferred_node(alloc: current, inferred: node.inferred) + occurrence_allocator_after_match_pattern(alloc: current, pattern: node.match_pattern) +} + +fn parse_context_after_node(ctx: ParseContext, node: Node) -> ParseContext { + parse_context_with_occurrence_state( + ctx: ctx, + occurrence_allocator: Present { + value: occurrence_allocator_after_node( + alloc: parse_context_occurrence_allocator(ctx: ctx), + node: node + ), + }, + occurrence_index: ctx.occurrence_index, + declaration_occurrences: ctx.declaration_occurrences, + reference_occurrences: ctx.reference_occurrences + ) +} + fn stamp_parsed_node_list( nodes: List, ancestors: FreeMonoid, @@ -1512,27 +1594,23 @@ fn stamp_parsed_node( ) let indexed_ctx = match occurrence { Present { value: id } => { - if occurrence_index_contains(entries: parse_context_occurrence_index(ctx: ctx).entries, occurrence: id) { - ctx - } else { - let containment = OccurrenceContainmentPath { ancestors: ancestors, terminal: id } - let with_index = parse_context_with_occurrence_state( - ctx: ctx, - occurrence_allocator: ctx.occurrence_allocator, - occurrence_index: Present { value: OccurrenceIndex { - entries: list_push( - parse_context_occurrence_index(ctx: ctx).entries, - OccurrenceIndexEntry { - projection: OccurrenceProjection { occurrence: id, authored_name: node.name, diagnostic_span: node.span }, - containment: containment, - } - ), - } }, - declaration_occurrences: ctx.declaration_occurrences, - reference_occurrences: ctx.reference_occurrences - ) - parse_context_record_occurrence(ctx: with_index, role: effective_role, occurrence: id, containment: containment, diagnostic_span: node.span) - } + let containment = OccurrenceContainmentPath { ancestors: ancestors, terminal: id } + let with_index = parse_context_with_occurrence_state( + ctx: ctx, + occurrence_allocator: ctx.occurrence_allocator, + occurrence_index: Present { value: OccurrenceIndex { + entries: list_push( + parse_context_occurrence_index(ctx: ctx).entries, + OccurrenceIndexEntry { + projection: OccurrenceProjection { occurrence: id, authored_name: node.name, diagnostic_span: node.span }, + containment: containment, + } + ), + } }, + declaration_occurrences: ctx.declaration_occurrences, + reference_occurrences: ctx.reference_occurrences + ) + parse_context_record_occurrence(ctx: with_index, role: effective_role, occurrence: id, containment: containment, diagnostic_span: node.span) } Absent => ctx } @@ -1812,7 +1890,7 @@ fn parse_imports_acc(tokens: TokenStream, ctx: ParseContext, acc: List) -> if tok_is_keyword(tok: token_stream_first(stream: tokens), kw: "import") { let r = parse_import(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ImportsResult { imports: [], tokens: r.tokens, ctx: r.ctx, err: r.err } } - parse_imports_acc(tokens: r.tokens, ctx: r.ctx, acc: list_push(acc, r.import)) + parse_imports_acc(tokens: r.tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.import), acc: list_push(acc, r.import)) } else { ImportsResult { imports: acc, tokens: tokens, ctx: ctx, err: none } } @@ -1829,7 +1907,7 @@ fn parse_items_acc(tokens: TokenStream, ctx: ParseContext, acc: List) -> I } else { let r = parse_item(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ItemsResult { items: acc, tokens: r.tokens, ctx: r.ctx, err: r.err } } - parse_items_acc(tokens: r.tokens, ctx: r.ctx, acc: list_push(acc, r.item)) + parse_items_acc(tokens: r.tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.item), acc: list_push(acc, r.item)) } } diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index daca2459934..58f80ccd8dc 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -2602,20 +2602,6 @@ pub fn occurrence_ancestors_push( ) } -pub fn occurrence_index_contains( - entries: Rc>>, - occurrence: OccurrenceId, -) -> bool { - entries - .iter() - .cloned() - .fold(false, |found: bool, entry: Rc| { - (found - || (entry.projection.clone().occurrence.clone().value.clone() - == occurrence.value.clone())) - }) -} - pub fn occurrence_allocator_after_index( alloc: OccurrenceIdAllocator, entries: Rc>>, @@ -2636,6 +2622,124 @@ pub fn occurrence_allocator_after_index( ) } +pub fn occurrence_allocator_after_identity( + alloc: OccurrenceIdAllocator, + identity: Rc, +) -> OccurrenceIdAllocator { + match (*identity.clone()).clone() { + NodeOccurrenceIdentity::OccurrenceMinted { id: id, .. } => { + if (alloc.next_id.clone() <= id.value.clone()) { + OccurrenceIdAllocator { + next_id: (id.value.clone() + 1), + } + } else { + alloc + } + } + NodeOccurrenceIdentity::OccurrenceProjected { id, .. } => { + if (alloc.next_id.clone() <= id.value.clone()) { + OccurrenceIdAllocator { + next_id: (id.value.clone() + 1), + } + } else { + alloc + } + } + NodeOccurrenceIdentity::OccurrenceSynthetic => alloc, + } +} + +pub fn occurrence_allocator_after_node_list( + alloc: OccurrenceIdAllocator, + nodes: Rc>>, +) -> OccurrenceIdAllocator { + nodes.iter().cloned().fold( + alloc.clone(), + |current: OccurrenceIdAllocator, node: Rc| { + occurrence_allocator_after_node(current, node.clone()) + }, + ) +} + +pub fn occurrence_allocator_after_optional_node( + alloc: OccurrenceIdAllocator, + node: Option>, +) -> OccurrenceIdAllocator { + match node.clone() { + Some(value) => occurrence_allocator_after_node(alloc.clone(), value.clone()), + None => alloc.clone(), + } +} + +pub fn occurrence_allocator_after_inferred_node( + alloc: OccurrenceIdAllocator, + inferred: Option>, +) -> OccurrenceIdAllocator { + match inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { node: node, .. }) => { + occurrence_allocator_after_node(alloc.clone(), node.clone()) + } + Some(InferredNode::CompilerError { .. }) => alloc.clone(), + Some(InferredNode::TypeVariable { id: _, .. }) => alloc.clone(), + None => alloc.clone(), + } +} + +pub fn occurrence_allocator_after_match_pattern( + alloc: OccurrenceIdAllocator, + pattern: Option>, +) -> OccurrenceIdAllocator { + match pattern.clone().as_deref().cloned() { + Some(MatchPattern::Bind { + declaration: declaration, + .. + }) => occurrence_allocator_after_node(alloc.clone(), declaration.clone()), + Some(MatchPattern::VariantPattern { + field_bindings: bindings, + .. + }) => occurrence_allocator_after_node_list(alloc.clone(), bindings.clone()), + Some(MatchPattern::LitPattern { value: _, .. }) => alloc.clone(), + Some(MatchPattern::Wildcard) => alloc.clone(), + None => alloc.clone(), + } +} + +pub fn occurrence_allocator_after_node( + alloc: OccurrenceIdAllocator, + node: Rc, +) -> OccurrenceIdAllocator { + { + let current = + occurrence_allocator_after_identity(alloc.clone(), node.occurrence_identity.clone()); + let current = occurrence_allocator_after_node_list(current.clone(), node.children.clone()); + let current = occurrence_allocator_after_node_list(current.clone(), node.params.clone()); + let current = occurrence_allocator_after_node_list(current.clone(), node.uses.clone()); + let current = + occurrence_allocator_after_node_list(current.clone(), node.properties.clone()); + let current = occurrence_allocator_after_optional_node(current.clone(), node.body.clone()); + let current = + occurrence_allocator_after_optional_node(current.clone(), node.transport.clone()); + let current = + occurrence_allocator_after_optional_node(current.clone(), node.type_annotation.clone()); + let current = + occurrence_allocator_after_inferred_node(current.clone(), node.inferred.clone()); + occurrence_allocator_after_match_pattern(current.clone(), node.match_pattern.clone()) + } +} + +pub fn parse_context_after_node(ctx: Rc, node: Rc) -> Rc { + parse_context_with_occurrence_state( + ctx.clone(), + Some(occurrence_allocator_after_node( + parse_context_occurrence_allocator(ctx.clone()), + node.clone(), + )), + ctx.occurrence_index.clone(), + ctx.declaration_occurrences.clone(), + ctx.reference_occurrences.clone(), + ) +} + pub fn stamp_parsed_node_list( nodes: Rc>>, ancestors: Rc>, @@ -3018,45 +3122,36 @@ pub fn stamp_parsed_node( let effective_role = parsed_occurrence_role_for_node(node.clone(), role.clone()); let indexed_ctx = match occurrence.clone() { Some(id) => { - if occurrence_index_contains( - parse_context_occurrence_index(ctx.clone()).entries.clone(), + let containment = Rc::new(OccurrenceContainmentPath { + ancestors: ancestors.clone(), + terminal: id.clone(), + }); + let with_index = parse_context_with_occurrence_state( + ctx.clone(), + ctx.occurrence_allocator.clone(), + Some(Rc::new(OccurrenceIndex { + entries: v1_rt::rc_list_push( + parse_context_occurrence_index(ctx.clone()).entries.clone(), + Rc::new(OccurrenceIndexEntry { + projection: Rc::new(OccurrenceProjection { + occurrence: id.clone(), + authored_name: node.name.clone(), + diagnostic_span: node.span.clone(), + }), + containment: containment.clone(), + }), + ), + })), + ctx.declaration_occurrences.clone(), + ctx.reference_occurrences.clone(), + ); + parse_context_record_occurrence( + with_index.clone(), + effective_role.clone(), id.clone(), - ) { - ctx.clone() - } else { - { - let containment = Rc::new(OccurrenceContainmentPath { - ancestors: ancestors.clone(), - terminal: id.clone(), - }); - let with_index = parse_context_with_occurrence_state( - ctx.clone(), - ctx.occurrence_allocator.clone(), - Some(Rc::new(OccurrenceIndex { - entries: v1_rt::rc_list_push( - parse_context_occurrence_index(ctx.clone()).entries.clone(), - Rc::new(OccurrenceIndexEntry { - projection: Rc::new(OccurrenceProjection { - occurrence: id.clone(), - authored_name: node.name.clone(), - diagnostic_span: node.span.clone(), - }), - containment: containment.clone(), - }), - ), - })), - ctx.declaration_occurrences.clone(), - ctx.reference_occurrences.clone(), - ); - parse_context_record_occurrence( - with_index.clone(), - effective_role.clone(), - id.clone(), - containment.clone(), - node.span.clone(), - ) - } - } + containment.clone(), + node.span.clone(), + ) } None => ctx.clone(), }; @@ -3457,7 +3552,7 @@ pub fn parse_imports_acc( } { let __tco_0 = r.tokens.clone(); - let __tco_1 = r.ctx.clone(); + let __tco_1 = parse_context_after_node(r.ctx.clone(), r.import.clone()); let __tco_2 = v1_rt::rc_list_push(acc, r.import.clone()); tokens = __tco_0; ctx = __tco_1; @@ -3505,7 +3600,7 @@ pub fn parse_items_acc( } { let __tco_0 = r.tokens.clone(); - let __tco_1 = r.ctx.clone(); + let __tco_1 = parse_context_after_node(r.ctx.clone(), r.item.clone()); let __tco_2 = v1_rt::rc_list_push(acc, r.item.clone()); tokens = __tco_0; ctx = __tco_1; From 09b6a3f641e5e3f5619398f20adb530c7f4c4cdd Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 05:10:13 +0000 Subject: [PATCH 21/30] Control occurrence allocation across real modules --- .../tests/namespace_occurrence_serde.rs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/v1/stage0/tests/namespace_occurrence_serde.rs b/src/v1/stage0/tests/namespace_occurrence_serde.rs index 40b1c9ee4ee..66e21074a22 100644 --- a/src/v1/stage0/tests/namespace_occurrence_serde.rs +++ b/src/v1/stage0/tests/namespace_occurrence_serde.rs @@ -222,6 +222,45 @@ fn oci_digest_parser_does_not_reuse_authored_identity() { } } +#[test] +fn authored_identity_allocator_crosses_real_module_boundary() { + let materialization = parse_source( + include_str!("../../../../dag/extdeps/cache/materialization.dag"), + "dag/extdeps/cache/materialization.dag", + occurrence_id_allocator_initial(), + ); + assert!( + materialization.result.error.is_none(), + "{:?}", + materialization.result.error + ); + let digest = parse_source( + include_str!("../../../../dag/extdeps/container/oci/digest.dag"), + "dag/extdeps/container/oci/digest.dag", + materialization.occurrence_allocator.clone(), + ); + assert!(digest.result.error.is_none(), "{:?}", digest.result.error); + let left: HashSet = materialization + .occurrence_transport + .index + .entries + .iter() + .map(|entry| entry.projection.occurrence.value) + .collect(); + let overlap: Vec = digest + .occurrence_transport + .index + .entries + .iter() + .map(|entry| entry.projection.occurrence.value) + .filter(|id| left.contains(id)) + .collect(); + assert!( + overlap.is_empty(), + "cross-module identity overlap: {overlap:?}" + ); +} + #[test] fn expected_red_roster_items_remain_annotation_subjects() { let parsed = parse_source( From 3cb0158226517b8846c9aae029dc7a571be956ea Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 05:36:00 +0000 Subject: [PATCH 22/30] Publish occurrence allocation across parser lists --- src/v1/02_parse.dag | 46 ++++++++++-------- src/v1/stage0/src/v1_compiler_parse.rs | 48 +++++++++---------- .../tests/namespace_occurrence_serde.rs | 19 ++++++++ 3 files changed, 67 insertions(+), 46 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index e18fba1a8cc..4c56358c5e5 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -2386,11 +2386,12 @@ fn parse_predicates_acc(tokens: TokenStream, ctx: ParseContext, acc: List) let r = parse_single_predicate(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return PredsResult { predicates: [], tokens: r.tokens, ctx: r.ctx, err: r.err } } let acc = list_push(acc, r.predicate) + let ctx = parse_context_after_node(ctx: r.ctx, node: r.predicate) match eat(tokens: r.tokens, expected: ExpectComma) { EatConsumed { token: _, tokens: __ec } => - parse_predicates_acc(tokens: skip_newlines(tokens: __ec), ctx: r.ctx, acc: acc) + parse_predicates_acc(tokens: skip_newlines(tokens: __ec), ctx: ctx, acc: acc) EatUnchanged { tokens: __eu } => - PredsResult { predicates: acc, tokens: r.tokens, ctx: r.ctx, err: none } + PredsResult { predicates: acc, tokens: r.tokens, ctx: ctx, err: none } } } @@ -2565,7 +2566,7 @@ fn parse_more_variants_acc(tokens: TokenStream, ctx: ParseContext, acc: List VariantsResult { variants: acc, tokens: tokens, ctx: ctx, err: none } } @@ -2730,7 +2731,7 @@ fn collect_type_args(tokens: TokenStream, ctx: ParseContext, args: List) - EatConsumed { token: _, tokens: __ec } => let r = parse_type_angle_arg(tokens: __ec, ctx: ctx) if has_err(err: r.err) { return TypeArgsResult { args: args, tokens: r.tokens, ctx: r.ctx, err: r.err } } - collect_type_args(tokens: r.tokens, ctx: r.ctx, args: list_push(args, r.type_expr)) + collect_type_args(tokens: r.tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.type_expr), args: list_push(args, r.type_expr)) EatUnchanged { tokens: __eu } => TypeArgsResult { args: args, tokens: tokens, ctx: ctx, err: none } } @@ -2762,7 +2763,7 @@ fn parse_field_list_acc(tokens: TokenStream, ctx: ParseContext, acc: List) let tokens = r.tokens let e = eat(tokens: tokens, expected: ExpectComma) let tokens = skip_newlines(tokens: match e { EatConsumed { token: _, tokens: __ec } => __ec EatUnchanged { tokens: _ } => tokens }) - parse_field_list_acc(tokens: tokens, ctx: r.ctx, acc: list_push(acc, r.field)) + parse_field_list_acc(tokens: tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.field), acc: list_push(acc, r.field)) } else { FieldsResult { fields: acc, tokens: tokens, ctx: ctx, err: none } } @@ -3067,12 +3068,13 @@ fn parse_uses_list_acc(tokens: TokenStream, ctx: ParseContext, acc: List) let r = parse_uses_entry(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return UsesResult { uses: [], tokens: r.tokens, ctx: r.ctx, err: r.err } } let acc = list_push(acc, r.resource_use) + let ctx = parse_context_after_node(ctx: r.ctx, node: r.resource_use) match eat(tokens: r.tokens, expected: ExpectComma) { EatConsumed { token: _, tokens: __ec } => - parse_uses_list_acc(tokens: __ec, ctx: r.ctx, acc: acc) + parse_uses_list_acc(tokens: __ec, ctx: ctx, acc: acc) EatUnchanged { tokens: __eu } => - UsesResult { uses: acc, tokens: r.tokens, ctx: r.ctx, err: none } + UsesResult { uses: acc, tokens: r.tokens, ctx: ctx, err: none } } } @@ -3241,7 +3243,7 @@ fn parse_service_entries(tokens: TokenStream, ctx: ParseContext, config: Service if kw_text == "operation" { let r = parse_operation_def(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ServiceBodyResult { config: config, transport: transport, operations: operations, tokens: r.tokens, ctx: r.ctx, err: r.err } } - parse_service_entries(tokens: r.tokens, ctx: r.ctx, config: config, transport: transport, operations: list_push(operations, r.operation)) + parse_service_entries(tokens: r.tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.operation), config: config, transport: transport, operations: list_push(operations, r.operation)) } else { ServiceBodyResult { config: config, transport: transport, operations: operations, tokens: tokens, ctx: ctx, err: Present { value: parse_error(msg: "expected config, transport, or operation in service block", span: span) } } } @@ -3957,7 +3959,7 @@ fn parse_resource_entries(tokens: TokenStream, ctx: ParseContext, properties: Li if kw_text == "capability" { let r = parse_capability(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ResPropResult { properties: properties, capabilities: capabilities, tokens: r.tokens, ctx: r.ctx, err: r.err } } - parse_resource_entries(tokens: r.tokens, ctx: r.ctx, properties: properties, capabilities: list_push(capabilities, r.capability)) + parse_resource_entries(tokens: r.tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.capability), properties: properties, capabilities: list_push(capabilities, r.capability)) } else if kw_text == "acquire" { let r = expect(tokens: token_stream_advance(stream: tokens, n: 1), expected: ExpectLBrace) if has_err(err: r.err) { return ResPropResult { properties: properties, capabilities: capabilities, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -4202,17 +4204,18 @@ fn parse_param_list_acc(tokens: TokenStream, ctx: ParseContext, acc: List) let r = parse_param(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ParamsResult { params: [], tokens: r.tokens, ctx: r.ctx, err: r.err } } let acc = list_push(acc, r.param) + let ctx = parse_context_after_node(ctx: r.ctx, node: r.param) match eat(tokens: r.tokens, expected: ExpectComma) { EatConsumed { token: _, tokens: __ec } => let tokens = skip_newlines(tokens: __ec) if tok_is_rparen(tok: token_stream_first(stream: tokens)) { - ParamsResult { params: acc, tokens: tokens, ctx: r.ctx, err: none } + ParamsResult { params: acc, tokens: tokens, ctx: ctx, err: none } } else { - parse_param_list_acc(tokens: tokens, ctx: r.ctx, acc: acc) + parse_param_list_acc(tokens: tokens, ctx: ctx, acc: acc) } EatUnchanged { tokens: __eu } => - ParamsResult { params: acc, tokens: r.tokens, ctx: r.ctx, err: none } + ParamsResult { params: acc, tokens: r.tokens, ctx: ctx, err: none } } } @@ -4360,7 +4363,7 @@ fn parse_stmts_acc(tokens: TokenStream, ctx: ParseContext, acc: List) -> S } else { let r = parse_stmt(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return StmtsResult { stmts: acc, tokens: r.tokens, ctx: r.ctx, err: r.err } } - parse_stmts_acc(tokens: r.tokens, ctx: r.ctx, acc: list_push(acc, r.expr)) + parse_stmts_acc(tokens: r.tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.expr), acc: list_push(acc, r.expr)) } } @@ -4824,7 +4827,7 @@ fn parse_lambda_stmts(tokens: TokenStream, ctx: ParseContext, acc: List) - } else { let r = parse_stmt(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return StmtsResult { stmts: acc, tokens: r.tokens, ctx: r.ctx, err: r.err } } - parse_lambda_stmts(tokens: r.tokens, ctx: r.ctx, acc: list_push(acc, r.expr)) + parse_lambda_stmts(tokens: r.tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.expr), acc: list_push(acc, r.expr)) } } @@ -5063,17 +5066,18 @@ fn parse_arg_list_acc(tokens: TokenStream, ctx: ParseContext, acc: List) - let r = parse_single_arg(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ArgsResult { args: [], tokens: r.tokens, ctx: r.ctx, err: r.err } } let acc = list_push(acc, r.arg) + let ctx = parse_context_after_node(ctx: r.ctx, node: r.arg) match eat(tokens: r.tokens, expected: ExpectComma) { EatConsumed { token: _, tokens: __ec } => let tokens = skip_newlines(tokens: __ec) if tok_is_rparen(tok: token_stream_first(stream: tokens)) { - ArgsResult { args: acc, tokens: tokens, ctx: r.ctx, err: none } + ArgsResult { args: acc, tokens: tokens, ctx: ctx, err: none } } else { - parse_arg_list_acc(tokens: tokens, ctx: r.ctx, acc: acc) + parse_arg_list_acc(tokens: tokens, ctx: ctx, acc: acc) } EatUnchanged { tokens: __eu } => - ArgsResult { args: acc, tokens: r.tokens, ctx: r.ctx, err: none } + ArgsResult { args: acc, tokens: r.tokens, ctx: ctx, err: none } } } @@ -5243,7 +5247,7 @@ fn parse_match_arms_acc(tokens: TokenStream, ctx: ParseContext, acc: List) if has_err(err: r.err) { return ArmsResult { arms: acc, tokens: r.tokens, ctx: r.ctx, err: r.err } } let e = eat(tokens: r.tokens, expected: ExpectComma) let tokens = skip_newlines(tokens: match e { EatConsumed { token: _, tokens: __ec } => __ec EatUnchanged { tokens: _ } => r.tokens }) - parse_match_arms_acc(tokens: tokens, ctx: r.ctx, acc: list_push(acc, r.arm)) + parse_match_arms_acc(tokens: tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.arm), acc: list_push(acc, r.arm)) } } @@ -5304,7 +5308,7 @@ fn parse_match_arm_stmts(tokens: TokenStream, ctx: ParseContext, acc: List } else { let r = parse_stmt(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return StmtsResult { stmts: acc, tokens: r.tokens, ctx: r.ctx, err: r.err } } - parse_match_arm_stmts(tokens: r.tokens, ctx: r.ctx, acc: list_push(acc, r.expr)) + parse_match_arm_stmts(tokens: r.tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.expr), acc: list_push(acc, r.expr)) } } @@ -5680,7 +5684,7 @@ fn parse_field_init_list_acc(tokens: TokenStream, ctx: ParseContext, acc: List __ec EatUnchanged { tokens: _ } => r.tokens }) - parse_field_init_list_acc(tokens: tokens, ctx: r.ctx, acc: list_push(acc, r.field)) + parse_field_init_list_acc(tokens: tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.field), acc: list_push(acc, r.field)) } } @@ -5757,7 +5761,7 @@ fn parse_expr_list_until_acc(tokens: TokenStream, ctx: ParseContext, end_expecte if has_err(err: r.err) { return ExprsResult { exprs: [], tokens: r.tokens, ctx: r.ctx, err: r.err } } let e = eat(tokens: r.tokens, expected: ExpectComma) let tokens = skip_newlines(tokens: match e { EatConsumed { token: _, tokens: __ec } => __ec EatUnchanged { tokens: _ } => r.tokens }) - parse_expr_list_until_acc(tokens: tokens, ctx: r.ctx, end_expected: end_expected, acc: list_push(acc, r.expr)) + parse_expr_list_until_acc(tokens: tokens, ctx: parse_context_after_node(ctx: r.ctx, node: r.expr), end_expected: end_expected, acc: list_push(acc, r.expr)) } } diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index 58f80ccd8dc..0ee6b6f169d 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -5170,19 +5170,18 @@ pub fn parse_predicates_acc( }); } acc = v1_rt::rc_list_push(acc.clone(), r.predicate.clone()); + ctx = parse_context_after_node(r.ctx.clone(), r.predicate.clone()); match (*eat(r.tokens.clone(), Rc::new(ExpectedToken::ExpectComma))).clone() { EatResult::EatConsumed { tokens: __ec, .. } => { let __tco_0 = skip_newlines(__ec.clone()); - let __tco_1 = r.ctx.clone(); tokens = __tco_0; - ctx = __tco_1; continue; } EatResult::EatUnchanged { tokens: __eu, .. } => { break Rc::new(PredsResult { predicates: acc.clone(), tokens: r.tokens.clone(), - ctx: r.ctx.clone(), + ctx: ctx.clone(), err: None, }); } @@ -5877,7 +5876,7 @@ pub fn parse_more_variants_acc( } { let __tco_0 = r2.tokens.clone(); - let __tco_1 = r2.ctx.clone(); + let __tco_1 = parse_context_after_node(r2.ctx.clone(), r2.variant.clone()); let __tco_2 = v1_rt::rc_list_push(acc, r2.variant.clone()); tokens = __tco_0; ctx = __tco_1; @@ -6388,7 +6387,7 @@ pub fn collect_type_args( } { let __tco_0 = r.tokens.clone(); - let __tco_1 = r.ctx.clone(); + let __tco_1 = parse_context_after_node(r.ctx.clone(), r.type_expr.clone()); let __tco_2 = v1_rt::rc_list_push(args, r.type_expr.clone()); tokens = __tco_0; ctx = __tco_1; @@ -6490,7 +6489,7 @@ pub fn parse_field_list_acc( EatResult::EatUnchanged { tokens: _, .. } => tokens.clone(), }); { - let __tco_0 = r.ctx.clone(); + let __tco_0 = parse_context_after_node(r.ctx.clone(), r.field.clone()); let __tco_1 = v1_rt::rc_list_push(acc, r.field.clone()); ctx = __tco_0; acc = __tco_1; @@ -7445,19 +7444,18 @@ pub fn parse_uses_list_acc( }); } acc = v1_rt::rc_list_push(acc.clone(), r.resource_use.clone()); + ctx = parse_context_after_node(r.ctx.clone(), r.resource_use.clone()); match (*eat(r.tokens.clone(), Rc::new(ExpectedToken::ExpectComma))).clone() { EatResult::EatConsumed { tokens: __ec, .. } => { let __tco_0 = __ec.clone(); - let __tco_1 = r.ctx.clone(); tokens = __tco_0; - ctx = __tco_1; continue; } EatResult::EatUnchanged { tokens: __eu, .. } => { break Rc::new(UsesResult { uses: acc.clone(), tokens: r.tokens.clone(), - ctx: r.ctx.clone(), + ctx: ctx.clone(), err: None, }); } @@ -8045,7 +8043,8 @@ pub fn parse_service_entries( } { let __tco_0 = r.tokens.clone(); - let __tco_1 = r.ctx.clone(); + let __tco_1 = + parse_context_after_node(r.ctx.clone(), r.operation.clone()); let __tco_2 = v1_rt::rc_list_push(operations, r.operation.clone()); tokens = __tco_0; ctx = __tco_1; @@ -10599,7 +10598,8 @@ pub fn parse_resource_entries( } { let __tco_0 = r.tokens.clone(); - let __tco_1 = r.ctx.clone(); + let __tco_1 = + parse_context_after_node(r.ctx.clone(), r.capability.clone()); let __tco_2 = v1_rt::rc_list_push(capabilities, r.capability.clone()); tokens = __tco_0; ctx = __tco_1; @@ -11478,6 +11478,7 @@ pub fn parse_param_list_acc( }); } acc = v1_rt::rc_list_push(acc.clone(), r.param.clone()); + ctx = parse_context_after_node(r.ctx.clone(), r.param.clone()); match (*eat(r.tokens.clone(), Rc::new(ExpectedToken::ExpectComma))).clone() { EatResult::EatConsumed { tokens: __ec, .. } => { tokens = skip_newlines(__ec.clone()); @@ -11485,13 +11486,11 @@ pub fn parse_param_list_acc( break Rc::new(ParamsResult { params: acc.clone(), tokens: tokens.clone(), - ctx: r.ctx.clone(), + ctx: ctx.clone(), err: None, }); } else { { - let __tco_0 = r.ctx.clone(); - ctx = __tco_0; continue; } } @@ -11500,7 +11499,7 @@ pub fn parse_param_list_acc( break Rc::new(ParamsResult { params: acc.clone(), tokens: r.tokens.clone(), - ctx: r.ctx.clone(), + ctx: ctx.clone(), err: None, }); } @@ -11829,7 +11828,7 @@ pub fn parse_stmts_acc( } { let __tco_0 = r.tokens.clone(); - let __tco_1 = r.ctx.clone(); + let __tco_1 = parse_context_after_node(r.ctx.clone(), r.expr.clone()); let __tco_2 = v1_rt::rc_list_push(acc, r.expr.clone()); tokens = __tco_0; ctx = __tco_1; @@ -12986,7 +12985,7 @@ pub fn parse_lambda_stmts( } { let __tco_0 = r.tokens.clone(); - let __tco_1 = r.ctx.clone(); + let __tco_1 = parse_context_after_node(r.ctx.clone(), r.expr.clone()); let __tco_2 = v1_rt::rc_list_push(acc, r.expr.clone()); tokens = __tco_0; ctx = __tco_1; @@ -13680,6 +13679,7 @@ pub fn parse_arg_list_acc( }); } acc = v1_rt::rc_list_push(acc.clone(), r.arg.clone()); + ctx = parse_context_after_node(r.ctx.clone(), r.arg.clone()); match (*eat(r.tokens.clone(), Rc::new(ExpectedToken::ExpectComma))).clone() { EatResult::EatConsumed { tokens: __ec, .. } => { tokens = skip_newlines(__ec.clone()); @@ -13687,13 +13687,11 @@ pub fn parse_arg_list_acc( break Rc::new(ArgsResult { args: acc.clone(), tokens: tokens.clone(), - ctx: r.ctx.clone(), + ctx: ctx.clone(), err: None, }); } else { { - let __tco_0 = r.ctx.clone(); - ctx = __tco_0; continue; } } @@ -13702,7 +13700,7 @@ pub fn parse_arg_list_acc( break Rc::new(ArgsResult { args: acc.clone(), tokens: r.tokens.clone(), - ctx: r.ctx.clone(), + ctx: ctx.clone(), err: None, }); } @@ -14243,7 +14241,7 @@ pub fn parse_match_arms_acc( EatResult::EatUnchanged { tokens: _, .. } => r.tokens.clone(), }); { - let __tco_0 = r.ctx.clone(); + let __tco_0 = parse_context_after_node(r.ctx.clone(), r.arm.clone()); let __tco_1 = v1_rt::rc_list_push(acc, r.arm.clone()); ctx = __tco_0; acc = __tco_1; @@ -14405,7 +14403,7 @@ pub fn parse_match_arm_stmts( } { let __tco_0 = r.tokens.clone(); - let __tco_1 = r.ctx.clone(); + let __tco_1 = parse_context_after_node(r.ctx.clone(), r.expr.clone()); let __tco_2 = v1_rt::rc_list_push(acc, r.expr.clone()); tokens = __tco_0; ctx = __tco_1; @@ -15432,7 +15430,7 @@ pub fn parse_field_init_list_acc( EatResult::EatUnchanged { tokens: _, .. } => r.tokens.clone(), }); { - let __tco_0 = r.ctx.clone(); + let __tco_0 = parse_context_after_node(r.ctx.clone(), r.field.clone()); let __tco_1 = v1_rt::rc_list_push(acc, r.field.clone()); ctx = __tco_0; acc = __tco_1; @@ -15682,7 +15680,7 @@ pub fn parse_expr_list_until_acc( EatResult::EatUnchanged { tokens: _, .. } => r.tokens.clone(), }); { - let __tco_0 = r.ctx.clone(); + let __tco_0 = parse_context_after_node(r.ctx.clone(), r.expr.clone()); let __tco_1 = v1_rt::rc_list_push(acc, r.expr.clone()); ctx = __tco_0; acc = __tco_1; diff --git a/src/v1/stage0/tests/namespace_occurrence_serde.rs b/src/v1/stage0/tests/namespace_occurrence_serde.rs index 66e21074a22..b5c68fcf8b5 100644 --- a/src/v1/stage0/tests/namespace_occurrence_serde.rs +++ b/src/v1/stage0/tests/namespace_occurrence_serde.rs @@ -222,6 +222,25 @@ fn oci_digest_parser_does_not_reuse_authored_identity() { } } +#[test] +fn parser_lists_publish_accepted_child_identity() { + let parsed = parse_source( + include_str!("../../../../dag/examples/cost_estimate/cost_estimate.dag"), + "dag/examples/cost_estimate/cost_estimate.dag", + occurrence_id_allocator_initial(), + ); + assert!(parsed.result.error.is_none(), "{:?}", parsed.result.error); + let mut seen = HashSet::new(); + let duplicate = parsed + .occurrence_transport + .index + .entries + .iter() + .map(|entry| entry.projection.occurrence.value) + .find(|id| !seen.insert(*id)); + assert_eq!(duplicate, None, "accepted parser siblings must be disjoint"); +} + #[test] fn authored_identity_allocator_crosses_real_module_boundary() { let materialization = parse_source( From 531459349315778b4dd09c577422a9db9e603a4a Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 05:53:43 +0000 Subject: [PATCH 23/30] Floor function identities over accepted children --- src/v1/02_parse.dag | 56 ++++++++++++++++++++++- src/v1/stage0/src/v1_compiler_parse.rs | 62 +++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 4 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index 4c56358c5e5..2a9f99fef31 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -1272,6 +1272,51 @@ fn parse_context_after_node(ctx: ParseContext, node: Node) -> ParseContext { ) } +fn parse_context_after_node_list(ctx: ParseContext, nodes: List) -> ParseContext { + parse_context_with_occurrence_state( + ctx: ctx, + occurrence_allocator: Present { + value: occurrence_allocator_after_node_list( + alloc: parse_context_occurrence_allocator(ctx: ctx), + nodes: nodes + ), + }, + occurrence_index: ctx.occurrence_index, + declaration_occurrences: ctx.declaration_occurrences, + reference_occurrences: ctx.reference_occurrences + ) +} + +fn parse_context_after_optional_node(ctx: ParseContext, node: Node?) -> ParseContext { + parse_context_with_occurrence_state( + ctx: ctx, + occurrence_allocator: Present { + value: occurrence_allocator_after_optional_node( + alloc: parse_context_occurrence_allocator(ctx: ctx), + node: node + ), + }, + occurrence_index: ctx.occurrence_index, + declaration_occurrences: ctx.declaration_occurrences, + reference_occurrences: ctx.reference_occurrences + ) +} + +fn parse_context_after_inferred_node(ctx: ParseContext, inferred: InferredNode?) -> ParseContext { + parse_context_with_occurrence_state( + ctx: ctx, + occurrence_allocator: Present { + value: occurrence_allocator_after_inferred_node( + alloc: parse_context_occurrence_allocator(ctx: ctx), + inferred: inferred + ), + }, + occurrence_index: ctx.occurrence_index, + declaration_occurrences: ctx.declaration_occurrences, + reference_occurrences: ctx.reference_occurrences + ) +} + fn stamp_parsed_node_list( nodes: List, ancestors: FreeMonoid, @@ -2920,7 +2965,10 @@ fn parse_fn_body_from_prefix(prefix: ItemPrefixResult, start_span: SourceSpan) - let type_params = prefix.type_params let params = prefix.params let inferred = prefix.inferred - let ctx = prefix.ctx + let ctx = parse_context_after_inferred_node( + ctx: parse_context_after_node_list(ctx: prefix.ctx, nodes: concat(type_params, params)), + inferred: inferred + ) let all_params = concat(type_params, params) let named_dummy = Node { occurrence_identity: OccurrenceSynthetic, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: all_params, inferred: none, return_cardinality: Required, uses: [], body: none, connective: NoConnective, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } @@ -2944,7 +2992,11 @@ fn parse_fn_body_from_prefix(prefix: ItemPrefixResult, start_span: SourceSpan) - if has_err(err: body_result.err) { return ItemResult { item: named_dummy, tokens: body_result.tokens, ctx: body_result.ctx, err: body_result.err } } let body = body_result.expr - let minted = mint_parsed_node_identity(ctx: body_result.ctx) + let parent_ctx = parse_context_after_node_list( + ctx: parse_context_after_node(ctx: body_result.ctx, node: body), + nodes: admit_props + ) + let minted = mint_parsed_node_identity(ctx: parent_ctx) let item = Node { occurrence_identity: minted.identity, name: name, span: start_span, ident_span: Present { value: name_span }, children: [], params: all_params, inferred: inferred, return_cardinality: Required, uses: [], body: Present { value: body }, connective: NoConnective, transport: none, diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index 0ee6b6f169d..470a4090f14 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -2740,6 +2740,54 @@ pub fn parse_context_after_node(ctx: Rc, node: Rc) -> Rc, + nodes: Rc>>, +) -> Rc { + parse_context_with_occurrence_state( + ctx.clone(), + Some(occurrence_allocator_after_node_list( + parse_context_occurrence_allocator(ctx.clone()), + nodes.clone(), + )), + ctx.occurrence_index.clone(), + ctx.declaration_occurrences.clone(), + ctx.reference_occurrences.clone(), + ) +} + +pub fn parse_context_after_optional_node( + ctx: Rc, + node: Option>, +) -> Rc { + parse_context_with_occurrence_state( + ctx.clone(), + Some(occurrence_allocator_after_optional_node( + parse_context_occurrence_allocator(ctx.clone()), + node.clone(), + )), + ctx.occurrence_index.clone(), + ctx.declaration_occurrences.clone(), + ctx.reference_occurrences.clone(), + ) +} + +pub fn parse_context_after_inferred_node( + ctx: Rc, + inferred: Option>, +) -> Rc { + parse_context_with_occurrence_state( + ctx.clone(), + Some(occurrence_allocator_after_inferred_node( + parse_context_occurrence_allocator(ctx.clone()), + inferred.clone(), + )), + ctx.occurrence_index.clone(), + ctx.declaration_occurrences.clone(), + ctx.reference_occurrences.clone(), + ) +} + pub fn stamp_parsed_node_list( nodes: Rc>>, ancestors: Rc>, @@ -6939,7 +6987,13 @@ pub fn parse_fn_body_from_prefix( let type_params = prefix.type_params.clone(); let params = prefix.params.clone(); let inferred = prefix.inferred.clone(); - let ctx = prefix.ctx.clone(); + let ctx = parse_context_after_inferred_node( + parse_context_after_node_list( + prefix.ctx.clone(), + v1_rt::concat(type_params.clone(), params.clone()), + ), + inferred.clone(), + ); let all_params = v1_rt::concat(type_params.clone(), params.clone()); let named_dummy = Rc::new(Node { occurrence_identity: Rc::new(NodeOccurrenceIdentity::OccurrenceSynthetic), @@ -7015,7 +7069,11 @@ pub fn parse_fn_body_from_prefix( }); } let body = body_result.expr.clone(); - let minted = mint_parsed_node_identity(body_result.ctx.clone()); + let parent_ctx = parse_context_after_node_list( + parse_context_after_node(body_result.ctx.clone(), body.clone()), + admit_props.clone(), + ); + let minted = mint_parsed_node_identity(parent_ctx.clone()); let item = Rc::new(Node { occurrence_identity: minted.identity.clone(), name: name.clone(), From 249c7d0a7cb2a1ab0e9f7911212ce8d7380ca659 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 06:00:07 +0000 Subject: [PATCH 24/30] Publish condition identities through if parsing --- src/v1/02_parse.dag | 8 +-- src/v1/stage0/src/v1_compiler_parse.rs | 70 +++++++++++++++----------- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index 2a9f99fef31..b8701f1403a 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -5585,11 +5585,11 @@ fn parse_if(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } let condition = r.expr - let r = parse_block(tokens: skip_newlines(tokens: r.tokens), ctx: r.ctx) + let r = parse_block(tokens: skip_newlines(tokens: r.tokens), ctx: parse_context_after_node(ctx: r.ctx, node: condition)) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } let then_branch = r.expr let tokens = skip_newlines(tokens: r.tokens) - let ctx = r.ctx + let ctx = parse_context_after_node_list(ctx: r.ctx, nodes: [condition, then_branch]) match eat(tokens: tokens, expected: ExpectKeyword { text: "else" }) { EatConsumed { token: _, tokens: __ec } => @@ -5597,11 +5597,11 @@ fn parse_if(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if tok_is_keyword(tok: token_stream_first(stream: tokens), kw: "if") { let r2 = parse_if(tokens: tokens, ctx: ctx) if has_err(err: r2.err) { return ExprResult { expr: r2.expr, tokens: r2.tokens, ctx: r2.ctx, err: r2.err } } - parsed_expr_result(tokens: r2.tokens, ctx: r2.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprIf, children: [condition, then_branch, r2.expr], inferred: none, span: span)) + parsed_expr_result(tokens: r2.tokens, ctx: parse_context_after_node(ctx: r2.ctx, node: r2.expr), build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprIf, children: [condition, then_branch, r2.expr], inferred: none, span: span)) } else { let r2 = parse_block(tokens: tokens, ctx: ctx) if has_err(err: r2.err) { return ExprResult { expr: r2.expr, tokens: r2.tokens, ctx: r2.ctx, err: r2.err } } - parsed_expr_result(tokens: r2.tokens, ctx: r2.ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprIf, children: [condition, then_branch, r2.expr], inferred: none, span: span)) + parsed_expr_result(tokens: r2.tokens, ctx: parse_context_after_node(ctx: r2.ctx, node: r2.expr), build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprIf, children: [condition, then_branch, r2.expr], inferred: none, span: span)) } EatUnchanged { tokens: __eu } => parsed_expr_result(tokens: tokens, ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprIf, children: [condition, then_branch], inferred: none, span: span)) diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index 470a4090f14..2210dc345e1 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -15021,7 +15021,10 @@ pub fn parse_if(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc Date: Thu, 27 Aug 2026 06:27:26 +0000 Subject: [PATCH 25/30] Make parser occurrence allocation mandatory --- src/v1/02_parse.dag | 68 +++++++++++--------------- src/v1/stage0/src/v1_compiler_parse.rs | 47 +++++++----------- 2 files changed, 46 insertions(+), 69 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index b8701f1403a..e162051281a 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -131,7 +131,7 @@ fn token_stream_peek(stream: TokenStream, offset: Int) -> Token? { type ParseContext { source_indices: Map intern_table: InternTable - occurrence_allocator: OccurrenceIdAllocator? + occurrence_allocator: OccurrenceIdAllocator occurrence_index: OccurrenceIndex? declaration_occurrences: List? reference_occurrences: List? @@ -189,13 +189,13 @@ type ParsedNodeIdentityMint { fn mint_parsed_node_identity(ctx: ParseContext) -> ParsedNodeIdentityMint { let allocated = alloc_occurrence_id( - alloc: parse_context_occurrence_allocator(ctx: ctx) + alloc: ctx.occurrence_allocator ) ParsedNodeIdentityMint { identity: node_occurrence_identity_minted(id: allocated.id), ctx: parse_context_with_occurrence_state( ctx: ctx, - occurrence_allocator: Present { value: allocated.alloc }, + occurrence_allocator: allocated.alloc, occurrence_index: ctx.occurrence_index, declaration_occurrences: ctx.declaration_occurrences, reference_occurrences: ctx.reference_occurrences @@ -203,13 +203,6 @@ fn mint_parsed_node_identity(ctx: ParseContext) -> ParsedNodeIdentityMint { } } -fn parse_context_occurrence_allocator(ctx: ParseContext) -> OccurrenceIdAllocator { - match ctx.occurrence_allocator { - Present { value: allocator } => allocator - Absent => occurrence_id_allocator_initial() - } -} - fn parse_context_occurrence_index(ctx: ParseContext) -> OccurrenceIndex { match ctx.occurrence_index { Present { value: index } => index @@ -237,7 +230,7 @@ fn parse_context_reference_occurrences( fn parse_context_with_occurrence_state( ctx: ParseContext, - occurrence_allocator: OccurrenceIdAllocator?, + occurrence_allocator: OccurrenceIdAllocator, occurrence_index: OccurrenceIndex?, declaration_occurrences: List?, reference_occurrences: List? @@ -1260,12 +1253,10 @@ fn occurrence_allocator_after_node( fn parse_context_after_node(ctx: ParseContext, node: Node) -> ParseContext { parse_context_with_occurrence_state( ctx: ctx, - occurrence_allocator: Present { - value: occurrence_allocator_after_node( - alloc: parse_context_occurrence_allocator(ctx: ctx), - node: node - ), - }, + occurrence_allocator: occurrence_allocator_after_node( + alloc: ctx.occurrence_allocator, + node: node + ), occurrence_index: ctx.occurrence_index, declaration_occurrences: ctx.declaration_occurrences, reference_occurrences: ctx.reference_occurrences @@ -1275,12 +1266,10 @@ fn parse_context_after_node(ctx: ParseContext, node: Node) -> ParseContext { fn parse_context_after_node_list(ctx: ParseContext, nodes: List) -> ParseContext { parse_context_with_occurrence_state( ctx: ctx, - occurrence_allocator: Present { - value: occurrence_allocator_after_node_list( - alloc: parse_context_occurrence_allocator(ctx: ctx), - nodes: nodes - ), - }, + occurrence_allocator: occurrence_allocator_after_node_list( + alloc: ctx.occurrence_allocator, + nodes: nodes + ), occurrence_index: ctx.occurrence_index, declaration_occurrences: ctx.declaration_occurrences, reference_occurrences: ctx.reference_occurrences @@ -1290,12 +1279,10 @@ fn parse_context_after_node_list(ctx: ParseContext, nodes: List) -> ParseC fn parse_context_after_optional_node(ctx: ParseContext, node: Node?) -> ParseContext { parse_context_with_occurrence_state( ctx: ctx, - occurrence_allocator: Present { - value: occurrence_allocator_after_optional_node( - alloc: parse_context_occurrence_allocator(ctx: ctx), - node: node - ), - }, + occurrence_allocator: occurrence_allocator_after_optional_node( + alloc: ctx.occurrence_allocator, + node: node + ), occurrence_index: ctx.occurrence_index, declaration_occurrences: ctx.declaration_occurrences, reference_occurrences: ctx.reference_occurrences @@ -1305,12 +1292,10 @@ fn parse_context_after_optional_node(ctx: ParseContext, node: Node?) -> ParseCon fn parse_context_after_inferred_node(ctx: ParseContext, inferred: InferredNode?) -> ParseContext { parse_context_with_occurrence_state( ctx: ctx, - occurrence_allocator: Present { - value: occurrence_allocator_after_inferred_node( - alloc: parse_context_occurrence_allocator(ctx: ctx), - inferred: inferred - ), - }, + occurrence_allocator: occurrence_allocator_after_inferred_node( + alloc: ctx.occurrence_allocator, + inferred: inferred + ), occurrence_index: ctx.occurrence_index, declaration_occurrences: ctx.declaration_occurrences, reference_occurrences: ctx.reference_occurrences @@ -1753,9 +1738,7 @@ fn parse_with_table_at( let ctx = ParseContext { source_indices: source_indices, intern_table: pre_interned, - occurrence_allocator: Present { - value: occurrence_allocator, - }, + occurrence_allocator: occurrence_allocator, occurrence_index: Present { value: OccurrenceIndex { entries: [] }, }, @@ -1767,7 +1750,7 @@ fn parse_with_table_at( if has_err(err: r.err) { let occurrence_transport = occurrence_transport_from_parse_context(ctx: r.ctx) let occurrence_allocator = occurrence_allocator_after_index( - alloc: parse_context_occurrence_allocator(ctx: r.ctx), + alloc: r.ctx.occurrence_allocator, entries: occurrence_transport.index.entries ) ParseWithTableResult { @@ -1790,7 +1773,7 @@ fn parse_with_table_at( ) let occurrence_transport = occurrence_transport_from_parse_context(ctx: stamped.ctx) let occurrence_allocator = occurrence_allocator_after_index( - alloc: parse_context_occurrence_allocator(ctx: stamped.ctx), + alloc: stamped.ctx.occurrence_allocator, entries: occurrence_transport.index.entries ) ParseWithTableResult { @@ -4392,6 +4375,7 @@ fn parse_block(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let r = parse_stmts(tokens: tokens, ctx: ctx) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } let stmts = r.stmts + let ctx = parse_context_after_node_list(ctx: r.ctx, nodes: stmts) let tokens = skip_newlines(tokens: r.tokens) let r = expect(tokens: tokens, expected: ExpectRBrace) @@ -4578,6 +4562,7 @@ fn parse_expr_bp(tokens: TokenStream, ctx: ParseContext, min_bp: Int) -> ExprRes } fn parse_expr_loop(tokens: TokenStream, ctx: ParseContext, lhs: Node, min_bp: Int) -> ExprResult { + let ctx = parse_context_after_node(ctx: ctx, node: lhs) if tok_is_eof(tok: token_stream_first(stream: tokens)) { ExprResult { expr: lhs, tokens: tokens, ctx: ctx, err: none } } else { @@ -5177,6 +5162,7 @@ fn parse_match(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let r = parse_expr_no_brace(tokens: r.tokens, ctx: ctx) if has_err(err: r.err) { return r } let scrutinee = r.expr + let ctx = parse_context_after_node(ctx: r.ctx, node: scrutinee) let r = expect(tokens: skip_newlines(tokens: r.tokens), expected: ExpectLBrace) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -5184,6 +5170,7 @@ fn parse_match(tokens: TokenStream, ctx: ParseContext) -> ExprResult { let r = parse_match_arms(tokens: skip_newlines(tokens: r.tokens), ctx: ctx) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } let arms = r.arms + let ctx = parse_context_after_node_list(ctx: r.ctx, nodes: arms) let r = expect(tokens: skip_newlines(tokens: r.tokens), expected: ExpectRBrace) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: ctx, err: r.err } } @@ -5223,6 +5210,7 @@ fn parse_expr_bp_no_brace(tokens: TokenStream, ctx: ParseContext, min_bp: Int) - } fn parse_expr_loop_no_brace(tokens: TokenStream, ctx: ParseContext, lhs: Node, min_bp: Int) -> ExprResult { + let ctx = parse_context_after_node(ctx: ctx, node: lhs) let tok = token_stream_first(stream: tokens) if tok_is_eof(tok: tok) || tok_is_lbrace(tok: tok) { ExprResult { expr: lhs, tokens: tokens, ctx: ctx, err: none } diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index 2210dc345e1..ff9f878ea8c 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -144,7 +144,7 @@ pub fn token_stream_peek(stream: Rc, offset: i64) -> Option>>, pub intern_table: Rc, - pub occurrence_allocator: Option, + pub occurrence_allocator: OccurrenceIdAllocator, pub occurrence_index: Option>, pub declaration_occurrences: Option>>>, pub reference_occurrences: Option>>>, @@ -224,12 +224,12 @@ pub struct ParsedNodeIdentityMint { pub fn mint_parsed_node_identity(ctx: Rc) -> Rc { { - let allocated = alloc_occurrence_id(parse_context_occurrence_allocator(ctx.clone())); + let allocated = alloc_occurrence_id(ctx.occurrence_allocator.clone()); Rc::new(ParsedNodeIdentityMint { identity: node_occurrence_identity_minted(allocated.id.clone()), ctx: parse_context_with_occurrence_state( ctx.clone(), - Some(allocated.alloc.clone()), + allocated.alloc.clone(), ctx.occurrence_index.clone(), ctx.declaration_occurrences.clone(), ctx.reference_occurrences.clone(), @@ -238,13 +238,6 @@ pub fn mint_parsed_node_identity(ctx: Rc) -> Rc) -> OccurrenceIdAllocator { - match ctx.occurrence_allocator.clone() { - Some(allocator) => allocator.clone(), - None => occurrence_id_allocator_initial(), - } -} - pub fn parse_context_occurrence_index(ctx: Rc) -> Rc { match ctx.occurrence_index.clone() { Some(index) => index.clone(), @@ -274,7 +267,7 @@ pub fn parse_context_reference_occurrences( pub fn parse_context_with_occurrence_state( ctx: Rc, - occurrence_allocator: Option, + occurrence_allocator: OccurrenceIdAllocator, occurrence_index: Option>, declaration_occurrences: Option>>>, reference_occurrences: Option>>>, @@ -2730,10 +2723,7 @@ pub fn occurrence_allocator_after_node( pub fn parse_context_after_node(ctx: Rc, node: Rc) -> Rc { parse_context_with_occurrence_state( ctx.clone(), - Some(occurrence_allocator_after_node( - parse_context_occurrence_allocator(ctx.clone()), - node.clone(), - )), + occurrence_allocator_after_node(ctx.occurrence_allocator.clone(), node.clone()), ctx.occurrence_index.clone(), ctx.declaration_occurrences.clone(), ctx.reference_occurrences.clone(), @@ -2746,10 +2736,7 @@ pub fn parse_context_after_node_list( ) -> Rc { parse_context_with_occurrence_state( ctx.clone(), - Some(occurrence_allocator_after_node_list( - parse_context_occurrence_allocator(ctx.clone()), - nodes.clone(), - )), + occurrence_allocator_after_node_list(ctx.occurrence_allocator.clone(), nodes.clone()), ctx.occurrence_index.clone(), ctx.declaration_occurrences.clone(), ctx.reference_occurrences.clone(), @@ -2762,10 +2749,7 @@ pub fn parse_context_after_optional_node( ) -> Rc { parse_context_with_occurrence_state( ctx.clone(), - Some(occurrence_allocator_after_optional_node( - parse_context_occurrence_allocator(ctx.clone()), - node.clone(), - )), + occurrence_allocator_after_optional_node(ctx.occurrence_allocator.clone(), node.clone()), ctx.occurrence_index.clone(), ctx.declaration_occurrences.clone(), ctx.reference_occurrences.clone(), @@ -2778,10 +2762,10 @@ pub fn parse_context_after_inferred_node( ) -> Rc { parse_context_with_occurrence_state( ctx.clone(), - Some(occurrence_allocator_after_inferred_node( - parse_context_occurrence_allocator(ctx.clone()), + occurrence_allocator_after_inferred_node( + ctx.occurrence_allocator.clone(), inferred.clone(), - )), + ), ctx.occurrence_index.clone(), ctx.declaration_occurrences.clone(), ctx.reference_occurrences.clone(), @@ -3327,7 +3311,7 @@ pub fn parse_with_table_at( let ctx = Rc::new(ParseContext { source_indices: source_indices.clone(), intern_table: pre_interned.clone(), - occurrence_allocator: Some(occurrence_allocator.clone()), + occurrence_allocator: occurrence_allocator.clone(), occurrence_index: Some(Rc::new(OccurrenceIndex { entries: Rc::new(vec![]), })), @@ -3340,7 +3324,7 @@ pub fn parse_with_table_at( { let occurrence_transport = occurrence_transport_from_parse_context(r.ctx.clone()); let occurrence_allocator = occurrence_allocator_after_index( - parse_context_occurrence_allocator(r.ctx.clone()), + r.ctx.clone().occurrence_allocator.clone(), occurrence_transport.index.clone().entries.clone(), ); Rc::new(ParseWithTableResult { @@ -3369,7 +3353,7 @@ pub fn parse_with_table_at( let occurrence_transport = occurrence_transport_from_parse_context(stamped.ctx.clone()); let occurrence_allocator = occurrence_allocator_after_index( - parse_context_occurrence_allocator(stamped.ctx.clone()), + stamped.ctx.clone().occurrence_allocator.clone(), occurrence_transport.index.clone().entries.clone(), ); Rc::new(ParseWithTableResult { @@ -11823,6 +11807,7 @@ pub fn parse_block(tokens: Rc, ctx: Rc) -> Rc Rc { loop { + ctx = parse_context_after_node(ctx.clone(), lhs.clone()); if tok_is_eof(token_stream_first(tokens.clone())) { break Rc::new(ExprResult { expr: lhs.clone(), @@ -13919,6 +13905,7 @@ pub fn parse_match(tokens: Rc, ctx: Rc) -> Rc, ctx: Rc) -> Rc Rc { loop { + ctx = parse_context_after_node(ctx.clone(), lhs.clone()); let tok = token_stream_first(tokens.clone()); if (tok_is_eof(tok.clone()) || tok_is_lbrace(tok.clone())) { break Rc::new(ExprResult { From a3c3ccf8aca790cad1564ce917888e6d51231c98 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 07:22:16 +0000 Subject: [PATCH 26/30] Avoid duplicate node declaration occurrence --- src/v1/02_parse.dag | 3 +- src/v1/stage0/src/v1_compiler_parse.rs | 6 +--- .../tests/namespace_occurrence_serde.rs | 31 +++++++++++++++++++ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index e162051281a..7261319f4fa 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -4512,7 +4512,6 @@ fn parse_node_decl(tokens: TokenStream, ctx: ParseContext) -> ExprResult { if has_err(err: r3.err) { return r3 } let ret = parse_optional_inferred(tokens: r3.tokens, ctx: r3.ctx) if has_err(err: ret.err) { return ExprResult { expr: dummy_expr, tokens: ret.tokens, ctx: ret.ctx, err: ret.err } } - let type_ann = match e_colon { EatConsumed { token: _, tokens: _ } => Present { value: r3.expr } EatUnchanged { tokens: _ } => none } parsed_expr_result( tokens: ret.tokens, ctx: ret.ctx, @@ -4520,7 +4519,7 @@ fn parse_node_decl(tokens: TokenStream, ctx: ParseContext) -> ExprResult { ident_span: Present { value: name_span }, children: [r3.expr], connective: NoConnective, params: [], inferred: ret.inferred, return_cardinality: Required, uses: [], body: none, transport: none, - properties: cr.constraints, type_annotation: type_ann, is_self_recursive: false, + properties: cr.constraints, type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: ExprLet } ) } diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index ff9f878ea8c..8849b7ab304 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -12091,10 +12091,6 @@ pub fn parse_node_decl(tokens: Rc, ctx: Rc) -> Rc Some(r3.expr.clone()), - EatResult::EatUnchanged { tokens: _, .. } => None, - }; parsed_expr_result(ret.tokens.clone(), ret.ctx.clone(), |identity| { Rc::new(Node { occurrence_identity: identity.clone(), @@ -12110,7 +12106,7 @@ pub fn parse_node_decl(tokens: Rc, ctx: Rc) -> Rc Date: Thu, 27 Aug 2026 07:32:02 +0000 Subject: [PATCH 27/30] Record parser context publication rung --- src/v1/02_parse.dag | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index 7261319f4fa..7baec673edc 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -293,6 +293,16 @@ type EatResult type TokenResult { token: Token, tokens: TokenStream, err: ErrorNode? } type NameResult { name: String, span: SourceSpan, tokens: TokenStream, err: ErrorNode? } +// GUARANTEE RUNG (DESIGN section 4b): parser result publication is MITIGATABLE. +// Invariant: a combinator must publish the context its accepted child returned, never the +// context it received. The bounded population repaired here is function parent publication +// after params/type params/inferred/body/properties (5314593493), if condition/branch/parent +// publication (249c7d0a7c), and recursive accepted-child lists (3cb0158226); this is not a +// claim over every parse shape. The attainable ceiling is STRUCTURALLY IMPOSSIBLE. +// NEXT-RUNG TRIGGER (DESIGN section 4b(2)): introduce a distinct published-context carrier: +// parse functions consume an input context, successful child results carry an advanced +// context, and legitimate unchanged-context paths require an explicit named conversion, so +// returning the input context where an advanced context is required becomes a type error. type ExprResult { expr: Node, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type ItemResult { item: Node, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } type TypeResult { type_expr: Node, tokens: TokenStream, ctx: ParseContext, err: ErrorNode? } From 7478c9d129669b3e5fae51423183eb8e194fbddc Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 07:34:52 +0000 Subject: [PATCH 28/30] Use durable parser repair citation --- src/v1/02_parse.dag | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index 7baec673edc..2fa6a50b39e 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -296,9 +296,9 @@ type NameResult { name: String, span: SourceSpan, tokens: TokenStream, err: Erro // GUARANTEE RUNG (DESIGN section 4b): parser result publication is MITIGATABLE. // Invariant: a combinator must publish the context its accepted child returned, never the // context it received. The bounded population repaired here is function parent publication -// after params/type params/inferred/body/properties (5314593493), if condition/branch/parent -// publication (249c7d0a7c), and recursive accepted-child lists (3cb0158226); this is not a -// claim over every parse shape. The attainable ceiling is STRUCTURALLY IMPOSSIBLE. +// after params/type params/inferred/body/properties, if condition/branch/parent publication, +// and recursive accepted-child lists (#9344); this is not a claim over every parse shape. +// The attainable ceiling is STRUCTURALLY IMPOSSIBLE. // NEXT-RUNG TRIGGER (DESIGN section 4b(2)): introduce a distinct published-context carrier: // parse functions consume an input context, successful child results carry an advanced // context, and legitimate unchanged-context paths require an explicit named conversion, so From 671e5a82871c6e876278435d6282539680223da3 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 09:09:15 +0000 Subject: [PATCH 29/30] Publish list slice operand identities --- src/v1/02_parse.dag | 6 ++-- src/v1/stage0/src/v1_compiler_parse.rs | 3 +- .../tests/namespace_occurrence_serde.rs | 31 +++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index 2fa6a50b39e..4129749aaba 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -297,7 +297,8 @@ type NameResult { name: String, span: SourceSpan, tokens: TokenStream, err: Erro // Invariant: a combinator must publish the context its accepted child returned, never the // context it received. The bounded population repaired here is function parent publication // after params/type params/inferred/body/properties, if condition/branch/parent publication, -// and recursive accepted-child lists (#9344); this is not a claim over every parse shape. +// recursive accepted-child lists, and index/slice operand publication (#9344); this is not +// a claim over every parse shape. // The attainable ceiling is STRUCTURALLY IMPOSSIBLE. // NEXT-RUNG TRIGGER (DESIGN section 4b(2)): introduce a distinct published-context carrier: // parse functions consume an input context, successful child results carry an advanced @@ -5070,12 +5071,13 @@ fn parse_index_or_slice(tokens: TokenStream, ctx: ParseContext, base: Node, span if has_err(err: r.err) { return ExprResult { expr: r.expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } let first_expr = r.expr let tokens = r.tokens - let ctx = r.ctx + let ctx = parse_context_after_node(ctx: r.ctx, node: first_expr) if tok_is_dot_dot(tok: token_stream_first(stream: tokens)) { let r = parse_expr(tokens: token_stream_advance(stream: tokens, n: 1), ctx: ctx) if has_err(err: r.err) { return ExprResult { expr: r.expr, tokens: r.tokens, ctx: r.ctx, err: r.err } } let end_expr = r.expr + let ctx = parse_context_after_node(ctx: r.ctx, node: end_expr) let r = expect(tokens: r.tokens, expected: ExpectRBracket) if has_err(err: r.err) { return ExprResult { expr: dummy_expr, tokens: r.tokens, ctx: ctx, err: r.err } } parsed_expr_result(tokens: r.tokens, ctx: ctx, build: identity => make_expr_node(occurrence_identity: identity, expr_data: ExprSlice, children: [base, first_expr, end_expr], inferred: none, span: span)) diff --git a/src/v1/stage0/src/v1_compiler_parse.rs b/src/v1/stage0/src/v1_compiler_parse.rs index 8849b7ab304..82f9ce77890 100644 --- a/src/v1/stage0/src/v1_compiler_parse.rs +++ b/src/v1/stage0/src/v1_compiler_parse.rs @@ -13595,7 +13595,7 @@ pub fn parse_index_or_slice( } let first_expr = r.expr.clone(); let tokens = r.tokens.clone(); - let ctx = r.ctx.clone(); + let ctx = parse_context_after_node(r.ctx.clone(), first_expr.clone()); if tok_is_dot_dot(token_stream_first(tokens.clone())) { { let r = parse_expr(token_stream_advance(tokens.clone(), 1), ctx.clone()); @@ -13608,6 +13608,7 @@ pub fn parse_index_or_slice( }); } let end_expr = r.expr.clone(); + let ctx = parse_context_after_node(r.ctx.clone(), end_expr.clone()); let r = expect(r.tokens.clone(), Rc::new(ExpectedToken::ExpectRBracket)); if has_err(r.err.clone()) { return Rc::new(ExprResult { diff --git a/src/v1/stage0/tests/namespace_occurrence_serde.rs b/src/v1/stage0/tests/namespace_occurrence_serde.rs index a028a74d5ec..3fc1579f3ee 100644 --- a/src/v1/stage0/tests/namespace_occurrence_serde.rs +++ b/src/v1/stage0/tests/namespace_occurrence_serde.rs @@ -253,6 +253,37 @@ fn tailscale_credential_parser_does_not_reuse_authored_identity() { } } +#[test] +fn list_slice_parser_does_not_reuse_authored_identity() { + let parsed = parse_source( + "module e0308slice\n\nimport std.types { Int }\n\nfn tail(items: List) -> List {\n items[1..3]\n}\n", + "test.dag", + occurrence_id_allocator_initial(), + ); + assert!(parsed.result.error.is_none(), "{:?}", parsed.result.error); + let mut seen = HashSet::new(); + if let Some(duplicate) = parsed + .occurrence_transport + .index + .entries + .iter() + .map(|entry| entry.projection.occurrence.value) + .find(|id| !seen.insert(*id)) + { + let mut descriptions = Vec::new(); + node_occurrence_descriptions( + parsed + .result + .module + .as_ref() + .expect("successful parse module"), + duplicate, + &mut descriptions, + ); + panic!("duplicate authored identity {duplicate}: {descriptions:?}"); + } +} + #[test] fn parser_lists_publish_accepted_child_identity() { let parsed = parse_source( From ef38f94654e08ea82039b9e6fe86d50f79799743 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 27 Aug 2026 09:30:50 +0000 Subject: [PATCH 30/30] Clarify slice publication repair population --- src/v1/02_parse.dag | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/v1/02_parse.dag b/src/v1/02_parse.dag index 4129749aaba..956ef20cfbb 100644 --- a/src/v1/02_parse.dag +++ b/src/v1/02_parse.dag @@ -297,8 +297,9 @@ type NameResult { name: String, span: SourceSpan, tokens: TokenStream, err: Erro // Invariant: a combinator must publish the context its accepted child returned, never the // context it received. The bounded population repaired here is function parent publication // after params/type params/inferred/body/properties, if condition/branch/parent publication, -// recursive accepted-child lists, and index/slice operand publication (#9344); this is not -// a claim over every parse shape. +// recursive accepted-child lists, and slice end-operand publication (#9344); the index arm +// was made uniform but had no observed failure. Refusing error paths publish no successful +// node/context pair and are outside this population. This is not a claim over every parse shape. // The attainable ceiling is STRUCTURALLY IMPOSSIBLE. // NEXT-RUNG TRIGGER (DESIGN section 4b(2)): introduce a distinct published-context carrier: // parse functions consume an input context, successful child results carry an advanced