Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7cb7d1f
v2 emit: every module member has one target realization or one typed …
Sep 29, 2026
9f7790e
One module authority on both emission paths; the failure-mode row fol…
Sep 29, 2026
eebe928
v2 emit: a tail Atom body projects through the one atom projection (b…
Sep 29, 2026
204b6b9
v2 emit: positive declaration-kind channels -- records emit as struct…
Sep 29, 2026
645bcf9
v2 emit: signature type atoms resolve through the target, never by fa…
Sep 29, 2026
79b66f3
Claims for commits 1-3: the declaration-kind matrix, Bool and declare…
Sep 29, 2026
e940dc4
Merge remote-tracking branch 'origin/main' into session/silent-swift-…
Sep 29, 2026
1dd4842
Resolve signature realizations against the base target; capture refin…
Sep 29, 2026
85f2518
v2 emit: field types and declared-type references are spelled by the …
Sep 29, 2026
ab0b9fa
v2 emit: where-refinements realize as the target declares (Rust: tran…
Sep 29, 2026
4a46099
Merge remote-tracking branch 'origin/main' into session/silent-swift-…
Sep 29, 2026
79bea35
Record vs refinement is one DeclaredTypeKind per declaration (review …
Sep 30, 2026
5808836
module_graph: import ends_with, the bare reference the touched-file g…
Sep 30, 2026
c537a66
Merge remote-tracking branch 'origin/main' into session/silent-swift-…
Sep 30, 2026
ddf2db4
Retire the four ends_with debt rows my module_graph import made stale…
Sep 30, 2026
81b9c0b
floor share: serve member_emission_supplied_refinement warm to its al…
Sep 30, 2026
da23d6e
module_graph: use the std ends_with method, not gunbc.rust_item_scan'…
Sep 30, 2026
b2ebd7d
One type-declaration route, admitted against the map it serializes wi…
Sep 30, 2026
406fd62
Merge remote-tracking branch 'origin/main' into session/silent-swift-…
Sep 30, 2026
f5a293b
Refinement route claim asserts the alias: main now lowers the carrier
Sep 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions src/v2/compiler/03_normalize.dag
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ import v2.compiler.body_lowering_fold {
body_lower_fn_decl_to_census_arrow,
body_lower_service_decl,
body_lower_is_deferred_lower_at_normalize,
body_lower_type_decl_record_name_optional
DeclaredTypeKind,
body_lower_type_decl_declared_kind_optional,
declared_record_names
}
import v2.compiler.normalized_tree {
CensusTree,
Expand Down Expand Up @@ -358,13 +360,12 @@ fn import_binding_capture(tree: ParseTree, nodes: List<Node>) -> Outcome<FreeMon
)
}

// WHICH OF THIS MODULE'S TYPES ARE RECORDS, read from the parse tree for the reason
// import_binding_capture reads imports there: after lowering, a record is a bare
// `Conj { R: payload }` that no reader can tell from a where-alias or a module spine. The question is
// answered by the rehome's own predicate (v2.compiler.body_lowering_fold
// body_lower_type_decl_record_name_optional), so what is carried and what was rehomed are one
// decision, not two.
fn record_declaration_capture(nodes: List<Node>) -> FreeMonoid<Symbol> {
// WHICH KIND EACH OF THIS MODULE'S PLAIN-CONJ TYPES IS, read from the parse tree for the reason
// import_binding_capture reads imports there: after lowering, a record, a where-refinement and a
// payload-bearing single variant are one `Conj { R: payload }` shape. The question is answered by the
// lowering's own predicate (v2.compiler.body_lowering_fold body_lower_type_decl_declared_kind_optional),
// so what is carried and what was lowered are one decision, not two.
fn type_declaration_kind_capture(nodes: List<Node>) -> FreeMonoid<DeclaredTypeKind> {
fold_list(
xs: nodes,
empty: Empty,
Expand All @@ -375,16 +376,22 @@ fn record_declaration_capture(nodes: List<Node>) -> FreeMonoid<Symbol> {
if id != ^dag_surface_type_decl {
acc
} else {
match body_lower_type_decl_record_name_optional(shell: n) {
match body_lower_type_decl_declared_kind_optional(shell: n) {
Absent => acc
Present { value: name } => list_snoc_item(xs: acc, item: name)
Present { value: kind } => list_snoc_item(xs: acc, item: kind)
}
}
}
}
)
}

// The record names alone, for the census and the fixtures that fill a symbol index: a projection of
// the one capture above, never a second reading of the parse.
fn record_declaration_capture(nodes: List<Node>) -> FreeMonoid<Symbol> {
declared_record_names(kinds: type_declaration_kind_capture(nodes: nodes))
}

fn bind_retention_free(o: Outcome<BodyLoweredTree>) -> Outcome<Node> {
match o {
Rejected { diagnostics: r } => Rejected { diagnostics: r }
Expand Down Expand Up @@ -417,7 +424,7 @@ fn normalize(parse_tree: ParseTree) -> Outcome<NormalizedTree> {
root: grafted,
test_markers: markers,
import_bindings: bindings,
record_declarations: record_declaration_capture(nodes: parse_nodes),
type_declaration_kinds: type_declaration_kind_capture(nodes: parse_nodes),
diagnostics: d1
)
}
Expand Down
50 changes: 49 additions & 1 deletion src/v2/compiler/body_lowering_fold.dag
Original file line number Diff line number Diff line change
Expand Up @@ -8170,7 +8170,8 @@ fn body_lower_find_where_host_conj(root: Node) -> Optional<Node> {
// SO IT IS CARRIED FROM HERE, not recovered downstream: body_lower_type_decl_record_name_optional
// (below) is the one predicate that says which type_decl is a record; this dispatch and
// v2.compiler.normalize record_declaration_capture both ask it, and the capture rides to the symbol
// index on NormalizedTree record_declarations, where the pattern-binder classifier reads it (Pkg16).
// index on NormalizedTree type_declaration_kinds (its record projection), where the pattern-binder
// classifier reads it (Pkg16).
// The record-versus-where-alias control is v2.test.claim.match_arm_binder_frame
// mab_where_alias_is_not_a_record.
fn body_lower_record_type_decl(shell: Node, type_name: Symbol, block_shell: Node, type_params: DeclTypeParams) -> Outcome<Node> {
Expand Down Expand Up @@ -8400,6 +8401,53 @@ fn body_lower_type_decl_record_name_optional(shell: Node) -> Optional<Symbol> {
}
}

// WHICH KIND OF PLAIN-CONJ DECLARATION A type_decl IS, ASKED ONCE, BY THE ARMS body_lower_type_decl_by_body
// TAKES. After lowering, a record, a where-refinement and a payload-bearing single variant share the
// Conj { Name: payload } shape, so the kind is read HERE, on the parse, and carried on
// v2.compiler.normalized_tree NormalizedTree type_declaration_kinds. One value per declaration: a record
// and a refinement are authored alternatives, so the carrier has no state naming one declaration as
// both. A record is what body_lower_type_decl_record_name_optional says; otherwise a where clause --
// here still its dag_surface_where_refinement_clause production shell, the parse-level form of the arm
// the by-body dispatch finds as a Named edge -- makes a refinement; anything else carries no kind, and
// a plain Conj member without one is undecided downstream, never inferred.
type DeclaredTypeKind
= DeclaredRecord { name: Symbol }
| DeclaredRefinement { name: Symbol }

fn body_lower_type_decl_declared_kind_optional(shell: Node) -> Optional<DeclaredTypeKind> {
match body_lower_type_decl_record_name_optional(shell: shell) {
Present { value: name } => Present { value: DeclaredRecord { name: name } }
Absent =>
match parse_production_captured_child_optional(node: shell) {
Absent => Absent
Present { value: captured } =>
match body_lower_find_production_shell_optional(root: captured, emitted: ^dag_surface_where_refinement_clause) {
Absent => Absent
Present { value: _ } =>
match dag_surface_kw_then_ident_from_captured(captured: captured) {
Absent => Absent
Present { value: name } => Present { value: DeclaredRefinement { name: name } }
}
}
}
}
}

// The record names among a module's declaration kinds: the projection every record-only consumer (the
// symbol-index fill, the pattern-binder classifier, the census) reads, so records have one authority.
fn declared_record_names(kinds: FreeMonoid<DeclaredTypeKind>) -> FreeMonoid<Symbol> {
fold_list(
xs: kinds,
empty: Empty,
cons: fn(acc, k) {
match k {
DeclaredRecord { name: n } => list_snoc_item(xs: acc, item: n)
DeclaredRefinement { name: _ } => acc
}
}
)
}

fn body_lower_type_decl(shell: Node) -> Outcome<Node> {
match parse_production_captured_child_optional(node: shell) {
Absent => body_lower_type_decl_unreadable(shell: shell)
Expand Down
Loading