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