1 import jdk.incubator.code.CodeReflection;
   2 import java.util.Collection;
   3 import java.util.RandomAccess;
   4 import java.util.Stack;
   5 
   6 /*
   7  * @test
   8  * @modules jdk.incubator.code
   9  * @build SwitchStatementTest
  10  * @build CodeReflectionTester
  11  * @run main CodeReflectionTester SwitchStatementTest
  12  */
  13 public class SwitchStatementTest {
  14 
  15     @IR("""
  16             func @"caseConstantRuleExpression" (%0 : java.lang.String)java.lang.String -> {
  17                   %1 : Var<java.lang.String> = var %0 @"r";
  18                   %2 : java.lang.String = constant @"";
  19                   %3 : Var<java.lang.String> = var %2 @"s";
  20                   %4 : java.lang.String = var.load %1;
  21                   java.switch.statement %4
  22                       (%5 : java.lang.String)boolean -> {
  23                           %6 : java.lang.String = constant @"FOO";
  24                           %7 : boolean = invoke %5 %6 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
  25                           yield %7;
  26                       }
  27                       ()void -> {
  28                           %8 : java.lang.String = var.load %3;
  29                           %9 : java.lang.String = constant @"BAR";
  30                           %10 : java.lang.String = concat %8 %9;
  31                           var.store %3 %10;
  32                           yield;
  33                       }
  34                       (%11 : java.lang.String)boolean -> {
  35                           %12 : java.lang.String = constant @"BAR";
  36                           %13 : boolean = invoke %11 %12 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
  37                           yield %13;
  38                       }
  39                       ()void -> {
  40                           %14 : java.lang.String = var.load %3;
  41                           %15 : java.lang.String = constant @"BAZ";
  42                           %16 : java.lang.String = concat %14 %15;
  43                           var.store %3 %16;
  44                           yield;
  45                       }
  46                       (%17 : java.lang.String)boolean -> {
  47                           %18 : java.lang.String = constant @"BAZ";
  48                           %19 : boolean = invoke %17 %18 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
  49                           yield %19;
  50                       }
  51                       ()void -> {
  52                           %20 : java.lang.String = var.load %3;
  53                           %21 : java.lang.String = constant @"FOO";
  54                           %22 : java.lang.String = concat %20 %21;
  55                           var.store %3 %22;
  56                           yield;
  57                       }
  58                       ()boolean -> {
  59                           %26 : boolean = constant @"true";
  60                           yield %26;
  61                       }
  62                       ()void -> {
  63                           %23 : java.lang.String = var.load %3;
  64                           %24 : java.lang.String = constant @"else";
  65                           %25 : java.lang.String = concat %23 %24;
  66                           var.store %3 %25;
  67                           yield;
  68                       };
  69                   %26 : java.lang.String = var.load %3;
  70                   return %26;
  71               };
  72             """)
  73     @CodeReflection
  74     public static String caseConstantRuleExpression(String r) {
  75         String s = "";
  76         switch (r) {
  77             case "FOO" -> s += "BAR";
  78             case "BAR" -> s += "BAZ";
  79             case "BAZ" -> s += "FOO";
  80             default -> s += "else";
  81         }
  82         return s;
  83     }
  84 
  85     @IR("""
  86             func @"caseConstantRuleBlock" (%0 : java.lang.String)java.lang.String -> {
  87                   %1 : Var<java.lang.String> = var %0 @"r";
  88                   %2 : java.lang.String = constant @"";
  89                   %3 : Var<java.lang.String> = var %2 @"s";
  90                   %4 : java.lang.String = var.load %1;
  91                   java.switch.statement %4
  92                       (%5 : java.lang.String)boolean -> {
  93                           %6 : java.lang.String = constant @"FOO";
  94                           %7 : boolean = invoke %5 %6 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
  95                           yield %7;
  96                       }
  97                       ()void -> {
  98                           %8 : java.lang.String = var.load %3;
  99                           %9 : java.lang.String = constant @"BAR";
 100                           %10 : java.lang.String = concat %8 %9;
 101                           var.store %3 %10;
 102                           yield;
 103                       }
 104                       (%11 : java.lang.String)boolean -> {
 105                           %12 : java.lang.String = constant @"BAR";
 106                           %13 : boolean = invoke %11 %12 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 107                           yield %13;
 108                       }
 109                       ()void -> {
 110                           %14 : java.lang.String = var.load %3;
 111                           %15 : java.lang.String = constant @"BAZ";
 112                           %16 : java.lang.String = concat %14 %15;
 113                           var.store %3 %16;
 114                           yield;
 115                       }
 116                       (%17 : java.lang.String)boolean -> {
 117                           %18 : java.lang.String = constant @"BAZ";
 118                           %19 : boolean = invoke %17 %18 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 119                           yield %19;
 120                       }
 121                       ()void -> {
 122                           %20 : java.lang.String = var.load %3;
 123                           %21 : java.lang.String = constant @"FOO";
 124                           %22 : java.lang.String = concat %20 %21;
 125                           var.store %3 %22;
 126                           yield;
 127                       }
 128                       ()boolean -> {
 129                           %26 : boolean = constant @"true";
 130                           yield %26;
 131                       }
 132                       ()void -> {
 133                           %23 : java.lang.String = var.load %3;
 134                           %24 : java.lang.String = constant @"else";
 135                           %25 : java.lang.String = concat %23 %24;
 136                           var.store %3 %25;
 137                           yield;
 138                       };
 139                   %26 : java.lang.String = var.load %3;
 140                   return %26;
 141               };
 142             """)
 143     @CodeReflection
 144     public static String caseConstantRuleBlock(String r) {
 145         String s = "";
 146         switch (r) {
 147             case "FOO" -> {
 148                 s += "BAR";
 149             }
 150             case "BAR" -> {
 151                 s += "BAZ";
 152             }
 153             case "BAZ" -> {
 154                 s += "FOO";
 155             }
 156             default -> {
 157                 s += "else";
 158             }
 159         }
 160         return s;
 161     }
 162 
 163     @IR("""
 164             func @"caseConstantStatement" (%0 : java.lang.String)java.lang.String -> {
 165                   %1 : Var<java.lang.String> = var %0 @"s";
 166                   %2 : java.lang.String = constant @"";
 167                   %3 : Var<java.lang.String> = var %2 @"r";
 168                   %4 : java.lang.String = var.load %1;
 169                   java.switch.statement %4
 170                       (%5 : java.lang.String)boolean -> {
 171                           %6 : java.lang.String = constant @"FOO";
 172                           %7 : boolean = invoke %5 %6 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 173                           yield %7;
 174                       }
 175                       ()void -> {
 176                           %8 : java.lang.String = var.load %3;
 177                           %9 : java.lang.String = constant @"BAR";
 178                           %10 : java.lang.String = concat %8 %9;
 179                           var.store %3 %10;
 180                           java.break;
 181                       }
 182                       (%11 : java.lang.String)boolean -> {
 183                           %12 : java.lang.String = constant @"BAR";
 184                           %13 : boolean = invoke %11 %12 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 185                           yield %13;
 186                       }
 187                       ()void -> {
 188                           %14 : java.lang.String = var.load %3;
 189                           %15 : java.lang.String = constant @"BAZ";
 190                           %16 : java.lang.String = concat %14 %15;
 191                           var.store %3 %16;
 192                           java.break;
 193                       }
 194                       (%17 : java.lang.String)boolean -> {
 195                           %18 : java.lang.String = constant @"BAZ";
 196                           %19 : boolean = invoke %17 %18 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 197                           yield %19;
 198                       }
 199                       ()void -> {
 200                           %20 : java.lang.String = var.load %3;
 201                           %21 : java.lang.String = constant @"FOO";
 202                           %22 : java.lang.String = concat %20 %21;
 203                           var.store %3 %22;
 204                           java.break;
 205                       }
 206                       ()boolean -> {
 207                           %26 : boolean = constant @"true";
 208                           yield %26;
 209                       }
 210                       ()void -> {
 211                           %23 : java.lang.String = var.load %3;
 212                           %24 : java.lang.String = constant @"else";
 213                           %25 : java.lang.String = concat %23 %24;
 214                           var.store %3 %25;
 215                           yield;
 216                       };
 217                   %26 : java.lang.String = var.load %3;
 218                   return %26;
 219               };
 220             """)
 221     @CodeReflection
 222     private static String caseConstantStatement(String s) {
 223         String r = "";
 224         switch (s) {
 225             case "FOO":
 226                 r += "BAR";
 227                 break;
 228             case "BAR":
 229                 r += "BAZ";
 230                 break;
 231             case "BAZ":
 232                 r += "FOO";
 233                 break;
 234             default:
 235                 r += "else";
 236         }
 237         return r;
 238     }
 239 
 240     @IR("""
 241             func @"caseConstantMultiLabels" (%0 : char)java.lang.String -> {
 242                 %1 : Var<char> = var %0 @"c";
 243                 %2 : java.lang.String = constant @"";
 244                 %3 : Var<java.lang.String> = var %2 @"r";
 245                 %4 : char = var.load %1;
 246                 %5 : char = invoke %4 @"java.lang.Character::toLowerCase(char)char";
 247                 java.switch.statement %5
 248                     (%6 : char)boolean -> {
 249                         %7 : boolean = java.cor
 250                             ()boolean -> {
 251                                 %8 : char = constant @"a";
 252                                 %9 : boolean = eq %6 %8;
 253                                 yield %9;
 254                             }
 255                             ()boolean -> {
 256                                 %10 : char = constant @"e";
 257                                 %11 : boolean = eq %6 %10;
 258                                 yield %11;
 259                             }
 260                             ()boolean -> {
 261                                 %12 : char = constant @"i";
 262                                 %13 : boolean = eq %6 %12;
 263                                 yield %13;
 264                             }
 265                             ()boolean -> {
 266                                 %14 : char = constant @"o";
 267                                 %15 : boolean = eq %6 %14;
 268                                 yield %15;
 269                             }
 270                             ()boolean -> {
 271                                 %16 : char = constant @"u";
 272                                 %17 : boolean = eq %6 %16;
 273                                 yield %17;
 274                             };
 275                         yield %7;
 276                     }
 277                     ()void -> {
 278                         %18 : java.lang.String = var.load %3;
 279                         %19 : java.lang.String = constant @"vowel";
 280                         %20 : java.lang.String = concat %18 %19;
 281                         var.store %3 %20;
 282                         java.break;
 283                     }
 284                     ()boolean -> {
 285                         %24 : boolean = constant @"true";
 286                         yield %24;
 287                     }
 288                     ()void -> {
 289                         %21 : java.lang.String = var.load %3;
 290                         %22 : java.lang.String = constant @"consonant";
 291                         %23 : java.lang.String = concat %21 %22;
 292                         var.store %3 %23;
 293                         yield;
 294                     };
 295                 %24 : java.lang.String = var.load %3;
 296                 return %24;
 297             };
 298             """)
 299     @CodeReflection
 300     private static String caseConstantMultiLabels(char c) {
 301         String r = "";
 302         switch (Character.toLowerCase(c)) {
 303             case 'a', 'e', 'i', 'o', 'u':
 304                 r += "vowel";
 305                 break;
 306             default:
 307                 r += "consonant";
 308         }
 309         return r;
 310     }
 311 
 312     @IR("""
 313             func @"caseConstantThrow" (%0 : java.lang.Integer)java.lang.String -> {
 314                 %1 : Var<java.lang.Integer> = var %0 @"i";
 315                 %2 : java.lang.String = constant @"";
 316                 %3 : Var<java.lang.String> = var %2 @"r";
 317                 %4 : java.lang.Integer = var.load %1;
 318                 java.switch.statement %4
 319                     (%5 : java.lang.Integer)boolean -> {
 320                         %6 : int = constant @"8";
 321                         %7 : java.lang.Integer = invoke %6 @"java.lang.Integer::valueOf(int)java.lang.Integer";
 322                         %8 : boolean = invoke %5 %7 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 323                         yield %8;
 324                     }
 325                     ()void -> {
 326                         %9 : java.lang.IllegalArgumentException = new @"func<java.lang.IllegalArgumentException>";
 327                         throw %9;
 328                     }
 329                     (%10 : java.lang.Integer)boolean -> {
 330                         %11 : int = constant @"9";
 331                         %12 : java.lang.Integer = invoke %11 @"java.lang.Integer::valueOf(int)java.lang.Integer";
 332                         %13 : boolean = invoke %10 %12 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 333                         yield %13;
 334                     }
 335                     ()void -> {
 336                         %14 : java.lang.String = var.load %3;
 337                         %15 : java.lang.String = constant @"Nine";
 338                         %16 : java.lang.String = concat %14 %15;
 339                         var.store %3 %16;
 340                         yield;
 341                     }
 342                     ()boolean -> {
 343                         %17 : boolean = constant @"true";
 344                         yield %17;
 345                     }
 346                     ()void -> {
 347                         %17 : java.lang.String = var.load %3;
 348                         %18 : java.lang.String = constant @"An integer";
 349                         %19 : java.lang.String = concat %17 %18;
 350                         var.store %3 %19;
 351                         yield;
 352                     };
 353                 %20 : java.lang.String = var.load %3;
 354                 return %20;
 355             };
 356             """)
 357     @CodeReflection
 358     private static String caseConstantThrow(Integer i) {
 359         String r = "";
 360         switch (i) {
 361             case 8 -> throw new IllegalArgumentException();
 362             case 9 -> r += "Nine";
 363             default -> r += "An integer";
 364         }
 365         return r;
 366     }
 367 
 368     @IR("""
 369             func @"caseConstantNullLabel" (%0 : java.lang.String)java.lang.String -> {
 370                 %1 : Var<java.lang.String> = var %0 @"s";
 371                 %2 : java.lang.String = constant @"";
 372                 %3 : Var<java.lang.String> = var %2 @"r";
 373                 %4 : java.lang.String = var.load %1;
 374                 java.switch.statement %4
 375                     (%5 : java.lang.String)boolean -> {
 376                         %6 : java.lang.Object = constant @null;
 377                         %7 : boolean = invoke %5 %6 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 378                         yield %7;
 379                     }
 380                     ()void -> {
 381                         %8 : java.lang.String = var.load %3;
 382                         %9 : java.lang.String = constant @"null";
 383                         %10 : java.lang.String = concat %8 %9;
 384                         var.store %3 %10;
 385                         yield;
 386                     }
 387                     ()boolean -> {
 388                         %17 : boolean = constant @"true";
 389                         yield %17;
 390                     }
 391                     ()void -> {
 392                         %11 : java.lang.String = var.load %3;
 393                         %12 : java.lang.String = constant @"non null";
 394                         %13 : java.lang.String = concat %11 %12;
 395                         var.store %3 %13;
 396                         yield;
 397                     };
 398                 %14 : java.lang.String = var.load %3;
 399                 return %14;
 400             };
 401             """)
 402     @CodeReflection
 403     private static String caseConstantNullLabel(String s) {
 404         String r = "";
 405         switch (s) {
 406             case null -> r += "null";
 407             default -> r += "non null";
 408         }
 409         return r;
 410     }
 411 
 412 //    @CodeReflection
 413 //    @@@ not supported
 414     private static String caseConstantNullAndDefault(String s) {
 415         String r = "";
 416         switch (s) {
 417             case "abc" -> r += "alphabet";
 418             case null, default -> r += "null or default";
 419         }
 420         return r;
 421     }
 422 
 423     @IR("""
 424             func @"caseConstantFallThrough" (%0 : char)java.lang.String -> {
 425                   %1 : Var<char> = var %0 @"c";
 426                   %2 : java.lang.String = constant @"";
 427                   %3 : Var<java.lang.String> = var %2 @"r";
 428                   %4 : char = var.load %1;
 429                   java.switch.statement %4
 430                       (%5 : char)boolean -> {
 431                           %6 : char = constant @"A";
 432                           %7 : boolean = eq %5 %6;
 433                           yield %7;
 434                       }
 435                       ()void -> {
 436                           java.switch.fallthrough;
 437                       }
 438                       (%8 : char)boolean -> {
 439                           %9 : char = constant @"B";
 440                           %10 : boolean = eq %8 %9;
 441                           yield %10;
 442                       }
 443                       ()void -> {
 444                           %11 : java.lang.String = var.load %3;
 445                           %12 : java.lang.String = constant @"A or B";
 446                           %13 : java.lang.String = concat %11 %12;
 447                           var.store %3 %13;
 448                           java.break;
 449                       }
 450                       ()boolean -> {
 451                           %17 : boolean = constant @"true";
 452                           yield %17;
 453                       }
 454                       ()void -> {
 455                           %14 : java.lang.String = var.load %3;
 456                           %15 : java.lang.String = constant @"Neither A nor B";
 457                           %16 : java.lang.String = concat %14 %15;
 458                           var.store %3 %16;
 459                           yield;
 460                       };
 461                   %17 : java.lang.String = var.load %3;
 462                   return %17;
 463               };
 464             """)
 465     @CodeReflection
 466     private static String caseConstantFallThrough(char c) {
 467         String r = "";
 468         switch (c) {
 469             case 'A':
 470             case 'B':
 471                 r += "A or B";
 472                 break;
 473             default:
 474                 r += "Neither A nor B";
 475         }
 476         return r;
 477     }
 478 
 479     enum Day {
 480         MON, TUE, WED, THU, FRI, SAT, SUN
 481     }
 482     @IR("""
 483             func @"caseConstantEnum" (%0 : SwitchStatementTest$Day)java.lang.String -> {
 484                   %1 : Var<SwitchStatementTest$Day> = var %0 @"d";
 485                   %2 : java.lang.String = constant @"";
 486                   %3 : Var<java.lang.String> = var %2 @"r";
 487                   %4 : SwitchStatementTest$Day = var.load %1;
 488                   java.switch.statement %4
 489                       (%5 : SwitchStatementTest$Day)boolean -> {
 490                           %6 : boolean = java.cor
 491                               ()boolean -> {
 492                                   %7 : SwitchStatementTest$Day = field.load @"SwitchStatementTest$Day::MON()SwitchStatementTest$Day";
 493                                   %8 : boolean = invoke %5 %7 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 494                                   yield %8;
 495                               }
 496                               ()boolean -> {
 497                                   %9 : SwitchStatementTest$Day = field.load @"SwitchStatementTest$Day::FRI()SwitchStatementTest$Day";
 498                                   %10 : boolean = invoke %5 %9 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 499                                   yield %10;
 500                               }
 501                               ()boolean -> {
 502                                   %11 : SwitchStatementTest$Day = field.load @"SwitchStatementTest$Day::SUN()SwitchStatementTest$Day";
 503                                   %12 : boolean = invoke %5 %11 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 504                                   yield %12;
 505                               };
 506                           yield %6;
 507                       }
 508                       ()void -> {
 509                           %13 : java.lang.String = var.load %3;
 510                           %14 : int = constant @"6";
 511                           %15 : java.lang.String = concat %13 %14;
 512                           var.store %3 %15;
 513                           yield;
 514                       }
 515                       (%16 : SwitchStatementTest$Day)boolean -> {
 516                           %17 : SwitchStatementTest$Day = field.load @"SwitchStatementTest$Day::TUE()SwitchStatementTest$Day";
 517                           %18 : boolean = invoke %16 %17 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 518                           yield %18;
 519                       }
 520                       ()void -> {
 521                           %19 : java.lang.String = var.load %3;
 522                           %20 : int = constant @"7";
 523                           %21 : java.lang.String = concat %19 %20;
 524                           var.store %3 %21;
 525                           yield;
 526                       }
 527                       (%22 : SwitchStatementTest$Day)boolean -> {
 528                           %23 : boolean = java.cor
 529                               ()boolean -> {
 530                                   %24 : SwitchStatementTest$Day = field.load @"SwitchStatementTest$Day::THU()SwitchStatementTest$Day";
 531                                   %25 : boolean = invoke %22 %24 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 532                                   yield %25;
 533                               }
 534                               ()boolean -> {
 535                                   %26 : SwitchStatementTest$Day = field.load @"SwitchStatementTest$Day::SAT()SwitchStatementTest$Day";
 536                                   %27 : boolean = invoke %22 %26 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 537                                   yield %27;
 538                               };
 539                           yield %23;
 540                       }
 541                       ()void -> {
 542                           %28 : java.lang.String = var.load %3;
 543                           %29 : int = constant @"8";
 544                           %30 : java.lang.String = concat %28 %29;
 545                           var.store %3 %30;
 546                           yield;
 547                       }
 548                       (%31 : SwitchStatementTest$Day)boolean -> {
 549                           %32 : SwitchStatementTest$Day = field.load @"SwitchStatementTest$Day::WED()SwitchStatementTest$Day";
 550                           %33 : boolean = invoke %31 %32 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 551                           yield %33;
 552                       }
 553                       ()void -> {
 554                           %34 : java.lang.String = var.load %3;
 555                           %35 : int = constant @"9";
 556                           %36 : java.lang.String = concat %34 %35;
 557                           var.store %3 %36;
 558                           yield;
 559                       };
 560                   %37 : java.lang.String = var.load %3;
 561                   return %37;
 562               };
 563             """)
 564     @CodeReflection
 565     private static String caseConstantEnum(Day d) {
 566         String r = "";
 567         switch (d) {
 568             // @@@ concat of String and int is modeled as: add str Integer
 569             case MON, FRI, SUN -> r += 6;
 570             case TUE -> r += 7;
 571             case THU, SAT -> r += 8;
 572             case WED -> r += 9;
 573         }
 574         return r;
 575     }
 576 
 577     static class Constants {
 578         static final int c1 = 12;
 579     }
 580     @IR("""
 581             func @"caseConstantOtherKindsOfExpr" (%0 : int)java.lang.String -> {
 582                   %1 : Var<int> = var %0 @"i";
 583                   %2 : java.lang.String = constant @"";
 584                   %3 : Var<java.lang.String> = var %2 @"r";
 585                   %4 : int = constant @"11";
 586                   %5 : Var<int> = var %4 @"eleven";
 587                   %6 : int = var.load %1;
 588                   java.switch.statement %6
 589                       (%7 : int)boolean -> {
 590                           %8 : int = constant @"1";
 591                           %9 : int = constant @"15";
 592                           %10 : int = and %8 %9;
 593                           %11 : boolean = eq %7 %10;
 594                           yield %11;
 595                       }
 596                       ()void -> {
 597                           %12 : java.lang.String = var.load %3;
 598                           %13 : int = constant @"1";
 599                           %14 : java.lang.String = concat %12 %13;
 600                           var.store %3 %14;
 601                           yield;
 602                       }
 603                       (%15 : int)boolean -> {
 604                           %16 : int = constant @"4";
 605                           %17 : int = constant @"1";
 606                           %18 : int = ashr %16 %17;
 607                           %19 : boolean = eq %15 %18;
 608                           yield %19;
 609                       }
 610                       ()void -> {
 611                           %20 : java.lang.String = var.load %3;
 612                           %21 : java.lang.String = constant @"2";
 613                           %22 : java.lang.String = concat %20 %21;
 614                           var.store %3 %22;
 615                           yield;
 616                       }
 617                       (%23 : int)boolean -> {
 618                           %24 : long = constant @"3";
 619                           %25 : int = conv %24;
 620                           %26 : boolean = eq %23 %25;
 621                           yield %26;
 622                       }
 623                       ()void -> {
 624                           %27 : java.lang.String = var.load %3;
 625                           %28 : int = constant @"3";
 626                           %29 : java.lang.String = concat %27 %28;
 627                           var.store %3 %29;
 628                           yield;
 629                       }
 630                       (%30 : int)boolean -> {
 631                           %31 : int = constant @"2";
 632                           %32 : int = constant @"1";
 633                           %33 : int = lshl %31 %32;
 634                           %34 : boolean = eq %30 %33;
 635                           yield %34;
 636                       }
 637                       ()void -> {
 638                           %35 : java.lang.String = var.load %3;
 639                           %36 : int = constant @"4";
 640                           %37 : java.lang.String = concat %35 %36;
 641                           var.store %3 %37;
 642                           yield;
 643                       }
 644                       (%38 : int)boolean -> {
 645                           %39 : int = constant @"10";
 646                           %40 : int = constant @"2";
 647                           %41 : int = div %39 %40;
 648                           %42 : boolean = eq %38 %41;
 649                           yield %42;
 650                       }
 651                       ()void -> {
 652                           %43 : java.lang.String = var.load %3;
 653                           %44 : int = constant @"5";
 654                           %45 : java.lang.String = concat %43 %44;
 655                           var.store %3 %45;
 656                           yield;
 657                       }
 658                       (%46 : int)boolean -> {
 659                           %47 : int = constant @"12";
 660                           %48 : int = constant @"6";
 661                           %49 : int = sub %47 %48;
 662                           %50 : boolean = eq %46 %49;
 663                           yield %50;
 664                       }
 665                       ()void -> {
 666                           %51 : java.lang.String = var.load %3;
 667                           %52 : int = constant @"6";
 668                           %53 : java.lang.String = concat %51 %52;
 669                           var.store %3 %53;
 670                           yield;
 671                       }
 672                       (%54 : int)boolean -> {
 673                           %55 : int = constant @"3";
 674                           %56 : int = constant @"4";
 675                           %57 : int = add %55 %56;
 676                           %58 : boolean = eq %54 %57;
 677                           yield %58;
 678                       }
 679                       ()void -> {
 680                           %59 : java.lang.String = var.load %3;
 681                           %60 : int = constant @"7";
 682                           %61 : java.lang.String = concat %59 %60;
 683                           var.store %3 %61;
 684                           yield;
 685                       }
 686                       (%62 : int)boolean -> {
 687                           %63 : int = constant @"2";
 688                           %64 : int = constant @"2";
 689                           %65 : int = mul %63 %64;
 690                           %66 : int = constant @"2";
 691                           %67 : int = mul %65 %66;
 692                           %68 : boolean = eq %62 %67;
 693                           yield %68;
 694                       }
 695                       ()void -> {
 696                           %69 : java.lang.String = var.load %3;
 697                           %70 : int = constant @"8";
 698                           %71 : java.lang.String = concat %69 %70;
 699                           var.store %3 %71;
 700                           yield;
 701                       }
 702                       (%72 : int)boolean -> {
 703                           %73 : int = constant @"8";
 704                           %74 : int = constant @"1";
 705                           %75 : int = or %73 %74;
 706                           %76 : boolean = eq %72 %75;
 707                           yield %76;
 708                       }
 709                       ()void -> {
 710                           %77 : java.lang.String = var.load %3;
 711                           %78 : int = constant @"9";
 712                           %79 : java.lang.String = concat %77 %78;
 713                           var.store %3 %79;
 714                           yield;
 715                       }
 716                       (%80 : int)boolean -> {
 717                           %81 : int = constant @"10";
 718                           %82 : boolean = eq %80 %81;
 719                           yield %82;
 720                       }
 721                       ()void -> {
 722                           %83 : java.lang.String = var.load %3;
 723                           %84 : int = constant @"10";
 724                           %85 : java.lang.String = concat %83 %84;
 725                           var.store %3 %85;
 726                           yield;
 727                       }
 728                       (%86 : int)boolean -> {
 729                           %87 : int = var.load %5;
 730                           %88 : boolean = eq %86 %87;
 731                           yield %88;
 732                       }
 733                       ()void -> {
 734                           %89 : java.lang.String = var.load %3;
 735                           %90 : int = constant @"11";
 736                           %91 : java.lang.String = concat %89 %90;
 737                           var.store %3 %91;
 738                           yield;
 739                       }
 740                       (%92 : int)boolean -> {
 741                           %93 : int = field.load @"SwitchStatementTest$Constants::c1()int";
 742                           %94 : boolean = eq %92 %93;
 743                           yield %94;
 744                       }
 745                       ()void -> {
 746                           %95 : java.lang.String = var.load %3;
 747                           %96 : int = field.load @"SwitchStatementTest$Constants::c1()int";
 748                           %97 : java.lang.String = concat %95 %96;
 749                           var.store %3 %97;
 750                           yield;
 751                       }
 752                       (%98 : int)boolean -> {
 753                           %99 : int = java.cexpression
 754                               ()boolean -> {
 755                                   %100 : int = constant @"1";
 756                                   %101 : int = constant @"0";
 757                                   %102 : boolean = gt %100 %101;
 758                                   yield %102;
 759                               }
 760                               ()int -> {
 761                                   %103 : int = constant @"13";
 762                                   yield %103;
 763                               }
 764                               ()int -> {
 765                                   %104 : int = constant @"133";
 766                                   yield %104;
 767                               };
 768                           %105 : boolean = eq %98 %99;
 769                           yield %105;
 770                       }
 771                       ()void -> {
 772                           %106 : java.lang.String = var.load %3;
 773                           %107 : int = constant @"13";
 774                           %108 : java.lang.String = concat %106 %107;
 775                           var.store %3 %108;
 776                           yield;
 777                       }
 778                       ()boolean -> {
 779                           %109 : boolean = constant @"true";
 780                           yield %109;
 781                       }
 782                       ()void -> {
 783                           %110 : java.lang.String = var.load %3;
 784                           %111 : java.lang.String = constant @"an int";
 785                           %112 : java.lang.String = concat %110 %111;
 786                           var.store %3 %112;
 787                           yield;
 788                       };
 789                   %113 : java.lang.String = var.load %3;
 790                   return %113;
 791               };
 792             """)
 793     @CodeReflection
 794     private static String caseConstantOtherKindsOfExpr(int i) {
 795         String r = "";
 796         final int eleven = 11;
 797         switch (i) {
 798             case 1 & 0xF -> r += 1;
 799             case 4>>1 -> r += "2";
 800             case (int) 3L -> r += 3;
 801             case 2<<1 -> r += 4;
 802             case 10 / 2 -> r += 5;
 803             case 12 - 6 -> r += 6;
 804             case 3 + 4 -> r += 7;
 805             case 2 * 2 * 2 -> r += 8;
 806             case 8 | 1 -> r += 9;
 807             case (10) -> r += 10;
 808             case eleven -> r += 11;
 809             case Constants.c1 -> r += Constants.c1;
 810             case 1 > 0 ? 13 : 133 -> r += 13;
 811             default -> r += "an int";
 812         }
 813         return r;
 814     }
 815 
 816     @IR("""
 817             func @"caseConstantConv" (%0 : short)java.lang.String -> {
 818                   %1 : Var<short> = var %0 @"a";
 819                   %2 : int = constant @"1";
 820                   %3 : short = conv %2;
 821                   %4 : Var<short> = var %3 @"s";
 822                   %5 : int = constant @"2";
 823                   %6 : byte = conv %5;
 824                   %7 : Var<byte> = var %6 @"b";
 825                   %8 : java.lang.String = constant @"";
 826                   %9 : Var<java.lang.String> = var %8 @"r";
 827                   %10 : short = var.load %1;
 828                   java.switch.statement %10
 829                       (%11 : short)boolean -> {
 830                           %12 : short = var.load %4;
 831                           %13 : boolean = eq %11 %12;
 832                           yield %13;
 833                       }
 834                       ()void -> {
 835                           %14 : java.lang.String = var.load %9;
 836                           %15 : java.lang.String = constant @"one";
 837                           %16 : java.lang.String = concat %14 %15;
 838                           var.store %9 %16;
 839                           yield;
 840                       }
 841                       (%17 : short)boolean -> {
 842                           %18 : byte = var.load %7;
 843                           %19 : short = conv %18;
 844                           %20 : boolean = eq %17 %19;
 845                           yield %20;
 846                       }
 847                       ()void -> {
 848                           %21 : java.lang.String = var.load %9;
 849                           %22 : java.lang.String = constant @"two";
 850                           %23 : java.lang.String = concat %21 %22;
 851                           var.store %9 %23;
 852                           yield;
 853                       }
 854                       (%24 : short)boolean -> {
 855                           %25 : int = constant @"3";
 856                           %26 : short = conv %25;
 857                           %27 : boolean = eq %24 %26;
 858                           yield %27;
 859                       }
 860                       ()void -> {
 861                           %28 : java.lang.String = var.load %9;
 862                           %29 : java.lang.String = constant @"three";
 863                           %30 : java.lang.String = concat %28 %29;
 864                           var.store %9 %30;
 865                           yield;
 866                       }
 867                       ()boolean -> {
 868                           %17 : boolean = constant @"true";
 869                           yield %17;
 870                       }
 871                       ()void -> {
 872                           %31 : java.lang.String = var.load %9;
 873                           %32 : java.lang.String = constant @"else";
 874                           %33 : java.lang.String = concat %31 %32;
 875                           var.store %9 %33;
 876                           yield;
 877                       };
 878                   %34 : java.lang.String = var.load %9;
 879                   return %34;
 880               };
 881             """)
 882     @CodeReflection
 883     static String caseConstantConv(short a) {
 884         final short s = 1;
 885         final byte b = 2;
 886         String r = "";
 887         switch (a) {
 888             case s -> r += "one"; // identity, short -> short
 889             case b -> r += "two"; // widening primitive conversion, byte -> short
 890             case 3 -> r += "three"; // narrowing primitive conversion, int -> short
 891             default -> r += "else";
 892         }
 893         return r;
 894     }
 895 
 896     @IR("""
 897             func @"caseConstantConv2" (%0 : java.lang.Byte)java.lang.String -> {
 898                 %1 : Var<java.lang.Byte> = var %0 @"a";
 899                 %2 : int = constant @"2";
 900                 %3 : byte = conv %2;
 901                 %4 : Var<byte> = var %3 @"b";
 902                 %5 : java.lang.String = constant @"";
 903                 %6 : Var<java.lang.String> = var %5 @"r";
 904                 %7 : java.lang.Byte = var.load %1;
 905                 java.switch.statement %7
 906                     (%8 : java.lang.Byte)boolean -> {
 907                         %9 : int = constant @"1";
 908                         %10 : byte = conv %9;
 909                         %11 : java.lang.Byte = invoke %10 @"java.lang.Byte::valueOf(byte)java.lang.Byte";
 910                         %12 : boolean = invoke %8 %11 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 911                         yield %12;
 912                     }
 913                     ()void -> {
 914                         %13 : java.lang.String = var.load %6;
 915                         %14 : java.lang.String = constant @"one";
 916                         %15 : java.lang.String = concat %13 %14;
 917                         var.store %6 %15;
 918                         yield;
 919                     }
 920                     (%16 : java.lang.Byte)boolean -> {
 921                         %17 : byte = var.load %4;
 922                         %18 : java.lang.Byte = invoke %17 @"java.lang.Byte::valueOf(byte)java.lang.Byte";
 923                         %19 : boolean = invoke %16 %18 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
 924                         yield %19;
 925                     }
 926                     ()void -> {
 927                         %20 : java.lang.String = var.load %6;
 928                         %21 : java.lang.String = constant @"two";
 929                         %22 : java.lang.String = concat %20 %21;
 930                         var.store %6 %22;
 931                         yield;
 932                     }
 933                     ()boolean -> {
 934                         %17 : boolean = constant @"true";
 935                         yield %17;
 936                     }
 937                     ()void -> {
 938                         %23 : java.lang.String = var.load %6;
 939                         %24 : java.lang.String = constant @"default";
 940                         %25 : java.lang.String = concat %23 %24;
 941                         var.store %6 %25;
 942                         yield;
 943                     };
 944                 %26 : java.lang.String = var.load %6;
 945                 return %26;
 946             };
 947             """)
 948     @CodeReflection
 949     static String caseConstantConv2(Byte a) {
 950         final byte b = 2;
 951         String r = "";
 952         switch (a) {
 953             case 1 -> r+= "one"; // narrowing primitive conversion followed by a boxing conversion, int -> bye -> Byte
 954             case b -> r+= "two"; // boxing, byte -> Byte
 955             default -> r+= "default";
 956         }
 957         return r;
 958     }
 959 
 960     @IR("""
 961             func @"nonEnhancedSwStatNoDefault" (%0 : int)java.lang.String -> {
 962                   %1 : Var<int> = var %0 @"a";
 963                   %2 : java.lang.String = constant @"";
 964                   %3 : Var<java.lang.String> = var %2 @"r";
 965                   %4 : int = var.load %1;
 966                   java.switch.statement %4
 967                       (%5 : int)boolean -> {
 968                           %6 : int = constant @"1";
 969                           %7 : boolean = eq %5 %6;
 970                           yield %7;
 971                       }
 972                       ()void -> {
 973                           %8 : java.lang.String = var.load %3;
 974                           %9 : java.lang.String = constant @"1";
 975                           %10 : java.lang.String = concat %8 %9;
 976                           var.store %3 %10;
 977                           yield;
 978                       }
 979                       (%11 : int)boolean -> {
 980                           %12 : int = constant @"2";
 981                           %13 : boolean = eq %11 %12;
 982                           yield %13;
 983                       }
 984                       ()void -> {
 985                           %14 : java.lang.String = var.load %3;
 986                           %15 : int = constant @"2";
 987                           %16 : java.lang.String = concat %14 %15;
 988                           var.store %3 %16;
 989                           yield;
 990                       };
 991                   %17 : java.lang.String = var.load %3;
 992                   return %17;
 993               };
 994             """)
 995     @CodeReflection
 996     static String nonEnhancedSwStatNoDefault(int a) {
 997         String r = "";
 998         switch (a) {
 999             case 1 -> r += "1";
1000             case 2 -> r += 2;
1001         }
1002         return r;
1003     }
1004 
1005     enum E {A, B}
1006     @IR("""
1007             func @"enhancedSwStatNoDefault1" (%0 : SwitchStatementTest$E)java.lang.String -> {
1008                   %1 : Var<SwitchStatementTest$E> = var %0 @"e";
1009                   %2 : java.lang.String = constant @"";
1010                   %3 : Var<java.lang.String> = var %2 @"r";
1011                   %4 : SwitchStatementTest$E = var.load %1;
1012                   java.switch.statement %4
1013                       (%5 : SwitchStatementTest$E)boolean -> {
1014                           %6 : SwitchStatementTest$E = field.load @"SwitchStatementTest$E::A()SwitchStatementTest$E";
1015                           %7 : boolean = invoke %5 %6 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
1016                           yield %7;
1017                       }
1018                       ()void -> {
1019                           %8 : java.lang.String = var.load %3;
1020                           %9 : SwitchStatementTest$E = field.load @"SwitchStatementTest$E::A()SwitchStatementTest$E";
1021                           %10 : java.lang.String = cast %9 @"java.lang.String";
1022                           %11 : java.lang.String = concat %8 %10;
1023                           var.store %3 %11;
1024                           yield;
1025                       }
1026                       (%12 : SwitchStatementTest$E)boolean -> {
1027                           %13 : SwitchStatementTest$E = field.load @"SwitchStatementTest$E::B()SwitchStatementTest$E";
1028                           %14 : boolean = invoke %12 %13 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
1029                           yield %14;
1030                       }
1031                       ()void -> {
1032                           %15 : java.lang.String = var.load %3;
1033                           %16 : SwitchStatementTest$E = field.load @"SwitchStatementTest$E::B()SwitchStatementTest$E";
1034                           %17 : java.lang.String = cast %16 @"java.lang.String";
1035                           %18 : java.lang.String = concat %15 %17;
1036                           var.store %3 %18;
1037                           yield;
1038                       }
1039                       (%19 : SwitchStatementTest$E)boolean -> {
1040                           %20 : java.lang.Object = constant @null;
1041                           %21 : boolean = invoke %19 %20 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
1042                           yield %21;
1043                       }
1044                       ()void -> {
1045                           %22 : java.lang.String = var.load %3;
1046                           %23 : java.lang.String = constant @"null";
1047                           %24 : java.lang.String = concat %22 %23;
1048                           var.store %3 %24;
1049                           yield;
1050                       }
1051                       ()boolean -> {
1052                           %17 : boolean = constant @"true";
1053                           yield %17;
1054                       }
1055                       ()void -> {
1056                           %25 : java.lang.MatchException = new @"func<java.lang.MatchException>";
1057                           throw %25;
1058                       };
1059                   %26 : java.lang.String = var.load %3;
1060                   return %26;
1061               };
1062             """)
1063     @CodeReflection
1064     static String enhancedSwStatNoDefault1(E e) {
1065         String r = "";
1066         switch (e) {
1067             case A -> r += E.A;
1068             case B -> r += E.B;
1069             case null -> r += "null";
1070         }
1071         return r;
1072     }
1073 
1074     sealed interface I permits K, J {}
1075     record K() implements I {}
1076     static final class J implements I {}
1077     @IR("""
1078             func @"enhancedSwStatNoDefault2" (%0 : SwitchStatementTest$I)java.lang.String -> {
1079                 %1 : Var<SwitchStatementTest$I> = var %0 @"i";
1080                 %2 : java.lang.String = constant @"";
1081                 %3 : Var<java.lang.String> = var %2 @"r";
1082                 %4 : SwitchStatementTest$I = var.load %1;
1083                 %5 : SwitchStatementTest$K = constant @null;
1084                 %6 : Var<SwitchStatementTest$K> = var %5 @"k";
1085                 %7 : SwitchStatementTest$J = constant @null;
1086                 %8 : Var<SwitchStatementTest$J> = var %7 @"j";
1087                 java.switch.statement %4
1088                     (%9 : SwitchStatementTest$I)boolean -> {
1089                         %10 : boolean = pattern.match %9
1090                             ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<SwitchStatementTest$K> -> {
1091                                 %11 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<SwitchStatementTest$K> = pattern.type @"k";
1092                                 yield %11;
1093                             }
1094                             (%12 : SwitchStatementTest$K)void -> {
1095                                 var.store %6 %12;
1096                                 yield;
1097                             };
1098                         yield %10;
1099                     }
1100                     ()void -> {
1101                         %13 : java.lang.String = var.load %3;
1102                         %14 : java.lang.String = constant @"K";
1103                         %15 : java.lang.String = concat %13 %14;
1104                         var.store %3 %15;
1105                         yield;
1106                     }
1107                     (%16 : SwitchStatementTest$I)boolean -> {
1108                         %17 : boolean = pattern.match %16
1109                             ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<SwitchStatementTest$J> -> {
1110                                 %18 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<SwitchStatementTest$J> = pattern.type @"j";
1111                                 yield %18;
1112                             }
1113                             (%19 : SwitchStatementTest$J)void -> {
1114                                 var.store %8 %19;
1115                                 yield;
1116                             };
1117                         yield %17;
1118                     }
1119                     ()void -> {
1120                         %20 : java.lang.String = var.load %3;
1121                         %21 : java.lang.String = constant @"J";
1122                         %22 : java.lang.String = concat %20 %21;
1123                         var.store %3 %22;
1124                         yield;
1125                     }
1126                     ()boolean -> {
1127                         %17 : boolean = constant @"true";
1128                         yield %17;
1129                     }
1130                     ()void -> {
1131                         %23 : java.lang.MatchException = new @"func<java.lang.MatchException>";
1132                         throw %23;
1133                     };
1134                 %24 : java.lang.String = var.load %3;
1135                 return %24;
1136             };
1137             """)
1138     @CodeReflection
1139     static String enhancedSwStatNoDefault2(I i) {
1140         String r = "";
1141         switch (i) {
1142             case K k -> r += "K";
1143             case J j -> r += "J";
1144         }
1145         return r;
1146     }
1147 
1148     @IR("""
1149             func @"enhancedSwStatUnconditionalPattern" (%0 : java.lang.String)java.lang.String -> {
1150                 %1 : Var<java.lang.String> = var %0 @"s";
1151                 %2 : java.lang.String = constant @"";
1152                 %3 : Var<java.lang.String> = var %2 @"r";
1153                 %4 : java.lang.String = var.load %1;
1154                 %5 : java.lang.Object = constant @null;
1155                 %6 : Var<java.lang.Object> = var %5 @"o";
1156                 java.switch.statement %4
1157                     (%7 : java.lang.String)boolean -> {
1158                         %8 : java.lang.String = constant @"A";
1159                         %9 : boolean = invoke %7 %8 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
1160                         yield %9;
1161                     }
1162                     ()void -> {
1163                         %10 : java.lang.String = var.load %3;
1164                         %11 : java.lang.String = constant @"A";
1165                         %12 : java.lang.String = concat %10 %11;
1166                         var.store %3 %12;
1167                         yield;
1168                     }
1169                     (%13 : java.lang.String)boolean -> {
1170                         %14 : boolean = pattern.match %13
1171                             ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Object> -> {
1172                                 %15 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Object> = pattern.type @"o";
1173                                 yield %15;
1174                             }
1175                             (%16 : java.lang.Object)void -> {
1176                                 var.store %6 %16;
1177                                 yield;
1178                             };
1179                         yield %14;
1180                     }
1181                     ()void -> {
1182                         %17 : java.lang.String = var.load %3;
1183                         %18 : java.lang.String = constant @"obj";
1184                         %19 : java.lang.String = concat %17 %18;
1185                         var.store %3 %19;
1186                         yield;
1187                     };
1188                 %20 : java.lang.String = var.load %3;
1189                 return %20;
1190             };
1191             """)
1192     @CodeReflection
1193     static String enhancedSwStatUnconditionalPattern(String s) {
1194         String r = "";
1195         switch (s) {
1196             case "A" -> r += "A";
1197             case Object o -> r += "obj";
1198         }
1199         return r;
1200     }
1201 
1202     @IR("""
1203             func @"casePatternRuleExpression" (%0 : java.lang.Object)java.lang.String -> {
1204                   %1 : Var<java.lang.Object> = var %0 @"o";
1205                   %2 : java.lang.String = constant @"";
1206                   %3 : Var<java.lang.String> = var %2 @"r";
1207                   %4 : java.lang.Object = var.load %1;
1208                   %5 : java.lang.Integer = constant @null;
1209                   %6 : Var<java.lang.Integer> = var %5 @"i";
1210                   %7 : java.lang.String = constant @null;
1211                   %8 : Var<java.lang.String> = var %7 @"s";
1212                   java.switch.statement %4
1213                       (%9 : java.lang.Object)boolean -> {
1214                           %10 : boolean = pattern.match %9
1215                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Integer> -> {
1216                                   %11 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Integer> = pattern.type @"i";
1217                                   yield %11;
1218                               }
1219                               (%12 : java.lang.Integer)void -> {
1220                                   var.store %6 %12;
1221                                   yield;
1222                               };
1223                           yield %10;
1224                       }
1225                       ()void -> {
1226                           %13 : java.lang.String = var.load %3;
1227                           %14 : java.lang.String = constant @"integer";
1228                           %15 : java.lang.String = concat %13 %14;
1229                           var.store %3 %15;
1230                           yield;
1231                       }
1232                       (%16 : java.lang.Object)boolean -> {
1233                           %17 : boolean = pattern.match %16
1234                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
1235                                   %18 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type @"s";
1236                                   yield %18;
1237                               }
1238                               (%19 : java.lang.String)void -> {
1239                                   var.store %8 %19;
1240                                   yield;
1241                               };
1242                           yield %17;
1243                       }
1244                       ()void -> {
1245                           %20 : java.lang.String = var.load %3;
1246                           %21 : java.lang.String = constant @"string";
1247                           %22 : java.lang.String = concat %20 %21;
1248                           var.store %3 %22;
1249                           yield;
1250                       }
1251                       ()boolean -> {
1252                           %17 : boolean = constant @"true";
1253                           yield %17;
1254                       }
1255                       ()void -> {
1256                           %23 : java.lang.String = var.load %3;
1257                           %24 : java.lang.String = constant @"else";
1258                           %25 : java.lang.String = concat %23 %24;
1259                           var.store %3 %25;
1260                           yield;
1261                       };
1262                   %26 : java.lang.String = var.load %3;
1263                   return %26;
1264               };
1265             """)
1266     @CodeReflection
1267     private static String casePatternRuleExpression(Object o) {
1268         String r = "";
1269         switch (o) {
1270             case Integer i -> r += "integer";
1271             case String s -> r+= "string";
1272             default -> r+= "else";
1273         }
1274         return r;
1275     }
1276 
1277     @IR("""
1278             func @"casePatternRuleBlock" (%0 : java.lang.Object)java.lang.String -> {
1279                   %1 : Var<java.lang.Object> = var %0 @"o";
1280                   %2 : java.lang.String = constant @"";
1281                   %3 : Var<java.lang.String> = var %2 @"r";
1282                   %4 : java.lang.Object = var.load %1;
1283                   %5 : java.lang.Integer = constant @null;
1284                   %6 : Var<java.lang.Integer> = var %5 @"i";
1285                   %7 : java.lang.String = constant @null;
1286                   %8 : Var<java.lang.String> = var %7 @"s";
1287                   java.switch.statement %4
1288                       (%9 : java.lang.Object)boolean -> {
1289                           %10 : boolean = pattern.match %9
1290                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Integer> -> {
1291                                   %11 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Integer> = pattern.type @"i";
1292                                   yield %11;
1293                               }
1294                               (%12 : java.lang.Integer)void -> {
1295                                   var.store %6 %12;
1296                                   yield;
1297                               };
1298                           yield %10;
1299                       }
1300                       ()void -> {
1301                           %13 : java.lang.String = var.load %3;
1302                           %14 : java.lang.String = constant @"integer";
1303                           %15 : java.lang.String = concat %13 %14;
1304                           var.store %3 %15;
1305                           yield;
1306                       }
1307                       (%16 : java.lang.Object)boolean -> {
1308                           %17 : boolean = pattern.match %16
1309                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
1310                                   %18 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type @"s";
1311                                   yield %18;
1312                               }
1313                               (%19 : java.lang.String)void -> {
1314                                   var.store %8 %19;
1315                                   yield;
1316                               };
1317                           yield %17;
1318                       }
1319                       ()void -> {
1320                           %20 : java.lang.String = var.load %3;
1321                           %21 : java.lang.String = constant @"string";
1322                           %22 : java.lang.String = concat %20 %21;
1323                           var.store %3 %22;
1324                           yield;
1325                       }
1326                       ()boolean -> {
1327                           %17 : boolean = constant @"true";
1328                           yield %17;
1329                       }
1330                       ()void -> {
1331                           %23 : java.lang.String = var.load %3;
1332                           %24 : java.lang.String = constant @"else";
1333                           %25 : java.lang.String = concat %23 %24;
1334                           var.store %3 %25;
1335                           yield;
1336                       };
1337                   %26 : java.lang.String = var.load %3;
1338                   return %26;
1339               };
1340             """)
1341     @CodeReflection
1342     private static String casePatternRuleBlock(Object o) {
1343         String r = "";
1344         switch (o) {
1345             case Integer i -> {
1346                 r += "integer";
1347             }
1348             case String s -> {
1349                 r += "string";
1350             }
1351             default -> {
1352                 r += "else";
1353             }
1354         }
1355         return r;
1356     }
1357 
1358     @IR("""
1359             func @"casePatternStatement" (%0 : java.lang.Object)java.lang.String -> {
1360                   %1 : Var<java.lang.Object> = var %0 @"o";
1361                   %2 : java.lang.String = constant @"";
1362                   %3 : Var<java.lang.String> = var %2 @"r";
1363                   %4 : java.lang.Object = var.load %1;
1364                   %5 : java.lang.Integer = constant @null;
1365                   %6 : Var<java.lang.Integer> = var %5 @"i";
1366                   %7 : java.lang.String = constant @null;
1367                   %8 : Var<java.lang.String> = var %7 @"s";
1368                   java.switch.statement %4
1369                       (%9 : java.lang.Object)boolean -> {
1370                           %10 : boolean = pattern.match %9
1371                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Integer> -> {
1372                                   %11 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Integer> = pattern.type @"i";
1373                                   yield %11;
1374                               }
1375                               (%12 : java.lang.Integer)void -> {
1376                                   var.store %6 %12;
1377                                   yield;
1378                               };
1379                           yield %10;
1380                       }
1381                       ()void -> {
1382                           %13 : java.lang.String = var.load %3;
1383                           %14 : java.lang.String = constant @"integer";
1384                           %15 : java.lang.String = concat %13 %14;
1385                           var.store %3 %15;
1386                           java.break;
1387                       }
1388                       (%16 : java.lang.Object)boolean -> {
1389                           %17 : boolean = pattern.match %16
1390                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
1391                                   %18 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type @"s";
1392                                   yield %18;
1393                               }
1394                               (%19 : java.lang.String)void -> {
1395                                   var.store %8 %19;
1396                                   yield;
1397                               };
1398                           yield %17;
1399                       }
1400                       ()void -> {
1401                           %20 : java.lang.String = var.load %3;
1402                           %21 : java.lang.String = constant @"string";
1403                           %22 : java.lang.String = concat %20 %21;
1404                           var.store %3 %22;
1405                           java.break;
1406                       }
1407                       ()boolean -> {
1408                           %17 : boolean = constant @"true";
1409                           yield %17;
1410                       }
1411                       ()void -> {
1412                           %23 : java.lang.String = var.load %3;
1413                           %24 : java.lang.String = constant @"else";
1414                           %25 : java.lang.String = concat %23 %24;
1415                           var.store %3 %25;
1416                           yield;
1417                       };
1418                   %26 : java.lang.String = var.load %3;
1419                   return %26;
1420               };
1421             """)
1422     @CodeReflection
1423     private static String casePatternStatement(Object o) {
1424         String r = "";
1425         switch (o) {
1426             case Integer i:
1427                 r += "integer";
1428                 break;
1429             case String s:
1430                 r += "string";
1431                 break;
1432             default:
1433                 r += "else";
1434         }
1435         return r;
1436     }
1437 
1438     @IR("""
1439             func @"casePatternThrow" (%0 : java.lang.Object)java.lang.String -> {
1440                 %1 : Var<java.lang.Object> = var %0 @"o";
1441                 %2 : java.lang.String = constant @"";
1442                 %3 : Var<java.lang.String> = var %2 @"r";
1443                 %4 : java.lang.Object = var.load %1;
1444                 %5 : java.lang.Number = constant @null;
1445                 %6 : Var<java.lang.Number> = var %5 @"n";
1446                 %7 : java.lang.String = constant @null;
1447                 %8 : Var<java.lang.String> = var %7 @"s";
1448                 java.switch.statement %4
1449                     (%9 : java.lang.Object)boolean -> {
1450                         %10 : boolean = pattern.match %9
1451                             ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Number> -> {
1452                                 %11 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Number> = pattern.type @"n";
1453                                 yield %11;
1454                             }
1455                             (%12 : java.lang.Number)void -> {
1456                                 var.store %6 %12;
1457                                 yield;
1458                             };
1459                         yield %10;
1460                     }
1461                     ()void -> {
1462                         %13 : java.lang.IllegalArgumentException = new @"func<java.lang.IllegalArgumentException>";
1463                         throw %13;
1464                     }
1465                     (%14 : java.lang.Object)boolean -> {
1466                         %15 : boolean = pattern.match %14
1467                             ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
1468                                 %16 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type @"s";
1469                                 yield %16;
1470                             }
1471                             (%17 : java.lang.String)void -> {
1472                                 var.store %8 %17;
1473                                 yield;
1474                             };
1475                         yield %15;
1476                     }
1477                     ()void -> {
1478                         %18 : java.lang.String = var.load %3;
1479                         %19 : java.lang.String = constant @"a string";
1480                         %20 : java.lang.String = concat %18 %19;
1481                         var.store %3 %20;
1482                         yield;
1483                     }
1484                     ()boolean -> {
1485                         %17 : boolean = constant @"true";
1486                         yield %17;
1487                     }
1488                     ()void -> {
1489                         %21 : java.lang.String = var.load %3;
1490                         %22 : java.lang.Object = var.load %1;
1491                         %23 : java.lang.Class<+<java.lang.Object>> = invoke %22 @"java.lang.Object::getClass()java.lang.Class";
1492                         %24 : java.lang.String = invoke %23 @"java.lang.Class::getName()java.lang.String";
1493                         %25 : java.lang.String = concat %21 %24;
1494                         var.store %3 %25;
1495                         yield;
1496                     };
1497                 %26 : java.lang.String = var.load %3;
1498                 return %26;
1499             };
1500             """)
1501     @CodeReflection
1502     private static String casePatternThrow(Object o) {
1503         String r = "";
1504         switch (o) {
1505             case Number n -> throw new IllegalArgumentException();
1506             case String s -> r += "a string";
1507             default -> r += o.getClass().getName();
1508         }
1509         return r;
1510     }
1511 
1512     // @@@ code model for such as code is not supported
1513 //    @CodeReflection
1514     private static String casePatternMultiLabel(Object o) {
1515         String r = "";
1516         switch (o) {
1517             case Integer _, Long _, Character _, Byte _, Short _-> r += "integral type";
1518             default -> r += "non integral type";
1519         }
1520         return r;
1521     }
1522 
1523     @IR("""
1524             func @"casePatternWithCaseConstant" (%0 : java.lang.Integer)java.lang.String -> {
1525                   %1 : Var<java.lang.Integer> = var %0 @"a";
1526                   %2 : java.lang.String = constant @"";
1527                   %3 : Var<java.lang.String> = var %2 @"r";
1528                   %4 : java.lang.Integer = var.load %1;
1529                   %5 : java.lang.Integer = constant @null;
1530                   %6 : Var<java.lang.Integer> = var %5 @"i";
1531                   %7 : java.lang.Integer = constant @null;
1532                   %8 : Var<java.lang.Integer> = var %7 @"i";
1533                   java.switch.statement %4
1534                       (%9 : java.lang.Integer)boolean -> {
1535                           %10 : int = constant @"42";
1536                           %11 : java.lang.Integer = invoke %10 @"java.lang.Integer::valueOf(int)java.lang.Integer";
1537                           %12 : boolean = invoke %9 %11 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
1538                           yield %12;
1539                       }
1540                       ()void -> {
1541                           %13 : java.lang.String = var.load %3;
1542                           %14 : java.lang.String = constant @"forty two";
1543                           %15 : java.lang.String = concat %13 %14;
1544                           var.store %3 %15;
1545                           yield;
1546                       }
1547                       (%16 : java.lang.Integer)boolean -> {
1548                           %17 : boolean = java.cand
1549                               ()boolean -> {
1550                                   %18 : boolean = pattern.match %16
1551                                       ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Integer> -> {
1552                                           %19 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Integer> = pattern.type @"i";
1553                                           yield %19;
1554                                       }
1555                                       (%20 : java.lang.Integer)void -> {
1556                                           var.store %6 %20;
1557                                           yield;
1558                                       };
1559                                   yield %18;
1560                               }
1561                               ()boolean -> {
1562                                   %21 : java.lang.Integer = var.load %6;
1563                                   %22 : int = invoke %21 @"java.lang.Integer::intValue()int";
1564                                   %23 : int = constant @"0";
1565                                   %24 : boolean = gt %22 %23;
1566                                   yield %24;
1567                               };
1568                           yield %17;
1569                       }
1570                       ()void -> {
1571                           %25 : java.lang.String = var.load %3;
1572                           %26 : java.lang.String = constant @"positive int";
1573                           %27 : java.lang.String = concat %25 %26;
1574                           var.store %3 %27;
1575                           yield;
1576                       }
1577                       (%28 : java.lang.Integer)boolean -> {
1578                           %29 : boolean = java.cand
1579                               ()boolean -> {
1580                                   %30 : boolean = pattern.match %28
1581                                       ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Integer> -> {
1582                                           %31 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Integer> = pattern.type @"i";
1583                                           yield %31;
1584                                       }
1585                                       (%32 : java.lang.Integer)void -> {
1586                                           var.store %8 %32;
1587                                           yield;
1588                                       };
1589                                   yield %30;
1590                               }
1591                               ()boolean -> {
1592                                   %33 : java.lang.Integer = var.load %8;
1593                                   %34 : int = invoke %33 @"java.lang.Integer::intValue()int";
1594                                   %35 : int = constant @"0";
1595                                   %36 : boolean = lt %34 %35;
1596                                   yield %36;
1597                               };
1598                           yield %29;
1599                       }
1600                       ()void -> {
1601                           %37 : java.lang.String = var.load %3;
1602                           %38 : java.lang.String = constant @"negative int";
1603                           %39 : java.lang.String = concat %37 %38;
1604                           var.store %3 %39;
1605                           yield;
1606                       }
1607                       ()boolean -> {
1608                           %17 : boolean = constant @"true";
1609                           yield %17;
1610                       }
1611                       ()void -> {
1612                           %40 : java.lang.String = var.load %3;
1613                           %41 : java.lang.String = constant @"zero";
1614                           %42 : java.lang.String = concat %40 %41;
1615                           var.store %3 %42;
1616                           yield;
1617                       };
1618                   %43 : java.lang.String = var.load %3;
1619                   return %43;
1620               };
1621             """)
1622     @CodeReflection
1623     static String casePatternWithCaseConstant(Integer a) {
1624         String r = "";
1625         switch (a) {
1626             case 42 -> r += "forty two";
1627             // @@@ case int will not match, because of the way InstanceOfOp is interpreted
1628             case Integer i when i > 0 -> r += "positive int";
1629             case Integer i when i < 0 -> r += "negative int";
1630             default -> r += "zero";
1631         }
1632         return r;
1633     }
1634 
1635     @IR("""
1636             func @"caseTypePattern" (%0 : java.lang.Object)java.lang.String -> {
1637                   %1 : Var<java.lang.Object> = var %0 @"o";
1638                   %2 : java.lang.String = constant @"";
1639                   %3 : Var<java.lang.String> = var %2 @"r";
1640                   %4 : java.lang.Object = var.load %1;
1641                   %5 : java.lang.String = constant @null;
1642                   %6 : Var<java.lang.String> = var %5;
1643                   %7 : java.util.RandomAccess = constant @null;
1644                   %8 : Var<java.util.RandomAccess> = var %7;
1645                   %9 : int[] = constant @null;
1646                   %10 : Var<int[]> = var %9;
1647                   %11 : java.util.Stack[][] = constant @null;
1648                   %12 : Var<java.util.Stack[][]> = var %11;
1649                   %13 : java.util.Collection[][][] = constant @null;
1650                   %14 : Var<java.util.Collection[][][]> = var %13;
1651                   %15 : java.lang.Number = constant @null;
1652                   %16 : Var<java.lang.Number> = var %15 @"n";
1653                   java.switch.statement %4
1654                       (%17 : java.lang.Object)boolean -> {
1655                           %18 : boolean = pattern.match %17
1656                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
1657                                   %19 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type;
1658                                   yield %19;
1659                               }
1660                               (%20 : java.lang.String)void -> {
1661                                   var.store %6 %20;
1662                                   yield;
1663                               };
1664                           yield %18;
1665                       }
1666                       ()void -> {
1667                           %21 : java.lang.String = var.load %3;
1668                           %22 : java.lang.String = constant @"String";
1669                           %23 : java.lang.String = concat %21 %22;
1670                           var.store %3 %23;
1671                           yield;
1672                       }
1673                       (%24 : java.lang.Object)boolean -> {
1674                           %25 : boolean = pattern.match %24
1675                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.util.RandomAccess> -> {
1676                                   %26 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.util.RandomAccess> = pattern.type;
1677                                   yield %26;
1678                               }
1679                               (%27 : java.util.RandomAccess)void -> {
1680                                   var.store %8 %27;
1681                                   yield;
1682                               };
1683                           yield %25;
1684                       }
1685                       ()void -> {
1686                           %28 : java.lang.String = var.load %3;
1687                           %29 : java.lang.String = constant @"RandomAccess";
1688                           %30 : java.lang.String = concat %28 %29;
1689                           var.store %3 %30;
1690                           yield;
1691                       }
1692                       (%31 : java.lang.Object)boolean -> {
1693                           %32 : boolean = pattern.match %31
1694                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<int[]> -> {
1695                                   %33 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<int[]> = pattern.type;
1696                                   yield %33;
1697                               }
1698                               (%34 : int[])void -> {
1699                                   var.store %10 %34;
1700                                   yield;
1701                               };
1702                           yield %32;
1703                       }
1704                       ()void -> {
1705                           %35 : java.lang.String = var.load %3;
1706                           %36 : java.lang.String = constant @"int[]";
1707                           %37 : java.lang.String = concat %35 %36;
1708                           var.store %3 %37;
1709                           yield;
1710                       }
1711                       (%38 : java.lang.Object)boolean -> {
1712                           %39 : boolean = pattern.match %38
1713                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.util.Stack[][]> -> {
1714                                   %40 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.util.Stack[][]> = pattern.type;
1715                                   yield %40;
1716                               }
1717                               (%41 : java.util.Stack[][])void -> {
1718                                   var.store %12 %41;
1719                                   yield;
1720                               };
1721                           yield %39;
1722                       }
1723                       ()void -> {
1724                           %42 : java.lang.String = var.load %3;
1725                           %43 : java.lang.String = constant @"Stack[][]";
1726                           %44 : java.lang.String = concat %42 %43;
1727                           var.store %3 %44;
1728                           yield;
1729                       }
1730                       (%45 : java.lang.Object)boolean -> {
1731                           %46 : boolean = pattern.match %45
1732                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.util.Collection[][][]> -> {
1733                                   %47 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.util.Collection[][][]> = pattern.type;
1734                                   yield %47;
1735                               }
1736                               (%48 : java.util.Collection[][][])void -> {
1737                                   var.store %14 %48;
1738                                   yield;
1739                               };
1740                           yield %46;
1741                       }
1742                       ()void -> {
1743                           %49 : java.lang.String = var.load %3;
1744                           %50 : java.lang.String = constant @"Collection[][][]";
1745                           %51 : java.lang.String = concat %49 %50;
1746                           var.store %3 %51;
1747                           yield;
1748                       }
1749                       (%52 : java.lang.Object)boolean -> {
1750                           %53 : boolean = pattern.match %52
1751                               ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Number> -> {
1752                                   %54 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Number> = pattern.type @"n";
1753                                   yield %54;
1754                               }
1755                               (%55 : java.lang.Number)void -> {
1756                                   var.store %16 %55;
1757                                   yield;
1758                               };
1759                           yield %53;
1760                       }
1761                       ()void -> {
1762                           %56 : java.lang.String = var.load %3;
1763                           %57 : java.lang.String = constant @"Number";
1764                           %58 : java.lang.String = concat %56 %57;
1765                           var.store %3 %58;
1766                           yield;
1767                       }
1768                       ()boolean -> {
1769                           %59 : boolean = constant @"true";
1770                           yield %59;
1771                       }
1772                       ()void -> {
1773                           %60 : java.lang.String = var.load %3;
1774                           %61 : java.lang.String = constant @"something else";
1775                           %62 : java.lang.String = concat %60 %61;
1776                           var.store %3 %62;
1777                           yield;
1778                       };
1779                   %63 : java.lang.String = var.load %3;
1780                   return %63;
1781             };
1782             """)
1783     @CodeReflection
1784     static String caseTypePattern(Object o) {
1785         String r = "";
1786         switch (o) {
1787             case String _ -> r+= "String"; // class
1788             case RandomAccess _ -> r+= "RandomAccess"; // interface
1789             case int[] _ -> r+= "int[]"; // array primitive
1790             case Stack[][] _ -> r+= "Stack[][]"; // array class
1791             case Collection[][][] _ -> r+= "Collection[][][]"; // array interface
1792             case final Number n -> r+= "Number"; // final modifier
1793             default -> r+= "something else";
1794         }
1795         return r;
1796     }
1797 
1798     record R(Number n) {}
1799     @IR("""
1800             func @"caseRecordPattern" (%0 : java.lang.Object)java.lang.String -> {
1801                 %1 : Var<java.lang.Object> = var %0 @"o";
1802                 %2 : java.lang.String = constant @"";
1803                 %3 : Var<java.lang.String> = var %2 @"r";
1804                 %4 : java.lang.Object = var.load %1;
1805                 %5 : java.lang.Number = constant @null;
1806                 %6 : Var<java.lang.Number> = var %5 @"n";
1807                 java.switch.statement %4
1808                     (%7 : java.lang.Object)boolean -> {
1809                         %8 : boolean = pattern.match %7
1810                             ()jdk.incubator.code.op.ExtendedOp$Pattern$Record<SwitchStatementTest$R> -> {
1811                                 %9 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Number> = pattern.type @"n";
1812                                 %10 : jdk.incubator.code.op.ExtendedOp$Pattern$Record<SwitchStatementTest$R> = pattern.record %9 @"(java.lang.Number n)SwitchStatementTest$R";
1813                                 yield %10;
1814                             }
1815                             (%11 : java.lang.Number)void -> {
1816                                 var.store %6 %11;
1817                                 yield;
1818                             };
1819                         yield %8;
1820                     }
1821                     ()void -> {
1822                         %12 : java.lang.String = var.load %3;
1823                         %13 : java.lang.String = constant @"R(_)";
1824                         %14 : java.lang.String = concat %12 %13;
1825                         var.store %3 %14;
1826                         yield;
1827                     }
1828                     ()boolean -> {
1829                         %17 : boolean = constant @"true";
1830                         yield %17;
1831                     }
1832                     ()void -> {
1833                         %15 : java.lang.String = var.load %3;
1834                         %16 : java.lang.String = constant @"else";
1835                         %17 : java.lang.String = concat %15 %16;
1836                         var.store %3 %17;
1837                         yield;
1838                     };
1839                 %18 : java.lang.String = var.load %3;
1840                 return %18;
1841             };
1842             """)
1843     @CodeReflection
1844     static String caseRecordPattern(Object o) {
1845         String r = "";
1846         switch (o) {
1847             case R(Number n) -> r += "R(_)";
1848             default -> r+= "else";
1849         }
1850         return r;
1851     }
1852 
1853     @IR("""
1854             func @"casePatternGuard" (%0 : java.lang.Object)java.lang.String -> {
1855                 %1 : Var<java.lang.Object> = var %0 @"obj";
1856                 %2 : java.lang.String = constant @"";
1857                 %3 : Var<java.lang.String> = var %2 @"r";
1858                 %4 : java.lang.Object = var.load %1;
1859                 %5 : java.lang.String = constant @null;
1860                 %6 : Var<java.lang.String> = var %5 @"s";
1861                 %7 : java.lang.Number = constant @null;
1862                 %8 : Var<java.lang.Number> = var %7 @"n";
1863                 java.switch.statement %4
1864                     (%9 : java.lang.Object)boolean -> {
1865                         %10 : boolean = java.cand
1866                             ()boolean -> {
1867                                 %11 : boolean = pattern.match %9
1868                                     ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
1869                                         %12 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type @"s";
1870                                         yield %12;
1871                                     }
1872                                     (%13 : java.lang.String)void -> {
1873                                         var.store %6 %13;
1874                                         yield;
1875                                     };
1876                                 yield %11;
1877                             }
1878                             ()boolean -> {
1879                                 %14 : java.lang.String = var.load %6;
1880                                 %15 : int = invoke %14 @"java.lang.String::length()int";
1881                                 %16 : int = constant @"3";
1882                                 %17 : boolean = gt %15 %16;
1883                                 yield %17;
1884                             };
1885                         yield %10;
1886                     }
1887                     ()void -> {
1888                         %18 : java.lang.String = var.load %3;
1889                         %19 : java.lang.String = constant @"str with length > %d";
1890                         %20 : java.lang.String = var.load %6;
1891                         %21 : int = invoke %20 @"java.lang.String::length()int";
1892                         %22 : java.lang.Integer = invoke %21 @"java.lang.Integer::valueOf(int)java.lang.Integer";
1893                         %23 : java.lang.String = invoke %19 %22 @invoke.kind="INSTANCE" @invoke.varargs="true" @"java.lang.String::formatted(java.lang.Object[])java.lang.String";
1894                         %24 : java.lang.String = concat %18 %23;
1895                         var.store %3 %24;
1896                         yield;
1897                     }
1898                     (%25 : java.lang.Object)boolean -> {
1899                         %26 : boolean = java.cand
1900                             ()boolean -> {
1901                                 %27 : boolean = pattern.match %25
1902                                     ()jdk.incubator.code.op.ExtendedOp$Pattern$Record<SwitchStatementTest$R> -> {
1903                                         %28 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Number> = pattern.type @"n";
1904                                         %29 : jdk.incubator.code.op.ExtendedOp$Pattern$Record<SwitchStatementTest$R> = pattern.record %28 @"(java.lang.Number n)SwitchStatementTest$R";
1905                                         yield %29;
1906                                     }
1907                                     (%30 : java.lang.Number)void -> {
1908                                         var.store %8 %30;
1909                                         yield;
1910                                     };
1911                                 yield %27;
1912                             }
1913                             ()boolean -> {
1914                                 %31 : java.lang.Number = var.load %8;
1915                                 %32 : java.lang.Class<+<java.lang.Object>> = invoke %31 @"java.lang.Object::getClass()java.lang.Class";
1916                                 %33 : java.lang.Class = constant @"java.lang.Double";
1917                                 %34 : boolean = invoke %32 %33 @"java.lang.Object::equals(java.lang.Object)boolean";
1918                                 yield %34;
1919                             };
1920                         yield %26;
1921                     }
1922                     ()void -> {
1923                         %35 : java.lang.String = var.load %3;
1924                         %36 : java.lang.String = constant @"R(Double)";
1925                         %37 : java.lang.String = concat %35 %36;
1926                         var.store %3 %37;
1927                         yield;
1928                     }
1929                     ()boolean -> {
1930                         %17 : boolean = constant @"true";
1931                         yield %17;
1932                     }
1933                     ()void -> {
1934                         %38 : java.lang.String = var.load %3;
1935                         %39 : java.lang.String = constant @"else";
1936                         %40 : java.lang.String = concat %38 %39;
1937                         var.store %3 %40;
1938                         yield;
1939                     };
1940                 %41 : java.lang.String = var.load %3;
1941                 return %41;
1942             };
1943             """)
1944     @CodeReflection
1945     static String casePatternGuard(Object obj) {
1946         String r = "";
1947         switch (obj) {
1948             case String s when s.length() > 3 -> r += "str with length > %d".formatted(s.length());
1949             case R(Number n) when n.getClass().equals(Double.class) -> r += "R(Double)";
1950             default -> r += "else";
1951         }
1952         return r;
1953     }
1954 
1955     @IR("""
1956             func @"defaultCaseNotTheLast" (%0 : java.lang.String)java.lang.String -> {
1957                 %1 : Var<java.lang.String> = var %0 @"s";
1958                 %2 : java.lang.String = constant @"";
1959                 %3 : Var<java.lang.String> = var %2 @"r";
1960                 %4 : java.lang.String = var.load %1;
1961                 java.switch.statement %4
1962                     (%5 : java.lang.String)boolean -> {
1963                         %6 : java.lang.String = constant @"M";
1964                         %7 : boolean = invoke %5 %6 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
1965                         yield %7;
1966                     }
1967                     ()void -> {
1968                         %8 : java.lang.String = var.load %3;
1969                         %9 : java.lang.String = constant @"Mow";
1970                         %10 : java.lang.String = concat %8 %9;
1971                         var.store %3 %10;
1972                         yield;
1973                     }
1974                     (%11 : java.lang.String)boolean -> {
1975                         %12 : java.lang.String = constant @"A";
1976                         %13 : boolean = invoke %11 %12 @"java.util.Objects::equals(java.lang.Object, java.lang.Object)boolean";
1977                         yield %13;
1978                     }
1979                     ()void -> {
1980                         %14 : java.lang.String = var.load %3;
1981                         %15 : java.lang.String = constant @"Aow";
1982                         %16 : java.lang.String = concat %14 %15;
1983                         var.store %3 %16;
1984                         yield;
1985                     }
1986                     ()boolean -> {
1987                         %17 : boolean = constant @"true";
1988                         yield %17;
1989                     }
1990                     ()void -> {
1991                         %17 : java.lang.String = var.load %3;
1992                         %18 : java.lang.String = constant @"else";
1993                         %19 : java.lang.String = concat %17 %18;
1994                         var.store %3 %19;
1995                         yield;
1996                     };
1997                 %20 : java.lang.String = var.load %3;
1998                 return %20;
1999             };
2000             """)
2001     @CodeReflection
2002     static String defaultCaseNotTheLast(String s) {
2003         String r = "";
2004         switch (s) {
2005             default -> r += "else";
2006             case "M" -> r += "Mow";
2007             case "A" -> r += "Aow";
2008         }
2009         return r;
2010     }
2011 }