github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/src/cmd/compile/internal/gc/swt.go (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 package gc 6 7 import ( 8 "cmd/internal/obj" 9 "sort" 10 "strconv" 11 ) 12 13 const ( 14 // expression switch 15 switchKindExpr = iota // switch a {...} or switch 5 {...} 16 switchKindTrue // switch true {...} or switch {...} 17 switchKindFalse // switch false {...} 18 19 // type switch 20 switchKindType // switch a.(type) {...} 21 ) 22 23 const ( 24 caseKindDefault = iota // default: 25 26 // expression switch 27 caseKindExprConst // case 5: 28 caseKindExprVar // case x: 29 30 // type switch 31 caseKindTypeNil // case nil: 32 caseKindTypeConst // case time.Time: (concrete type, has type hash) 33 caseKindTypeVar // case io.Reader: (interface type) 34 ) 35 36 const binarySearchMin = 4 // minimum number of cases for binary search 37 38 // An exprSwitch walks an expression switch. 39 type exprSwitch struct { 40 exprname *Node // node for the expression being switched on 41 kind int // kind of switch statement (switchKind*) 42 } 43 44 // A typeSwitch walks a type switch. 45 type typeSwitch struct { 46 hashname *Node // node for the hash of the type of the variable being switched on 47 facename *Node // node for the concrete type of the variable being switched on 48 okname *Node // boolean node used for comma-ok type assertions 49 } 50 51 // A caseClause is a single case clause in a switch statement. 52 type caseClause struct { 53 node *Node // points at case statement 54 ordinal int // position in switch 55 hash uint32 // hash of a type switch 56 typ uint8 // type of case 57 } 58 59 // typecheckswitch typechecks a switch statement. 60 func typecheckswitch(n *Node) { 61 lno := int(lineno) 62 typechecklist(n.Ninit, Etop) 63 64 var nilonly string 65 var top int 66 var t *Type 67 68 if n.Left != nil && n.Left.Op == OTYPESW { 69 // type switch 70 top = Etype 71 typecheck(&n.Left.Right, Erv) 72 t = n.Left.Right.Type 73 if t != nil && t.Etype != TINTER { 74 Yyerror("cannot type switch on non-interface value %v", Nconv(n.Left.Right, obj.FmtLong)) 75 } 76 } else { 77 // expression switch 78 top = Erv 79 if n.Left != nil { 80 typecheck(&n.Left, Erv) 81 defaultlit(&n.Left, nil) 82 t = n.Left.Type 83 } else { 84 t = Types[TBOOL] 85 } 86 if t != nil { 87 var badtype *Type 88 switch { 89 case !okforeq[t.Etype]: 90 Yyerror("cannot switch on %v", Nconv(n.Left, obj.FmtLong)) 91 case t.Etype == TARRAY && !Isfixedarray(t): 92 nilonly = "slice" 93 case t.Etype == TARRAY && Isfixedarray(t) && algtype1(t, nil) == ANOEQ: 94 Yyerror("cannot switch on %v", Nconv(n.Left, obj.FmtLong)) 95 case t.Etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ: 96 Yyerror("cannot switch on %v (struct containing %v cannot be compared)", Nconv(n.Left, obj.FmtLong), badtype) 97 case t.Etype == TFUNC: 98 nilonly = "func" 99 case t.Etype == TMAP: 100 nilonly = "map" 101 } 102 } 103 } 104 105 n.Type = t 106 107 var def *Node 108 var ll *NodeList 109 for l := n.List; l != nil; l = l.Next { 110 ncase := l.N 111 setlineno(n) 112 if ncase.List == nil { 113 // default 114 if def != nil { 115 Yyerror("multiple defaults in switch (first at %v)", def.Line()) 116 } else { 117 def = ncase 118 } 119 } else { 120 for ll = ncase.List; ll != nil; ll = ll.Next { 121 setlineno(ll.N) 122 typecheck(&ll.N, Erv|Etype) 123 if ll.N.Type == nil || t == nil { 124 continue 125 } 126 setlineno(ncase) 127 switch top { 128 // expression switch 129 case Erv: 130 defaultlit(&ll.N, t) 131 switch { 132 case ll.N.Op == OTYPE: 133 Yyerror("type %v is not an expression", ll.N.Type) 134 case ll.N.Type != nil && assignop(ll.N.Type, t, nil) == 0 && assignop(t, ll.N.Type, nil) == 0: 135 if n.Left != nil { 136 Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", ll.N, n.Left, ll.N.Type, t) 137 } else { 138 Yyerror("invalid case %v in switch (mismatched types %v and bool)", ll.N, ll.N.Type) 139 } 140 case nilonly != "" && !Isconst(ll.N, CTNIL): 141 Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ll.N, nilonly, n.Left) 142 } 143 144 // type switch 145 case Etype: 146 var missing, have *Type 147 var ptr int 148 switch { 149 case ll.N.Op == OLITERAL && Istype(ll.N.Type, TNIL): 150 case ll.N.Op != OTYPE && ll.N.Type != nil: // should this be ||? 151 Yyerror("%v is not a type", Nconv(ll.N, obj.FmtLong)) 152 // reset to original type 153 ll.N = n.Left.Right 154 case ll.N.Type.Etype != TINTER && t.Etype == TINTER && !implements(ll.N.Type, t, &missing, &have, &ptr): 155 if have != nil && !missing.Broke && !have.Broke { 156 Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort)) 157 } else if !missing.Broke { 158 Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym) 159 } 160 } 161 } 162 } 163 } 164 165 if top == Etype && n.Type != nil { 166 ll = ncase.List 167 if ncase.Rlist != nil { 168 nvar := ncase.Rlist.N 169 if ll != nil && ll.Next == nil && ll.N.Type != nil && !Istype(ll.N.Type, TNIL) { 170 // single entry type switch 171 nvar.Name.Param.Ntype = typenod(ll.N.Type) 172 } else { 173 // multiple entry type switch or default 174 nvar.Name.Param.Ntype = typenod(n.Type) 175 } 176 177 typecheck(&nvar, Erv|Easgn) 178 ncase.Rlist.N = nvar 179 } 180 } 181 182 typechecklist(ncase.Nbody, Etop) 183 } 184 185 lineno = int32(lno) 186 } 187 188 // walkswitch walks a switch statement. 189 func walkswitch(sw *Node) { 190 // convert switch {...} to switch true {...} 191 if sw.Left == nil { 192 sw.Left = Nodbool(true) 193 typecheck(&sw.Left, Erv) 194 } 195 196 if sw.Left.Op == OTYPESW { 197 var s typeSwitch 198 s.walk(sw) 199 } else { 200 var s exprSwitch 201 s.walk(sw) 202 } 203 } 204 205 // walk generates an AST implementing sw. 206 // sw is an expression switch. 207 // The AST is generally of the form of a linear 208 // search using if..goto, although binary search 209 // is used with long runs of constants. 210 func (s *exprSwitch) walk(sw *Node) { 211 casebody(sw, nil) 212 213 cond := sw.Left 214 sw.Left = nil 215 216 s.kind = switchKindExpr 217 if Isconst(cond, CTBOOL) { 218 s.kind = switchKindTrue 219 if !cond.Val().U.(bool) { 220 s.kind = switchKindFalse 221 } 222 } 223 224 walkexpr(&cond, &sw.Ninit) 225 t := sw.Type 226 if t == nil { 227 return 228 } 229 230 // convert the switch into OIF statements 231 var cas *NodeList 232 if s.kind == switchKindTrue || s.kind == switchKindFalse { 233 s.exprname = Nodbool(s.kind == switchKindTrue) 234 } else if consttype(cond) >= 0 { 235 // leave constants to enable dead code elimination (issue 9608) 236 s.exprname = cond 237 } else { 238 s.exprname = temp(cond.Type) 239 cas = list1(Nod(OAS, s.exprname, cond)) 240 typechecklist(cas, Etop) 241 } 242 243 // enumerate the cases, and lop off the default case 244 cc := caseClauses(sw, s.kind) 245 sw.List = nil 246 var def *Node 247 if len(cc) > 0 && cc[0].typ == caseKindDefault { 248 def = cc[0].node.Right 249 cc = cc[1:] 250 } else { 251 def = Nod(OBREAK, nil, nil) 252 } 253 254 // handle the cases in order 255 for len(cc) > 0 { 256 // deal with expressions one at a time 257 if !okforcmp[t.Etype] || cc[0].typ != caseKindExprConst { 258 a := s.walkCases(cc[:1]) 259 cas = list(cas, a) 260 cc = cc[1:] 261 continue 262 } 263 264 // do binary search on runs of constants 265 var run int 266 for run = 1; run < len(cc) && cc[run].typ == caseKindExprConst; run++ { 267 } 268 269 // sort and compile constants 270 sort.Sort(caseClauseByExpr(cc[:run])) 271 a := s.walkCases(cc[:run]) 272 cas = list(cas, a) 273 cc = cc[run:] 274 } 275 276 // handle default case 277 if nerrors == 0 { 278 cas = list(cas, def) 279 sw.Nbody = concat(cas, sw.Nbody) 280 walkstmtlist(sw.Nbody) 281 } 282 } 283 284 // walkCases generates an AST implementing the cases in cc. 285 func (s *exprSwitch) walkCases(cc []*caseClause) *Node { 286 if len(cc) < binarySearchMin { 287 // linear search 288 var cas *NodeList 289 for _, c := range cc { 290 n := c.node 291 lno := int(setlineno(n)) 292 293 a := Nod(OIF, nil, nil) 294 if (s.kind != switchKindTrue && s.kind != switchKindFalse) || assignop(n.Left.Type, s.exprname.Type, nil) == OCONVIFACE || assignop(s.exprname.Type, n.Left.Type, nil) == OCONVIFACE { 295 a.Left = Nod(OEQ, s.exprname, n.Left) // if name == val 296 typecheck(&a.Left, Erv) 297 } else if s.kind == switchKindTrue { 298 a.Left = n.Left // if val 299 } else { 300 // s.kind == switchKindFalse 301 a.Left = Nod(ONOT, n.Left, nil) // if !val 302 typecheck(&a.Left, Erv) 303 } 304 a.Nbody = list1(n.Right) // goto l 305 306 cas = list(cas, a) 307 lineno = int32(lno) 308 } 309 return liststmt(cas) 310 } 311 312 // find the middle and recur 313 half := len(cc) / 2 314 a := Nod(OIF, nil, nil) 315 mid := cc[half-1].node.Left 316 le := Nod(OLE, s.exprname, mid) 317 if Isconst(mid, CTSTR) { 318 // Search by length and then by value; see exprcmp. 319 lenlt := Nod(OLT, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil)) 320 leneq := Nod(OEQ, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil)) 321 a.Left = Nod(OOROR, lenlt, Nod(OANDAND, leneq, le)) 322 } else { 323 a.Left = le 324 } 325 typecheck(&a.Left, Erv) 326 a.Nbody = list1(s.walkCases(cc[:half])) 327 a.Rlist = list1(s.walkCases(cc[half:])) 328 return a 329 } 330 331 // casebody builds separate lists of statements and cases. 332 // It makes labels between cases and statements 333 // and deals with fallthrough, break, and unreachable statements. 334 func casebody(sw *Node, typeswvar *Node) { 335 if sw.List == nil { 336 return 337 } 338 339 lno := setlineno(sw) 340 341 var cas *NodeList // cases 342 var stat *NodeList // statements 343 var def *Node // defaults 344 br := Nod(OBREAK, nil, nil) 345 346 for l := sw.List; l != nil; l = l.Next { 347 n := l.N 348 setlineno(n) 349 if n.Op != OXCASE { 350 Fatalf("casebody %v", Oconv(int(n.Op), 0)) 351 } 352 n.Op = OCASE 353 needvar := count(n.List) != 1 || n.List.N.Op == OLITERAL 354 355 jmp := Nod(OGOTO, newCaseLabel(), nil) 356 if n.List == nil { 357 if def != nil { 358 Yyerror("more than one default case") 359 } 360 // reuse original default case 361 n.Right = jmp 362 def = n 363 } 364 365 if n.List != nil && n.List.Next == nil { 366 // one case -- reuse OCASE node 367 n.Left = n.List.N 368 n.Right = jmp 369 n.List = nil 370 cas = list(cas, n) 371 } else { 372 // expand multi-valued cases 373 for lc := n.List; lc != nil; lc = lc.Next { 374 cas = list(cas, Nod(OCASE, lc.N, jmp)) 375 } 376 } 377 378 stat = list(stat, Nod(OLABEL, jmp.Left, nil)) 379 if typeswvar != nil && needvar && n.Rlist != nil { 380 l := list1(Nod(ODCL, n.Rlist.N, nil)) 381 l = list(l, Nod(OAS, n.Rlist.N, typeswvar)) 382 typechecklist(l, Etop) 383 stat = concat(stat, l) 384 } 385 stat = concat(stat, n.Nbody) 386 387 // botch - shouldn't fall thru declaration 388 last := stat.End.N 389 if last.Xoffset == n.Xoffset && last.Op == OXFALL { 390 if typeswvar != nil { 391 setlineno(last) 392 Yyerror("cannot fallthrough in type switch") 393 } 394 395 if l.Next == nil { 396 setlineno(last) 397 Yyerror("cannot fallthrough final case in switch") 398 } 399 400 last.Op = OFALL 401 } else { 402 stat = list(stat, br) 403 } 404 } 405 406 stat = list(stat, br) 407 if def != nil { 408 cas = list(cas, def) 409 } 410 411 sw.List = cas 412 sw.Nbody = stat 413 lineno = lno 414 } 415 416 // nSwitchLabel is the number of switch labels generated. 417 // This should be per-function, but it is a global counter for now. 418 var nSwitchLabel int 419 420 func newCaseLabel() *Node { 421 label := strconv.Itoa(nSwitchLabel) 422 nSwitchLabel++ 423 return newname(Lookup(label)) 424 } 425 426 // caseClauses generates a slice of caseClauses 427 // corresponding to the clauses in the switch statement sw. 428 // Kind is the kind of switch statement. 429 func caseClauses(sw *Node, kind int) []*caseClause { 430 var cc []*caseClause 431 for l := sw.List; l != nil; l = l.Next { 432 n := l.N 433 c := new(caseClause) 434 cc = append(cc, c) 435 c.ordinal = len(cc) 436 c.node = n 437 438 if n.Left == nil { 439 c.typ = caseKindDefault 440 continue 441 } 442 443 if kind == switchKindType { 444 // type switch 445 switch { 446 case n.Left.Op == OLITERAL: 447 c.typ = caseKindTypeNil 448 case Istype(n.Left.Type, TINTER): 449 c.typ = caseKindTypeVar 450 default: 451 c.typ = caseKindTypeConst 452 c.hash = typehash(n.Left.Type) 453 } 454 } else { 455 // expression switch 456 switch consttype(n.Left) { 457 case CTFLT, CTINT, CTRUNE, CTSTR: 458 c.typ = caseKindExprConst 459 default: 460 c.typ = caseKindExprVar 461 } 462 } 463 } 464 465 if cc == nil { 466 return nil 467 } 468 469 // sort by value and diagnose duplicate cases 470 if kind == switchKindType { 471 // type switch 472 sort.Sort(caseClauseByType(cc)) 473 for i, c1 := range cc { 474 if c1.typ == caseKindTypeNil || c1.typ == caseKindDefault { 475 break 476 } 477 for _, c2 := range cc[i+1:] { 478 if c2.typ == caseKindTypeNil || c2.typ == caseKindDefault || c1.hash != c2.hash { 479 break 480 } 481 if Eqtype(c1.node.Left.Type, c2.node.Left.Type) { 482 yyerrorl(int(c2.node.Lineno), "duplicate case %v in type switch\n\tprevious case at %v", c2.node.Left.Type, c1.node.Line()) 483 } 484 } 485 } 486 } else { 487 // expression switch 488 sort.Sort(caseClauseByExpr(cc)) 489 for i, c1 := range cc { 490 if i+1 == len(cc) { 491 break 492 } 493 c2 := cc[i+1] 494 if exprcmp(c1, c2) != 0 { 495 continue 496 } 497 setlineno(c2.node) 498 Yyerror("duplicate case %v in switch\n\tprevious case at %v", c1.node.Left, c1.node.Line()) 499 } 500 } 501 502 // put list back in processing order 503 sort.Sort(caseClauseByOrd(cc)) 504 return cc 505 } 506 507 // walk generates an AST that implements sw, 508 // where sw is a type switch. 509 // The AST is generally of the form of a linear 510 // search using if..goto, although binary search 511 // is used with long runs of concrete types. 512 func (s *typeSwitch) walk(sw *Node) { 513 cond := sw.Left 514 sw.Left = nil 515 516 if cond == nil { 517 sw.List = nil 518 return 519 } 520 if cond.Right == nil { 521 setlineno(sw) 522 Yyerror("type switch must have an assignment") 523 return 524 } 525 526 walkexpr(&cond.Right, &sw.Ninit) 527 if !Istype(cond.Right.Type, TINTER) { 528 Yyerror("type switch must be on an interface") 529 return 530 } 531 532 var cas *NodeList 533 534 // predeclare temporary variables and the boolean var 535 s.facename = temp(cond.Right.Type) 536 537 a := Nod(OAS, s.facename, cond.Right) 538 typecheck(&a, Etop) 539 cas = list(cas, a) 540 541 s.okname = temp(Types[TBOOL]) 542 typecheck(&s.okname, Erv) 543 544 s.hashname = temp(Types[TUINT32]) 545 typecheck(&s.hashname, Erv) 546 547 // set up labels and jumps 548 casebody(sw, s.facename) 549 550 // calculate type hash 551 t := cond.Right.Type 552 if isnilinter(t) { 553 a = syslook("efacethash", 1) 554 } else { 555 a = syslook("ifacethash", 1) 556 } 557 substArgTypes(a, t) 558 a = Nod(OCALL, a, nil) 559 a.List = list1(s.facename) 560 a = Nod(OAS, s.hashname, a) 561 typecheck(&a, Etop) 562 cas = list(cas, a) 563 564 cc := caseClauses(sw, switchKindType) 565 sw.List = nil 566 var def *Node 567 if len(cc) > 0 && cc[0].typ == caseKindDefault { 568 def = cc[0].node.Right 569 cc = cc[1:] 570 } else { 571 def = Nod(OBREAK, nil, nil) 572 } 573 574 // insert type equality check into each case block 575 for _, c := range cc { 576 n := c.node 577 switch c.typ { 578 case caseKindTypeNil: 579 var v Val 580 v.U = new(NilVal) 581 a = Nod(OIF, nil, nil) 582 a.Left = Nod(OEQ, s.facename, nodlit(v)) 583 typecheck(&a.Left, Erv) 584 a.Nbody = list1(n.Right) // if i==nil { goto l } 585 n.Right = a 586 587 case caseKindTypeVar, caseKindTypeConst: 588 n.Right = s.typeone(n) 589 } 590 } 591 592 // generate list of if statements, binary search for constant sequences 593 for len(cc) > 0 { 594 if cc[0].typ != caseKindTypeConst { 595 n := cc[0].node 596 cas = list(cas, n.Right) 597 cc = cc[1:] 598 continue 599 } 600 601 // identify run of constants 602 var run int 603 for run = 1; run < len(cc) && cc[run].typ == caseKindTypeConst; run++ { 604 } 605 606 // sort by hash 607 sort.Sort(caseClauseByType(cc[:run])) 608 609 // for debugging: linear search 610 if false { 611 for i := 0; i < run; i++ { 612 n := cc[i].node 613 cas = list(cas, n.Right) 614 } 615 continue 616 } 617 618 // combine adjacent cases with the same hash 619 ncase := 0 620 for i := 0; i < run; i++ { 621 ncase++ 622 hash := list1(cc[i].node.Right) 623 for j := i + 1; j < run && cc[i].hash == cc[j].hash; j++ { 624 hash = list(hash, cc[j].node.Right) 625 } 626 cc[i].node.Right = liststmt(hash) 627 } 628 629 // binary search among cases to narrow by hash 630 cas = list(cas, s.walkCases(cc[:ncase])) 631 cc = cc[ncase:] 632 } 633 634 // handle default case 635 if nerrors == 0 { 636 cas = list(cas, def) 637 sw.Nbody = concat(cas, sw.Nbody) 638 sw.List = nil 639 walkstmtlist(sw.Nbody) 640 } 641 } 642 643 // typeone generates an AST that jumps to the 644 // case body if the variable is of type t. 645 func (s *typeSwitch) typeone(t *Node) *Node { 646 var name *Node 647 var init *NodeList 648 if t.Rlist == nil { 649 name = nblank 650 typecheck(&nblank, Erv|Easgn) 651 } else { 652 name = t.Rlist.N 653 init = list1(Nod(ODCL, name, nil)) 654 a := Nod(OAS, name, nil) 655 typecheck(&a, Etop) 656 init = list(init, a) 657 } 658 659 a := Nod(OAS2, nil, nil) 660 a.List = list(list1(name), s.okname) // name, ok = 661 b := Nod(ODOTTYPE, s.facename, nil) 662 b.Type = t.Left.Type // interface.(type) 663 a.Rlist = list1(b) 664 typecheck(&a, Etop) 665 init = list(init, a) 666 667 c := Nod(OIF, nil, nil) 668 c.Left = s.okname 669 c.Nbody = list1(t.Right) // if ok { goto l } 670 671 return liststmt(list(init, c)) 672 } 673 674 // walkCases generates an AST implementing the cases in cc. 675 func (s *typeSwitch) walkCases(cc []*caseClause) *Node { 676 if len(cc) < binarySearchMin { 677 var cas *NodeList 678 for _, c := range cc { 679 n := c.node 680 if c.typ != caseKindTypeConst { 681 Fatalf("typeSwitch walkCases") 682 } 683 a := Nod(OIF, nil, nil) 684 a.Left = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash))) 685 typecheck(&a.Left, Erv) 686 a.Nbody = list1(n.Right) 687 cas = list(cas, a) 688 } 689 return liststmt(cas) 690 } 691 692 // find the middle and recur 693 half := len(cc) / 2 694 a := Nod(OIF, nil, nil) 695 a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash))) 696 typecheck(&a.Left, Erv) 697 a.Nbody = list1(s.walkCases(cc[:half])) 698 a.Rlist = list1(s.walkCases(cc[half:])) 699 return a 700 } 701 702 type caseClauseByOrd []*caseClause 703 704 func (x caseClauseByOrd) Len() int { return len(x) } 705 func (x caseClauseByOrd) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 706 func (x caseClauseByOrd) Less(i, j int) bool { 707 c1, c2 := x[i], x[j] 708 switch { 709 // sort default first 710 case c1.typ == caseKindDefault: 711 return true 712 case c2.typ == caseKindDefault: 713 return false 714 715 // sort nil second 716 case c1.typ == caseKindTypeNil: 717 return true 718 case c2.typ == caseKindTypeNil: 719 return false 720 } 721 722 // sort by ordinal 723 return c1.ordinal < c2.ordinal 724 } 725 726 type caseClauseByExpr []*caseClause 727 728 func (x caseClauseByExpr) Len() int { return len(x) } 729 func (x caseClauseByExpr) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 730 func (x caseClauseByExpr) Less(i, j int) bool { 731 return exprcmp(x[i], x[j]) < 0 732 } 733 734 func exprcmp(c1, c2 *caseClause) int { 735 // sort non-constants last 736 if c1.typ != caseKindExprConst { 737 return +1 738 } 739 if c2.typ != caseKindExprConst { 740 return -1 741 } 742 743 n1 := c1.node.Left 744 n2 := c2.node.Left 745 746 // sort by type (for switches on interface) 747 ct := int(n1.Val().Ctype()) 748 if ct > int(n2.Val().Ctype()) { 749 return +1 750 } 751 if ct < int(n2.Val().Ctype()) { 752 return -1 753 } 754 if !Eqtype(n1.Type, n2.Type) { 755 if n1.Type.Vargen > n2.Type.Vargen { 756 return +1 757 } else { 758 return -1 759 } 760 } 761 762 // sort by constant value to enable binary search 763 switch ct { 764 case CTFLT: 765 return mpcmpfltflt(n1.Val().U.(*Mpflt), n2.Val().U.(*Mpflt)) 766 case CTINT, CTRUNE: 767 return Mpcmpfixfix(n1.Val().U.(*Mpint), n2.Val().U.(*Mpint)) 768 case CTSTR: 769 // Sort strings by length and then by value. 770 // It is much cheaper to compare lengths than values, 771 // and all we need here is consistency. 772 // We respect this sorting in exprSwitch.walkCases. 773 a := n1.Val().U.(string) 774 b := n2.Val().U.(string) 775 if len(a) < len(b) { 776 return -1 777 } 778 if len(a) > len(b) { 779 return +1 780 } 781 if a == b { 782 return 0 783 } 784 if a < b { 785 return -1 786 } 787 return +1 788 } 789 790 return 0 791 } 792 793 type caseClauseByType []*caseClause 794 795 func (x caseClauseByType) Len() int { return len(x) } 796 func (x caseClauseByType) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 797 func (x caseClauseByType) Less(i, j int) bool { 798 c1, c2 := x[i], x[j] 799 switch { 800 // sort non-constants last 801 case c1.typ != caseKindTypeConst: 802 return false 803 case c2.typ != caseKindTypeConst: 804 return true 805 806 // sort by hash code 807 case c1.hash != c2.hash: 808 return c1.hash < c2.hash 809 } 810 811 // sort by ordinal 812 return c1.ordinal < c2.ordinal 813 }