add branch info to switches

This commit is contained in:
Folkert 2021-01-31 20:36:40 +01:00
parent ac3788ba85
commit 3ccf6de2cf
2 changed files with 88 additions and 2 deletions

View file

@ -2158,4 +2158,61 @@ mod gen_primitives {
i64
);
}
#[test]
fn switch_fuse_rc_non_exhaustive() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [ main ] to "./platform"
Foo : [ A I64 Foo, B I64 Foo, C I64 Foo, Empty ]
sum : Foo, I64 -> I64
sum = \foo, accum ->
when foo is
A x resta -> sum resta (x + accum)
B x restb -> sum restb (x + accum)
# Empty -> accum
# C x restc -> sum restc (x + accum)
_ -> accum
main : I64
main =
A 1 (B 2 (C 3 Empty))
|> sum 0
"#
),
3,
i64
);
}
#[test]
fn switch_fuse_rc_exhaustive() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [ main ] to "./platform"
Foo : [ A I64 Foo, B I64 Foo, C I64 Foo, Empty ]
sum : Foo, I64 -> I64
sum = \foo, accum ->
when foo is
A x resta -> sum resta (x + accum)
B x restb -> sum restb (x + accum)
C x restc -> sum restc (x + accum)
Empty -> accum
main : I64
main =
A 1 (B 2 (C 3 Empty))
|> sum 0
"#
),
6,
i64
);
}
}

View file

@ -1654,6 +1654,9 @@ fn decide_to_branching<'a>(
let mut branches = bumpalo::collections::Vec::with_capacity_in(tests.len(), env.arena);
let mut tag_id_sum: i64 = (0..tests.len() as i64 + 1).sum();
let mut union_size: i64 = -1;
for (test, decider) in tests {
let branch = decide_to_branching(
env,
@ -1675,8 +1678,34 @@ fn decide_to_branching<'a>(
other => todo!("other {:?}", other),
};
branches.push((tag, BranchInfo::None, branch));
// branch info is only useful for refcounted values
let branch_info = if let Test::IsCtor { tag_id, union, .. } = test {
tag_id_sum -= tag_id as i64;
union_size = union.alternatives.len() as i64;
BranchInfo::Constructor {
scrutinee: inner_cond_symbol,
layout: inner_cond_layout.clone(),
tag_id,
}
} else {
tag_id_sum = -1;
BranchInfo::None
};
branches.push((tag, branch_info, branch));
}
// determine if the switch is exhaustive
let default_branch_info = if tag_id_sum > 0 && union_size > 0 {
BranchInfo::Constructor {
scrutinee: inner_cond_symbol,
layout: inner_cond_layout.clone(),
tag_id: tag_id_sum as u8,
}
} else {
BranchInfo::None
};
// We have learned more about the exact layout of the cond (based on the path)
// but tests are still relative to the original cond symbol
@ -1684,7 +1713,7 @@ fn decide_to_branching<'a>(
cond_layout: inner_cond_layout,
cond_symbol: inner_cond_symbol,
branches: branches.into_bump_slice(),
default_branch: (BranchInfo::None, env.arena.alloc(default_branch)),
default_branch: (default_branch_info, env.arena.alloc(default_branch)),
ret_layout,
};