graphcal_compiler/desugar/mod.rs
1//! Generic desugaring pipeline.
2//!
3//! Transforms `File<Raw>` (parser output, with all surface sugar) into
4//! `File<Desugared>` (canonical form consumed by name resolution, IR lowering,
5//! TIR, and evaluation).
6//!
7//! # Architecture
8//!
9//! Each surface sugar implements [`DesugarSugar`] — a node-level transform
10//! that maps one raw sugar variant to its desugared equivalent. The generic
11//! walker in this module traverses the AST, dispatching `Sugar(_)` arms to
12//! the appropriate [`DesugarSugar`] impl while every other variant is
13//! rebuilt phase-by-phase with its children desugared recursively.
14//!
15//! ```text
16//! File<Raw> ──┬─► (walker) ──┬─► File<Desugared>
17//! │ │
18//! ├─ MultiDecl ───┘ via DesugarSugar
19//! └─ TableLiteral ──► (desugar to MapLiteral)
20//! ```
21//!
22//! # Adding a new customer
23//!
24//! 1. Add a variant to [`crate::syntax::ast::RawDeclSugar`] or
25//! [`crate::syntax::ast::RawExprSugar`].
26//! 2. Implement [`DesugarSugar`] for that variant in a submodule of this
27//! module.
28//! 3. Wire it into the walker's `Sugar(_)` dispatch.
29//!
30//! No changes to downstream consumers are needed — they only see
31//! `File<Desugared>` and never observed the sugar in the first place.
32//!
33//! # Span fidelity
34//!
35//! Desugaring preserves source spans: every synthesized node carries the
36//! span of the surface construct it came from. Diagnostics emitted on
37//! desugared AST still point at the original source.
38
39pub mod convert;
40pub mod desugared_ast;
41
42/// Single-node desugaring step.
43///
44/// Implementors map one surface sugar form to its desugared equivalent.
45/// The output type is generic so different sugars can desugar to different
46/// shapes — e.g., `MultiDecl` desugars to `Vec<Declaration<Desugared>>`,
47/// while `TableLiteral` desugars to `ExprKind<Desugared>`.
48pub trait DesugarSugar {
49 /// The raw surface form being desugared.
50 type RawNode;
51 /// The shape produced by desugaring (often a single node, sometimes
52 /// a `Vec` for one-to-many expansions).
53 type DesugaredOut;
54
55 /// Perform the desugaring.
56 fn desugar_sugar(raw: Self::RawNode) -> Self::DesugaredOut;
57}