github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/cmd/gc/swt.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include <u.h> 6 #include <libc.h> 7 #include "go.h" 8 9 enum 10 { 11 Snorm = 0, 12 Strue, 13 Sfalse, 14 Stype, 15 16 Tdefault, // default case 17 Texprconst, // normal constant case 18 Texprvar, // normal variable case 19 Ttypenil, // case nil 20 Ttypeconst, // type hashes 21 Ttypevar, // interface type 22 23 Ncase = 4, // count needed to split 24 }; 25 26 typedef struct Case Case; 27 struct Case 28 { 29 Node* node; // points at case statement 30 uint32 hash; // hash of a type switch 31 uint8 type; // type of case 32 uint8 diag; // suppress multiple diagnostics 33 uint16 ordinal; // position in switch 34 Case* link; // linked list to link 35 }; 36 #define C ((Case*)nil) 37 /*c2go Case *C; */ 38 39 void 40 dumpcase(Case *c0) 41 { 42 Case *c; 43 44 for(c=c0; c!=C; c=c->link) { 45 switch(c->type) { 46 case Tdefault: 47 print("case-default\n"); 48 print(" ord=%d\n", c->ordinal); 49 break; 50 case Texprconst: 51 print("case-exprconst\n"); 52 print(" ord=%d\n", c->ordinal); 53 break; 54 case Texprvar: 55 print("case-exprvar\n"); 56 print(" ord=%d\n", c->ordinal); 57 print(" op=%O\n", c->node->left->op); 58 break; 59 case Ttypenil: 60 print("case-typenil\n"); 61 print(" ord=%d\n", c->ordinal); 62 break; 63 case Ttypeconst: 64 print("case-typeconst\n"); 65 print(" ord=%d\n", c->ordinal); 66 print(" hash=%ux\n", c->hash); 67 break; 68 case Ttypevar: 69 print("case-typevar\n"); 70 print(" ord=%d\n", c->ordinal); 71 break; 72 default: 73 print("case-???\n"); 74 print(" ord=%d\n", c->ordinal); 75 print(" op=%O\n", c->node->left->op); 76 print(" hash=%ux\n", c->hash); 77 break; 78 } 79 } 80 print("\n"); 81 } 82 83 static int 84 ordlcmp(Case *c1, Case *c2) 85 { 86 // sort default first 87 if(c1->type == Tdefault) 88 return -1; 89 if(c2->type == Tdefault) 90 return +1; 91 92 // sort nil second 93 if(c1->type == Ttypenil) 94 return -1; 95 if(c2->type == Ttypenil) 96 return +1; 97 98 // sort by ordinal 99 if(c1->ordinal > c2->ordinal) 100 return +1; 101 if(c1->ordinal < c2->ordinal) 102 return -1; 103 return 0; 104 } 105 106 static int 107 exprcmp(Case *c1, Case *c2) 108 { 109 int ct, n; 110 Node *n1, *n2; 111 112 // sort non-constants last 113 if(c1->type != Texprconst) 114 return +1; 115 if(c2->type != Texprconst) 116 return -1; 117 118 n1 = c1->node->left; 119 n2 = c2->node->left; 120 121 // sort by type (for switches on interface) 122 ct = n1->val.ctype; 123 if(ct != n2->val.ctype) 124 return ct - n2->val.ctype; 125 if(!eqtype(n1->type, n2->type)) { 126 if(n1->type->vargen > n2->type->vargen) 127 return +1; 128 else 129 return -1; 130 } 131 132 // sort by constant value 133 n = 0; 134 switch(ct) { 135 case CTFLT: 136 n = mpcmpfltflt(n1->val.u.fval, n2->val.u.fval); 137 break; 138 case CTINT: 139 case CTRUNE: 140 n = mpcmpfixfix(n1->val.u.xval, n2->val.u.xval); 141 break; 142 case CTSTR: 143 n = cmpslit(n1, n2); 144 break; 145 } 146 147 return n; 148 } 149 150 static int 151 typecmp(Case *c1, Case *c2) 152 { 153 154 // sort non-constants last 155 if(c1->type != Ttypeconst) 156 return +1; 157 if(c2->type != Ttypeconst) 158 return -1; 159 160 // sort by hash code 161 if(c1->hash > c2->hash) 162 return +1; 163 if(c1->hash < c2->hash) 164 return -1; 165 166 // sort by ordinal so duplicate error 167 // happens on later case. 168 if(c1->ordinal > c2->ordinal) 169 return +1; 170 if(c1->ordinal < c2->ordinal) 171 return -1; 172 return 0; 173 } 174 175 static Case* 176 csort(Case *l, int(*f)(Case*, Case*)) 177 { 178 Case *l1, *l2, *le; 179 180 if(l == C || l->link == C) 181 return l; 182 183 l1 = l; 184 l2 = l; 185 for(;;) { 186 l2 = l2->link; 187 if(l2 == C) 188 break; 189 l2 = l2->link; 190 if(l2 == C) 191 break; 192 l1 = l1->link; 193 } 194 195 l2 = l1->link; 196 l1->link = C; 197 l1 = csort(l, f); 198 l2 = csort(l2, f); 199 200 /* set up lead element */ 201 if((*f)(l1, l2) < 0) { 202 l = l1; 203 l1 = l1->link; 204 } else { 205 l = l2; 206 l2 = l2->link; 207 } 208 le = l; 209 210 for(;;) { 211 if(l1 == C) { 212 while(l2) { 213 le->link = l2; 214 le = l2; 215 l2 = l2->link; 216 } 217 le->link = C; 218 break; 219 } 220 if(l2 == C) { 221 while(l1) { 222 le->link = l1; 223 le = l1; 224 l1 = l1->link; 225 } 226 break; 227 } 228 if((*f)(l1, l2) < 0) { 229 le->link = l1; 230 le = l1; 231 l1 = l1->link; 232 } else { 233 le->link = l2; 234 le = l2; 235 l2 = l2->link; 236 } 237 } 238 le->link = C; 239 return l; 240 } 241 242 static Node* 243 newlabel(void) 244 { 245 static int label; 246 247 label++; 248 snprint(namebuf, sizeof(namebuf), "%.6d", label); 249 return newname(lookup(namebuf)); 250 } 251 252 /* 253 * build separate list of statements and cases 254 * make labels between cases and statements 255 * deal with fallthrough, break, unreachable statements 256 */ 257 static void 258 casebody(Node *sw, Node *typeswvar) 259 { 260 Node *n, *c, *last; 261 Node *def; 262 NodeList *cas, *stat, *l, *lc; 263 Node *go, *br; 264 int32 lno, needvar; 265 266 if(sw->list == nil) 267 return; 268 269 lno = setlineno(sw); 270 271 cas = nil; // cases 272 stat = nil; // statements 273 def = N; // defaults 274 br = nod(OBREAK, N, N); 275 276 for(l=sw->list; l; l=l->next) { 277 n = l->n; 278 setlineno(n); 279 if(n->op != OXCASE) 280 fatal("casebody %O", n->op); 281 n->op = OCASE; 282 needvar = count(n->list) != 1 || n->list->n->op == OLITERAL; 283 284 go = nod(OGOTO, newlabel(), N); 285 if(n->list == nil) { 286 if(def != N) 287 yyerror("more than one default case"); 288 // reuse original default case 289 n->right = go; 290 def = n; 291 } 292 293 if(n->list != nil && n->list->next == nil) { 294 // one case - reuse OCASE node. 295 c = n->list->n; 296 n->left = c; 297 n->right = go; 298 n->list = nil; 299 cas = list(cas, n); 300 } else { 301 // expand multi-valued cases 302 for(lc=n->list; lc; lc=lc->next) { 303 c = lc->n; 304 cas = list(cas, nod(OCASE, c, go)); 305 } 306 } 307 308 stat = list(stat, nod(OLABEL, go->left, N)); 309 if(typeswvar && needvar && n->nname != N) { 310 NodeList *l; 311 312 l = list1(nod(ODCL, n->nname, N)); 313 l = list(l, nod(OAS, n->nname, typeswvar)); 314 typechecklist(l, Etop); 315 stat = concat(stat, l); 316 } 317 stat = concat(stat, n->nbody); 318 319 // botch - shouldn't fall thru declaration 320 last = stat->end->n; 321 if(last->xoffset == n->xoffset && last->op == OXFALL) { 322 if(typeswvar) { 323 setlineno(last); 324 yyerror("cannot fallthrough in type switch"); 325 } 326 if(l->next == nil) { 327 setlineno(last); 328 yyerror("cannot fallthrough final case in switch"); 329 } 330 last->op = OFALL; 331 } else 332 stat = list(stat, br); 333 } 334 335 stat = list(stat, br); 336 if(def) 337 cas = list(cas, def); 338 339 sw->list = cas; 340 sw->nbody = stat; 341 lineno = lno; 342 } 343 344 static Case* 345 mkcaselist(Node *sw, int arg) 346 { 347 Node *n; 348 Case *c, *c1, *c2; 349 NodeList *l; 350 int ord; 351 352 c = C; 353 ord = 0; 354 355 for(l=sw->list; l; l=l->next) { 356 n = l->n; 357 c1 = mal(sizeof(*c1)); 358 c1->link = c; 359 c = c1; 360 361 ord++; 362 if((uint16)ord != ord) 363 fatal("too many cases in switch"); 364 c->ordinal = ord; 365 c->node = n; 366 367 if(n->left == N) { 368 c->type = Tdefault; 369 continue; 370 } 371 372 switch(arg) { 373 case Stype: 374 c->hash = 0; 375 if(n->left->op == OLITERAL) { 376 c->type = Ttypenil; 377 continue; 378 } 379 if(istype(n->left->type, TINTER)) { 380 c->type = Ttypevar; 381 continue; 382 } 383 384 c->hash = typehash(n->left->type); 385 c->type = Ttypeconst; 386 continue; 387 388 case Snorm: 389 case Strue: 390 case Sfalse: 391 c->type = Texprvar; 392 c->hash = typehash(n->left->type); 393 switch(consttype(n->left)) { 394 case CTFLT: 395 case CTINT: 396 case CTRUNE: 397 case CTSTR: 398 c->type = Texprconst; 399 } 400 continue; 401 } 402 } 403 404 if(c == C) 405 return C; 406 407 // sort by value and diagnose duplicate cases 408 switch(arg) { 409 case Stype: 410 c = csort(c, typecmp); 411 for(c1=c; c1!=C; c1=c1->link) { 412 for(c2=c1->link; c2!=C && c2->hash==c1->hash; c2=c2->link) { 413 if(c1->type == Ttypenil || c1->type == Tdefault) 414 break; 415 if(c2->type == Ttypenil || c2->type == Tdefault) 416 break; 417 if(!eqtype(c1->node->left->type, c2->node->left->type)) 418 continue; 419 yyerrorl(c2->node->lineno, "duplicate case %T in type switch\n\tprevious case at %L", c2->node->left->type, c1->node->lineno); 420 } 421 } 422 break; 423 case Snorm: 424 case Strue: 425 case Sfalse: 426 c = csort(c, exprcmp); 427 for(c1=c; c1->link!=C; c1=c1->link) { 428 if(exprcmp(c1, c1->link) != 0) 429 continue; 430 setlineno(c1->link->node); 431 yyerror("duplicate case %N in switch\n\tprevious case at %L", c1->node->left, c1->node->lineno); 432 } 433 break; 434 } 435 436 // put list back in processing order 437 c = csort(c, ordlcmp); 438 return c; 439 } 440 441 static Node* exprname; 442 443 static Node* 444 exprbsw(Case *c0, int ncase, int arg) 445 { 446 NodeList *cas; 447 Node *a, *n; 448 Case *c; 449 int i, half, lno; 450 451 cas = nil; 452 if(ncase < Ncase) { 453 for(i=0; i<ncase; i++) { 454 n = c0->node; 455 lno = setlineno(n); 456 457 if(assignop(n->left->type, exprname->type, nil) == OCONVIFACE || 458 assignop(exprname->type, n->left->type, nil) == OCONVIFACE) 459 goto snorm; 460 461 switch(arg) { 462 case Strue: 463 a = nod(OIF, N, N); 464 a->ntest = n->left; // if val 465 a->nbody = list1(n->right); // then goto l 466 break; 467 468 case Sfalse: 469 a = nod(OIF, N, N); 470 a->ntest = nod(ONOT, n->left, N); // if !val 471 typecheck(&a->ntest, Erv); 472 a->nbody = list1(n->right); // then goto l 473 break; 474 475 default: 476 snorm: 477 a = nod(OIF, N, N); 478 a->ntest = nod(OEQ, exprname, n->left); // if name == val 479 typecheck(&a->ntest, Erv); 480 a->nbody = list1(n->right); // then goto l 481 break; 482 } 483 484 cas = list(cas, a); 485 c0 = c0->link; 486 lineno = lno; 487 } 488 return liststmt(cas); 489 } 490 491 // find the middle and recur 492 c = c0; 493 half = ncase>>1; 494 for(i=1; i<half; i++) 495 c = c->link; 496 a = nod(OIF, N, N); 497 a->ntest = nod(OLE, exprname, c->node->left); 498 typecheck(&a->ntest, Erv); 499 a->nbody = list1(exprbsw(c0, half, arg)); 500 a->nelse = list1(exprbsw(c->link, ncase-half, arg)); 501 return a; 502 } 503 504 /* 505 * normal (expression) switch. 506 * rebulid case statements into if .. goto 507 */ 508 static void 509 exprswitch(Node *sw) 510 { 511 Node *def; 512 NodeList *cas; 513 Node *a; 514 Case *c0, *c, *c1; 515 Type *t; 516 int arg, ncase; 517 518 casebody(sw, N); 519 520 arg = Snorm; 521 if(isconst(sw->ntest, CTBOOL)) { 522 arg = Strue; 523 if(sw->ntest->val.u.bval == 0) 524 arg = Sfalse; 525 } 526 walkexpr(&sw->ntest, &sw->ninit); 527 t = sw->type; 528 if(t == T) 529 return; 530 531 /* 532 * convert the switch into OIF statements 533 */ 534 exprname = N; 535 cas = nil; 536 if(arg != Strue && arg != Sfalse) { 537 exprname = temp(sw->ntest->type); 538 cas = list1(nod(OAS, exprname, sw->ntest)); 539 typechecklist(cas, Etop); 540 } else { 541 exprname = nodbool(arg == Strue); 542 } 543 544 c0 = mkcaselist(sw, arg); 545 if(c0 != C && c0->type == Tdefault) { 546 def = c0->node->right; 547 c0 = c0->link; 548 } else { 549 def = nod(OBREAK, N, N); 550 } 551 552 loop: 553 if(c0 == C) { 554 cas = list(cas, def); 555 sw->nbody = concat(cas, sw->nbody); 556 sw->list = nil; 557 walkstmtlist(sw->nbody); 558 return; 559 } 560 561 // deal with the variables one-at-a-time 562 if(!okforcmp[t->etype] || c0->type != Texprconst) { 563 a = exprbsw(c0, 1, arg); 564 cas = list(cas, a); 565 c0 = c0->link; 566 goto loop; 567 } 568 569 // do binary search on run of constants 570 ncase = 1; 571 for(c=c0; c->link!=C; c=c->link) { 572 if(c->link->type != Texprconst) 573 break; 574 ncase++; 575 } 576 577 // break the chain at the count 578 c1 = c->link; 579 c->link = C; 580 581 // sort and compile constants 582 c0 = csort(c0, exprcmp); 583 a = exprbsw(c0, ncase, arg); 584 cas = list(cas, a); 585 586 c0 = c1; 587 goto loop; 588 589 } 590 591 static Node* hashname; 592 static Node* facename; 593 static Node* boolname; 594 595 static Node* 596 typeone(Node *t) 597 { 598 NodeList *init; 599 Node *a, *b, *var; 600 601 var = t->nname; 602 init = nil; 603 if(var == N) { 604 typecheck(&nblank, Erv | Easgn); 605 var = nblank; 606 } else 607 init = list1(nod(ODCL, var, N)); 608 609 a = nod(OAS2, N, N); 610 a->list = list(list1(var), boolname); // var,bool = 611 b = nod(ODOTTYPE, facename, N); 612 b->type = t->left->type; // interface.(type) 613 a->rlist = list1(b); 614 typecheck(&a, Etop); 615 init = list(init, a); 616 617 b = nod(OIF, N, N); 618 b->ntest = boolname; 619 b->nbody = list1(t->right); // if bool { goto l } 620 a = liststmt(list(init, b)); 621 return a; 622 } 623 624 static Node* 625 typebsw(Case *c0, int ncase) 626 { 627 NodeList *cas; 628 Node *a, *n; 629 Case *c; 630 int i, half; 631 632 cas = nil; 633 634 if(ncase < Ncase) { 635 for(i=0; i<ncase; i++) { 636 n = c0->node; 637 if(c0->type != Ttypeconst) 638 fatal("typebsw"); 639 a = nod(OIF, N, N); 640 a->ntest = nod(OEQ, hashname, nodintconst(c0->hash)); 641 typecheck(&a->ntest, Erv); 642 a->nbody = list1(n->right); 643 cas = list(cas, a); 644 c0 = c0->link; 645 } 646 return liststmt(cas); 647 } 648 649 // find the middle and recur 650 c = c0; 651 half = ncase>>1; 652 for(i=1; i<half; i++) 653 c = c->link; 654 a = nod(OIF, N, N); 655 a->ntest = nod(OLE, hashname, nodintconst(c->hash)); 656 typecheck(&a->ntest, Erv); 657 a->nbody = list1(typebsw(c0, half)); 658 a->nelse = list1(typebsw(c->link, ncase-half)); 659 return a; 660 } 661 662 /* 663 * convert switch of the form 664 * switch v := i.(type) { case t1: ..; case t2: ..; } 665 * into if statements 666 */ 667 static void 668 typeswitch(Node *sw) 669 { 670 Node *def; 671 NodeList *cas, *hash; 672 Node *a, *n; 673 Case *c, *c0, *c1; 674 int ncase; 675 Type *t; 676 Val v; 677 678 if(sw->ntest == nil) 679 return; 680 if(sw->ntest->right == nil) { 681 setlineno(sw); 682 yyerror("type switch must have an assignment"); 683 return; 684 } 685 walkexpr(&sw->ntest->right, &sw->ninit); 686 if(!istype(sw->ntest->right->type, TINTER)) { 687 yyerror("type switch must be on an interface"); 688 return; 689 } 690 cas = nil; 691 692 /* 693 * predeclare temporary variables 694 * and the boolean var 695 */ 696 facename = temp(sw->ntest->right->type); 697 a = nod(OAS, facename, sw->ntest->right); 698 typecheck(&a, Etop); 699 cas = list(cas, a); 700 701 casebody(sw, facename); 702 703 boolname = temp(types[TBOOL]); 704 typecheck(&boolname, Erv); 705 706 hashname = temp(types[TUINT32]); 707 typecheck(&hashname, Erv); 708 709 t = sw->ntest->right->type; 710 if(isnilinter(t)) 711 a = syslook("efacethash", 1); 712 else 713 a = syslook("ifacethash", 1); 714 argtype(a, t); 715 a = nod(OCALL, a, N); 716 a->list = list1(facename); 717 a = nod(OAS, hashname, a); 718 typecheck(&a, Etop); 719 cas = list(cas, a); 720 721 c0 = mkcaselist(sw, Stype); 722 if(c0 != C && c0->type == Tdefault) { 723 def = c0->node->right; 724 c0 = c0->link; 725 } else { 726 def = nod(OBREAK, N, N); 727 } 728 729 /* 730 * insert if statement into each case block 731 */ 732 for(c=c0; c!=C; c=c->link) { 733 n = c->node; 734 switch(c->type) { 735 736 case Ttypenil: 737 v.ctype = CTNIL; 738 a = nod(OIF, N, N); 739 a->ntest = nod(OEQ, facename, nodlit(v)); 740 typecheck(&a->ntest, Erv); 741 a->nbody = list1(n->right); // if i==nil { goto l } 742 n->right = a; 743 break; 744 745 case Ttypevar: 746 case Ttypeconst: 747 n->right = typeone(n); 748 break; 749 } 750 } 751 752 /* 753 * generate list of if statements, binary search for constant sequences 754 */ 755 while(c0 != C) { 756 if(c0->type != Ttypeconst) { 757 n = c0->node; 758 cas = list(cas, n->right); 759 c0=c0->link; 760 continue; 761 } 762 763 // identify run of constants 764 c1 = c = c0; 765 while(c->link!=C && c->link->type==Ttypeconst) 766 c = c->link; 767 c0 = c->link; 768 c->link = nil; 769 770 // sort by hash 771 c1 = csort(c1, typecmp); 772 773 // for debugging: linear search 774 if(0) { 775 for(c=c1; c!=C; c=c->link) { 776 n = c->node; 777 cas = list(cas, n->right); 778 } 779 continue; 780 } 781 782 // combine adjacent cases with the same hash 783 ncase = 0; 784 for(c=c1; c!=C; c=c->link) { 785 ncase++; 786 hash = list1(c->node->right); 787 while(c->link != C && c->link->hash == c->hash) { 788 hash = list(hash, c->link->node->right); 789 c->link = c->link->link; 790 } 791 c->node->right = liststmt(hash); 792 } 793 794 // binary search among cases to narrow by hash 795 cas = list(cas, typebsw(c1, ncase)); 796 } 797 if(nerrors == 0) { 798 cas = list(cas, def); 799 sw->nbody = concat(cas, sw->nbody); 800 sw->list = nil; 801 walkstmtlist(sw->nbody); 802 } 803 } 804 805 void 806 walkswitch(Node *sw) 807 { 808 /* 809 * reorder the body into (OLIST, cases, statements) 810 * cases have OGOTO into statements. 811 * both have inserted OBREAK statements 812 */ 813 if(sw->ntest == N) { 814 sw->ntest = nodbool(1); 815 typecheck(&sw->ntest, Erv); 816 } 817 818 if(sw->ntest->op == OTYPESW) { 819 typeswitch(sw); 820 //dump("sw", sw); 821 return; 822 } 823 exprswitch(sw); 824 // Discard old AST elements after a walk. They can confuse racewealk. 825 sw->ntest = nil; 826 sw->list = nil; 827 } 828 829 /* 830 * type check switch statement 831 */ 832 void 833 typecheckswitch(Node *n) 834 { 835 int top, lno, ptr; 836 char *nilonly; 837 Type *t, *badtype, *missing, *have; 838 NodeList *l, *ll; 839 Node *ncase, *nvar; 840 Node *def; 841 842 lno = lineno; 843 typechecklist(n->ninit, Etop); 844 nilonly = nil; 845 846 if(n->ntest != N && n->ntest->op == OTYPESW) { 847 // type switch 848 top = Etype; 849 typecheck(&n->ntest->right, Erv); 850 t = n->ntest->right->type; 851 if(t != T && t->etype != TINTER) 852 yyerror("cannot type switch on non-interface value %lN", n->ntest->right); 853 } else { 854 // value switch 855 top = Erv; 856 if(n->ntest) { 857 typecheck(&n->ntest, Erv); 858 defaultlit(&n->ntest, T); 859 t = n->ntest->type; 860 } else 861 t = types[TBOOL]; 862 if(t) { 863 if(!okforeq[t->etype]) 864 yyerror("cannot switch on %lN", n->ntest); 865 else if(t->etype == TARRAY && !isfixedarray(t)) 866 nilonly = "slice"; 867 else if(t->etype == TARRAY && isfixedarray(t) && algtype1(t, nil) == ANOEQ) 868 yyerror("cannot switch on %lN", n->ntest); 869 else if(t->etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ) 870 yyerror("cannot switch on %lN (struct containing %T cannot be compared)", n->ntest, badtype); 871 else if(t->etype == TFUNC) 872 nilonly = "func"; 873 else if(t->etype == TMAP) 874 nilonly = "map"; 875 } 876 } 877 n->type = t; 878 879 def = N; 880 for(l=n->list; l; l=l->next) { 881 ncase = l->n; 882 setlineno(n); 883 if(ncase->list == nil) { 884 // default 885 if(def != N) 886 yyerror("multiple defaults in switch (first at %L)", def->lineno); 887 else 888 def = ncase; 889 } else { 890 for(ll=ncase->list; ll; ll=ll->next) { 891 setlineno(ll->n); 892 typecheck(&ll->n, Erv | Etype); 893 if(ll->n->type == T || t == T) 894 continue; 895 setlineno(ncase); 896 switch(top) { 897 case Erv: // expression switch 898 defaultlit(&ll->n, t); 899 if(ll->n->op == OTYPE) 900 yyerror("type %T is not an expression", ll->n->type); 901 else if(ll->n->type != T && !assignop(ll->n->type, t, nil) && !assignop(t, ll->n->type, nil)) { 902 if(n->ntest) 903 yyerror("invalid case %N in switch on %N (mismatched types %T and %T)", ll->n, n->ntest, ll->n->type, t); 904 else 905 yyerror("invalid case %N in switch (mismatched types %T and bool)", ll->n, ll->n->type); 906 } else if(nilonly && !isconst(ll->n, CTNIL)) { 907 yyerror("invalid case %N in switch (can only compare %s %N to nil)", ll->n, nilonly, n->ntest); 908 } 909 break; 910 case Etype: // type switch 911 if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL)) { 912 ; 913 } else if(ll->n->op != OTYPE && ll->n->type != T) { // should this be ||? 914 yyerror("%lN is not a type", ll->n); 915 // reset to original type 916 ll->n = n->ntest->right; 917 } else if(ll->n->type->etype != TINTER && t->etype == TINTER && !implements(ll->n->type, t, &missing, &have, &ptr)) { 918 if(have && !missing->broke && !have->broke) 919 yyerror("impossible type switch case: %lN cannot have dynamic type %T" 920 " (wrong type for %S method)\n\thave %S%hT\n\twant %S%hT", 921 n->ntest->right, ll->n->type, missing->sym, have->sym, have->type, 922 missing->sym, missing->type); 923 else if(!missing->broke) 924 yyerror("impossible type switch case: %lN cannot have dynamic type %T" 925 " (missing %S method)", n->ntest->right, ll->n->type, missing->sym); 926 } 927 break; 928 } 929 } 930 } 931 if(top == Etype && n->type != T) { 932 ll = ncase->list; 933 nvar = ncase->nname; 934 if(nvar != N) { 935 if(ll && ll->next == nil && ll->n->type != T && !istype(ll->n->type, TNIL)) { 936 // single entry type switch 937 nvar->ntype = typenod(ll->n->type); 938 } else { 939 // multiple entry type switch or default 940 nvar->ntype = typenod(n->type); 941 } 942 } 943 } 944 typechecklist(ncase->nbody, Etop); 945 } 946 947 lineno = lno; 948 }