Iter 10: Term::Seq sequencing operator
Adds `Term::Seq { lhs, rhs }` (serde tag "seq") as a first-class
AST node for sequencing effectful expressions. Equivalent in
behaviour to `let _ = lhs in rhs`, but the dedicated node gives the
pretty-printer and diagnostics a cleaner shape and surfaces the
intent ("run for effect, then yield rhs") to future tooling.
Typecheck: lhs must be Unit; rhs's type is the result; effects
accumulate.
Codegen: lower lhs (drop SSA), lower rhs (return).
Capture / deps walkers: recurse into both sides.
Refactored examples/list_map.ail.json's print_list to use seq
instead of `let _ = ...`. Output unchanged (2/4/6).
Hash stability: existing examples without Term::Seq serialise
bit-identical; only list_map.ail.json's hashes changed (deliberate
refactor).
Tests: 51 green (was 50). New unit test
`ailang_check::tests::seq_lhs_must_be_unit` covers the type-error
path; existing list_map e2e covers the happy path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -634,6 +634,12 @@ impl<'a> Emitter<'a> {
|
||||
Term::Lam { params, param_tys, ret_ty, effects: _, body } => {
|
||||
self.lower_lambda(params, param_tys, ret_ty, body)
|
||||
}
|
||||
Term::Seq { lhs, rhs } => {
|
||||
// Iter 10: lower lhs for its effects, discard the SSA;
|
||||
// lower rhs and return its value as the whole expression.
|
||||
let _ = self.lower_term(lhs)?;
|
||||
self.lower_term(rhs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1326,6 +1332,10 @@ impl<'a> Emitter<'a> {
|
||||
bound.remove(&n);
|
||||
}
|
||||
}
|
||||
Term::Seq { lhs, rhs } => {
|
||||
Self::collect_captures(lhs, bound, captures, captures_set, builtins, top_level, import_map);
|
||||
Self::collect_captures(rhs, bound, captures, captures_set, builtins, top_level, import_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user