@@ -534,25 +534,14 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern)
534534 || lookup->get_kind () == TyTy::TypeKind::SLICE
535535 || lookup->get_kind () == TyTy::REF );
536536
537- size_t array_element_index = 0 ;
537+ // function ptr that points to either array_index_expression or
538+ // slice_index_expression depending on the scrutinee's type
539+ tree (*scrutinee_index_expr_func) (tree, tree, location_t ) = nullptr ;
540+
538541 switch (lookup->get_kind ())
539542 {
540543 case TyTy::TypeKind::ARRAY :
541- for (auto &pattern_member : pattern.get_items ())
542- {
543- tree array_index_tree
544- = Backend::size_constant_expression (array_element_index++);
545- tree element_expr
546- = Backend::array_index_expression (match_scrutinee_expr,
547- array_index_tree,
548- pattern.get_locus ());
549- tree check_expr_sub
550- = CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
551- ctx);
552- check_expr = Backend::arithmetic_or_logical_expression (
553- ArithmeticOrLogicalOperator::BITWISE_AND , check_expr,
554- check_expr_sub, pattern.get_locus ());
555- }
544+ scrutinee_index_expr_func = Backend::array_index_expression;
556545 break ;
557546 case TyTy::TypeKind::SLICE :
558547 rust_sorry_at (
@@ -562,36 +551,153 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern)
562551 case TyTy::TypeKind::REF :
563552 {
564553 rust_assert (RS_DST_FLAG_P (TREE_TYPE (match_scrutinee_expr)));
554+ scrutinee_index_expr_func = Backend::slice_index_expression;
565555 tree size_field
566556 = Backend::struct_field_expression (match_scrutinee_expr, 1 ,
567557 pattern.get_locus ());
568558
569- // First compare the size
570- check_expr = Backend::comparison_expression (
571- ComparisonOperator::EQUAL , size_field,
572- build_int_cst (size_type_node, pattern.get_items ().size ()),
573- pattern.get_locus ());
559+ // for slices, generate a dynamic size comparison expression tree
560+ // because size checking is done at runtime.
561+ switch (pattern.get_items ().get_item_type ())
562+ {
563+ case HIR ::SlicePatternItems::ItemType::NO_REST :
564+ {
565+ auto &items = static_cast <HIR ::SlicePatternItemsNoRest &> (
566+ pattern.get_items ());
567+ check_expr = Backend::comparison_expression (
568+ ComparisonOperator::EQUAL , size_field,
569+ build_int_cst (size_type_node, items.get_patterns ().size ()),
570+ pattern.get_locus ());
571+ }
572+ break ;
573+ case HIR ::SlicePatternItems::ItemType::HAS_REST :
574+ {
575+ auto &items = static_cast <HIR ::SlicePatternItemsHasRest &> (
576+ pattern.get_items ());
577+ auto pattern_min_cap = items.get_lower_patterns ().size ()
578+ + items.get_upper_patterns ().size ();
579+ check_expr = Backend::comparison_expression (
580+ ComparisonOperator::GREATER_OR_EQUAL , size_field,
581+ build_int_cst (size_type_node, pattern_min_cap),
582+ pattern.get_locus ());
583+ }
584+ break ;
585+ }
586+ }
587+ break ;
588+ default :
589+ rust_unreachable ();
590+ }
591+
592+ rust_assert (scrutinee_index_expr_func != nullptr );
574593
575- // Then compare each element in the slice pattern
576- for (auto &pattern_member : pattern.get_items ())
594+ // Generate tree to compare every element within array/slice
595+ size_t element_index = 0 ;
596+ switch (pattern.get_items ().get_item_type ())
597+ {
598+ case HIR ::SlicePatternItems::ItemType::NO_REST :
599+ {
600+ auto &items
601+ = static_cast <HIR ::SlicePatternItemsNoRest &> (pattern.get_items ());
602+ for (auto &pattern_member : items.get_patterns ())
577603 {
578- tree slice_index_tree
579- = Backend::size_constant_expression (array_element_index ++);
604+ tree index_tree
605+ = Backend::size_constant_expression (element_index ++);
580606 tree element_expr
581- = Backend::slice_index_expression (match_scrutinee_expr,
582- slice_index_tree,
583- pattern.get_locus ());
607+ = scrutinee_index_expr_func (match_scrutinee_expr, index_tree,
608+ pattern.get_locus ());
609+ tree check_expr_sub
610+ = CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
611+ ctx);
612+ check_expr = Backend::arithmetic_or_logical_expression (
613+ ArithmeticOrLogicalOperator::BITWISE_AND , check_expr,
614+ check_expr_sub, pattern.get_locus ());
615+ }
616+ break ;
617+ }
618+ case HIR ::SlicePatternItems::ItemType::HAS_REST :
619+ {
620+ auto &items
621+ = static_cast <HIR ::SlicePatternItemsHasRest &> (pattern.get_items ());
622+ for (auto &pattern_member : items.get_lower_patterns ())
623+ {
624+ tree index_tree
625+ = Backend::size_constant_expression (element_index++);
626+ tree element_expr
627+ = scrutinee_index_expr_func (match_scrutinee_expr, index_tree,
628+ pattern.get_locus ());
584629 tree check_expr_sub
585630 = CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
586631 ctx);
587632 check_expr = Backend::arithmetic_or_logical_expression (
588633 ArithmeticOrLogicalOperator::BITWISE_AND , check_expr,
589634 check_expr_sub, pattern.get_locus ());
590635 }
636+
637+ // handle codegen for upper patterns differently for both types
638+ switch (lookup->get_kind ())
639+ {
640+ case TyTy::TypeKind::ARRAY :
641+ {
642+ // for array type scrutinee, we can simply get the capacity as a
643+ // const and calculate how many elements to skip
644+ auto array_ty = static_cast <TyTy::ArrayType *> (lookup);
645+ auto cap_tree = array_ty->get_capacity ()->get_value ();
646+ size_t cap_wi = (size_t ) wi::to_wide (cap_tree).to_uhwi ();
647+ element_index = cap_wi - items.get_upper_patterns ().size ();
648+ for (auto &pattern_member : items.get_upper_patterns ())
649+ {
650+ tree index_tree
651+ = Backend::size_constant_expression (element_index++);
652+ tree element_expr
653+ = scrutinee_index_expr_func (match_scrutinee_expr,
654+ index_tree,
655+ pattern.get_locus ());
656+ tree check_expr_sub
657+ = CompilePatternCheckExpr::Compile (*pattern_member,
658+ element_expr, ctx);
659+ check_expr = Backend::arithmetic_or_logical_expression (
660+ ArithmeticOrLogicalOperator::BITWISE_AND , check_expr,
661+ check_expr_sub, pattern.get_locus ());
662+ }
663+ }
664+ break ;
665+ case TyTy::TypeKind::REF :
666+ {
667+ // for slice type scrutinee, size is dyanamic, so number of
668+ // elements to skip is calculated during runtime
669+ tree slice_size
670+ = Backend::struct_field_expression (match_scrutinee_expr, 1 ,
671+ pattern.get_locus ());
672+ tree upper_patterns_size = Backend::size_constant_expression (
673+ items.get_upper_patterns ().size ());
674+ tree index_tree = Backend::arithmetic_or_logical_expression (
675+ ArithmeticOrLogicalOperator::SUBTRACT , slice_size,
676+ upper_patterns_size, pattern.get_locus ());
677+ for (auto &pattern_member : items.get_upper_patterns ())
678+ {
679+ tree element_expr
680+ = scrutinee_index_expr_func (match_scrutinee_expr,
681+ index_tree,
682+ pattern.get_locus ());
683+ tree check_expr_sub
684+ = CompilePatternCheckExpr::Compile (*pattern_member,
685+ element_expr, ctx);
686+ check_expr = Backend::arithmetic_or_logical_expression (
687+ ArithmeticOrLogicalOperator::BITWISE_AND , check_expr,
688+ check_expr_sub, pattern.get_locus ());
689+ index_tree = Backend::arithmetic_or_logical_expression (
690+ ArithmeticOrLogicalOperator::ADD , index_tree,
691+ Backend::size_constant_expression (1 ),
692+ pattern.get_locus ());
693+ }
694+ }
695+ break ;
696+ default :
697+ rust_unreachable ();
698+ }
591699 }
592700 break ;
593- default :
594- rust_unreachable ();
595701 }
596702}
597703
@@ -932,43 +1038,121 @@ CompilePatternBindings::visit (HIR::SlicePattern &pattern)
9321038 || lookup->get_kind () == TyTy::TypeKind::SLICE
9331039 || lookup->get_kind () == TyTy::REF );
9341040
935- size_t array_element_index = 0 ;
1041+ // function ptr that points to either array_index_expression or
1042+ // slice_index_expression depending on the scrutinee's type
1043+ tree (*scrutinee_index_expr_func) (tree, tree, location_t ) = nullptr ;
1044+
9361045 switch (lookup->get_kind ())
9371046 {
9381047 case TyTy::TypeKind::ARRAY :
939- for (auto &pattern_member : pattern.get_items ())
940- {
941- tree array_index_tree
942- = Backend::size_constant_expression (array_element_index++);
943- tree element_expr
944- = Backend::array_index_expression (match_scrutinee_expr,
945- array_index_tree,
946- pattern.get_locus ());
947- CompilePatternBindings::Compile (*pattern_member, element_expr, ctx);
948- }
1048+ scrutinee_index_expr_func = Backend::array_index_expression;
9491049 break ;
9501050 case TyTy::TypeKind::SLICE :
951- rust_sorry_at (
952- pattern. get_locus (),
953- " SlicePattern matching against non-ref slices are not yet supported" );
1051+ rust_sorry_at (pattern. get_locus (),
1052+ " SlicePattern matching against non-ref slices are "
1053+ " not yet supported" );
9541054 break ;
9551055 case TyTy::TypeKind::REF :
1056+ scrutinee_index_expr_func = Backend::slice_index_expression;
1057+ break ;
1058+ default :
1059+ rust_unreachable ();
1060+ }
1061+
1062+ rust_assert (scrutinee_index_expr_func != nullptr );
1063+
1064+ size_t element_index = 0 ;
1065+
1066+ switch (pattern.get_items ().get_item_type ())
1067+ {
1068+ case HIR ::SlicePatternItems::ItemType::NO_REST :
9561069 {
957- for (auto &pattern_member : pattern.get_items ())
1070+ auto &items
1071+ = static_cast <HIR ::SlicePatternItemsNoRest &> (pattern.get_items ());
1072+ for (auto &pattern_member : items.get_patterns ())
9581073 {
959- tree slice_index_tree
960- = Backend::size_constant_expression (array_element_index ++);
1074+ tree index_tree
1075+ = Backend::size_constant_expression (element_index ++);
9611076 tree element_expr
962- = Backend::slice_index_expression (match_scrutinee_expr,
963- slice_index_tree,
964- pattern.get_locus ());
1077+ = scrutinee_index_expr_func (match_scrutinee_expr, index_tree,
1078+ pattern.get_locus ());
9651079 CompilePatternBindings::Compile (*pattern_member, element_expr,
9661080 ctx);
9671081 }
968- break ;
9691082 }
970- default :
971- rust_unreachable ();
1083+ break ;
1084+ case HIR ::SlicePatternItems::ItemType::HAS_REST :
1085+ {
1086+ auto &items
1087+ = static_cast <HIR ::SlicePatternItemsHasRest &> (pattern.get_items ());
1088+ for (auto &pattern_member : items.get_lower_patterns ())
1089+ {
1090+ tree index_tree
1091+ = Backend::size_constant_expression (element_index++);
1092+ tree element_expr
1093+ = scrutinee_index_expr_func (match_scrutinee_expr, index_tree,
1094+ pattern.get_locus ());
1095+ CompilePatternBindings::Compile (*pattern_member, element_expr,
1096+ ctx);
1097+ }
1098+
1099+ // handle codegen for upper patterns differently for both types
1100+ switch (lookup->get_kind ())
1101+ {
1102+ case TyTy::TypeKind::ARRAY :
1103+ {
1104+ auto array_ty = static_cast <TyTy::ArrayType *> (lookup);
1105+ auto cap_tree = array_ty->get_capacity ()->get_value ();
1106+ size_t cap_wi = (size_t ) wi::to_wide (cap_tree).to_uhwi ();
1107+ element_index = cap_wi - items.get_upper_patterns ().size ();
1108+ for (auto &pattern_member : items.get_upper_patterns ())
1109+ {
1110+ tree index_tree
1111+ = Backend::size_constant_expression (element_index++);
1112+ tree element_expr
1113+ = scrutinee_index_expr_func (match_scrutinee_expr,
1114+ index_tree,
1115+ pattern.get_locus ());
1116+ CompilePatternBindings::Compile (*pattern_member,
1117+ element_expr, ctx);
1118+ }
1119+ }
1120+ break ;
1121+ case TyTy::TypeKind::SLICE :
1122+ rust_sorry_at (pattern.get_locus (),
1123+ " SlicePattern matching against non-ref slices are "
1124+ " not yet supported" );
1125+ break ;
1126+ case TyTy::TypeKind::REF :
1127+ {
1128+ tree slice_size
1129+ = Backend::struct_field_expression (match_scrutinee_expr, 1 ,
1130+ pattern.get_locus ());
1131+ tree upper_patterns_size = Backend::size_constant_expression (
1132+ items.get_upper_patterns ().size ());
1133+ tree index_tree = Backend::arithmetic_or_logical_expression (
1134+ ArithmeticOrLogicalOperator::SUBTRACT , slice_size,
1135+ upper_patterns_size, pattern.get_locus ());
1136+ for (auto &pattern_member : items.get_upper_patterns ())
1137+ {
1138+ tree element_expr
1139+ = scrutinee_index_expr_func (match_scrutinee_expr,
1140+ index_tree,
1141+ pattern.get_locus ());
1142+ CompilePatternBindings::Compile (*pattern_member,
1143+ element_expr, ctx);
1144+ index_tree = Backend::arithmetic_or_logical_expression (
1145+ ArithmeticOrLogicalOperator::ADD , index_tree,
1146+ Backend::size_constant_expression (1 ),
1147+ pattern.get_locus ());
1148+ }
1149+ }
1150+ break ;
1151+ default :
1152+ rust_unreachable ();
1153+ }
1154+ }
1155+ break ;
9721156 }
9731157}
9741158
0 commit comments