Skip to content

Commit 18470f0

Browse files
committed
Elaborate if expressions in lexicographic order
1 parent f12cd26 commit 18470f0

File tree

3 files changed

+17
-10
lines changed

3 files changed

+17
-10
lines changed

fathom/src/core.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,8 @@ pub enum Term<'arena> {
175175

176176
/// Constant literals.
177177
ConstLit(Span, Const),
178-
/// Match on a constant.
179-
///
180-
/// (head_expr, pattern_branches, default_expr)
178+
/// Match on a constant. The pattern branches should be unique, and listed
179+
/// in lexicographic order.
181180
ConstMatch(
182181
Span,
183182
&'arena Term<'arena>,

fathom/src/surface/distillation.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -733,8 +733,8 @@ fn match_if_then_else<'arena>(
733733
default_expr: Option<&'arena core::Term<'arena>>,
734734
) -> Option<(&'arena core::Term<'arena>, &'arena core::Term<'arena>)> {
735735
match (branches, default_expr) {
736-
([(Const::Bool(true), then_expr), (Const::Bool(false), else_expr)], None)
737-
| ([(Const::Bool(false), else_expr), (Const::Bool(true), then_expr)], None)
736+
([(Const::Bool(false), else_expr), (Const::Bool(true), then_expr)], None)
737+
// TODO: Normalise boolean branches when elaborating patterns
738738
| ([(Const::Bool(true), then_expr)], Some(else_expr))
739739
| ([(Const::Bool(false), else_expr)], Some(then_expr)) => Some((then_expr, else_expr)),
740740
_ => None,

fathom/src/surface/elaboration.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -933,16 +933,17 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
933933
let cond_expr = self.check(cond_expr, &self.bool_type.clone());
934934
let then_expr = self.check(then_expr, &expected_type);
935935
let else_expr = self.check(else_expr, &expected_type);
936-
let match_expr = core::Term::ConstMatch(
936+
937+
core::Term::ConstMatch(
937938
range.into(),
938939
self.scope.to_scope(cond_expr),
940+
// NOTE: in lexicographic order: in Rust, `false < true`
939941
self.scope.to_scope_from_iter([
940-
(Const::Bool(true), then_expr),
941942
(Const::Bool(false), else_expr),
943+
(Const::Bool(true), then_expr),
942944
]),
943945
None,
944-
);
945-
match_expr
946+
)
946947
}
947948
(Term::Match(range, scrutinee_expr, equations), _) => {
948949
self.check_match(*range, scrutinee_expr, equations, &expected_type)
@@ -1192,15 +1193,18 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
11921193
let cond_expr = self.check(cond_expr, &self.bool_type.clone());
11931194
let (then_expr, r#type) = self.synth(then_expr);
11941195
let else_expr = self.check(else_expr, &r#type);
1196+
11951197
let match_expr = core::Term::ConstMatch(
11961198
range.into(),
11971199
self.scope.to_scope(cond_expr),
1200+
// NOTE: in lexicographic order: in Rust, `false < true`
11981201
self.scope.to_scope_from_iter([
1199-
(Const::Bool(true), then_expr),
12001202
(Const::Bool(false), else_expr),
1203+
(Const::Bool(true), then_expr),
12011204
]),
12021205
None,
12031206
);
1207+
12041208
(match_expr, r#type)
12051209
}
12061210
Term::Match(range, scrutinee_expr, equations) => {
@@ -1979,6 +1983,10 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
19791983
CheckedPattern::Binder(range, name) => {
19801984
self.check_match_reachable(is_reachable, range);
19811985

1986+
// TODO: If we know this is an exhaustive match, bind the
1987+
// scrutinee to a let binding with the elaborated body, and
1988+
// add it to the branches. This will simplify the
1989+
// distillation of if expressions.
19821990
(self.local_env).push_param(Some(name), match_info.scrutinee.r#type.clone());
19831991
default_expr = self.check(body_expr, &match_info.expected_type);
19841992
self.local_env.pop();

0 commit comments

Comments
 (0)