hir: Compile `MatchExpr` to if statements
The main purpose of this commit is to refactor the old switch-based logic we had for compiling match expressions and use an if-statement-based approach.
So, naturally, the old logic was removed in this commit. That includes
sort_tuple_patterns, simplify_tuple_match, PatternMerge and patterns_mergeable.
In the new approach, each arm is transformed into an if statement. And for any if statement, there are two main components: the condition and the then_block.
The entity responsible for handling the condition is CompileMatchArmCondition.
It's a class that traverses down the arm pattern and the match scrutinee expression
simultaneously. Whenever it meets a base-case in the pattern (i.e. expression or identifier
but identifiers are not handled for now), it takes the respective field of the scrutinee
and returns a backend comparison expression for them.
As for the then_block, it's compiled by SimplifyMatchExpr::compile_case_expr.
This function transforms the HIR::Expr match case final expression
into a backend block so it can be used easily inside the if_statement. In case
the expr is of type BlockExpr, then we can easily compile it using CompileBlock::compile.
Otherwise, we'll have to create a new block and add the expression as a statement.
Now we have the means of creating the if statements. All that's left is to glue the
multiple match arms (if_statements) together, and that's where
SimplifyMatchExpr::simplify_remaining_cases comes in. It compiles the condition and
then_block with the help of the functions mentioned earlier. As for the else_block,
it should contain the if_statements for the remaining match arms. So
simplify_remaining_cases calculates the else_block recursively by calling itself.
After that it returns the compiled if_statement with the condition, then_block, and
else_block.
@philberty do you have any idea why it's failing? I think it's overflowing somewhere but I can't figure it out.
For reference this is the assert that fails:
template <typename storage>
inline wi::storage_ref
wi::int_traits < generic_wide_int <storage> >::
decompose (HOST_WIDE_INT *, unsigned int precision,
const generic_wide_int <storage> &x)
{
gcc_checking_assert (precision == x.get_precision ());
return wi::storage_ref (x.get_val (), x.get_len (), precision);
}
Btw, this implementation also handles the path-to-tuple scrutinee and nested tuples. Added tests for that.
@goar5670 are you still working on this? No pressure/implied obligation intended
I think we should think about finishing this work off soon. GCC auto optimizes cases to switch blocks too and lets not worry about pattern exhaustiveness checks for now.