Iter 16a: nested constructor patterns via AST desugaring
Lifts the gate that rejected `(pat-ctor Cons a (pat-ctor Cons b _))`.
Approach: a pure AST → AST pass `ailang_core::desugar::desugar_module`
that flattens nested-Ctor sub-patterns into chains of single-level
matches with let-bound fresh vars and duplicate fall-through. Both
ailang-check and ailang-codegen call the pass at pipeline entry.
Hash-relevant canonical bytes are untouched: the pass runs after
load_module, in memory only. `check`'s returned CheckedModule.symbols
still carries hashes of the original defs so `ail diff` / `ail manifest`
see on-disk identities.
Lit sub-patterns inside a Ctor still rejected — that's the narrower
scope of `nested-ctor-pattern-not-allowed` post-16a; the variant doc
reflects the new meaning.
Fresh-name safety: `$` is a valid ident character in form (A), so
the Desugarer pre-walks every Term::Var / Pattern::Var name into a
BTreeSet and bumps its counter past any user-spelled `$mp_N`.
Already-flat matches go through `is_flat()` and emit identical AST
shapes; every existing fixture produces the same output as before.
New: examples/nested_pat.{ailx,ail.json} prints 30 from
first_two_sum on [10, 20, 30]. e2e test
`nested_ctor_pattern_first_two_sum` guards the path.
Tests: 92/92 (e2e 32→33, ailang-core unit 10→12).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -348,6 +348,19 @@ fn render_parse_round_trip_canonical() {
|
||||
assert_eq!(orig, round, "render | parse must produce canonical bytes");
|
||||
}
|
||||
|
||||
/// Iter 16a: nested constructor patterns. Property protected:
|
||||
/// `ailang_core::desugar` flattens `Cons a (Cons b _)` to a chain of
|
||||
/// single-level matches before the checker/codegen sees it. Without
|
||||
/// the desugar pass the checker would emit
|
||||
/// `nested-ctor-pattern-not-allowed`; without the pre-codegen call,
|
||||
/// the inner binders would be silently dropped by the codegen.
|
||||
#[test]
|
||||
fn nested_ctor_pattern_first_two_sum() {
|
||||
let stdout = build_and_run("nested_pat.ail.json");
|
||||
let lines: Vec<&str> = stdout.lines().collect();
|
||||
assert_eq!(lines, vec!["30"]);
|
||||
}
|
||||
|
||||
/// Iter 15d: `std_either` end-to-end. First stdlib ADT with two type
|
||||
/// parameters (`Either<e, a>`); first combinator with three type vars
|
||||
/// (`either : (e -> c) -> (a -> c) -> Either<e, a> -> c`).
|
||||
|
||||
Reference in New Issue
Block a user